Clean up and add multi-component configuration

This commit is contained in:
sylviamoss 2021-04-16 16:54:16 +02:00
parent 3f1a3f3c8e
commit 7478a9044c
31 changed files with 160 additions and 1132 deletions

124
.golangci.yml Normal file
View File

@ -0,0 +1,124 @@
issues:
# List of regexps of issue texts to exclude, empty list by default.
# But independently from this option we use default exclude patterns,
# it can be disabled by `exclude-use-default: false`. To list all
# excluded by default patterns execute `golangci-lint run --help`
exclude-rules:
# Exclude gosimple bool check
- linters:
- gosimple
text: "S(1002|1008|1021)"
# Exclude failing staticchecks for now
- linters:
- staticcheck
text: "SA(1006|1019|4006|4010|4017|5007|6005|9004):"
# Exclude lll issues for long lines with go:generate
- linters:
- lll
source: "^//go:generate "
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
max-same-issues: 0
linters:
disable-all: true
enable:
- deadcode
- errcheck
- goimports
- gosimple
- govet
- ineffassign
- staticcheck
- unconvert
- unused
- varcheck
fast: true
# options for analysis running
run:
# default concurrency is a available CPU number
concurrency: 4
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 10m
# exit code when at least one issue was found, default is 1
issues-exit-code: 1
# include test files or not, default is true
tests: true
# list of build tags, all linters use it. Default is empty list.
#build-tags:
# - mytag
# which dirs to skip: issues from them won't be reported;
# can use regexp here: generated.*, regexp is applied on full path;
# default value is empty list, but default dirs are skipped independently
# from this option's value (see skip-dirs-use-default).
#skip-dirs:
# - src/external_libs
# - autogenerated_by_my_lib
# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs-use-default: true
# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
skip-files:
- ".*\\.hcl2spec\\.go$"
# - lib/bad.go
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
# If invoked with -mod=readonly, the go command is disallowed from the implicit
# automatic updating of go.mod described above. Instead, it fails when any changes
# to go.mod are needed. This setting is most useful to check that go.mod does
# not need updates, such as in a continuous integration and testing system.
# If invoked with -mod=vendor, the go command assumes that the vendor
# directory holds the correct copies of dependencies and ignores
# the dependency descriptions in go.mod.
# modules-download-mode: vendor
# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: colored-line-number
# print lines of code with issue, default is true
print-issued-lines: true
# print linter name in the end of issue text, default is true
print-linter-name: true
# make issues output unique by line, default is true
uniq-by-line: true
# all available settings of specific linters
linters-settings:
errcheck:
# report about not checking of errors in type assetions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: false
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
# default is false: such cases aren't reported by default.
check-blank: false
# [deprecated] comma-separated list of pairs of the form pkg:regex
# the regex is used to ignore names within pkg. (default "fmt:.*").
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
ignore: fmt:.*,io/ioutil:^Read.*,io:Close
# path to a file containing a list of functions to exclude from checking
# see https://github.com/kisielk/errcheck#excluding-functions for details
#exclude: /path/to/file.txt

View File

@ -1,4 +1,4 @@
# This is an example goreleaser.yaml file with some defaults.
# This is an example goreleaser.yaml file with some sane defaults.
# Make sure to check the documentation at http://goreleaser.com
env:
- CGO_ENABLED=0
@ -9,7 +9,7 @@ before:
- go test ./...
# As part of the release doc files are included as a separate deliverable for
# consumption by Packer.io. To include a separate docs.zip uncomment the following command.
#- /bin/sh -c "[ -d docs ] && zip -r docs.zip docs/"
- make ci-release-docs
builds:
# A separated build to run the packer-plugins-check only once for a linux_amd64 binary
-
@ -78,8 +78,8 @@ release:
# draft: true
# As part of the release doc files are included as a separate deliverable for consumption by Packer.io.
# To include a separate docs.zip uncomment the extra_files config and the docs.zip command hook above.
#extra_files:
#- glob: ./docs.zip
extra_files:
- glob: ./docs.zip
changelog:
skip: true

