(2) Implement datasources (#10440)

This commit is contained in:
Sylvia Moss 2021-01-20 10:37:16 +01:00 committed by GitHub
parent ab98409069
commit 291121dd55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
54 changed files with 1729 additions and 207 deletions

View File

@ -12,7 +12,6 @@ import (
"strings"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer/plugin"
)
@ -130,22 +129,23 @@ func discoverAndLoad() error {
}
// TODO: validate correctness of plugins loaded by checking them against the output of the `describe` command.
builders, provisioners, postProcessors := config.GetPlugins()
if len(builders) == 0 &&
len(provisioners) == 0 &&
len(postProcessors) == 0 {
return fmt.Errorf("couldn't load any Builder/Provisioner/Post-Processor from the plugin binary")
plugins := config.GetPlugins()
if len(plugins.Builders) == 0 &&
len(plugins.Provisioners) == 0 &&
len(plugins.PostProcessors) == 0 &&
len(plugins.DataSources) == 0 {
return fmt.Errorf("couldn't load any Builder/Provisioner/Post-Processor/Datasource from the plugin binary")
}
return checkHCL2ConfigSpec(builders, provisioners, postProcessors)
return checkHCL2ConfigSpec(plugins)
}
// checkHCL2ConfigSpec checks if the hcl2spec config is present for the given plugins by validating that ConfigSpec() does not
// return an empty map of specs.
func checkHCL2ConfigSpec(builders packer.BuilderStore, provisioners packer.ProvisionerStore, postProcessors packer.PostProcessorStore) error {
func checkHCL2ConfigSpec(plugins plugin.Plugins) error {
var errs *packersdk.MultiError
for _, b := range builders.List() {
builder, err := builders.Start(b)
for _, b := range plugins.Builders.List() {
builder, err := plugins.Builders.Start(b)
if err != nil {
return packersdk.MultiErrorAppend(err, errs)
}
@ -153,8 +153,8 @@ func checkHCL2ConfigSpec(builders packer.BuilderStore, provisioners packer.Provi
errs = packersdk.MultiErrorAppend(fmt.Errorf("builder %q does not contain the required hcl2spec configuration", b), errs)
}
}
for _, p := range provisioners.List() {
provisioner, err := provisioners.Start(p)
for _, p := range plugins.Provisioners.List() {
provisioner, err := plugins.Provisioners.Start(p)
if err != nil {
return packersdk.MultiErrorAppend(err, errs)
}
@ -162,8 +162,8 @@ func checkHCL2ConfigSpec(builders packer.BuilderStore, provisioners packer.Provi
errs = packersdk.MultiErrorAppend(fmt.Errorf("provisioner %q does not contain the required hcl2spec configuration", p), errs)
}
}
for _, pp := range postProcessors.List() {
postProcessor, err := postProcessors.Start(pp)
for _, pp := range plugins.PostProcessors.List() {
postProcessor, err := plugins.PostProcessors.Start(pp)
if err != nil {
return packersdk.MultiErrorAppend(err, errs)
}
@ -171,6 +171,15 @@ func checkHCL2ConfigSpec(builders packer.BuilderStore, provisioners packer.Provi
errs = packersdk.MultiErrorAppend(fmt.Errorf("post-processor %q does not contain the required hcl2spec configuration", pp), errs)
}
}
for _, d := range plugins.DataSources.List() {
datasource, err := plugins.DataSources.Start(d)
if err != nil {
return packersdk.MultiErrorAppend(err, errs)
}
if len(datasource.ConfigSpec()) == 0 {
errs = packersdk.MultiErrorAppend(fmt.Errorf("datasource %q does not contain the required hcl2spec configuration", d), errs)
}
}
if errs != nil && len(errs.Errors) > 0 {
return errs
}

View File

@ -70,6 +70,7 @@ func (m *Meta) GetConfigFromHCL(cla *MetaArgs) (*hcl2template.PackerConfig, int)
BuilderSchemas: m.CoreConfig.Components.BuilderStore,
ProvisionersSchemas: m.CoreConfig.Components.ProvisionerStore,
PostProcessorsSchemas: m.CoreConfig.Components.PostProcessorStore,
DatasourceSchemas: m.CoreConfig.Components.DatasourceStore,
}
cfg, diags := parser.Parse(cla.Path, cla.VarFiles, cla.Vars)
return cfg, writeDiags(m.Ui, parser.Files(), diags)
@ -147,7 +148,7 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int
if ret != 0 {
return ret
}
diags := packerStarter.Initialize()
diags := packerStarter.Initialize(packer.InitializeOptions{})
ret = writeDiags(c.Ui, nil, diags)
if ret != 0 {
return ret

View File

@ -371,6 +371,17 @@ func TestBuild(t *testing.T) {
},
expectedCode: 1,
},
{
name: "hcl - execute and use datasource",
args: []string{
testFixture("hcl", "datasource.pkr.hcl"),
},
fileCheck: fileCheck{
expectedContent: map[string]string{
"chocolate.txt": "chocolate",
},
},
},
}
for _, tt := range tc {
@ -849,6 +860,9 @@ func testCoreConfigBuilder(t *testing.T) *packer.CoreConfig {
"shell-local": func() (packersdk.PostProcessor, error) { return &shell_local_pp.PostProcessor{}, nil },
"manifest": func() (packersdk.PostProcessor, error) { return &manifest.PostProcessor{}, nil },
},
DatasourceStore: packersdk.MapOfDatasource{
"mock": func() (packersdk.Datasource, error) { return &packersdk.MockDatasource{}, nil },
},
}
return &packer.CoreConfig{
Components: components,

View File

@ -60,7 +60,7 @@ func (c *ConsoleCommand) RunContext(ctx context.Context, cla *ConsoleArgs) int {
return ret
}
_ = packerStarter.Initialize()
_ = packerStarter.Initialize(packer.InitializeOptions{})
// Determine if stdin is a pipe. If so, we evaluate directly.
if c.StdinPiped() {

View File

@ -11,7 +11,7 @@ type CoreWrapper struct {
*packer.Core
}
func (c *CoreWrapper) Initialize() hcl.Diagnostics {
func (c *CoreWrapper) Initialize(_ packer.InitializeOptions) hcl.Diagnostics {
err := c.Core.Initialize()
if err != nil {
return hcl.Diagnostics{

View File

@ -13,8 +13,8 @@ import (
texttemplate "text/template"
"github.com/hashicorp/hcl/v2/hclwrite"
hcl2shim "github.com/hashicorp/packer-plugin-sdk/hcl2helper"
"github.com/hashicorp/packer-plugin-sdk/template"
hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
"github.com/mitchellh/mapstructure"
"github.com/posener/complete"
"github.com/zclconf/go-cty/cty"

View File

@ -46,7 +46,7 @@ func (c *InspectCommand) RunContext(ctx context.Context, cla *InspectArgs) int {
}
// here we ignore init diags to allow unknown variables to be used
_ = packerStarter.Initialize()
_ = packerStarter.Initialize(packer.InitializeOptions{})
return packerStarter.InspectConfig(packer.InspectConfigOptions{
Ui: c.Ui,

View File

@ -212,7 +212,9 @@ var PostProcessors = map[string]packersdk.PostProcessor{
"yandex-import": new(yandeximportpostprocessor.PostProcessor),
}
var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)")
var Datasources = map[string]packersdk.Datasource{}
var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner|datasource)-(.+)")
func (c *PluginCommand) Run(args []string) int {
// This is an internal call (users should not call this directly) so we're
@ -261,6 +263,13 @@ func (c *PluginCommand) Run(args []string) int {
return 1
}
server.RegisterPostProcessor(postProcessor)
case "datasource":
datasource, found := Datasources[pluginName]
if !found {
c.Ui.Error(fmt.Sprintf("Could not load datasource: %s", pluginName))
return 1
}
server.RegisterDatasource(datasource)
}
server.Serve()

View File

@ -0,0 +1,14 @@
data "mock" "content" {
foo = "chocolate"
}
source "file" "chocolate" {
content = data.mock.content.foo
target = "chocolate.txt"
}
build {
sources = [
"sources.file.chocolate",
]
}

View File

@ -0,0 +1,16 @@
packer {
required_version = ">= v1.0.0"
}
data "mock" "content" {
foo = "content"
}
source "file" "chocolate" {
target = "chocolate.txt"
content = data.mock.content.foo
}
build {
sources = ["source.file.chocolate"]
}

View File

@ -56,7 +56,9 @@ func (c *ValidateCommand) RunContext(ctx context.Context, cla *ValidateArgs) int
return 0
}
diags := packerStarter.Initialize()
diags := packerStarter.Initialize(packer.InitializeOptions{
SkipDatasourcesExecution: true,
})
ret = writeDiags(c.Ui, nil, diags)
if ret != 0 {
return ret

View File

@ -5,6 +5,7 @@ import (
"testing"
"github.com/google/go-cmp/cmp"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestValidateCommand(t *testing.T) {
@ -45,6 +46,29 @@ func TestValidateCommand(t *testing.T) {
}
}
func TestValidateCommand_SkipDatasourceExecution(t *testing.T) {
datasourceMock := &packersdk.MockDatasource{}
meta := testMetaFile(t)
meta.CoreConfig.Components.DatasourceStore = packersdk.MapOfDatasource{
"mock": func() (packersdk.Datasource, error) {
return datasourceMock, nil
},
}
c := &ValidateCommand{
Meta: meta,
}
args := []string{filepath.Join(testFixture("validate"), "datasource.pkr.hcl")}
if code := c.Run(args); code != 0 {
fatalCommand(t, c.Meta)
}
if datasourceMock.ExecuteCalled {
t.Fatalf("Datasource should not be executed on validation")
}
if !datasourceMock.OutputSpecCalled {
t.Fatalf("Datasource OutPutSpec should be called on validation")
}
}
func TestValidateCommand_SyntaxOnly(t *testing.T) {
tt := []struct {
path string

View File

@ -30,6 +30,7 @@ type config struct {
Builders packer.MapOfBuilder `json:"-"`
Provisioners packer.MapOfProvisioner `json:"-"`
PostProcessors packer.MapOfPostProcessor `json:"-"`
Datasources packer.MapOfDatasource `json:"-"`
Plugins plugin.Config
}
@ -186,5 +187,17 @@ func (c *config) discoverInternalComponents() error {
}
}
for dataSource := range command.Datasources {
dataSource := dataSource
_, found := (c.Datasources)[dataSource]
if !found {
c.Datasources[dataSource] = func() (packersdk.Datasource, error) {
bin := fmt.Sprintf("%s%splugin%spacker-datasource-%s",
packerPath, PACKERSPACE, PACKERSPACE, dataSource)
return c.Plugins.Client(bin).Datasource()
}
}
}
return nil
}

0
datasource/.gitkeep Normal file
View File

2
go.mod
View File

@ -49,7 +49,7 @@ require (
github.com/hashicorp/go-uuid v1.0.2
github.com/hashicorp/go-version v1.2.0
github.com/hashicorp/hcl/v2 v2.8.0
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210111224258-fd30ebb797f0
github.com/hashicorp/packer-plugin-sdk v0.0.7
github.com/hashicorp/vault/api v1.0.4
github.com/hetznercloud/hcloud-go v1.15.1
github.com/hyperonecom/h1-client-go v0.0.0-20191203060043-b46280e4c4a4

121
go.sum
View File

@ -3,42 +3,32 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0 h1:MZQCQQaRwOrAcuKjiHWHrgKykt4fZyuwF2dtiG3fGW8=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0 h1:Dg9iHVQfrhq82rUNu9ZxUDrJLaxFUe/HlCVaLyRruq8=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.66.0 h1:DZeAkuQGQqnm9Xv36SbMJEU8aFBz4wL04UpMWPWwjzg=
cloud.google.com/go v0.66.0/go.mod h1:dgqGAjKCDxyhGTtC9dAREQGUJpkceNm1yt590Qno0Ko=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0 h1:sAbMqjY1PEQKZBWfbu6Y6bsupJ9c4QdHnzg/VvYTLcE=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0 h1:xE3CPsOgttP4ACBePh79zTKALtXwn/Edhcr16R5hMWU=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0 h1:Kt+gOPPp2LEPWp8CSfxhsM8ik9CcyE/gYu+0r+RnZvM=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0 h1:/May9ojXjRkPBNVrq+oWLqmWCkr4OU5uRY29bu0mRyQ=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0 h1:9/vpR43S4aJaROxqQHQ3nH9lfyKKV0dC3vOmnw8ebQQ=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0 h1:Lpy6hKgdcl7a3WGSfJIFmxmcdjSpP6OmBEfcOv1Y680=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0 h1:UDpwYIwla4jHGzZJaEJYx1tOejbgSoNqsAfHAUYe2r8=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0 h1:STgFzyU5/8miMl0//zKh2aQeTyeaUH3WN9bSUiJ09bA=
@ -79,12 +69,10 @@ github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbt
github.com/Azure/go-ntlmssp v0.0.0-20180810175552-4a21cbd618b4/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/Azure/go-ntlmssp v0.0.0-20191115201650-bad6df29494a h1:3FwiePtHk5YJrooV799oo5jIfsgRdES25VdngJM03dU=
github.com/Azure/go-ntlmssp v0.0.0-20191115201650-bad6df29494a/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022 h1:y8Gs8CzNfDF5AZvjr+5UyGQvQEBL7pwo+v+wX6q9JI8=
github.com/ChrisTrenkamp/goxpath v0.0.0-20170922090931-c385f95c6022/go.mod h1:nuWgzSkT5PnyOd+272uUmV0dnAnAn42Mk7PiQC5VzN4=
github.com/DataDog/datadog-go v2.2.0+incompatible h1:V5BKkxACZLjzHjSgBbr2gvLA2Ae49yhc6CSY7MLy5k4=
github.com/DataDog/datadog-go v2.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0 h1:0nxjOH7NurPGUWNG5BCrASWjB0uuhGbgJAKLqj2ZDTo=
github.com/NaverCloudPlatform/ncloud-sdk-go-v2 v1.1.0/go.mod h1:P+3VS0ETiQPyWOx3vB/oeC8J3qd7jnVZLYAFwWgGRt8=
@ -116,9 +104,7 @@ github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbj
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
github.com/approvals/go-approval-tests v0.0.0-20160714161514-ad96e53bea43 h1:ePCAQPf5tUc5IMcUvu6euhSGna7jzs7eiXtJXHig6Zc=
github.com/approvals/go-approval-tests v0.0.0-20160714161514-ad96e53bea43/go.mod h1:S6puKjZ9ZeqUPBv2hEBnMZGcM2J6mOsDRQcmxkMAND0=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da h1:8GUt8eRujhVEGZFFEjBj46YV4rDjvGrNxb0KMWYkL2I=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878 h1:EFSB7Zo9Eg91v7MJPVsifUysc/wPdN+NOnVe6bWbdBM=
github.com/armon/go-metrics v0.0.0-20190430140413-ec5e00d3c878/go.mod h1:3AMJUQhVx52RsWOnlkpikZr01T/yAVN2gn0861vByNg=
@ -127,14 +113,11 @@ github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go v1.15.78/go.mod h1:E3/ieXAlvM0XWO57iftYVDLLvQ824smPP3ATZkfNZeM=
github.com/aws/aws-sdk-go v1.26.3/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go v1.30.8 h1:4BHbh8K3qKmcnAgToZ2LShldRF9inoqIBccpCLNCy3I=
github.com/aws/aws-sdk-go v1.30.8/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.31.9/go.mod h1:5zCpMtNQVjRREroY7sYe8lOMRSxkhG6MZveU8YkpAk0=
github.com/aws/aws-sdk-go v1.36.0 h1:CscTrS+szX5iu34zk2bZrChnGO/GMtUYgMK1Xzs2hYo=
github.com/aws/aws-sdk-go v1.36.0/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/aws/aws-sdk-go v1.36.5 h1:SouM2ar1A8f+3DYWW622sDdqkkZAO3ha4j8GQjiPLFg=
github.com/aws/aws-sdk-go v1.36.5/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
@ -146,7 +129,6 @@ github.com/bmatcuk/doublestar v1.1.5 h1:2bNwBOmhyFEFcoB3tGvTD5xanq+4kyOZlB8wFYbM
github.com/bmatcuk/doublestar v1.1.5/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee h1:BnPxIde0gjtTnc9Er7cxvBk8DHLWhEux0SxayC8dP6I=
github.com/c2h5oh/datasize v0.0.0-20200112174442-28bbd4740fee/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/census-instrumentation/opencensus-proto v0.2.1 h1:glEXhBS5PSLLv4IXzLA5yPRVX4bilULVyxxbrfOtDAk=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cheggaaa/pb v1.0.27 h1:wIkZHkNfC7R6GI5w7l/PdAdzXzlrbcI3p8OAlnkTsnc=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
@ -156,12 +138,9 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5O
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 h1:q763qf9huN11kDQavWsoZXJNW3xEE4JJyHa5Q25/sd8=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible h1:C29Ae4G5GtYyYMm1aztcyj/J5ckgJm2zwdDajFbx1NY=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3 h1:TJH+oke8D16535+jHExHj4nQvzlZrj7ug5D7I/orNUA=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f h1:WBZRG4aNOuI15bLRrCgN8fCq8E5Xuty6jGbmSNEvSsU=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
@ -185,15 +164,12 @@ github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08 h1:0bp6/GrNOrTD
github.com/dylanmei/winrmtest v0.0.0-20170819153634-c2fbb09e6c08/go.mod h1:VBVDFSBXCIW8JaHQpI8lldSKfYaLMzP9oyq6IJ4fhzY=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4 h1:rEvIZUSZ3fx39WIi3JkQqQBitGwpELBIYWeBVh6wn+E=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0 h1:EQciDnbrYxy13PgWoY8AqoxGiPrpgBZ1R8UNe3ddc+A=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/exoscale/egoscale v0.18.1 h1:1FNZVk8jHUx0AvWhOZxLEDNlacTU0chMXUUNkm9EZaI=
github.com/exoscale/egoscale v0.18.1/go.mod h1:Z7OOdzzTOz1Q1PjQXumlz9Wn/CddH0zSYdCF3rnBKXE=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
@ -210,7 +186,6 @@ github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3I
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 h1:JVrqSeQfdhYRFk24TvhTZWU0q8lfCojxZQFi3Ou7+uY=
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48/go.mod h1:dZGr0i9PLlaaTD4H/hoZIDjQ+r6xq8mgbRzHZf7f2J8=
github.com/go-resty/resty/v2 v2.3.0 h1:JOOeAvjSlapTT92p8xiS19Zxev1neGikoHsXJeOq8So=
github.com/go-resty/resty/v2 v2.3.0/go.mod h1:UpN9CgLZNsv4e9XG50UU8xdI0F43UQ4HmxLBDwaroHU=
@ -223,14 +198,10 @@ github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJA
github.com/gofrs/flock v0.7.3 h1:I0EKY9l8HZCXTMYC4F80vwT6KNypV9uYKP3Alm/hjmQ=
github.com/gofrs/flock v0.7.3/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/protobuf v1.2.1 h1:/s5zKNz0uPFCZ5hddgPdo2TK2TVrUNMn0OOX8/aZMTE=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -244,15 +215,11 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
@ -264,17 +231,12 @@ github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c h1:964Od4U6p2jUkFxvCydnIczKteheJEzHRToSGK3Bnlw=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
@ -299,7 +261,6 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9 h1:JM174NTeGNJ2m/oLH3UOWOvWQQKd+BoL3hcSCUWFLt0=
github.com/google/shlex v0.0.0-20150127133951-6f45313302b9/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE=
github.com/google/uuid v0.0.0-20170306145142-6a5e28554805/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
@ -327,7 +288,6 @@ github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/U
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de h1:XDCSythtg8aWSRSO29uwhgh7b127fWr+m5SemqjSUL8=
github.com/hashicorp/go-checkpoint v0.0.0-20171009173528-1545e56e46de/go.mod h1:xIwEieBHERyEvaeKF/TcHh1Hu+lxPM+n2vT1+g9I4m4=
github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6KdvN3Gig=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1 h1:dH3aiDG9Jvb5r5+bYHsikaOUIpcM0xvgMXVoDkXMzJM=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@ -346,15 +306,12 @@ github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0 h1:d4QkX8FRTYaKaCZBoXYY8zJX2BXjWxurN/GA2tkrmZM=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0 h1:AKDB1HM5PWEA7i4nhcpwOrO2byshxBjXVn/J/3+z5/0=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.1.0 h1:vN9wG1D6KG6YHRTWr8512cxGOVgTMEfgEdSj/hr8MPc=
github.com/hashicorp/go-immutable-radix v1.1.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3 h1:zKjpN5BK/P5lMYrLmBHdBULWbJ0XpYR+7NGzqkZzoD4=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-msgpack v0.5.5 h1:i9R9JSrqIz0QVLz3sz+i3YJdT7TTSLcfLLzJi9aZTuI=
github.com/hashicorp/go-msgpack v0.5.5/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0 h1:iVjPR7a6H0tWELX5NxNe7bYopibicUzc7uPribsnS6o=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
@ -369,50 +326,41 @@ github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5O
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-sockaddr v1.0.0 h1:GeH6tui99pF4NJgfnhp+L6+FfobzVW3Ah46sLo0ICXs=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-syslog v1.0.0 h1:KaodqZuhUoZereWVIYmpUgZysurB1kBLX2j0MwMrUAE=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2 h1:cfejS+Tpcp13yd5nYHWDI6qVCny6wyX2Mt5SGur2IGE=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.0.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.3 h1:YPkqC67at8FYaadspW/6uE0COsBxS2656RLEr8Bppgk=
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.6.0 h1:3krZOfGY6SziUXa6H9PJU6TyohHn7I+ARYnhbeNBz+o=
github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
github.com/hashicorp/hcl/v2 v2.8.0 h1:iHLEAsNDp3N2MtqroP1wf0nF/zB2+McHN5YCzwqIm80=
github.com/hashicorp/hcl/v2 v2.8.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/mdns v1.0.1 h1:XFSOubp8KWB+Jd2PDyaX5xUd5bhSP/+pTDZVDMzZJM8=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/memberlist v0.1.3 h1:EmmoJme1matNzb+hMpDuR/0sbJSUisxyqBGG676r31M=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/packer v1.6.6/go.mod h1:meJucaEeJro8UP1jw+KaOCpaiC4VE+itPLXY8lbIU2A=
github.com/hashicorp/packer v1.6.7-0.20210107234516-6564ee76e807/go.mod h1:fBz288Z4of8zkpDWwL/ngG1txC36jGSXS7dnUmUaLUs=
github.com/hashicorp/packer-plugin-sdk v0.0.6 h1:BN2G4APXSMvDURFdnk+6DspwsU83pZeMsbEur7NmGsA=
github.com/hashicorp/packer-plugin-sdk v0.0.6/go.mod h1:Nvh28f+Jmpp2rcaN79bULTouNkGNDRfHckhHKTAXtyU=
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210111224258-fd30ebb797f0 h1:2GsORpJjcMQN84ZA1IEyHzx0zPY6QH6tNGbZc7CP6QE=
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210111224258-fd30ebb797f0/go.mod h1:YdWTt5w6cYfaQG7IOi5iorL+3SXnz8hI0gJCi8Db/LI=
github.com/hashicorp/serf v0.8.2 h1:YZ7UKsJv+hKjqGVUUbtE3HNj79Eln2oQ75tniF6iPt0=
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210113192617-8a28198491f7 h1:2N1NAfBCmG1vIkbdlIOb/YbaYXCW40YOllWqMZDjnHM=
github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210113192617-8a28198491f7/go.mod h1:YdWTt5w6cYfaQG7IOi5iorL+3SXnz8hI0gJCi8Db/LI=
github.com/hashicorp/packer-plugin-sdk v0.0.7 h1:adELlId/KOGWXmQ79L+NwYSgKES6811RVXiRCj4FE0s=
github.com/hashicorp/packer-plugin-sdk v0.0.7/go.mod h1:YdWTt5w6cYfaQG7IOi5iorL+3SXnz8hI0gJCi8Db/LI=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/serf v0.9.2 h1:yJoyfZXo4Pk2p/M/viW+YLibBFiIbKoP79gu7kDAFP0=
github.com/hashicorp/serf v0.9.2/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
@ -433,9 +381,7 @@ github.com/jdcloud-api/jdcloud-sdk-go v1.9.1-0.20190605102154-3d81a50ca961/go.mo
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 h1:IPJ3dvxmJ4uczJe5YQdrYB16oTJlGSC/OyZDqUk9xX4=
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869/go.mod h1:cJ6Cj7dQo+O6GJNiMx+Pa94qKj+TG8ONdKHgMNIyyag=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc=
github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
@ -464,7 +410,6 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGi
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169 h1:YUrU1/jxRqnt0PSrKj1Uj/wEjk/fjnE80QFfi2Zlj7Q=
github.com/kr/fs v0.0.0-20131111012553-2788f0dbd169/go.mod h1:glhvuHOU9Hy7/8PwwdtnarXqLagOX0b/TbZx2zLMqEg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@ -478,20 +423,16 @@ github.com/linode/linodego v0.14.0/go.mod h1:2ce3S00NrDqJfp4i55ZuSlT0U3cKNELNYAC
github.com/masterzen/simplexml v0.0.0-20160608183007-4572e39b1ab9/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 h1:2ZKn+w/BJeL43sCxI2jhPLRv73oVVOjEKZjKkflyqxg=
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786/go.mod h1:kCEbxUJlNDEBNbdQMkPSp6yaKcRXVI6f4ddk8Riv4bc=
github.com/masterzen/winrm v0.0.0-20200615185753-c42b5136ff88 h1:cxuVcCvCLD9yYDbRCWw0jSgh1oT6P6mv3aJDKK5o7X4=
github.com/masterzen/winrm v0.0.0-20200615185753-c42b5136ff88/go.mod h1:a2HXwefeat3evJHxFXSayvRHpYEPJYtErl4uIzfaUqY=
github.com/masterzen/winrm v0.0.0-20201030141608-56ca5c5f2380 h1:uKhPH5dYpx3Z8ZAnaTGfGZUiHOWa5p5mdG8wZlh+tLo=
github.com/masterzen/winrm v0.0.0-20201030141608-56ca5c5f2380/go.mod h1:a2HXwefeat3evJHxFXSayvRHpYEPJYtErl4uIzfaUqY=
github.com/mattn/go-colorable v0.0.9 h1:UVL0vNpWh04HeJXV0KLcaT7r06gOH2l4OW6ddYRUIY4=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6 h1:6Su7aK7lXmJ/U79bYtBjLNaha4Fs1Rg9plHpcH+vvnE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4 h1:bnP0vzxcAdeI1zdubAl5PjU6zsERjGZb7raWodagDYs=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10 h1:qxFzApOv4WsAL965uUPIsXzAKCZxN2p9UqdhFS4ZW10=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
@ -500,42 +441,34 @@ github.com/mattn/go-runewidth v0.0.4 h1:2BvfKmzob6Bmd4YsL0zygOqfdFnK7GR4QL06Do4/
github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08 h1:8YAWbq7rJqfbc6IaAvA2eCQuOQvf6Bs4vHKcOyWw//E=
github.com/mattn/go-tty v0.0.0-20191112051231-74040eebce08/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26 h1:gPxPSwALAeHJSjarOs00QjVdV9QoBvc1D2ujQUr5BzU=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/mitchellh/cli v1.0.0 h1:iGBIsUe3+HZ/AD/Vd7DErOt5sU9fa8Uj7A2s1aggv1Y=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/cli v1.1.0 h1:tEElEatulEHDeedTxwckzyYMA5c86fbmNIUL1hBIiTg=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7 h1:PXPMDtfqV+rZJshQHOiwUFqlqErXaAcuWy+/ZmyRfNc=
github.com/mitchellh/go-fs v0.0.0-20180402234041-7b48fa161ea7/go.mod h1:g7SZj7ABpStq3tM4zqHiVEG5un/DZ1+qJJKO7qx1EvU=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.3 h1:gqwbsGvc0jbhAPW/26WfEoSiPANAVlR49AAVdvaTjI4=
github.com/mitchellh/go-testing-interface v1.0.3/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed h1:FI2NIv6fpef6BQl2u3IZX/Cj20tfypRF4yd+uaHOMtI=
github.com/mitchellh/go-vnc v0.0.0-20150629162542-723ed9867aed/go.mod h1:3rdaFaCv4AyBgu5ALFM0+tSuHrBh6v692nyQe3ikrq0=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/gox v1.0.1 h1:x0jD3dcHk9a9xPSDN6YEL4xL6Qz0dvNYm8yZqui5chI=
github.com/mitchellh/gox v1.0.1/go.mod h1:ED6BioOGXMswlXa2zxfh/xdd5QhwYliBFn9V18Ap4z4=
github.com/mitchellh/iochan v1.0.0 h1:C+X3KsSTLFVBr/tK1eYN/vs4rJcvsiLU338UhYPJWeY=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.2.3 h1:f/MjBEBDLttYCGfRaKBbKSRVF5aV2O6fnBpzknuE3jU=
github.com/mitchellh/mapstructure v1.2.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.0 h1:7ks8ZkOP5/ujthUsT07rNv+nkLXCQWKNHuwzOAesEks=
github.com/mitchellh/mapstructure v1.4.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
@ -561,15 +494,12 @@ github.com/outscale/osc-sdk-go/osc v0.0.0-20200722135656-d654809d0699 h1:SHe9i7h
github.com/outscale/osc-sdk-go/osc v0.0.0-20200722135656-d654809d0699/go.mod h1:5AqqNH1X8zCHescKVlpSHRzrat1KCKDXqZoQPe8fY3A=
github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a h1:A3QMuteviunoaY/8ex+RKFqwhcZJ/Cf3fCW3IwL2wx4=
github.com/packer-community/winrmcp v0.0.0-20180921204643-0fd363d6159a/go.mod h1:f6Izs6JvFTdnRbziASagjZ2vmf55NSIkC/weStxCHqk=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c h1:Lgl0gzECD8GnQ5QCWA8o6BtfL6mDH5rQgM4/fX3avOs=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.0 h1:WdK/asTD0HN+q6hsWO3/vpuAkAr+tw6aNJNDFFf0+qw=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -577,24 +507,18 @@ github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca h1:k8gsErq3rkcbAyCnpOycQs
github.com/pkg/sftp v0.0.0-20160118190721-e84cc8c755ca/go.mod h1:NxmoDg/QLVWluQDUYG7XBZTLUpKeFa8e3aMf1BfjyHk=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1 h1:ccV59UEOTzVDnDUEFdT95ZzHVZ+5+158q8+SJb2QV5w=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible h1:ZoVHH6voxW9Onzo6z2yLtocVoN6mBocyDoqoyAMHokE=
github.com/profitbricks/profitbricks-sdk-go v4.0.2+incompatible/go.mod h1:T3/WrziK7fYH3C8ilAFAHe99R452/IzIG3YYkqaOFeQ=
github.com/prometheus/client_golang v0.9.2 h1:awm861/B8OKDd2I/6o1dy3ra4BamzKhYOiGItCeZ740=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275 h1:PnBWHBf+6L0jOqq0gIVUe6Yk0/QMZ640k6NvkxcBf+8=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a h1:9a8MnZMP0X2nLJdBg+pBmGgkJlSaKC2KaQmTCk1XDtE=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible h1:j1Wcmh8OrK4Q7GXY+V7SVSY8nUWQxHW5TkBe7YUl+2s=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
@ -610,7 +534,6 @@ github.com/shirou/gopsutil v2.18.12+incompatible h1:1eaJvGomDnH74/5cF4CTmTbLHAri
github.com/shirou/gopsutil v2.18.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4 h1:udFKJ0aHUL60LboW/A+DfgoHVedieIzIXE8uylPue0U=
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@ -621,23 +544,17 @@ github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:X
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tencentcloud/tencentcloud-sdk-go v3.0.222+incompatible h1:bs+0lcG4RELNbE8PsBC9oaPP0/qExr0DuEGnZyocm84=
github.com/tencentcloud/tencentcloud-sdk-go v3.0.222+incompatible/go.mod h1:0PfYow01SHPMhKY31xa+EFz2RStxIqj6JFAJS+IkCi4=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926 h1:G3dpKMzFDjgEh2q1Z7zUUtKa8ViPtH+ocF0bE0g00O8=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/ucloud/ucloud-sdk-go v0.16.3 h1:DCh4A5vSxFr3EvtvJL+g0Ehy4hSlEkMpQmEvxEQhYdo=
github.com/ucloud/ucloud-sdk-go v0.16.3/go.mod h1:dyLmFHmUfgb4RZKYQP9IArlvQ2pxzFthfhwxRzOEPIw=
@ -647,7 +564,6 @@ github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1 h1:U6ufy3mLDgg9RYupntOvA
github.com/ugorji/go v0.0.0-20151218193438-646ae4a518c1/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ=
github.com/ulikunitz/xz v0.5.5 h1:pFrO0lVpTBXLpYw+pnLj6TbvHuyjXMfjGeCwSqCVwok=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/vmihailenco/msgpack v3.3.3+incompatible h1:wapg9xDUZDzGCNFlwc5SqI1rvcciqcxEHac4CYj89xI=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
@ -666,18 +582,14 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zclconf/go-cty v1.0.0/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
github.com/zclconf/go-cty v1.4.0 h1:+q+tmgyUB94HIdH/uVTIi/+kt3pt4sHwEZAcTyLoGsQ=
github.com/zclconf/go-cty v1.4.0/go.mod h1:nHzOclRkoj++EU9ZjSrZvRG0BXIWt8c7loYc0qXAFGQ=
github.com/zclconf/go-cty v1.7.0 h1:yMqLinUwNCYkmiHjEH+luio1yGl35cjqVzjvdRg2WlY=
github.com/zclconf/go-cty v1.7.0/go.mod h1:VDR4+I79ubFBGm1uJac1226K5yANQFHeauxPBoP54+o=
github.com/zclconf/go-cty-yaml v1.0.1 h1:up11wlgAaDvlAGENcFDnZgkn0qUJurso7k6EpURKNF8=
github.com/zclconf/go-cty-yaml v1.0.1/go.mod h1:IP3Ylp0wQpYm50IHK8OZWKMu6sPJIUgKa8XhiVHura0=
go.opencensus.io v0.21.0 h1:mU6zScU4U1YAFPHEHYk+3JC4SY7JxgkqS10ZOSyksNg=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4 h1:LYy1Hy3MJdrCdMwwzxA/dRok4ejH+RwNGbuoD9fCjto=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
@ -685,22 +597,17 @@ go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3 h1:KYQXGkl6vs02hK7pK4eIbw0NpNPedieTSTEiJ//bwGs=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190222235706-ffb98f73852f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5 h1:58fnuSXlxZmFdJyvtTFVmVhcMLU6v5fEb/ok4wyqtNU=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200422194213-44a606286825 h1:dSChiwOTvzwbHFTMq2l6uRardHH7/E6SqEkqccinS/o=
golang.org/x/crypto v0.0.0-20200422194213-44a606286825/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9 h1:sYNJzB4J8toYPQTM6pAkcmBRgw9SnQKP9oXCHfgy604=
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
@ -710,12 +617,10 @@ golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxT
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587 h1:5Uz0rkjCFu9BC9gCRN7EkwVvhNyQgGWb8KNJrPwBoHY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6 h1:QE6XYQK6naiK1EPAe1g/ILLxN5RBoH5xkJk3CqlMI/Y=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -726,25 +631,20 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367 h1:0IiAsCRByjO2QjX7ZPkw5oU9x+n1YqRL802rjC0c3Aw=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20191130191448-5c0e7e404af8 h1:9w7mvrikkrG9zFfEJfuFe08FVKrg8Yi0ePhOdGAKpUw=
golang.org/x/mobile v0.0.0-20191130191448-5c0e7e404af8/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ=
golang.org/x/mobile v0.0.0-20201208152944-da85bec010a2 h1:3HADozU50HyrJ2jklLtr3xr0itFkz9u4LxCJhqKVdjI=
golang.org/x/mobile v0.0.0-20201208152944-da85bec010a2/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee h1:WG0RUwxtNT4qqaXX3DPA8zHFNm/D9xaBpxzHt1WcA/E=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@ -752,18 +652,14 @@ golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc h1:a3CU5tJYVj92DY2LaA1kUkrsqD5/3mLDhx2NcNqyW+0=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd h1:HuTn7WObtcDo9uEEU7rEqL0jYthdXAmZ6PP+meazmaU=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a h1:oWX7TPOiFAMXLq8o0ikBYfCJVlRHBcsciT5bXOrH628=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859 h1:R/3boaszxrf1GEUWTVDzSKVwLmSJpwZ1yqXm8j0v2QI=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@ -783,13 +679,9 @@ golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974 h1:IX6qOQeG5uLjB/hjjwjedwfjND0hgjPMMyO1RoIXQNI=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11 h1:lwlPPsmjDKK0J6eG6xDWd5XPehI0R024zxjDnw3esPA=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@ -797,7 +689,6 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43 h1:ld7aEMNHoBnnDAX15v1T6z31v8HwR2A9FYOuAhWqkwc=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@ -807,11 +698,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03iWnKLEWinaScsxF2Vm2o=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9 h1:SQFwaSi55rU7vdNs9Yr0Z324VNlrF+0wMqRXT4St8ck=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -857,7 +745,6 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200828194041-157a740278f4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

View File

@ -33,6 +33,9 @@ func getBasicParser() *Parser {
"amazon-import": func() (packersdk.PostProcessor, error) { return &MockPostProcessor{}, nil },
"manifest": func() (packersdk.PostProcessor, error) { return &MockPostProcessor{}, nil },
},
DatasourceSchemas: packersdk.MapOfDatasource{
"amazon-ami": func() (packersdk.Datasource, error) { return &MockDatasource{}, nil },
},
}
}
@ -62,7 +65,7 @@ func testParse(t *testing.T, tests []parseTest) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
gotCfg, gotDiags := tt.parser.Parse(tt.args.filename, tt.args.varFiles, tt.args.vars)
moreDiags := gotCfg.Initialize()
moreDiags := gotCfg.Initialize(packer.InitializeOptions{})
gotDiags = append(gotDiags, moreDiags...)
if tt.parseWantDiags == (gotDiags == nil) {
t.Fatalf("Parser.parse() unexpected %q diagnostics.", gotDiags)
@ -125,13 +128,39 @@ var (
Tags: []MockTag{},
}
// everything in the tests is a basicNestedMockConfig this allow to test
// each known type to packer ( and embedding ) in one go.
builderBasicNestedMockConfig = NestedMockConfig{
String: "string",
Int: 42,
Int64: 43,
Bool: true,
Trilean: config.TriTrue,
Duration: 10 * time.Second,
MapStringString: map[string]string{
"a": "b",
"c": "d",
},
SliceString: []string{
"a",
"b",
"c",
},
SliceSliceString: [][]string{
{"a", "b"},
{"c", "d"},
},
Tags: []MockTag{},
Datasource: "string",
}
basicMockBuilder = &MockBuilder{
Config: MockConfig{
NestedMockConfig: basicNestedMockConfig,
Nested: basicNestedMockConfig,
NestedMockConfig: builderBasicNestedMockConfig,
Nested: builderBasicNestedMockConfig,
NestedSlice: []NestedMockConfig{
basicNestedMockConfig,
basicNestedMockConfig,
builderBasicNestedMockConfig,
builderBasicNestedMockConfig,
},
},
}
@ -226,6 +255,7 @@ var cmpOpts = []cmp.Option{
PackerConfig{},
Variable{},
SourceBlock{},
Datasource{},
ProvisionerBlock{},
PostProcessorBlock{},
packer.CoreBuild{},

View File

@ -7,6 +7,7 @@ import (
"time"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer-plugin-sdk/hcl2helper"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template/config"
"github.com/zclconf/go-cty/cty"
@ -26,6 +27,7 @@ type NestedMockConfig struct {
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string"`
NamedString NamedString `mapstructure:"named_string"`
Tags []MockTag `mapstructure:"tag"`
Datasource string `mapstructure:"data_source"`
}
type MockTag struct {
@ -103,6 +105,32 @@ func (b *MockProvisioner) Provision(ctx context.Context, ui packersdk.Ui, comm p
return nil
}
//////
// MockDatasource
//////
type MockDatasource struct {
Config MockConfig
}
var _ packersdk.Datasource = new(MockDatasource)
func (d *MockDatasource) ConfigSpec() hcldec.ObjectSpec {
return d.Config.FlatMapstructure().HCL2Spec()
}
func (d *MockDatasource) OutputSpec() hcldec.ObjectSpec {
return d.Config.FlatMapstructure().HCL2Spec()
}
func (d *MockDatasource) Configure(raws ...interface{}) error {
return d.Config.Prepare(raws...)
}
func (d *MockDatasource) Execute() (cty.Value, error) {
return hcl2helper.HCL2ValueFromConfig(d.Config, d.OutputSpec()), nil
}
//////
// MockPostProcessor
//////

View File

@ -23,6 +23,7 @@ type FlatMockConfig struct {
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
Nested *FlatNestedMockConfig `mapstructure:"nested" cty:"nested" hcl:"nested"`
NestedSlice []FlatNestedMockConfig `mapstructure:"nested_slice" cty:"nested_slice" hcl:"nested_slice"`
}
@ -52,6 +53,7 @@ func (*FlatMockConfig) HCL2Spec() map[string]hcldec.Spec {
"named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
"named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
"data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
"nested": &hcldec.BlockSpec{TypeName: "nested", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
"nested_slice": &hcldec.BlockListSpec{TypeName: "nested_slice", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
}
@ -98,6 +100,7 @@ type FlatNestedMockConfig struct {
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
}
// FlatMapstructure returns a new FlatNestedMockConfig.
@ -124,6 +127,7 @@ func (*FlatNestedMockConfig) HCL2Spec() map[string]hcldec.Spec {
"named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
"named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
"data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
}
return s
}

View File

@ -20,6 +20,7 @@ const (
variablesLabel = "variables"
variableLabel = "variable"
localsLabel = "locals"
dataSourceLabel = "data"
buildLabel = "build"
communicatorLabel = "communicator"
)
@ -31,6 +32,7 @@ var configSchema = &hcl.BodySchema{
{Type: variablesLabel},
{Type: variableLabel, LabelNames: []string{"name"}},
{Type: localsLabel},
{Type: dataSourceLabel, LabelNames: []string{"type", "name"}},
{Type: buildLabel},
{Type: communicatorLabel, LabelNames: []string{"type", "name"}},
},
@ -60,6 +62,8 @@ type Parser struct {
ProvisionersSchemas packer.ProvisionerStore
PostProcessorsSchemas packer.PostProcessorStore
DatasourceSchemas packer.DatasourceStore
}
const (
@ -129,6 +133,7 @@ func (p *Parser) Parse(filename string, varFiles []string, argVars map[string]st
builderSchemas: p.BuilderSchemas,
provisionersSchemas: p.ProvisionersSchemas,
postProcessorsSchemas: p.PostProcessorsSchemas,
datasourceSchemas: p.DatasourceSchemas,
parser: p,
files: files,
}
@ -155,6 +160,11 @@ func (p *Parser) Parse(filename string, varFiles []string, argVars map[string]st
diags = append(diags, cfg.decodeInputVariables(file)...)
}
for _, file := range files {
morediags := p.decodeDatasources(file, cfg)
diags = append(diags, morediags...)
}
for _, file := range files {
moreLocals, morediags := cfg.parseLocalVariables(file)
diags = append(diags, morediags...)
@ -247,13 +257,14 @@ func sniffCoreVersionRequirements(body hcl.Body) ([]VersionConstraint, hcl.Diagn
return constraints, diags
}
func (cfg *PackerConfig) Initialize() hcl.Diagnostics {
func (cfg *PackerConfig) Initialize(opts packer.InitializeOptions) hcl.Diagnostics {
var diags hcl.Diagnostics
_, moreDiags := cfg.InputVariables.Values()
diags = append(diags, moreDiags...)
_, moreDiags = cfg.LocalVariables.Values()
diags = append(diags, moreDiags...)
diags = append(diags, cfg.evaluateDatasources(opts.SkipDatasourcesExecution)...)
diags = append(diags, cfg.evaluateLocalVariables(cfg.LocalBlocks)...)
for _, variable := range cfg.InputVariables {
@ -328,3 +339,41 @@ func (p *Parser) decodeConfig(f *hcl.File, cfg *PackerConfig) hcl.Diagnostics {
return diags
}
func (p *Parser) decodeDatasources(file *hcl.File, cfg *PackerConfig) hcl.Diagnostics {
var diags hcl.Diagnostics
body := dynblock.Expand(file.Body, cfg.EvalContext(nil))
content, moreDiags := body.Content(configSchema)
diags = append(diags, moreDiags...)
for _, block := range content.Blocks {
switch block.Type {
case dataSourceLabel:
datasource, moreDiags := p.decodeDataBlock(block)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
}
ref := datasource.Ref()
if existing, found := cfg.Datasources[ref]; found {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Duplicate " + dataSourceLabel + " block",
Detail: fmt.Sprintf("This "+dataSourceLabel+" block has the "+
"same data type and name as a previous block declared "+
"at %s. Each "+dataSourceLabel+" must have a unique name per builder type.",
existing.block.DefRange.Ptr()),
Subject: datasource.block.DefRange.Ptr(),
})
continue
}
if cfg.Datasources == nil {
cfg.Datasources = Datasources{}
}
cfg.Datasources[ref] = *datasource
}
}
return diags
}

40
hcl2template/shim/mock.go Normal file
View File

@ -0,0 +1,40 @@
//go:generate mapstructure-to-hcl2 -type MockConfig,NestedMockConfig,MockTag
package hcl2shim
import (
"time"
"github.com/hashicorp/packer-plugin-sdk/template/config"
)
type NestedMockConfig struct {
String string `mapstructure:"string"`
Int int `mapstructure:"int"`
Int64 int64 `mapstructure:"int64"`
Bool bool `mapstructure:"bool"`
Trilean config.Trilean `mapstructure:"trilean"`
Duration time.Duration `mapstructure:"duration"`
MapStringString map[string]string `mapstructure:"map_string_string"`
SliceString []string `mapstructure:"slice_string"`
SliceSliceString [][]string `mapstructure:"slice_slice_string"`
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string"`
NamedString NamedString `mapstructure:"named_string"`
Tags []MockTag `mapstructure:"tag"`
Datasource string `mapstructure:"data_source"`
}
type MockTag struct {
Key string `mapstructure:"key"`
Value string `mapstructure:"value"`
}
type MockConfig struct {
NotSquashed string `mapstructure:"not_squashed"`
NestedMockConfig `mapstructure:",squash"`
Nested NestedMockConfig `mapstructure:"nested"`
NestedSlice []NestedMockConfig `mapstructure:"nested_slice"`
}
type NamedMapStringString map[string]string
type NamedString string

View File

@ -0,0 +1,133 @@
// Code generated by "mapstructure-to-hcl2 -type MockConfig,NestedMockConfig,MockTag"; DO NOT EDIT.
package hcl2shim
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatMockConfig is an auto-generated flat version of MockConfig.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatMockConfig struct {
NotSquashed *string `mapstructure:"not_squashed" cty:"not_squashed" hcl:"not_squashed"`
String *string `mapstructure:"string" cty:"string" hcl:"string"`
Int *int `mapstructure:"int" cty:"int" hcl:"int"`
Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
Nested *FlatNestedMockConfig `mapstructure:"nested" cty:"nested" hcl:"nested"`
NestedSlice []FlatNestedMockConfig `mapstructure:"nested_slice" cty:"nested_slice" hcl:"nested_slice"`
}
// FlatMapstructure returns a new FlatMockConfig.
// FlatMockConfig is an auto-generated flat version of MockConfig.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*MockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatMockConfig)
}
// HCL2Spec returns the hcl spec of a MockConfig.
// This spec is used by HCL to read the fields of MockConfig.
// The decoded values from this spec will then be applied to a FlatMockConfig.
func (*FlatMockConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"not_squashed": &hcldec.AttrSpec{Name: "not_squashed", Type: cty.String, Required: false},
"string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
"int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
"int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
"bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
"trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
"duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
"map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
"slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
"slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
"named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
"named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
"data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
"nested": &hcldec.BlockSpec{TypeName: "nested", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
"nested_slice": &hcldec.BlockListSpec{TypeName: "nested_slice", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
}
return s
}
// FlatMockTag is an auto-generated flat version of MockTag.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatMockTag struct {
Key *string `mapstructure:"key" cty:"key" hcl:"key"`
Value *string `mapstructure:"value" cty:"value" hcl:"value"`
}
// FlatMapstructure returns a new FlatMockTag.
// FlatMockTag is an auto-generated flat version of MockTag.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*MockTag) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatMockTag)
}
// HCL2Spec returns the hcl spec of a MockTag.
// This spec is used by HCL to read the fields of MockTag.
// The decoded values from this spec will then be applied to a FlatMockTag.
func (*FlatMockTag) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"key": &hcldec.AttrSpec{Name: "key", Type: cty.String, Required: false},
"value": &hcldec.AttrSpec{Name: "value", Type: cty.String, Required: false},
}
return s
}
// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatNestedMockConfig struct {
String *string `mapstructure:"string" cty:"string" hcl:"string"`
Int *int `mapstructure:"int" cty:"int" hcl:"int"`
Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
}
// FlatMapstructure returns a new FlatNestedMockConfig.
// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*NestedMockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatNestedMockConfig)
}
// HCL2Spec returns the hcl spec of a NestedMockConfig.
// This spec is used by HCL to read the fields of NestedMockConfig.
// The decoded values from this spec will then be applied to a FlatNestedMockConfig.
func (*FlatNestedMockConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
"int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
"int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
"bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
"trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
"duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
"map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
"slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
"slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
"named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
"named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
"data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
}
return s
}

View File

@ -4,15 +4,10 @@ import (
"fmt"
"math/big"
"github.com/hashicorp/packer-plugin-sdk/hcl2helper"
"github.com/zclconf/go-cty/cty"
)
// UnknownVariableValue is a sentinel value that can be used
// to denote that the value of a variable is unknown at this time.
// RawConfig uses this information to build up data about
// unknown keys.
const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66"
// ConfigValueFromHCL2 converts a value from HCL2 (really, from the cty dynamic
// types library that HCL2 uses) to a value type that matches what would've
// been produced from the HCL-based interpolator for an equivalent structure.
@ -22,7 +17,7 @@ const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66"
// need to detect and reject any null values.
func ConfigValueFromHCL2(v cty.Value) interface{} {
if !v.IsKnown() {
return UnknownVariableValue
return hcl2helper.UnknownVariableValue
}
if v.IsNull() {
return nil
@ -86,47 +81,104 @@ func ConfigValueFromHCL2(v cty.Value) interface{} {
panic(fmt.Errorf("can't convert %#v to config value", v))
}
// HCL2ValueFromConfigValue is the opposite of ConfigValueFromHCL2: it takes
// a value as would be returned from the old interpolator and turns it into
// a cty.Value so it can be used within, for example, an HCL2 EvalContext.
func HCL2ValueFromConfigValue(v interface{}) cty.Value {
if v == nil {
return cty.NullVal(cty.DynamicPseudoType)
// WriteUnknownPlaceholderValues will replace every Unknown value with a equivalent placeholder.
// This is useful to use before marshaling the value to JSON. The default values are:
// - string: "<unknown>"
// - number: 0
// - bool: false
// - objects/lists/tuples/sets/maps: empty
func WriteUnknownPlaceholderValues(v cty.Value) cty.Value {
if v.IsNull() {
return v
}
if v == UnknownVariableValue {
return cty.DynamicVal
}
switch tv := v.(type) {
case bool:
return cty.BoolVal(tv)
case string:
return cty.StringVal(tv)
case int:
return cty.NumberIntVal(int64(tv))
case float64:
return cty.NumberFloatVal(tv)
case []interface{}:
vals := make([]cty.Value, len(tv))
for i, ev := range tv {
vals[i] = HCL2ValueFromConfigValue(ev)
t := v.Type()
switch {
case t.IsPrimitiveType():
if v.IsKnown() {
return v
}
return cty.TupleVal(vals)
case []string:
vals := make([]cty.Value, len(tv))
for i, ev := range tv {
vals[i] = cty.StringVal(ev)
switch t {
case cty.String:
return cty.StringVal("<unknown>")
case cty.Number:
return cty.MustParseNumberVal("0")
case cty.Bool:
return cty.BoolVal(false)
default:
panic("unsupported primitive type")
}
return cty.ListVal(vals)
case map[string]interface{}:
vals := map[string]cty.Value{}
for k, ev := range tv {
vals[k] = HCL2ValueFromConfigValue(ev)
case t.IsListType():
if !v.IsKnown() {
return cty.ListValEmpty(t.ElementType())
}
return cty.ObjectVal(vals)
arr := []cty.Value{}
it := v.ElementIterator()
for it.Next() {
_, ev := it.Element()
arr = append(arr, WriteUnknownPlaceholderValues(ev))
}
if len(arr) == 0 {
return cty.ListValEmpty(t.ElementType())
}
return cty.ListVal(arr)
case t.IsSetType():
if !v.IsKnown() {
return cty.SetValEmpty(t.ElementType())
}
arr := []cty.Value{}
it := v.ElementIterator()
for it.Next() {
_, ev := it.Element()
arr = append(arr, WriteUnknownPlaceholderValues(ev))
}
if len(arr) == 0 {
return cty.SetValEmpty(t.ElementType())
}
return cty.SetVal(arr)
case t.IsMapType():
if !v.IsKnown() {
return cty.MapValEmpty(t.ElementType())
}
obj := map[string]cty.Value{}
it := v.ElementIterator()
for it.Next() {
ek, ev := it.Element()
obj[ek.AsString()] = WriteUnknownPlaceholderValues(ev)
}
if len(obj) == 0 {
return cty.MapValEmpty(t.ElementType())
}
return cty.MapVal(obj)
case t.IsTupleType():
if !v.IsKnown() {
return cty.EmptyTupleVal
}
arr := []cty.Value{}
it := v.ElementIterator()
for it.Next() {
_, ev := it.Element()
arr = append(arr, WriteUnknownPlaceholderValues(ev))
}
if len(arr) == 0 {
return cty.EmptyTupleVal
}
return cty.TupleVal(arr)
case t.IsObjectType():
if !v.IsKnown() {
return cty.EmptyObjectVal
}
obj := map[string]cty.Value{}
it := v.ElementIterator()
for it.Next() {
ek, ev := it.Element()
obj[ek.AsString()] = WriteUnknownPlaceholderValues(ev)
}
if len(obj) == 0 {
return cty.EmptyObjectVal
}
return cty.ObjectVal(obj)
default:
// HCL/HIL should never generate anything that isn't caught by
// the above, so if we get here something has gone very wrong.
panic(fmt.Errorf("can't convert %#v to cty.Value", v))
// should never happen
panic("unknown type")
}
}

View File

@ -5,6 +5,7 @@ import (
"reflect"
"testing"
"github.com/hashicorp/packer-plugin-sdk/hcl2helper"
"github.com/zclconf/go-cty/cty"
)
@ -81,7 +82,7 @@ func TestConfigValueFromHCL2(t *testing.T) {
},
{
cty.UnknownVal(cty.String),
UnknownVariableValue,
hcl2helper.UnknownVariableValue,
},
}
@ -94,3 +95,140 @@ func TestConfigValueFromHCL2(t *testing.T) {
})
}
}
func TestWriteUnknownPlaceholderValues(t *testing.T) {
tests := []struct {
Name string
Input cty.Value
Want cty.Value
}{
{
Name: "Unknown bool",
Input: cty.UnknownVal(cty.Bool),
Want: cty.False,
},
{
Name: "Unknown number",
Input: cty.UnknownVal(cty.Number),
Want: cty.NumberIntVal(0),
},
{
Name: "Unknown string",
Input: cty.UnknownVal(cty.String),
Want: cty.StringVal("<unknown>"),
},
{
Name: "Unknown object",
Input: cty.UnknownVal(cty.EmptyObject),
Want: cty.EmptyObjectVal,
},
{
Name: "Object with unknown values",
Input: cty.ObjectVal(map[string]cty.Value{
"name": cty.UnknownVal(cty.String),
"address": cty.UnknownVal(cty.EmptyObject),
}),
Want: cty.ObjectVal(map[string]cty.Value{
"name": cty.StringVal("<unknown>"),
"address": cty.EmptyObjectVal,
}),
},
{
Name: "Empty object",
Input: cty.ObjectVal(map[string]cty.Value{}),
Want: cty.EmptyObjectVal,
},
{
Name: "Unknown tuple",
Input: cty.UnknownVal(cty.EmptyTuple),
Want: cty.EmptyTupleVal,
},
{
Name: "Tuple with unknown values",
Input: cty.TupleVal([]cty.Value{
cty.UnknownVal(cty.String),
cty.UnknownVal(cty.Bool),
}),
Want: cty.TupleVal([]cty.Value{
cty.StringVal("<unknown>"),
cty.False,
}),
},
{
Name: "Empty tuple",
Input: cty.TupleVal([]cty.Value{}),
Want: cty.EmptyTupleVal,
},
{
Name: "Unknown list",
Input: cty.UnknownVal(cty.List(cty.String)),
Want: cty.ListValEmpty(cty.String),
},
{
Name: "List with unknown values",
Input: cty.ListVal([]cty.Value{
cty.UnknownVal(cty.String),
}),
Want: cty.ListVal([]cty.Value{
cty.StringVal("<unknown>"),
}),
},
{
Name: "Empty list",
Input: cty.ListValEmpty(cty.String),
Want: cty.ListValEmpty(cty.String),
},
{
Name: "Unknown set",
Input: cty.UnknownVal(cty.Set(cty.String)),
Want: cty.SetValEmpty(cty.String),
},
{
Name: "Set with unknown values",
Input: cty.SetVal([]cty.Value{
cty.UnknownVal(cty.String),
}),
Want: cty.SetVal([]cty.Value{
cty.StringVal("<unknown>"),
}),
},
{
Name: "Empty Set",
Input: cty.SetValEmpty(cty.String),
Want: cty.SetValEmpty(cty.String),
},
{
Name: "Unknown map",
Input: cty.UnknownVal(cty.Map(cty.String)),
Want: cty.MapValEmpty(cty.String),
},
{
Name: "Map with unknown values",
Input: cty.MapVal(map[string]cty.Value{
"name": cty.UnknownVal(cty.String),
}),
Want: cty.MapVal(map[string]cty.Value{
"name": cty.StringVal("<unknown>"),
}),
},
{
Name: "Empty Map",
Input: cty.MapValEmpty(cty.String),
Want: cty.MapValEmpty(cty.String),
},
{
Name: "Null val",
Input: cty.NullVal(cty.String),
Want: cty.NullVal(cty.String),
},
}
for _, test := range tests {
t.Run(t.Name(), func(t *testing.T) {
got := WriteUnknownPlaceholderValues(test.Input)
if got.Equals(test.Want).False() {
t.Errorf("wrong result\ninput: %#v\ngot: %#v\nwant: %#v", test.Input, got, test.Want)
}
})
}
}

View File

@ -0,0 +1,3 @@
data "amazon-ami" "test" {
string = "string"
}

View File

@ -26,6 +26,8 @@ source "virtualbox-iso" "ubuntu-1204" {
["c","d"]
]
data_source = data.amazon-ami.test.string
nested {
string = "string"
int = 42
@ -46,6 +48,7 @@ source "virtualbox-iso" "ubuntu-1204" {
["a","b"],
["c","d"]
]
data_source = data.amazon-ami.test.string
}
nested_slice {
@ -68,6 +71,7 @@ source "virtualbox-iso" "ubuntu-1204" {
["a","b"],
["c","d"]
]
data_source = data.amazon-ami.test.string
}
nested_slice {
@ -90,5 +94,6 @@ source "virtualbox-iso" "ubuntu-1204" {
["a","b"],
["c","d"]
]
data_source = data.amazon-ami.test.string
}
}

View File

@ -22,6 +22,7 @@ variable "availability_zone_names" {
locals {
feefoo = "${var.foo}_${var.image_id}"
data_source = data.amazon-ami.test.string
}

View File

@ -0,0 +1,87 @@
data "amazon-ami" "test" {
string = "string"
int = 42
int64 = 43
bool = true
trilean = true
duration = "10s"
map_string_string = {
a = "b"
c = "d"
}
slice_string = [
"a",
"b",
"c",
]
slice_slice_string = [
["a","b"],
["c","d"]
]
nested {
string = "string"
int = 42
int64 = 43
bool = true
trilean = true
duration = "10s"
map_string_string = {
a = "b"
c = "d"
}
slice_string = [
"a",
"b",
"c",
]
slice_slice_string = [
["a","b"],
["c","d"]
]
}
nested_slice {
string = "string"
int = 42
int64 = 43
bool = true
trilean = true
duration = "10s"
map_string_string = {
a = "b"
c = "d"
}
slice_string = [
"a",
"b",
"c",
]
slice_slice_string = [
["a","b"],
["c","d"]
]
}
nested_slice {
string = "string"
int = 42
int64 = 43
bool = true
trilean = true
duration = "10s"
map_string_string = {
a = "b"
c = "d"
}
slice_string = [
"a",
"b",
"c",
]
slice_slice_string = [
["a","b"],
["c","d"]
]
}
}

View File

@ -0,0 +1,2 @@
data "amazon-ami" "test" {}
data "amazon-ami" "test" {}

View File

@ -0,0 +1,3 @@
data "inexistant" "test" {
foo = "bar"
}

View File

@ -0,0 +1,3 @@
data "amazon-ami" {
foo = "bar"
}

View File

@ -0,0 +1,3 @@
data {
foo = "bar"
}

View File

@ -0,0 +1,146 @@
package hcl2template
import (
"fmt"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclsyntax"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
)
// DataBlock references an HCL 'data' block.
type Datasource struct {
Type string
Name string
value cty.Value
block *hcl.Block
}
type DatasourceRef struct {
Type string
Name string
}
type Datasources map[DatasourceRef]Datasource
func (data *Datasource) Ref() DatasourceRef {
return DatasourceRef{
Type: data.Type,
Name: data.Name,
}
}
func (ds *Datasources) Values() (map[string]cty.Value, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := map[string]cty.Value{}
valuesMap := map[string]map[string]cty.Value{}
for ref, datasource := range *ds {
if datasource.value == (cty.Value{}) {
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("empty value"),
Subject: &datasource.block.DefRange,
Severity: hcl.DiagError,
})
continue
}
inner := valuesMap[ref.Type]
if inner == nil {
inner = map[string]cty.Value{}
}
inner[ref.Name] = datasource.value
res[ref.Type] = cty.MapVal(inner)
// Keeps values of different datasources from same type
valuesMap[ref.Type] = inner
}
return res, diags
}
func (cfg *PackerConfig) startDatasource(dataSourceStore packer.DatasourceStore, ref DatasourceRef) (packersdk.Datasource, hcl.Diagnostics) {
var diags hcl.Diagnostics
block := cfg.Datasources[ref].block
if dataSourceStore == nil {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + dataSourceLabel + " type " + ref.Type,
Subject: block.LabelRanges[0].Ptr(),
Detail: fmt.Sprintf("packer does not currently know any data source."),
Severity: hcl.DiagError,
})
return nil, diags
}
if !dataSourceStore.Has(ref.Type) {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + dataSourceLabel + " type " + ref.Type,
Subject: block.LabelRanges[0].Ptr(),
Detail: fmt.Sprintf("known data sources: %v", dataSourceStore.List()),
Severity: hcl.DiagError,
})
return nil, diags
}
datasource, err := dataSourceStore.Start(ref.Type)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: err.Error(),
Subject: &block.DefRange,
Severity: hcl.DiagError,
})
}
if datasource == nil {
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("failed to start datasource plugin %q.%q", ref.Type, ref.Name),
Subject: &block.DefRange,
Severity: hcl.DiagError,
})
}
body := block.Body
decoded, moreDiags := decodeHCL2Spec(body, cfg.EvalContext(nil), datasource)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
return nil, diags
}
if err := datasource.Configure(decoded); err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: err.Error(),
Subject: &block.DefRange,
Severity: hcl.DiagError,
})
}
return datasource, diags
}
func (p *Parser) decodeDataBlock(block *hcl.Block) (*Datasource, hcl.Diagnostics) {
var diags hcl.Diagnostics
r := &Datasource{
Type: block.Labels[0],
Name: block.Labels[1],
block: block,
}
if !hclsyntax.ValidIdentifier(r.Type) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid data source name",
Detail: badIdentifierDetail,
Subject: &block.LabelRanges[0],
})
}
if !hclsyntax.ValidIdentifier(r.Name) {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Invalid data resource name",
Detail: badIdentifierDetail,
Subject: &block.LabelRanges[1],
})
}
return r, diags
}

