mirror of
https://github.com/hashicorp/packer.git
synced 2026-10-24 07:02:14 -04:00
backport of commit 1f4f2aebca
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:generate packer-sdc mapstructure-to-hcl2 -type Config,NestedFirst,NestedSecond,DatasourceOutput
|
||||
package dynamic
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"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 NestedSecond struct {
|
||||
Name string `mapstructure:"name" required:"true"`
|
||||
}
|
||||
|
||||
type NestedFirst struct {
|
||||
Name string `mapstructure:"name" required:"true"`
|
||||
Nesteds []NestedSecond `mapstructure:"extra" required:"false"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Nesteds []NestedFirst `mapstructure:"extra" required:"false"`
|
||||
}
|
||||
|
||||
type Datasource struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
type DatasourceOutput struct {
|
||||
Status string `mapstructure:"data"`
|
||||
}
|
||||
|
||||
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) {
|
||||
log.Printf("[DATASOURCE-DYNAMIC] Executing datasource dynamic")
|
||||
for _, nest := range d.config.Nesteds {
|
||||
log.Printf("[DATASOURCE-DYNAMIC] - First nest: %s", nest.Name)
|
||||
for _, nestedConfig := range nest.Nesteds {
|
||||
log.Printf("[DATASOURCE-DYNAMIC] - Second nest: %s.%s", nest.Name, nestedConfig.Name)
|
||||
}
|
||||
}
|
||||
|
||||
output := DatasourceOutput{
|
||||
Status: "OK",
|
||||
}
|
||||
return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
|
||||
|
||||
package dynamic
|
||||
|
||||
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 {
|
||||
Nesteds []FlatNestedFirst `mapstructure:"extra" required:"false" cty:"extra" hcl:"extra"`
|
||||
}
|
||||
|
||||
// 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{
|
||||
"extra": &hcldec.BlockListSpec{TypeName: "extra", Nested: hcldec.ObjectSpec((*FlatNestedFirst)(nil).HCL2Spec())},
|
||||
}
|
||||
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 {
|
||||
Status *string `mapstructure:"data" cty:"data" hcl:"data"`
|
||||
}
|
||||
|
||||
// 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{
|
||||
"data": &hcldec.AttrSpec{Name: "data", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatNestedFirst is an auto-generated flat version of NestedFirst.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatNestedFirst struct {
|
||||
Name *string `mapstructure:"name" required:"true" cty:"name" hcl:"name"`
|
||||
Nesteds []FlatNestedSecond `mapstructure:"extra" required:"false" cty:"extra" hcl:"extra"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatNestedFirst.
|
||||
// FlatNestedFirst is an auto-generated flat version of NestedFirst.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*NestedFirst) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatNestedFirst)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a NestedFirst.
|
||||
// This spec is used by HCL to read the fields of NestedFirst.
|
||||
// The decoded values from this spec will then be applied to a FlatNestedFirst.
|
||||
func (*FlatNestedFirst) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"name": &hcldec.AttrSpec{Name: "name", Type: cty.String, Required: false},
|
||||
"extra": &hcldec.BlockListSpec{TypeName: "extra", Nested: hcldec.ObjectSpec((*FlatNestedSecond)(nil).HCL2Spec())},
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// FlatNestedSecond is an auto-generated flat version of NestedSecond.
|
||||
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
|
||||
type FlatNestedSecond struct {
|
||||
Name *string `mapstructure:"name" required:"true" cty:"name" hcl:"name"`
|
||||
}
|
||||
|
||||
// FlatMapstructure returns a new FlatNestedSecond.
|
||||
// FlatNestedSecond is an auto-generated flat version of NestedSecond.
|
||||
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
|
||||
func (*NestedSecond) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
|
||||
return new(FlatNestedSecond)
|
||||
}
|
||||
|
||||
// HCL2Spec returns the hcl spec of a NestedSecond.
|
||||
// This spec is used by HCL to read the fields of NestedSecond.
|
||||
// The decoded values from this spec will then be applied to a FlatNestedSecond.
|
||||
func (*FlatNestedSecond) HCL2Spec() map[string]hcldec.Spec {
|
||||
s := map[string]hcldec.Spec{
|
||||
"name": &hcldec.AttrSpec{Name: "name", Type: cty.String, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dynamic
|
||||
|
||||
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)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
# Copyright (c) HashiCorp, Inc.
|
||||
# SPDX-License-Identifier: MPL-2.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}",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:generate packer-sdc mapstructure-to-hcl2 -type Config,DatasourceOutput
|
||||
package parrot
|
||||
|
||||
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 {
|
||||
Input []string `mapstructure:"input" required:"true"`
|
||||
}
|
||||
|
||||
type Datasource struct {
|
||||
config Config
|
||||
}
|
||||
|
||||
type DatasourceOutput struct {
|
||||
Output []string `mapstructure:"out"`
|
||||
}
|
||||
|
||||
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) {
|
||||
out := []string{}
|
||||
for _, d := range d.config.Input {
|
||||
out = append(out, d)
|
||||
}
|
||||
|
||||
output := DatasourceOutput{
|
||||
Output: out,
|
||||
}
|
||||
return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
|
||||
|
||||
package parrot
|
||||
|
||||
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 {
|
||||
Input []string `mapstructure:"input" required:"true" cty:"input" hcl:"input"`
|
||||
}
|
||||
|
||||
// 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{
|
||||
"input": &hcldec.AttrSpec{Name: "input", Type: cty.List(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 {
|
||||
Output []string `mapstructure:"out" cty:"out" hcl:"out"`
|
||||
}
|
||||
|
||||
// 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{
|
||||
"out": &hcldec.AttrSpec{Name: "out", Type: cty.List(cty.String), Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
//go:generate packer-sdc mapstructure-to-hcl2 -type Config,DatasourceOutput
|
||||
package sleeper
|
||||
|
||||
import (
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"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 {
|
||||
Duration string `mapstructure:"duration" required:"true"`
|
||||
}
|
||||
|
||||
type Datasource struct {
|
||||
config Config
|
||||
durationTime time.Duration
|
||||
}
|
||||
|
||||
type DatasourceOutput struct {
|
||||
Status bool `mapstructure:"status"`
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
dt, err := time.ParseDuration(d.config.Duration)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
d.durationTime = dt
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *Datasource) OutputSpec() hcldec.ObjectSpec {
|
||||
return (&DatasourceOutput{}).FlatMapstructure().HCL2Spec()
|
||||
}
|
||||
|
||||
func (d *Datasource) Execute() (cty.Value, error) {
|
||||
log.Printf("[sleeper] Sleeping for %s", d.config.Duration)
|
||||
time.Sleep(d.durationTime)
|
||||
log.Printf("[sleeper] Done sleeping!")
|
||||
|
||||
output := DatasourceOutput{
|
||||
Status: true,
|
||||
}
|
||||
return hcl2helper.HCL2ValueFromConfig(output, d.OutputSpec()), nil
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT.
|
||||
|
||||
package sleeper
|
||||
|
||||
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 {
|
||||
Duration *string `mapstructure:"duration" required:"true" cty:"duration" hcl:"duration"`
|
||||
}
|
||||
|
||||
// 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{
|
||||
"duration": &hcldec.AttrSpec{Name: "duration", 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 {
|
||||
Status *bool `mapstructure:"status" cty:"status" hcl:"status"`
|
||||
}
|
||||
|
||||
// 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{
|
||||
"status": &hcldec.AttrSpec{Name: "status", Type: cty.Bool, Required: false},
|
||||
}
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user