3
CHANGELOG.md Normal file
View File

@ -0,0 +1,3 @@
## 0.0.1 (Unreleased)
* VMware Plugin break out from Packer core. Changes prior to break out can be found in [Packer's CHANGELOG](https://github.com/hashicorp/packer/blob/master/CHANGELOG.md).

View File

@ -1,4 +1,4 @@
NAME=scaffolding
NAME=vmware
BINARY=packer-plugin-${NAME}
COUNT?=1
@ -13,6 +13,15 @@ dev: build
@mkdir -p ~/.packer.d/plugins/
@mv ${BINARY} ~/.packer.d/plugins/${BINARY}
generate:
@go install github.com/hashicorp/packer-plugin-sdk/cmd/packer-sdc@latest
@go generate -v ./...
ci-release-docs:
@go install github.com/hashicorp/packer-plugin-sdk/cmd/packer-sdc@latest
@packer-sdc renderdocs -src docs -partials docs-partials/ -dst docs/
@/bin/sh -c "[ -d docs ] && zip -r docs.zip docs/"
run-example: dev
@packer build ./example

View File

@ -1,32 +0,0 @@
package scaffolding
// packersdk.Artifact implementation
type Artifact struct {
// StateData should store data such as GeneratedData
// to be shared with post-processors
StateData map[string]interface{}
}
func (*Artifact) BuilderId() string {
return BuilderId
}
func (a *Artifact) Files() []string {
return []string{}
}
func (*Artifact) Id() string {
return ""
}
func (a *Artifact) String() string {
return ""
}
func (a *Artifact) State(name string) interface{} {
return a.StateData[name]
}
func (a *Artifact) Destroy() error {
return nil
}

View File

@ -1,80 +0,0 @@
//go:generate mapstructure-to-hcl2 -type Config
package scaffolding
import (
"context"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer-plugin-sdk/common"
"github.com/hashicorp/packer-plugin-sdk/multistep"
"github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps"
"github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template/config"
)
const BuilderId = "scaffolding.builder"
type Config struct {
common.PackerConfig `mapstructure:",squash"`
MockOption string `mapstructure:"mock"`
}
type Builder struct {
config Config
runner multistep.Runner
}
func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() }
func (b *Builder) Prepare(raws ...interface{}) (generatedVars []string, warnings []string, err error) {
err = config.Decode(&b.config, &config.DecodeOpts{
PluginType: "packer.builder.scaffolding",
Interpolate: true,
}, raws...)
if err != nil {
return nil, nil, err
}
// Return the placeholder for the generated data that will become available to provisioners and post-processors.
// If the builder doesn't generate any data, just return an empty slice of string: []string{}
buildGeneratedData := []string{"GeneratedMockData"}
return buildGeneratedData, nil, nil
}
func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (packer.Artifact, error) {
steps := []multistep.Step{}
steps = append(steps,
&StepSayConfig{
MockConfig: b.config.MockOption,
},
new(commonsteps.StepProvision),
)
// Setup the state bag and initial state for the steps
state := new(multistep.BasicStateBag)
state.Put("hook", hook)
state.Put("ui", ui)
// Set the value of the generated data that will become available to provisioners.
// To share the data with post-processors, use the StateData in the artifact.
state.Put("generated_data", map[string]interface{}{
"GeneratedMockData": "mock-build-data",
})
// Run!
b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui)
b.runner.Run(ctx, state)
// If there was an error, return that
if err, ok := state.GetOk("error"); ok {
return nil, err.(error)
}
artifact := &Artifact{
// Add the builder generated data to the artifact StateData so that post-processors
// can access them.
StateData: map[string]interface{}{"generated_data": state.Get("generated_data")},
}
return artifact, nil
}

View File