View File

@ -0,0 +1,93 @@
package hcl2template
import (
"path/filepath"
"testing"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)
func TestParse_datasource(t *testing.T) {
defaultParser := getBasicParser()
tests := []parseTest{
{"two basic datasources",
defaultParser,
parseTestArgs{"testdata/datasources/basic.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "datasources"),
Datasources: Datasources{
{
Type: "amazon-ami",
Name: "test",
}: {
Type: "amazon-ami",
Name: "test",
},
},
},
false, false,
[]packersdk.Build{},
false,
},
{"untyped datasource",
defaultParser,
parseTestArgs{"testdata/datasources/untyped.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "datasources"),
},
true, true,
nil,
false,
},
{"unnamed source",
defaultParser,
parseTestArgs{"testdata/datasources/unnamed.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "datasources"),
},
true, true,
nil,
false,
},
{"inexistent source",
defaultParser,
parseTestArgs{"testdata/datasources/inexistent.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "datasources"),
Datasources: Datasources{
{
Type: "inexistant",
Name: "test",
}: {
Type: "inexistant",
Name: "test",
},
},
},
true, true,
nil,
false,
},
{"duplicate source",
defaultParser,
parseTestArgs{"testdata/datasources/duplicate.pkr.hcl", nil, nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "datasources"),
Datasources: Datasources{
{
Type: "amazon-ami",
Name: "test",
}: {
Type: "amazon-ami",
Name: "test",
},
},
},
true, true,
nil,
false,
},
}
testParse(t, tests)
}