@ -1,46 +0,0 @@
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
package scaffolding
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
MockOption *string `mapstructure:"mock" cty:"mock" hcl:"mock"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"mock": &hcldec.AttrSpec{Name: "mock", Type: cty.String, Required: false},
}
return s
}

View File

@ -1,57 +0,0 @@
package scaffolding
import (
_ "embed"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"testing"
"github.com/hashicorp/packer-plugin-sdk/acctest"
)
//go:embed test-fixtures/template.pkr.hcl
var testBuilderHCL2Basic string
// Run with: PACKER_ACC=1 go test -count 1 -v ./builder/scaffolding/builder_acc_test.go -timeout=120m
func TestAccScaffoldingBuilder(t *testing.T) {
testCase := &acctest.PluginTestCase{
Name: "scaffolding_builder_basic_test",
Setup: func() error {
return nil
},
Teardown: func() error {
return nil
},
Template: testBuilderHCL2Basic,
Type: "scaffolding-my-builder",
Check: func(buildCommand *exec.Cmd, logfile string) error {
if buildCommand.ProcessState != nil {
if buildCommand.ProcessState.ExitCode() != 0 {
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
}
}
logs, err := os.Open(logfile)
if err != nil {
return fmt.Errorf("Unable find %s", logfile)
}
defer logs.Close()
logsBytes, err := ioutil.ReadAll(logs)
if err != nil {
return fmt.Errorf("Unable to read %s", logfile)
}
logsString := string(logsBytes)
buildGeneratedDataLog := "scaffolding-my-builder.basic-example: build generated data: mock-build-data"
if matched, _ := regexp.MatchString(buildGeneratedDataLog+".*", logsString); !matched {
t.Fatalf("logs doesn't contain expected foo value %q", logsString)
}
return nil
},
}
acctest.TestPlugin(t, testCase)
}

View File

@ -1,38 +0,0 @@
package scaffolding
import (
"context"
"fmt"
"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
// This is a definition of a builder step and should implement multistep.Step
type StepSayConfig struct {
MockConfig string
}
// Run should execute the purpose of this step
func (s *StepSayConfig) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packersdk.Ui)
if s.MockConfig == "" {
ui.Error("'mock' should be set to say something.")
// Errors should be added to the state to be check it out
// later at the end of the build
state.Put("error", fmt.Errorf("'mock' not set"))
// Determines that the build steps should be halted
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("The mock config is set to %q", s.MockConfig))
// Determines that should continue to the next step
return multistep.ActionContinue
}
// Cleanup can be used to clean up any artifact created by the step.
// A step's clean up always run at the end of a build, regardless of whether provisioning succeeds or fails.
func (s *StepSayConfig) Cleanup(_ multistep.StateBag) {
// Nothing to clean
}

View File

@ -1,15 +0,0 @@
source "scaffolding-my-builder" "basic-example" {
mock = "mock-config"
}
build {
sources = [
"source.scaffolding-my-builder.basic-example"
]
provisioner "shell-local" {
inline = [
"echo build generated data: ${build.GeneratedMockData}",
]
}
}

View File

@ -1,46 +0,0 @@
//go:generate mapstructure-to-hcl2 -type Config,DatasourceOutput
package scaffolding
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer-plugin-sdk/hcl2helper"
"github.com/hashicorp/packer-plugin-sdk/template/config"
"github.com/zclconf/go-cty/cty"
)
type Config struct {
MockOption string `mapstructure:"mock"`
}
type Datasource struct {
config Config
}
type DatasourceOutput struct {
Foo string `mapstructure:"foo"`
Bar string `mapstructure:"bar"`
}
func (d *Datasource) ConfigSpec() hcldec.ObjectSpec {
return d.config.FlatMapstructure().HCL2Spec()
}
func (d *Datasource) Configure(raws ...interface{}) error {
err := config.Decode(&d.config, nil, raws...)
if err != nil {
return err
}
return nil
}
func (d *Datasource) OutputSpec() hcldec.ObjectSpec {
return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
}
func (d *Datasource) Execute() (cty.Value, error) {
output := DatasourceOutput{
Foo: "foo-value",
Bar: "bar-value",
}
return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
}

View File

@ -1,56 +0,0 @@
// Code generated by "mapstructure-to-hcl2 -type Config,DatasourceOutput"; DO NOT EDIT.
package scaffolding
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
MockOption *string `mapstructure:"mock" cty:"mock" hcl:"mock"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"mock": &hcldec.AttrSpec{Name: "mock", Type: cty.String, Required: false},
}
return s
}
// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatDatasourceOutput struct {
Foo *string `mapstructure:"foo" cty:"foo" hcl:"foo"`
Bar *string `mapstructure:"bar" cty:"bar" hcl:"bar"`
}
// FlatMapstructure returns a new FlatDatasourceOutput.
// FlatDatasourceOutput is an auto-generated flat version of DatasourceOutput.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*DatasourceOutput) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatDatasourceOutput)
}
// HCL2Spec returns the hcl spec of a DatasourceOutput.
// This spec is used by HCL to read the fields of DatasourceOutput.
// The decoded values from this spec will then be applied to a FlatDatasourceOutput.
func (*FlatDatasourceOutput) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"foo": &hcldec.AttrSpec{Name: "foo", Type: cty.String, Required: false},
"bar": &hcldec.AttrSpec{Name: "bar", Type: cty.String, Required: false},
}
return s
}