View File

@ -7,6 +7,7 @@ import (
"github.com/gobwas/glob"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/hcl/v2/hclsyntax"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
pkrfunction "github.com/hashicorp/packer/hcl2template/function"
@ -40,6 +41,8 @@ type PackerConfig struct {
InputVariables Variables
LocalVariables Variables
Datasources Datasources
LocalBlocks []*LocalBlock
ValidationOptions
@ -47,11 +50,10 @@ type PackerConfig struct {
// Builds is the list of Build blocks defined in the config files.
Builds Builds
builderSchemas packer.BuilderStore
provisionersSchemas packer.ProvisionerStore
builderSchemas packer.BuilderStore
provisionersSchemas packer.ProvisionerStore
postProcessorsSchemas packer.PostProcessorStore
datasourceSchemas packer.DatasourceStore
except []glob.Glob
only []glob.Glob
@ -71,6 +73,7 @@ const (
sourcesAccessor = "source"
buildAccessor = "build"
packerAccessor = "packer"
dataAccessor = "data"
)
// EvalContext returns the *hcl.EvalContext that will be passed to an hcl
@ -79,6 +82,7 @@ const (
func (cfg *PackerConfig) EvalContext(variables map[string]cty.Value) *hcl.EvalContext {
inputVariables, _ := cfg.InputVariables.Values()
localVariables, _ := cfg.LocalVariables.Values()
datasourceVariables, _ := cfg.Datasources.Values()
ectx := &hcl.EvalContext{
Functions: Functions(cfg.Basedir),
Variables: map[string]cty.Value{
@ -96,6 +100,7 @@ func (cfg *PackerConfig) EvalContext(variables map[string]cty.Value) *hcl.EvalCo
"cwd": cty.StringVal(strings.ReplaceAll(cfg.Cwd, `\`, `/`)),
"root": cty.StringVal(strings.ReplaceAll(cfg.Basedir, `\`, `/`)),
}),
dataAccessor: cty.ObjectVal(datasourceVariables),
},
}
for k, v := range variables {
@ -235,6 +240,43 @@ func (c *PackerConfig) evaluateLocalVariable(local *LocalBlock) hcl.Diagnostics
return diags
}
func (cfg *PackerConfig) evaluateDatasources(skipExecution bool) hcl.Diagnostics {
var diags hcl.Diagnostics
for ref, ds := range cfg.Datasources {
if ds.value != (cty.Value{}) {
continue
}
datasource, startDiags := cfg.startDatasource(cfg.datasourceSchemas, ref)
diags = append(diags, startDiags...)
if diags.HasErrors() {
continue
}
if skipExecution {
placeholderValue := cty.UnknownVal(hcldec.ImpliedType(datasource.OutputSpec()))
ds.value = placeholderValue
cfg.Datasources[ref] = ds
continue
}
realValue, err := datasource.Execute()
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: err.Error(),
Subject: &cfg.Datasources[ref].block.DefRange,
Severity: hcl.DiagError,
})
continue
}
ds.value = realValue
cfg.Datasources[ref] = ds
}
return diags
}
// getCoreBuildProvisioners takes a list of provisioner block, starts according
// provisioners and sends parsed HCL2 over to it.
func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []*ProvisionerBlock, ectx *hcl.EvalContext) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {

View File

@ -59,6 +59,11 @@ func TestParser_complete(t *testing.T) {
Values: []VariableAssignment{{From: "default", Value: cty.StringVal("value_image-id-default")}},
Type: cty.String,
},
"data_source": &Variable{
Name: "data_source",
Values: []VariableAssignment{{From: "default", Value: cty.StringVal("string")}},
Type: cty.String,
},
"standard_tags": &Variable{
Name: "standard_tags",
Values: []VariableAssignment{{From: "default",
@ -100,6 +105,13 @@ func TestParser_complete(t *testing.T) {
}),
},
},
Datasources: Datasources{
DatasourceRef{Type: "amazon-ami", Name: "test"}: Datasource{
Type: "amazon-ami",
Name: "test",
value: cty.StringVal("foo"),
},
},
Sources: map[SourceRef]SourceBlock{
refVBIsoUbuntu1204: {Type: "virtualbox-iso", Name: "ubuntu-1204"},
refAWSEBSUbuntu1604: {Type: "amazon-ebs", Name: "ubuntu-1604"},

View File

@ -7,6 +7,7 @@ import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
)
@ -113,6 +114,12 @@ func (cfg *PackerConfig) startBuilder(source SourceBlock, ectx *hcl.EvalContext,
return nil, diags, nil
}
// In case of cty.Unknown values, this will write a equivalent placeholder of the same type
// Unknown types are not recognized by the json marshal during the RPC call and we have to do this here
// to avoid json parsing failures when running the validate command.
// We don't do this before so we can validate if variable types matches correctly on decodeHCL2Spec.
decoded = hcl2shim.WriteUnknownPlaceholderValues(decoded)
// Note: HCL prepares inside of the Start func, but Json does not. Json
// builds are instead prepared only in command/build.go
// TODO: either make json prepare when plugins are loaded, or make HCL

10
main.go
View File

@ -230,6 +230,7 @@ func wrappedMain() int {
BuilderStore: config.Builders,
ProvisionerStore: config.Provisioners,
PostProcessorStore: config.PostProcessors,
DatasourceStore: config.Datasources,
},
Version: version.Version,
},
@ -310,10 +311,11 @@ func loadConfig() (*config, error) {
}
// Copy plugins to general list
builders, provisioners, postProcessors := config.Plugins.GetPlugins()
config.Builders = builders
config.Provisioners = provisioners
config.PostProcessors = postProcessors
plugins := config.Plugins.GetPlugins()
config.Builders = plugins.Builders
config.Provisioners = plugins.Provisioners
config.PostProcessors = plugins.PostProcessors
config.Datasources = plugins.DataSources
// Finally, try to use an internal plugin. Note that this will not override
// any previously-loaded plugins.

View File

@ -81,6 +81,11 @@ type PostProcessorStore interface {
Start(name string) (packersdk.PostProcessor, error)
}
type DatasourceStore interface {
BasicStore
Start(name string) (packersdk.Datasource, error)
}
// ComponentFinder is a struct that contains the various function
// pointers necessary to look up components of Packer such as builders,
// commands, etc.
@ -91,6 +96,7 @@ type ComponentFinder struct {
BuilderStore BuilderStore
ProvisionerStore ProvisionerStore
PostProcessorStore PostProcessorStore
DatasourceStore DatasourceStore
}
// NewCore creates a new Core.

View File

@ -173,6 +173,16 @@ func (c *Client) Provisioner() (packersdk.Provisioner, error) {
return &cmdProvisioner{client.Provisioner(), c}, nil
}
// Returns a data source implementation that is communicating over this
// client. If the client hasn't been started, this will start it.
func (c *Client) Datasource() (packersdk.Datasource, error) {
client, err := c.Client()
if err != nil {
return nil, err
}
return &cmdDatasource{client.Datasource(), c}, nil
}
// End the executing subprocess (if it is running) and perform any cleanup
// tasks necessary such as capturing any remaining logs and so on.
//

View File

@ -0,0 +1,58 @@
package plugin
import (
"log"
"github.com/hashicorp/hcl/v2/hcldec"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/zclconf/go-cty/cty"
)
type cmdDatasource struct {
d packersdk.Datasource
client *Client
}
func (d *cmdDatasource) ConfigSpec() hcldec.ObjectSpec {
defer func() {
r := recover()
d.checkExit(r, nil)
}()
return d.d.ConfigSpec()
}
func (d *cmdDatasource) Configure(configs ...interface{}) error {
defer func() {
r := recover()
d.checkExit(r, nil)
}()
return d.d.Configure(configs...)
}
func (d *cmdDatasource) OutputSpec() hcldec.ObjectSpec {
defer func() {
r := recover()
d.checkExit(r, nil)
}()
return d.d.OutputSpec()
}
func (d *cmdDatasource) Execute() (cty.Value, error) {
defer func() {
r := recover()
d.checkExit(r, nil)
}()
return d.d.Execute()
}
func (d *cmdDatasource) checkExit(p interface{}, cb func()) {
if d.client.Exited() && cb != nil {
cb()
} else if p != nil && !Killed {
log.Panic(p)
}
}

View File

@ -0,0 +1,26 @@
package plugin
import (
"os/exec"
"testing"
)
func TestDatasource_NoExist(t *testing.T) {
c := NewClient(&ClientConfig{Cmd: exec.Command("i-should-not-exist")})
defer c.Kill()
_, err := c.Datasource()
if err == nil {
t.Fatal("should have error")
}
}
func TestDatasource_Good(t *testing.T) {
c := NewClient(&ClientConfig{Cmd: helperProcess("datasource")})
defer c.Kill()
_, err := c.Datasource()
if err != nil {
t.Fatalf("should not have error: %s", err)
}
}

View File

@ -26,10 +26,23 @@ type Config struct {
builders packer.MapOfBuilder
provisioners packer.MapOfProvisioner
postProcessors packer.MapOfPostProcessor
dataSources packer.MapOfDatasource
}
func (c *Config) GetPlugins() (packer.MapOfBuilder, packer.MapOfProvisioner, packer.MapOfPostProcessor) {
return c.builders, c.provisioners, c.postProcessors
type Plugins struct {
Builders packer.MapOfBuilder
Provisioners packer.MapOfProvisioner
PostProcessors packer.MapOfPostProcessor
DataSources packer.MapOfDatasource
}
func (c *Config) GetPlugins() Plugins {
return Plugins{
Builders: c.builders,
Provisioners: c.provisioners,
PostProcessors: c.postProcessors,
DataSources: c.dataSources,
}
}
// Discover discovers plugins.
@ -49,6 +62,9 @@ func (c *Config) Discover() error {
if c.postProcessors == nil {
c.postProcessors = packer.MapOfPostProcessor{}
}
if c.dataSources == nil {
c.dataSources = packer.MapOfDatasource{}
}
// If we are already inside a plugin process we should not need to
// discover anything.
@ -161,6 +177,22 @@ func (c *Config) discoverExternalComponents(path string) error {
log.Printf("using external provisioners %v", externallyUsed)
}
pluginPaths, err = c.discoverSingle(filepath.Join(path, "packer-datasource-*"))
if err != nil {
return err
}
for pluginName, pluginPath := range pluginPaths {
newPath := pluginPath // this needs to be stored in a new variable for the func below
c.dataSources[pluginName] = func() (packersdk.Datasource, error) {
return c.Client(newPath).Datasource()
}
externallyUsed = append(externallyUsed, pluginName)
}
if len(externallyUsed) > 0 {
sort.Strings(externallyUsed)
log.Printf("using external datasource %v", externallyUsed)
}
pluginPaths, err = c.discoverSingle(filepath.Join(path, "packer-plugin-*"))
if err != nil {
return err
@ -279,6 +311,16 @@ func (c *Config) discoverMultiPlugin(pluginName, pluginPath string) error {
log.Printf("found external %v provisioner from %s plugin", desc.Provisioners, pluginName)
}
for _, datasourceName := range desc.Datasources {
datasourceName := datasourceName // copy to avoid pointer overwrite issue
c.dataSources[pluginPrefix+datasourceName] = func() (packersdk.Datasource, error) {
return c.Client(pluginPath, "start", "datasource", datasourceName).Datasource()
}
}
if len(desc.Datasources) > 0 {
log.Printf("found external %v datasource from %s plugin", desc.Datasources, pluginName)
}
return nil
}

View File

@ -111,6 +111,49 @@ func TestEnvVarPackerPluginPath_MultiplePaths(t *testing.T) {
}
}
func TestDiscoverDatasource(t *testing.T) {
// Create a temporary directory to store plugins in
dir, _, cleanUpFunc, err := generateFakePlugins("custom_plugin_dir",
[]string{"packer-datasource-partyparrot"})
if err != nil {
t.Fatalf("Error creating fake custom plugins: %s", err)
}
defer cleanUpFunc()
pathsep := ":"
if runtime.GOOS == "windows" {
pathsep = ";"
}
// Create a second dir to look in that will be empty
decoyDir, err := ioutil.TempDir("", "decoy")
if err != nil {
t.Fatalf("Failed to create a temporary test dir.")
}
defer os.Remove(decoyDir)
pluginPath := dir + pathsep + decoyDir
// Add temp dir to path.
os.Setenv("PACKER_PLUGIN_PATH", pluginPath)
defer os.Unsetenv("PACKER_PLUGIN_PATH")
config := newConfig()
err = config.Discover()
if err != nil {
t.Fatalf("Should not have errored: %s", err)
}
if len(config.dataSources) == 0 {
t.Fatalf("Should have found partyparrot datasource")
}
if _, ok := config.dataSources["partyparrot"]; !ok {
t.Fatalf("Should have found partyparrot datasource.")
}
}
func generateFakePlugins(dirname string, pluginNames []string) (string, []string, func(), error) {
dir, err := ioutil.TempDir("", dirname)
if err != nil {
@ -268,6 +311,11 @@ var (
"smoke": nil,
},
},
"data": pluginsdk.Set{
Datasources: map[string]packersdk.Datasource{
"source": nil,
},
},
}
defaultNameMock = map[string]pluginsdk.Set{
@ -334,6 +382,12 @@ func Test_multiplugin_describe(t *testing.T) {
t.Fatalf("expected to find post-processor %q", expectedPostProcessorName)
}
}
for mockDatasourceName := range plugin.Datasources {
expectedDatasourceName := mockPluginName + "-" + mockDatasourceName
if _, found := c.dataSources[expectedDatasourceName]; !found {
t.Fatalf("expected to find datasource %q", expectedDatasourceName)
}
}
}
}

View File

@ -108,6 +108,18 @@ func TestHelperProcess(*testing.T) {
os.Exit(1)
}
server.Serve()
case "datasource":
server, err := pluginsdk.Server()
if err != nil {
log.Printf("[ERR] %s", err)
os.Exit(1)
}
err = server.RegisterDatasource(new(packersdk.MockDatasource))
if err != nil {
log.Printf("[ERR] %s", err)
os.Exit(1)
}
server.Serve()
case "start-timeout":
time.Sleep(1 * time.Minute)
os.Exit(1)

View File

@ -27,9 +27,15 @@ type Evaluator interface {
EvaluateExpression(expr string) (output string, exit bool, diags hcl.Diagnostics)
}
type InitializeOptions struct {
// When set, the execution of datasources will be skipped and the datasource will provide
// a output spec that will be used for validation only.
SkipDatasourcesExecution bool
}
// The packer.Handler handles all Packer things.
type Handler interface {
Initialize() hcl.Diagnostics
Initialize(InitializeOptions) hcl.Diagnostics
Evaluator
BuildGetter
ConfigFixer

31
scripts/generate-plugins.go Normal file → Executable file
View File

@ -43,12 +43,18 @@ func main() {
log.Fatalf("Failed to discover post processors: %s", err)
}
datasources, err := discoverDatasources()
if err != nil {
log.Fatalf("Failed to discover Datasources: %s", err)
}
// Do some simple code generation and templating
output := source
output = strings.Replace(output, "IMPORTS", makeImports(builders, provisioners, postProcessors), 1)
output = strings.Replace(output, "IMPORTS", makeImports(builders, provisioners, postProcessors, datasources), 1)
output = strings.Replace(output, "BUILDERS", makeMap("Builders", "Builder", builders), 1)
output = strings.Replace(output, "PROVISIONERS", makeMap("Provisioners", "Provisioner", provisioners), 1)
output = strings.Replace(output, "POSTPROCESSORS", makeMap("PostProcessors", "PostProcessor", postProcessors), 1)
output = strings.Replace(output, "DATASOURCES", makeMap("Datasources", "Datasource", datasources), 1)
// TODO sort the lists of plugins so we are not subjected to random OS ordering of the plugin lists
// TODO format the file
@ -105,7 +111,7 @@ func makeMap(varName, varType string, items []plugin) string {
return output
}
func makeImports(builders, provisioners, postProcessors []plugin) string {
func makeImports(builders, provisioners, postProcessors, Datasources []plugin) string {
plugins := []string{}
for _, builder := range builders {
@ -120,6 +126,10 @@ func makeImports(builders, provisioners, postProcessors []plugin) string {
plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/packer/%s\"\n", postProcessor.ImportName, filepath.ToSlash(postProcessor.Path)))
}
for _, datasource := range Datasources {
plugins = append(plugins, fmt.Sprintf("\t%s \"github.com/hashicorp/packer/%s\"\n", datasource.ImportName, filepath.ToSlash(datasource.Path)))
}
// Make things pretty
sort.Strings(plugins)
@ -229,6 +239,12 @@ func discoverBuilders() ([]plugin, error) {
return discoverTypesInPath(path, typeID)
}
func discoverDatasources() ([]plugin, error) {
path := "./datasource"
typeID := "Datasource"
return discoverTypesInPath(path, typeID)
}
func discoverProvisioners() ([]plugin, error) {
path := "./provisioner"
typeID := "Provisioner"
@ -270,7 +286,9 @@ PROVISIONERS
POSTPROCESSORS
var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner)-(.+)")
DATASOURCES
var pluginRegexp = regexp.MustCompile("packer-(builder|post-processor|provisioner|datasource)-(.+)")
func (c *PluginCommand) Run(args []string) int {
// This is an internal call (users should not call this directly) so we're
@ -319,6 +337,13 @@ func (c *PluginCommand) Run(args []string) int {
return 1
}
server.RegisterPostProcessor(postProcessor)
case "datasource":
datasource, found := Datasources[pluginName]
if !found {
c.Ui.Error(fmt.Sprintf("Could not load datasource: %s", pluginName))
return 1
}
server.RegisterDatasource(datasource)
}
server.Serve()

View File

@ -0,0 +1,102 @@
package acctest
import (
"bytes"
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"testing"
)
// DatasourceTestCase is a single set of tests to run for a data source.
// A DatasourceTestCase should generally map 1:1 to each test method for your
// acceptance tests.
type DatasourceTestCase struct {
// Check is called after this step is executed in order to test that
// the step executed successfully. If this is not set, then the next
// step will be called
Check func(*exec.Cmd, string) error
// Name is the name of the test case. Be simple but unique and descriptive.
Name string
// Setup, if non-nil, will be called once before the test case
// runs. This can be used for some setup like setting environment
// variables, or for validation prior to the
// test running. For example, you can use this to make sure certain
// binaries are installed, or text fixtures are in place.
Setup func() error
// Teardown will be called before the test case is over regardless
// of if the test succeeded or failed. This should return an error
// in the case that the test can't guarantee all resources were
// properly cleaned up.
Teardown TestTeardownFunc
// Template is the testing HCL2 template to use.
Template string
// Type is the type of data source.
Type string
}
//nolint:errcheck
func TestDatasource(t *testing.T, testCase *DatasourceTestCase) {
if os.Getenv(TestEnvVar) == "" {
t.Skip(fmt.Sprintf(
"Acceptance tests skipped unless env '%s' set",
TestEnvVar))
return
}
logfile := fmt.Sprintf("packer_log_%s.txt", testCase.Name)
templatePath := fmt.Sprintf("./%s.pkr.hcl", testCase.Name)
// Write config hcl2 template
out := bytes.NewBuffer(nil)
fmt.Fprintf(out, testCase.Template)
outputFile, err := os.Create(templatePath)
if err != nil {
t.Fatalf("bad: failed to create template file: %s", err.Error())
}
_, err = outputFile.Write(out.Bytes())
if err != nil {
t.Fatalf("bad: failed to write template file: %s", err.Error())
}
outputFile.Sync()
// Make sure packer is installed:
packerbin, err := exec.LookPath("packer")
if err != nil {
t.Fatalf("Couldn't find packer binary installed on system: %s", err.Error())
}
// Run build
buildCommand := exec.Command(packerbin, "build", "--machine-readable", templatePath)
buildCommand.Env = append(buildCommand.Env, os.Environ()...)
buildCommand.Env = append(buildCommand.Env, "PACKER_LOG=1",
fmt.Sprintf("PACKER_LOG_PATH=%s", logfile))
buildCommand.Run()
// Check for test custom pass/fail before we clean up
var checkErr error
if testCase.Check != nil {
checkErr = testCase.Check(buildCommand, logfile)
}
// Clean up anything created in data source run
if testCase.Teardown != nil {
cleanErr := testCase.Teardown()
if cleanErr != nil {
log.Printf("bad: failed to clean up test-created resources: %s", cleanErr.Error())
}
}
// Fail test if check failed.
if checkErr != nil {
cwd, _ := os.Getwd()
t.Fatalf(fmt.Sprintf("Error running data source acceptance"+
" tests: %s\nLogs can be found at %s\nand the "+
"acceptance test template can be found at %s",
checkErr.Error(), filepath.Join(cwd, logfile),
filepath.Join(cwd, templatePath)))
} else {
os.Remove(templatePath)
os.Remove(logfile)
}
}

View File

@ -0,0 +1,4 @@
/*
Package hcl2helper provides helper functions for parsing or getting hcl2 types to and from a Packer plugin config.
*/
package hcl2helper

View File

@ -0,0 +1,40 @@
//go:generate mapstructure-to-hcl2 -type MockConfig,NestedMockConfig,MockTag
package hcl2helper
import (
"time"
"github.com/hashicorp/packer-plugin-sdk/template/config"
)
type NestedMockConfig struct {
String string `mapstructure:"string"`
Int int `mapstructure:"int"`
Int64 int64 `mapstructure:"int64"`
Bool bool `mapstructure:"bool"`
Trilean config.Trilean `mapstructure:"trilean"`
Duration time.Duration `mapstructure:"duration"`
MapStringString map[string]string `mapstructure:"map_string_string"`
SliceString []string `mapstructure:"slice_string"`
SliceSliceString [][]string `mapstructure:"slice_slice_string"`
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string"`
NamedString NamedString `mapstructure:"named_string"`
Tags []MockTag `mapstructure:"tag"`
Datasource string `mapstructure:"data_source"`
}
type MockTag struct {
Key string `mapstructure:"key"`
Value string `mapstructure:"value"`
}
type MockConfig struct {
NotSquashed string `mapstructure:"not_squashed"`
NestedMockConfig `mapstructure:",squash"`
Nested NestedMockConfig `mapstructure:"nested"`
NestedSlice []NestedMockConfig `mapstructure:"nested_slice"`
}
type NamedMapStringString map[string]string
type NamedString string

View File

@ -0,0 +1,133 @@
// Code generated by "mapstructure-to-hcl2 -type MockConfig,NestedMockConfig,MockTag"; DO NOT EDIT.
package hcl2helper
import (
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/zclconf/go-cty/cty"
)
// FlatMockConfig is an auto-generated flat version of MockConfig.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatMockConfig struct {
NotSquashed *string `mapstructure:"not_squashed" cty:"not_squashed" hcl:"not_squashed"`
String *string `mapstructure:"string" cty:"string" hcl:"string"`
Int *int `mapstructure:"int" cty:"int" hcl:"int"`
Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
Nested *FlatNestedMockConfig `mapstructure:"nested" cty:"nested" hcl:"nested"`
NestedSlice []FlatNestedMockConfig `mapstructure:"nested_slice" cty:"nested_slice" hcl:"nested_slice"`
}
// FlatMapstructure returns a new FlatMockConfig.
// FlatMockConfig is an auto-generated flat version of MockConfig.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*MockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatMockConfig)
}
// HCL2Spec returns the hcl spec of a MockConfig.
// This spec is used by HCL to read the fields of MockConfig.
// The decoded values from this spec will then be applied to a FlatMockConfig.
func (*FlatMockConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"not_squashed": &hcldec.AttrSpec{Name: "not_squashed", Type: cty.String, Required: false},
"string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
"int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
"int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
"bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
"trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
"duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
"map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
"slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
"slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
"named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
"named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
"data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
"nested": &hcldec.BlockSpec{TypeName: "nested", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
"nested_slice": &hcldec.BlockListSpec{TypeName: "nested_slice", Nested: hcldec.ObjectSpec((*FlatNestedMockConfig)(nil).HCL2Spec())},
}
return s
}
// FlatMockTag is an auto-generated flat version of MockTag.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatMockTag struct {
Key *string `mapstructure:"key" cty:"key" hcl:"key"`
Value *string `mapstructure:"value" cty:"value" hcl:"value"`
}
// FlatMapstructure returns a new FlatMockTag.
// FlatMockTag is an auto-generated flat version of MockTag.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*MockTag) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatMockTag)
}
// HCL2Spec returns the hcl spec of a MockTag.
// This spec is used by HCL to read the fields of MockTag.
// The decoded values from this spec will then be applied to a FlatMockTag.
func (*FlatMockTag) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"key": &hcldec.AttrSpec{Name: "key", Type: cty.String, Required: false},
"value": &hcldec.AttrSpec{Name: "value", Type: cty.String, Required: false},
}
return s
}
// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatNestedMockConfig struct {
String *string `mapstructure:"string" cty:"string" hcl:"string"`
Int *int `mapstructure:"int" cty:"int" hcl:"int"`
Int64 *int64 `mapstructure:"int64" cty:"int64" hcl:"int64"`
Bool *bool `mapstructure:"bool" cty:"bool" hcl:"bool"`
Trilean *bool `mapstructure:"trilean" cty:"trilean" hcl:"trilean"`
Duration *string `mapstructure:"duration" cty:"duration" hcl:"duration"`
MapStringString map[string]string `mapstructure:"map_string_string" cty:"map_string_string" hcl:"map_string_string"`
SliceString []string `mapstructure:"slice_string" cty:"slice_string" hcl:"slice_string"`
SliceSliceString [][]string `mapstructure:"slice_slice_string" cty:"slice_slice_string" hcl:"slice_slice_string"`
NamedMapStringString NamedMapStringString `mapstructure:"named_map_string_string" cty:"named_map_string_string" hcl:"named_map_string_string"`
NamedString *NamedString `mapstructure:"named_string" cty:"named_string" hcl:"named_string"`
Tags []FlatMockTag `mapstructure:"tag" cty:"tag" hcl:"tag"`
Datasource *string `mapstructure:"data_source" cty:"data_source" hcl:"data_source"`
}
// FlatMapstructure returns a new FlatNestedMockConfig.
// FlatNestedMockConfig is an auto-generated flat version of NestedMockConfig.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*NestedMockConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatNestedMockConfig)
}
// HCL2Spec returns the hcl spec of a NestedMockConfig.
// This spec is used by HCL to read the fields of NestedMockConfig.
// The decoded values from this spec will then be applied to a FlatNestedMockConfig.
func (*FlatNestedMockConfig) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"string": &hcldec.AttrSpec{Name: "string", Type: cty.String, Required: false},
"int": &hcldec.AttrSpec{Name: "int", Type: cty.Number, Required: false},
"int64": &hcldec.AttrSpec{Name: "int64", Type: cty.Number, Required: false},
"bool": &hcldec.AttrSpec{Name: "bool", Type: cty.Bool, Required: false},
"trilean": &hcldec.AttrSpec{Name: "trilean", Type: cty.Bool, Required: false},
"duration": &hcldec.AttrSpec{Name: "duration", Type: cty.String, Required: false},
"map_string_string": &hcldec.AttrSpec{Name: "map_string_string", Type: cty.Map(cty.String), Required: false},
"slice_string": &hcldec.AttrSpec{Name: "slice_string", Type: cty.List(cty.String), Required: false},
"slice_slice_string": &hcldec.AttrSpec{Name: "slice_slice_string", Type: cty.List(cty.List(cty.String)), Required: false},
"named_map_string_string": &hcldec.AttrSpec{Name: "named_map_string_string", Type: cty.Map(cty.String), Required: false},
"named_string": &hcldec.AttrSpec{Name: "named_string", Type: cty.String, Required: false},
"tag": &hcldec.BlockListSpec{TypeName: "tag", Nested: hcldec.ObjectSpec((*FlatMockTag)(nil).HCL2Spec())},
"data_source": &hcldec.AttrSpec{Name: "data_source", Type: cty.String, Required: false},
}
return s
}

View File

@ -0,0 +1,131 @@
package hcl2helper
import (
"fmt"
"time"
"github.com/hashicorp/hcl/v2/hcldec"
"github.com/hashicorp/packer-plugin-sdk/template/config"
"github.com/mitchellh/mapstructure"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
)
// UnknownVariableValue is a sentinel value that can be used
// to denote that the value of a variable is unknown at this time.
// RawConfig uses this information to build up data about
// unknown keys.
const UnknownVariableValue = "74D93920-ED26-11E3-AC10-0800200C9A66"
// HCL2ValueFromConfigValue takes a value turns it into
// a cty.Value so it can be used within, for example, an HCL2 EvalContext.
func HCL2ValueFromConfigValue(v interface{}) cty.Value {
if v == nil {
return cty.NullVal(cty.DynamicPseudoType)
}
if v == UnknownVariableValue {
return cty.DynamicVal
}
switch tv := v.(type) {
case bool:
return cty.BoolVal(tv)
case string:
return cty.StringVal(tv)
case int:
return cty.NumberIntVal(int64(tv))
case float64:
return cty.NumberFloatVal(tv)
case []interface{}:
vals := make([]cty.Value, len(tv))
for i, ev := range tv {
vals[i] = HCL2ValueFromConfigValue(ev)
}
return cty.TupleVal(vals)
case []string:
vals := make([]cty.Value, len(tv))
for i, ev := range tv {
vals[i] = cty.StringVal(ev)
}
return cty.ListVal(vals)
case map[string]interface{}:
vals := map[string]cty.Value{}
for k, ev := range tv {
vals[k] = HCL2ValueFromConfigValue(ev)
}
return cty.ObjectVal(vals)
default:
// HCL/HIL should never generate anything that isn't caught by
// the above, so if we get here something has gone very wrong.
panic(fmt.Errorf("can't convert %#v to cty.Value", v))
}
}
// HCL2ValueFromConfig takes a struct with it's map of hcldec.Spec, and turns it into
// a cty.Value so it can be used as, for example, a Datasource value.
func HCL2ValueFromConfig(conf interface{}, configSpec map[string]hcldec.Spec) cty.Value {
c := map[string]interface{}{}
if err := mapstructure.Decode(conf, &c); err != nil {
panic(fmt.Errorf("can't convert %#v to cty.Value", conf))
}
// Use the HCL2Spec to know the expected cty.Type for an attribute
resp := map[string]cty.Value{}
for k, v := range c {
spec := configSpec[k]
switch st := spec.(type) {
case *hcldec.BlockListSpec:
// This should be a slice of objects, so we need to take a special care
if hcldec.ImpliedType(st.Nested).IsObjectType() {
res := []cty.Value{}
c := []interface{}{}
if err := mapstructure.Decode(v, &c); err != nil {
panic(fmt.Errorf("can't convert %#v to cty.Value", conf))
}
types := hcldec.ChildBlockTypes(spec)
for _, e := range c {
res = append(res, HCL2ValueFromConfig(e, types[k].(hcldec.ObjectSpec)))
}
if len(res) != 0 {
resp[k] = cty.ListVal(res)
continue
}
// At this point this is an empty list so we want it to go to gocty.ToCtyValue(v, impT)
// and make it a NullVal
}
}
impT := hcldec.ImpliedType(spec)
if value, err := gocty.ToCtyValue(v, impT); err == nil {
resp[k] = value
continue
}
// Uncommon types not caught until now
switch tv := v.(type) {
case config.Trilean:
resp[k] = cty.BoolVal(tv.True())
continue
case time.Duration:
if tv.Microseconds() == int64(0) {
resp[k] = cty.NumberIntVal(int64(0))
continue
}
resp[k] = cty.NumberIntVal(v.(time.Duration).Milliseconds())
continue
}
// This is a nested object and we should recursively go through the same process
if impT.IsObjectType() {
types := hcldec.ChildBlockTypes(spec)
resp[k] = HCL2ValueFromConfig(v, types[k].(hcldec.ObjectSpec))
continue
}
panic("not supported type - contact the Packer team with further information")
}
// This is decoding structs so it will always be an cty.ObjectVal at the end
return cty.ObjectVal(resp)
}