View File

@ -1,62 +0,0 @@
package scaffolding
import (
_ "embed"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"testing"
"github.com/hashicorp/packer-plugin-sdk/acctest"
)
//go:embed test-fixtures/template.pkr.hcl
var testDatasourceHCL2Basic string
// Run with: PACKER_ACC=1 go test -count 1 -v ./datasource/scaffolding/data_acc_test.go -timeout=120m
func TestAccScaffoldingDatasource(t *testing.T) {
testCase := &acctest.PluginTestCase{
Name: "scaffolding_datasource_basic_test",
Setup: func() error {
return nil
},
Teardown: func() error {
return nil
},
Template: testDatasourceHCL2Basic,
Type: "scaffolding-my-datasource",
Check: func(buildCommand *exec.Cmd, logfile string) error {
if buildCommand.ProcessState != nil {
if buildCommand.ProcessState.ExitCode() != 0 {
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
}
}
logs, err := os.Open(logfile)
if err != nil {
return fmt.Errorf("Unable find %s", logfile)
}
defer logs.Close()
logsBytes, err := ioutil.ReadAll(logs)
if err != nil {
return fmt.Errorf("Unable to read %s", logfile)
}
logsString := string(logsBytes)
fooLog := "null.basic-example: foo: foo-value"
barLog := "null.basic-example: bar: bar-value"
if matched, _ := regexp.MatchString(fooLog+".*", logsString); !matched {
t.Fatalf("logs doesn't contain expected foo value %q", logsString)
}
if matched, _ := regexp.MatchString(barLog+".*", logsString); !matched {
t.Fatalf("logs doesn't contain expected bar value %q", logsString)
}
return nil
},
}
acctest.TestPlugin(t, testCase)
}

View File

@ -1,25 +0,0 @@
data "scaffolding-my-datasource" "test" {
mock = "mock-config"
}
locals {
foo = data.scaffolding-my-datasource.test.foo
bar = data.scaffolding-my-datasource.test.bar
}
source "null" "basic-example" {
communicator = "none"
}
build {
sources = [
"source.null.basic-example"
]
provisioner "shell-local" {
inline = [
"echo foo: ${local.foo}",
"echo bar: ${local.bar}",
]
}
}

View File

@ -1,13 +1,4 @@
# Scaffolding Plugins
<!--
Include a short overview about the plugin.
This document is a great location for creating a table of contents for each
of the components the plugin may provide. This document should load automatically
when navigating to the docs directory for a plugin.
-->
# VMware Plugin
## Installation
@ -25,9 +16,9 @@ Then, run [`packer init`](https://www.packer.io/docs/commands/init).
```hcl
packer {
required_plugins {
name = {
vmware = {
version = ">= 0.0.1"
source = "github.com/hashicorp/name"
source = "github.com/hashicorp/vmware"
}
}
}
@ -46,33 +37,28 @@ To install the plugin, please follow the Packer documentation on
If you prefer to build the plugin from its source code, clone the GitHub
repository locally and run the command `go build` from the root
directory. Upon successful compilation, a `packer-plugin-name` plugin
directory. Upon successful compilation, a `packer-plugin-vmware` plugin
binary file can be found in the root directory.
To install the compiled plugin, please follow the official Packer documentation
on [installing a plugin](https://www.packer.io/docs/extending/plugins/#installing-plugins).
## Plugin Contents
## Plugin Components
The Scaffolding plugin is intended as a starting point for creating Packer plugins, containing:
The VMware Packer Plugin is able to create VMware virtual machines for use
with any VMware product.
### Builders
The plugin comes with multiple builders able to create VMware machines,
depending on the strategy you want to use to build the image. The supported VMware builders are:
- [builder](/docs/builders/builder-name.mdx) - The scaffolding builder is used to create endless Packer
plugins using a consistent plugin structure.
### Provisioners
- [provisioner](/docs/provisioners/provisioner-name.mdx) - The scaffolding provisioner is used to provisioner
Packer builds.
### Post-processors
- [post-processor](/docs/post-processors/postprocessor-name.mdx) - The scaffolding post-processor is used to
export scaffolding builds.
### Data Sources
- [data source](/docs/datasources/datasource-name.mdx) - The scaffolding data source is used to
export scaffolding data.
- [vmware-iso](/docs/builders/vmware-iso) - Starts from an ISO file,
creates a brand new VMware VM, installs an OS, provisions software within
the OS, then exports that machine to create an image. This is best for
people who want to start from scratch.
- [vmware-vmx](/docs/builders/vmware-vmx) - This builder imports an
existing VMware machine (from a VMX file), runs provisioners on top of that
VM, and exports that machine to create an image. This is best if you have
an existing VMware VM you want to use as the source. As an additional
benefit, you can feed the artifact of this builder back into Packer to
iterate on a machine.

View File

@ -1,63 +0,0 @@
---
description: >
The scaffolding builder is used to create endless Packer plugins using
a consistent plugin structure.
page_title: Scaffolding - Builders
nav_title: Scaffolding
---
# Scaffolding
Type: `scaffolding`
<!--
Include a short description about the builder. This is a good place
to call out what the builder does, and any requirements for the given
builder environment. See https://www.packer.io/docs/builders/null
-->
The scaffolding builder is used to create endless Packer plugins using
a consistent plugin structure.
<!-- Builder Configuration Fields -->
### Required
- `mock` (string) - The name of the mock to use for the Scaffolding API.
<!--
Optional Configuration Fields
Configuration options that are not required or have reasonable defaults
should be listed under the optionals section. Defaults values should be
noted in the description of the field
-->
### Optional
- `mock_api_url` (string) - The Scaffolding API endpoint to connect to.
Defaults to https://example.com
<!--
A basic example on the usage of the builder. Multiple examples
can be provided to highlight various build configurations.
-->
### Example Usage
```hcl
source "scaffolding" "example" {
mock = "bird"
}
build {
sources = ["source.scaffolding.example"]
}
```

View File

@ -1,78 +0,0 @@
---
description: >
The scaffolding data source is used to create endless Packer plugins using
a consistent plugin structure.
page_title: Scaffolding - Data Sources
nav_title: Scaffolding
---
# Scaffolding
Type: `scaffolding`
<!--
Include a short description about the data source. This is a good place
to call out what the data source does, and any requirements for the given
data source environment. See https://www.packer.io/docs/datasources/amazon-ami
-->
The scaffolding data source is used to create endless Packer plugins using
a consistent plugin structure.
<!-- Data source Configuration Fields -->
### Required
- `mock` (string) - The name of the mock to use for the Scaffolding API.
<!--
Optional Configuration Fields
Configuration options that are not required or have reasonable defaults
should be listed under the optionals section. Defaults values should be
noted in the description of the field
-->
### Optional
- `mock_api_url` (string) - The Scaffolding API endpoint to connect to.
Defaults to https://example.com
<!--
A basic example on the usage of the data source. Multiple examples
can be provided to highlight various build configurations.
-->
### OutPut
- `foo` (string) - The Scaffolding output foo value.
- `bar` (string) - The Scaffolding output bar value.
<!--
A basic example on the usage of the data source. Multiple examples
can be provided to highlight various build configurations.
-->
### Example Usage
```hcl
data "scaffolding" "example" {
mock = "bird"
}
source "scaffolding" "example" {
mock = data.scaffolding.example.foo
}
build {
sources = ["source.scaffolding.example"]
}
```

View File

@ -1,59 +0,0 @@
---
description: >
The scaffolding post-processor is used to export Packer Scaffolding builds.
page_title: Scaffolding - Post-Processors
nav_title: Scaffolding
---
# Scaffolding
Type: `scaffolding`
<!--
Include a short description about the post-processor. This is a good place
to call out what the post-processor does, and any additional text that might
be helpful to a user. See https://www.packer.io/docs/provisioners/null
-->
The scaffolding post-processor is used to export Packer Scaffolding builds.
<!-- Post-Processor Configuration Fields -->
### Required
- `mock` (string) - The output path where to save exported build to.
<!--
Optional Configuration Fields
Configuration options that are not required or have reasonable defaults
should be listed under the optionals section. Defaults values should be
noted in the description of the field
-->
### Optional
<!--
A basic example on the usage of the post-processor. Multiple examples
can be provided to highlight various configurations.
-->
### Example Usage
```hcl
source "scaffolding" "example" {
mock = "jay"
}
build {
sources = ["source.scaffolding.example"]
post-processor "scaffolding" {
mock = "builds/scaffolding.box"
}
}
```

View File

@ -1,62 +0,0 @@
---
description: >
The scaffolding provisioner is used to provisioner Packer builds.
page_title: Scaffolding - Provisioners
nav_title: Scaffolding
---
# Scaffolding
Type: `scaffolding`
<!--
Include a short description about the provisioner. This is a good place
to call out what the provisioner does, and any additional text that might
be helpful to a user. See https://www.packer.io/docs/provisioners/null
-->
The scaffolding provisioner is used to provisioner Packer builds.
<!-- Provisioner Configuration Fields -->
### Required
- `mock` (string) - The name of the mock string to display.
<!--
Optional Configuration Fields
Configuration options that are not required or have reasonable defaults
should be listed under the optionals section. Defaults values should be
noted in the description of the field
-->
### Optional
<!--
A basic example on the usage of the provisioner. Multiple examples
can be provided to highlight various configurations.
-->
### Example Usage
```hcl
source "null" "example" {
communicator = "none"
}
build {
source "null.example" {
name = "jay"
}
provisioner "scaffolding" {
mock = "mocking ${source.name}"
}
}
```

View File

@ -1,20 +0,0 @@
## The Example Folder
This folder must contain a fully working example of the plugin usage. The example must define the `required_plugins`
block. A pre-defined GitHub Action will run `packer init`, `packer validate`, and `packer build` to test your plugin
with the latest version available of Packer.
The folder can contain multiple HCL2 compatible files. The action will execute Packer at this folder level
running `packer init -upgrade .` and `packer build .`.
If the plugin requires authentication, the configuration should be provided via GitHub Secrets and set as environment
variables in the [test-plugin-example.yml](/.github/workflows/test-plugin-example.yml) file. Example:
```yml
- name: Build
working-directory: ${{ github.event.inputs.folder }}
run: PACKER_LOG=${{ github.event.inputs.logs }} packer build .
env:
AUTH_KEY: ${{ secrets.AUTH_KEY }}
AUTH_PASSWORD: ${{ secrets.AUTH_PASSWORD }}
```

View File

@ -1,40 +0,0 @@
packer {
required_plugins {
scaffolding = {
version = ">=v0.1.0"
source = "github.com/hashicorp/scaffolding"
}
}
}
source "scaffolding-my-builder" "foo-example" {
mock = local.foo
}
source "scaffolding-my-builder" "bar-example" {
mock = local.bar
}
build {
sources = [
"source.scaffolding-my-builder.foo-example",
]
source "source.scaffolding-my-builder.bar-example" {
name = "bar"
}
provisioner "scaffolding-my-provisioner" {
only = ["scaffolding-my-builder.foo-example"]
mock = "foo: ${local.foo}"
}
provisioner "scaffolding-my-provisioner" {
only = ["scaffolding-my-builder.bar"]
mock = "bar: ${local.bar}"
}
post-processor "scaffolding-my-post-processor" {
mock = "post-processor mock-config"
}
}

View File

@ -1,3 +0,0 @@
data "scaffolding-my-datasource" "mock-data" {
mock = "mock-config"
}

View File

@ -1,4 +0,0 @@
locals {
foo = data.scaffolding-my-datasource.mock-data.foo
bar = data.scaffolding-my-datasource.mock-data.bar
}

View File

@ -1,46 +0,0 @@
//go:generate mapstructure-to-hcl2 -type Config
package scaffolding
import (
"context"
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer-plugin-sdk/common"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template/config"
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
)
type Config struct {
common.PackerConfig `mapstructure:",squash"`
MockOption string `mapstructure:"mock"`
ctx interpolate.Context
}
type PostProcessor struct {
config Config
}
func (p *PostProcessor) ConfigSpec() hcldec.ObjectSpec { return p.config.FlatMapstructure().HCL2Spec() }
func (p *PostProcessor) Configure(raws ...interface{}) error {
err := config.Decode(&p.config, &config.DecodeOpts{
PluginType: "packer.post-processor.scaffolding",
Interpolate: true,
InterpolateContext: &p.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{},
},
}, raws...)
if err != nil {
return err
}
return nil
}
func (p *PostProcessor) PostProcess(ctx context.Context, ui packersdk.Ui, source packersdk.Artifact) (packersdk.Artifact, bool, bool, error) {
ui.Say(fmt.Sprintf("post-processor mock: %s", p.config.MockOption))
return source, true, true, nil
}

View File

@ -1,46 +0,0 @@
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
package scaffolding
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"`
PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"`
PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"`
PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"`
PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"`
PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"`
PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"`
PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"`
MockOption *string `mapstructure:"mock" cty:"mock" hcl:"mock"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false},
"packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false},
"packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false},
"packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false},
"packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false},
"packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false},
"packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false},
"packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false},
"mock": &hcldec.AttrSpec{Name: "mock", Type: cty.String, Required: false},
}
return s
}

View File

@ -1,57 +0,0 @@
package scaffolding
import (
_ "embed"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"testing"
"github.com/hashicorp/packer-plugin-sdk/acctest"
)
//go:embed test-fixtures/template.pkr.hcl
var testPostProcessorHCL2Basic string
// Run with: PACKER_ACC=1 go test -count 1 -v ./post-processor/scaffolding/post-processor_acc_test.go -timeout=120m
func TestAccScaffoldingPostProcessor(t *testing.T) {
testCase := &acctest.PluginTestCase{
Name: "scaffolding_post-processor_basic_test",
Setup: func() error {
return nil
},
Teardown: func() error {
return nil
},
Template: testPostProcessorHCL2Basic,
Type: "scaffolding-my-post-processor",
Check: func(buildCommand *exec.Cmd, logfile string) error {
if buildCommand.ProcessState != nil {
if buildCommand.ProcessState.ExitCode() != 0 {
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
}
}
logs, err := os.Open(logfile)
if err != nil {
return fmt.Errorf("Unable find %s", logfile)
}
defer logs.Close()
logsBytes, err := ioutil.ReadAll(logs)
if err != nil {
return fmt.Errorf("Unable to read %s", logfile)
}
logsString := string(logsBytes)
postProcessorOutputLog := "post-processor mock: my-mock-config"
if matched, _ := regexp.MatchString(postProcessorOutputLog+".*", logsString); !matched {
t.Fatalf("logs doesn't contain expected foo value %q", logsString)
}
return nil
},
}
acctest.TestPlugin(t, testCase)
}

View File

@ -1,13 +0,0 @@
source "null" "basic-example" {
communicator = "none"
}
build {
sources = [
"source.null.basic-example"
]
post-processor "scaffolding-my-post-processor" {
mock = "my-mock-config"
}
}

View File

@ -1,46 +0,0 @@
//go:generate mapstructure-to-hcl2 -type Config
package scaffolding
import (
"context"
"fmt"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template/config"
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
)
type Config struct {
MockOption string `mapstructure:"mock"`
ctx interpolate.Context
}
type Provisioner struct {
config Config
}
func (p *Provisioner) ConfigSpec() hcldec.ObjectSpec {
return p.config.FlatMapstructure().HCL2Spec()
}
func (p *Provisioner) Prepare(raws ...interface{}) error {
err := config.Decode(&p.config, &config.DecodeOpts{
PluginType: "packer.provisioner.scaffolding",
Interpolate: true,
InterpolateContext: &p.config.ctx,
InterpolateFilter: &interpolate.RenderFilter{
Exclude: []string{},
},
}, raws...)
if err != nil {
return err
}
return nil
}
func (p *Provisioner) Provision(_ context.Context, ui packer.Ui, _ packer.Communicator, generatedData map[string]interface{}) error {
ui.Say(fmt.Sprintf("provisioner mock: %s", p.config.MockOption))
return nil
}

View File

@ -1,30 +0,0 @@
// Code generated by "mapstructure-to-hcl2 -type Config"; DO NOT EDIT.
package scaffolding
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatConfig is an auto-generated flat version of Config.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatConfig struct {
MockOption *string `mapstructure:"mock" cty:"mock" hcl:"mock"`
}
// FlatMapstructure returns a new FlatConfig.
// FlatConfig is an auto-generated flat version of Config.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatConfig)
}
// HCL2Spec returns the hcl spec of a Config.
// This spec is used by HCL to read the fields of Config.
// The decoded values from this spec will then be applied to a FlatConfig.
func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"mock": &hcldec.AttrSpec{Name: "mock", Type: cty.String, Required: false},
}
return s
}

View File

@ -1,57 +0,0 @@
package scaffolding
import (
_ "embed"
"fmt"
"io/ioutil"
"os"
"os/exec"
"regexp"
"testing"
"github.com/hashicorp/packer-plugin-sdk/acctest"
)
//go:embed test-fixtures/template.pkr.hcl
var testProvisionerHCL2Basic string
// Run with: PACKER_ACC=1 go test -count 1 -v ./provisioner/scaffolding/provisioner_acc_test.go -timeout=120m
func TestAccScaffoldingProvisioner(t *testing.T) {
testCase := &acctest.PluginTestCase{
Name: "scaffolding_provisioner_basic_test",
Setup: func() error {
return nil
},
Teardown: func() error {
return nil
},
Template: testProvisionerHCL2Basic,
Type: "scaffolding-my-provisioner",
Check: func(buildCommand *exec.Cmd, logfile string) error {
if buildCommand.ProcessState != nil {
if buildCommand.ProcessState.ExitCode() != 0 {
return fmt.Errorf("Bad exit code. Logfile: %s", logfile)
}
}
logs, err := os.Open(logfile)
if err != nil {
return fmt.Errorf("Unable find %s", logfile)
}
defer logs.Close()
logsBytes, err := ioutil.ReadAll(logs)
if err != nil {
return fmt.Errorf("Unable to read %s", logfile)
}
logsString := string(logsBytes)
provisionerOutputLog := "null.basic-example: provisioner mock: my-mock-config"
if matched, _ := regexp.MatchString(provisionerOutputLog+".*", logsString); !matched {
t.Fatalf("logs doesn't contain expected foo value %q", logsString)
}
return nil
},
}
acctest.TestPlugin(t, testCase)
}

View File

@ -1,13 +0,0 @@
source "null" "basic-example" {
communicator = "none"
}
build {
sources = [
"source.null.basic-example"
]
provisioner "scaffolding-my-provisioner" {
mock = "my-mock-config"
}
}