View File

@ -13,12 +13,12 @@ import (
var GitCommit string
// Package version helps plugin creators set and track the sdk version using
const Version = "0.0.6"
const Version = "0.0.7"
// A pre-release marker for the version. If this is "" (empty string)
// then it means that it is a final release. Otherwise, this is a pre-release
// such as "dev" (in development), "beta", "rc1", etc.
const VersionPrerelease = "dev"
const VersionPrerelease = ""
// InitializePluginVersion initializes the SemVer and returns a version var.
// If the provided "version" string is not valid, the call to version.Must

3
vendor/modules.txt vendored
View File

@ -355,7 +355,7 @@ github.com/hashicorp/hcl/v2/hclparse
github.com/hashicorp/hcl/v2/hclsyntax
github.com/hashicorp/hcl/v2/hclwrite
github.com/hashicorp/hcl/v2/json
# github.com/hashicorp/packer-plugin-sdk v0.0.7-0.20210111224258-fd30ebb797f0
# github.com/hashicorp/packer-plugin-sdk v0.0.7
github.com/hashicorp/packer-plugin-sdk/acctest
github.com/hashicorp/packer-plugin-sdk/acctest/provisioneracc
github.com/hashicorp/packer-plugin-sdk/acctest/testutils
@ -368,6 +368,7 @@ github.com/hashicorp/packer-plugin-sdk/communicator/ssh
github.com/hashicorp/packer-plugin-sdk/communicator/sshkey
github.com/hashicorp/packer-plugin-sdk/filelock
github.com/hashicorp/packer-plugin-sdk/guestexec
github.com/hashicorp/packer-plugin-sdk/hcl2helper
github.com/hashicorp/packer-plugin-sdk/json
github.com/hashicorp/packer-plugin-sdk/multistep
github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps