Compare commits

...

23 Commits

Author SHA1 Message Date
Adrien Delorme acb194c4a6 WIP 2021-02-11 14:02:36 +01:00
Adrien Delorme ffbb110167 Test running plugins with fake and fresh plugins (#10595)
* show error as to why plugin discovery failed
* allow to run more manual tests after a plugin installation
* test that a freshly installed external plugin can run
2021-02-09 17:07:59 +01:00
mflorin 9afaa5a21f Profitbricks builder fixes (#10549) 2021-02-09 16:56:06 +01:00
Sylvia Moss f5006d0842 fix empty locals and source name with blank space (#10593) 2021-02-09 14:57:42 +01:00
Jessi 88c516b2d5 Add IMDSv2 support for AWS EBS builder (#10546) 2021-02-09 11:47:54 +01:00
Bryce Kalow d7bb60ea86 website: update next and nextjs-scripts (#10570)
website: update next and nextjs-scripts
2021-02-08 14:48:35 -06:00
Megan Marsh 08e67f8990 Merge pull request #10587 from hashicorp/azr_doc_init_less_highlights
Document init with less highlights
2021-02-08 11:09:04 -08:00
Wilken Rivera 8c3b3ca00f Update website/content/docs/commands/init.mdx 2021-02-08 13:34:14 -05:00
Bryce Kalow 4a686ef66d chore: upgrade nextjs-scripts & next 2021-02-08 17:47:18 +00:00
Sylvia Moss f616955ebc Fix issue when loading datasource single plugin type (#10589) 2021-02-08 13:58:35 +01:00
Adrien Delorme a1b2e71005 Update website/content/docs/commands/init.mdx
Co-authored-by: Sylvia Moss <moss@hashicorp.com>
2021-02-08 13:53:29 +01:00
Sylvia Moss d53488db68 Add aws_secretsmanager transformation to hcl2_upgrade (#10553) 2021-02-08 11:28:26 +01:00
Adrien Delorme b6cfe16444 Document the PKR_GITHUB_API_TOKEN setting in /configure#env vars 2021-02-08 10:59:04 +01:00
Adrien Delorme 4c02123142 init documentation: have less highlights and more text 2021-02-08 10:58:14 +01:00
Megan Marsh 13320650f0 document builder id of artifact for each builder's output on website (#10580)
* document builder id of artifact for each builder's output on website

* document postprocessor artifact ids on website

* Fix links to new communicator page

Co-authored-by: Wilken Rivera <dev@wilkenrivera.com>
2021-02-05 19:49:28 -05:00
Megan Marsh 2324f433f7 Merge pull request #10579 from hashicorp/fix-single-plugin-loading
Fix issue when loading single plugin type `packer-provisioner-comment` built with latest SDK
2021-02-05 14:06:27 -08:00
Megan Marsh ece5e94c3d remove dev line (#10578) 2021-02-05 16:47:41 -05:00
Wilken Rivera ad239bd2b9 Fix markdown link checker issues (#10575)
* Remove exclusions for docs on master

* Update extending redirects with new page locations

* Update documentation links for SaltStack
2021-02-05 16:46:53 -05:00
Wilken Rivera 39d550054d Fix lint errors 2021-02-05 16:46:24 -05:00
Wilken Rivera ef4d35097b Fix issue when loading single plugin type
This changes wraps the plugin client start call with an anonymous function so that Packer starts a
new plugin for each occurrence of a particular plugin block.

Before only one subprocess was being created causing subsquent calls to fail as it was trying start
an already started plugin subprocess.

Before Change
```
???????: failed loading comment: error dial unix /tmp/packer-plugin358226172: connect: no such file or directory
2021/02/05 16:09:13 On error:
2021/02/05 16:09:13 Waiting on builds to complete...

2021/02/05 16:09:13 Starting build run: null.basic-example
2021/02/05 16:09:13 Running builder:
2021/02/05 16:09:13 [INFO] (telemetry) Starting builder
  on examples/basic-example.pkr.hcl line 29:
  (source code not available)

dial unix /tmp/packer-plugin358226172: connect: no such file or directory

???????: failed loading comment: error dial unix /tmp/packer-plugin358226172: connect: no such file or directory

2021/02/05 16:09:13 packer.test plugin: [INFO] communicator disabled, will not connect
2021/02/05 16:09:13 packer.test plugin: Unable to load communicator config from state to populate provisionHookData
  on examples/basic-example.pkr.hcl line 38:
2021/02/05 16:09:13 packer.test plugin: Running the provision hook
  (source code not available)

dial unix /tmp/packer-plugin358226172: connect: no such file or directory

???????: failed loading comment: error dial unix /tmp/packer-plugin358226172: connect: no such file or directory

  on examples/basic-example.pkr.hcl line 42:
  (source code not available)

2021/02/05 16:09:13 [INFO] (telemetry) Starting provisioner comment
dial unix /tmp/packer-plugin358226172: connect: no such file or directory
```

After change
```

null.basic-example: output will be in this color.

==> null.basic-example:   ____                   _
==> null.basic-example:  | __ )    ___    __ _  (_)  _ __
==> null.basic-example:  |  _ \   / _ \  / _` | | | | '_ \
==> null.basic-example:  | |_) | |  __/ | (_| | | | | | | |
==> null.basic-example:  |____/   \___|  \__, | |_| |_| |_|
==> null.basic-example:                  |___/
==> null.basic-example:
==> null.basic-example: Running local shell script: /tmp/packer-shell646549657
    null.basic-example: This is a shell script
==> null.basic-example: Pausing at breakpoint provisioner.
==> null.basic-example: Press enter to continue.
==> null.basic-example: In the middle of Provisioning run
==> null.basic-example: Running local shell script: /tmp/packer-shell177279484
    null.basic-example: This is another shell script
==> null.basic-example:   _____               _
==> null.basic-example:  | ____|  _ __     __| |
==> null.basic-example:  |  _|   | '_ \   / _` |
==> null.basic-example:  | |___  | | | | | (_| |
==> null.basic-example:  |_____| |_| |_|  \__,_|
==> null.basic-example:
Build 'null.basic-example' finished after 1 second 32 milliseconds.

==> Wait completed after 1 second 32 milliseconds

==> Builds finished. The artifacts of successful builds are:
--> null.basic-example: Did not export anything. This is the null builder
 Please enter the commit message for your changes. Lines starting
```
2021-02-05 16:35:01 -05:00
Megan Marsh a63ad19b0c Merge pull request #10577 from hashicorp/fix_build_run_diags
plugin loading failure should be considered an error so build will no…
2021-02-05 13:31:40 -08:00
Megan Marsh ca123721a6 plugin loading failure should be considered an error so build will not try to run 2021-02-05 11:06:52 -08:00
Alex Chan 540effbbc0 Correct the spelling of heirarchical/hierarchical (#10576) 2021-02-05 16:32:28 +01:00
114 changed files with 2701 additions and 21506 deletions
+45 -1
View File
@@ -1,5 +1,5 @@
//go:generate struct-markdown
//go:generate mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement
//go:generate mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement,MetadataOptions
package common
@@ -44,6 +44,20 @@ type SecurityGroupFilterOptions struct {
config.NameValueFilter `mapstructure:",squash"`
}
// Configures the metadata options.
// See [Configure IMDS](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/configuring-instance-metadata-service.html) for details.
type MetadataOptions struct {
// A string to enable or disble the IMDS endpoint for an instance. Defaults to enabled.
// Accepts either "enabled" or "disabled"
HttpEndpoint string `mapstructure:"http_endpoint" required:"false"`
// A string to either set the use of IMDSv2 for the instance to optional or required. Defaults to "optional".
// Accepts either "optional" or "required"
HttpTokens string `mapstructure:"http_tokens" required:"false"`
// A numerical value to set an upper limit for the amount of hops allowed when communicating with IMDS endpoints.
// Defaults to 1.
HttpPutResponseHopLimit int64 `mapstructure:"http_put_response_hop_limit" required:"false"`
}
// RunConfig contains configuration for running an instance from a source
// AMI and details on how to access that launched image.
type RunConfig struct {
@@ -426,6 +440,9 @@ type RunConfig struct {
// 10m
WindowsPasswordTimeout time.Duration `mapstructure:"windows_password_timeout" required:"false"`
// [Metadata Settings](#metadata-settings)
Metadata MetadataOptions `mapstructure:"metadata_options" required:"false"`
// Communicator settings
Comm communicator.Config `mapstructure:",squash"`
@@ -486,6 +503,33 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error {
// Validation
errs := c.Comm.Prepare(ctx)
if c.Metadata.HttpEndpoint == "" {
c.Metadata.HttpEndpoint = "enabled"
}
if c.Metadata.HttpTokens == "" {
c.Metadata.HttpTokens = "optional"
}
if c.Metadata.HttpPutResponseHopLimit == 0 {
c.Metadata.HttpPutResponseHopLimit = 1
}
if c.Metadata.HttpEndpoint != "enabled" && c.Metadata.HttpEndpoint != "disabled" {
msg := fmt.Errorf("http_endpoint requires either disabled or enabled as its value")
errs = append(errs, msg)
}
if c.Metadata.HttpTokens != "optional" && c.Metadata.HttpTokens != "required" {
msg := fmt.Errorf("http_tokens requires either optional or required as its value")
errs = append(errs, msg)
}
if c.Metadata.HttpPutResponseHopLimit < 1 || c.Metadata.HttpPutResponseHopLimit > 64 {
msg := fmt.Errorf("http_put_response_hop_limit requires a number between 1 and 64")
errs = append(errs, msg)
}
// Copy singular tag maps
errs = append(errs, c.RunTag.CopyOn(&c.RunTags)...)
errs = append(errs, c.SpotTag.CopyOn(&c.SpotTags)...)
+28 -1
View File
@@ -1,4 +1,4 @@
// Code generated by "mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement"; DO NOT EDIT.
// Code generated by "mapstructure-to-hcl2 -type AmiFilterOptions,SecurityGroupFilterOptions,SubnetFilterOptions,VpcFilterOptions,PolicyDocument,Statement,MetadataOptions"; DO NOT EDIT.
package common
@@ -35,6 +35,33 @@ func (*FlatAmiFilterOptions) HCL2Spec() map[string]hcldec.Spec {
return s
}
// FlatMetadataOptions is an auto-generated flat version of MetadataOptions.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatMetadataOptions struct {
HttpEndpoint *string `mapstructure:"http_endpoint" required:"false" cty:"http_endpoint" hcl:"http_endpoint"`
HttpTokens *string `mapstructure:"http_tokens" required:"false" cty:"http_tokens" hcl:"http_tokens"`
HttpPutResponseHopLimit *int64 `mapstructure:"http_put_response_hop_limit" required:"false" cty:"http_put_response_hop_limit" hcl:"http_put_response_hop_limit"`
}
// FlatMapstructure returns a new FlatMetadataOptions.
// FlatMetadataOptions is an auto-generated flat version of MetadataOptions.
// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up.
func (*MetadataOptions) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } {
return new(FlatMetadataOptions)
}
// HCL2Spec returns the hcl spec of a MetadataOptions.
// This spec is used by HCL to read the fields of MetadataOptions.
// The decoded values from this spec will then be applied to a FlatMetadataOptions.
func (*FlatMetadataOptions) HCL2Spec() map[string]hcldec.Spec {
s := map[string]hcldec.Spec{
"http_endpoint": &hcldec.AttrSpec{Name: "http_endpoint", Type: cty.String, Required: false},
"http_tokens": &hcldec.AttrSpec{Name: "http_tokens", Type: cty.String, Required: false},
"http_put_response_hop_limit": &hcldec.AttrSpec{Name: "http_put_response_hop_limit", Type: cty.Number, Required: false},
}
return s
}
// FlatPolicyDocument is an auto-generated flat version of PolicyDocument.
// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up.
type FlatPolicyDocument struct {
@@ -29,6 +29,9 @@ type StepRunSourceInstance struct {
EbsOptimized bool
EnableT2Unlimited bool
ExpectedRootDevice string
HttpEndpoint string
HttpTokens string
HttpPutResponseHopLimit int64
InstanceInitiatedShutdownBehavior string
InstanceType string
IsRestricted bool
@@ -144,6 +147,10 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
runOpts.CreditSpecification = &ec2.CreditSpecificationRequest{CpuCredits: &creditOption}
}
if s.HttpEndpoint == "enabled" {
runOpts.MetadataOptions = &ec2.InstanceMetadataOptionsRequest{HttpEndpoint: &s.HttpEndpoint, HttpTokens: &s.HttpTokens, HttpPutResponseHopLimit: &s.HttpPutResponseHopLimit}
}
// Collect tags for tagging on resource creation
var tagSpecs []*ec2.TagSpecification
@@ -34,6 +34,9 @@ type StepRunSpotInstance struct {
Comm *communicator.Config
EbsOptimized bool
ExpectedRootDevice string
HttpEndpoint string
HttpTokens string
HttpPutResponseHopLimit int64
InstanceInitiatedShutdownBehavior string
InstanceType string
Region string
@@ -127,6 +130,10 @@ func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string,
}
if s.HttpEndpoint == "enabled" {
templateData.MetadataOptions = &ec2.LaunchTemplateInstanceMetadataOptionsRequest{HttpEndpoint: &s.HttpEndpoint, HttpTokens: &s.HttpTokens, HttpPutResponseHopLimit: &s.HttpPutResponseHopLimit}
}
// If instance type is not set, we'll just pick the lowest priced instance
// available.
if s.InstanceType != "" {
+6
View File
@@ -187,6 +187,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
ExpectedRootDevice: "ebs",
HttpEndpoint: b.config.Metadata.HttpEndpoint,
HttpTokens: b.config.Metadata.HttpTokens,
HttpPutResponseHopLimit: b.config.Metadata.HttpPutResponseHopLimit,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
Region: *ec2conn.Config.Region,
@@ -211,6 +214,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
EbsOptimized: b.config.EbsOptimized,
EnableT2Unlimited: b.config.EnableT2Unlimited,
ExpectedRootDevice: "ebs",
HttpEndpoint: b.config.Metadata.HttpEndpoint,
HttpTokens: b.config.Metadata.HttpTokens,
HttpPutResponseHopLimit: b.config.Metadata.HttpPutResponseHopLimit,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
+2
View File
@@ -90,6 +90,7 @@ type FlatConfig struct {
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
Metadata *common.FlatMetadataOptions `mapstructure:"metadata_options" required:"false" cty:"metadata_options" hcl:"metadata_options"`
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
@@ -240,6 +241,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"vpc_filter": &hcldec.BlockSpec{TypeName: "vpc_filter", Nested: hcldec.ObjectSpec((*common.FlatVpcFilterOptions)(nil).HCL2Spec())},
"vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false},
"windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false},
"metadata_options": &hcldec.BlockSpec{TypeName: "metadata_options", Nested: hcldec.ObjectSpec((*common.FlatMetadataOptions)(nil).HCL2Spec())},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
+6
View File
@@ -207,6 +207,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
ExpectedRootDevice: "ebs",
HttpEndpoint: b.config.Metadata.HttpEndpoint,
HttpTokens: b.config.Metadata.HttpTokens,
HttpPutResponseHopLimit: b.config.Metadata.HttpPutResponseHopLimit,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
Region: *ec2conn.Config.Region,
@@ -230,6 +233,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
EbsOptimized: b.config.EbsOptimized,
EnableT2Unlimited: b.config.EnableT2Unlimited,
ExpectedRootDevice: "ebs",
HttpEndpoint: b.config.Metadata.HttpEndpoint,
HttpTokens: b.config.Metadata.HttpTokens,
HttpPutResponseHopLimit: b.config.Metadata.HttpPutResponseHopLimit,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
@@ -113,6 +113,7 @@ type FlatConfig struct {
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
Metadata *common.FlatMetadataOptions `mapstructure:"metadata_options" required:"false" cty:"metadata_options" hcl:"metadata_options"`
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
@@ -263,6 +264,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"vpc_filter": &hcldec.BlockSpec{TypeName: "vpc_filter", Nested: hcldec.ObjectSpec((*common.FlatVpcFilterOptions)(nil).HCL2Spec())},
"vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false},
"windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false},
"metadata_options": &hcldec.BlockSpec{TypeName: "metadata_options", Nested: hcldec.ObjectSpec((*common.FlatMetadataOptions)(nil).HCL2Spec())},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
+6
View File
@@ -195,6 +195,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
Debug: b.config.PackerDebug,
EbsOptimized: b.config.EbsOptimized,
ExpectedRootDevice: "ebs",
HttpEndpoint: b.config.Metadata.HttpEndpoint,
HttpTokens: b.config.Metadata.HttpTokens,
HttpPutResponseHopLimit: b.config.Metadata.HttpPutResponseHopLimit,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
Region: *ec2conn.Config.Region,
@@ -218,6 +221,9 @@ func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook)
EbsOptimized: b.config.EbsOptimized,
EnableT2Unlimited: b.config.EnableT2Unlimited,
ExpectedRootDevice: "ebs",
HttpEndpoint: b.config.Metadata.HttpEndpoint,
HttpTokens: b.config.Metadata.HttpTokens,
HttpPutResponseHopLimit: b.config.Metadata.HttpPutResponseHopLimit,
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
InstanceType: b.config.InstanceType,
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
@@ -115,6 +115,7 @@ type FlatConfig struct {
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
Metadata *common.FlatMetadataOptions `mapstructure:"metadata_options" required:"false" cty:"metadata_options" hcl:"metadata_options"`
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
@@ -242,6 +243,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"vpc_filter": &hcldec.BlockSpec{TypeName: "vpc_filter", Nested: hcldec.ObjectSpec((*common.FlatVpcFilterOptions)(nil).HCL2Spec())},
"vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false},
"windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false},
"metadata_options": &hcldec.BlockSpec{TypeName: "metadata_options", Nested: hcldec.ObjectSpec((*common.FlatMetadataOptions)(nil).HCL2Spec())},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
@@ -90,6 +90,7 @@ type FlatConfig struct {
VpcFilter *common.FlatVpcFilterOptions `mapstructure:"vpc_filter" required:"false" cty:"vpc_filter" hcl:"vpc_filter"`
VpcId *string `mapstructure:"vpc_id" required:"false" cty:"vpc_id" hcl:"vpc_id"`
WindowsPasswordTimeout *string `mapstructure:"windows_password_timeout" required:"false" cty:"windows_password_timeout" hcl:"windows_password_timeout"`
Metadata *common.FlatMetadataOptions `mapstructure:"metadata_options" required:"false" cty:"metadata_options" hcl:"metadata_options"`
Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"`
PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"`
SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"`
@@ -245,6 +246,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"vpc_filter": &hcldec.BlockSpec{TypeName: "vpc_filter", Nested: hcldec.ObjectSpec((*common.FlatVpcFilterOptions)(nil).HCL2Spec())},
"vpc_id": &hcldec.AttrSpec{Name: "vpc_id", Type: cty.String, Required: false},
"windows_password_timeout": &hcldec.AttrSpec{Name: "windows_password_timeout", Type: cty.String, Required: false},
"metadata_options": &hcldec.BlockSpec{TypeName: "metadata_options", Nested: hcldec.ObjectSpec((*common.FlatMetadataOptions)(nil).HCL2Spec())},
"communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false},
"pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false},
"ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false},
+9 -4
View File
@@ -22,8 +22,11 @@ func (s *stepCreateServer) Run(ctx context.Context, state multistep.StateBag) mu
profitbricks.SetAuth(c.PBUsername, c.PBPassword)
profitbricks.SetDepth("5")
if sshkey, ok := state.GetOk("publicKey"); ok {
c.SSHKey = sshkey.(string)
if c.Comm.SSHPublicKey != nil {
c.SSHKey = string(c.Comm.SSHPublicKey)
} else {
ui.Error("No ssh private key set; ssh authentication won't be possible. Please specify your private key in the ssh_private_key_file configuration key.")
return multistep.ActionHalt
}
ui.Say("Creating Virtual Data Center...")
img := s.getImageId(c.Image, c)
@@ -204,7 +207,7 @@ func (d *stepCreateServer) setPB(username string, password string, url string) {
func (d *stepCreateServer) checkForErrors(instance profitbricks.Resp) error {
if instance.StatusCode > 299 {
return errors.New(fmt.Sprintf("Error occurred %s", string(instance.Body)))
return fmt.Errorf("Error occurred %s", string(instance.Body))
}
return nil
}
@@ -261,7 +264,9 @@ func (d *stepCreateServer) getImageAlias(imageAlias string, location string, ui
func parseErrorMessage(raw string) (toreturn string) {
var tmp map[string]interface{}
json.Unmarshal([]byte(raw), &tmp)
if json.Unmarshal([]byte(raw), &tmp) != nil {
return ""
}
for _, v := range tmp["messages"].([]interface{}) {
for index, i := range v.(map[string]interface{}) {
+125 -7
View File
@@ -3,6 +3,9 @@ package profitbricks
import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
"time"
"github.com/hashicorp/packer-plugin-sdk/multistep"
@@ -22,9 +25,32 @@ func (s *stepTakeSnapshot) Run(ctx context.Context, state multistep.StateBag) mu
dcId := state.Get("datacenter_id").(string)
volumeId := state.Get("volume_id").(string)
serverId := state.Get("instance_id").(string)
comm, _ := state.Get("communicator").(packersdk.Communicator)
if comm == nil {
ui.Error("no communicator found")
return multistep.ActionHalt
}
/* sync fs changes from the provisioning step */
os, err := s.getOs(dcId, serverId)
if err != nil {
ui.Error(fmt.Sprintf("an error occurred while getting the server os: %s", err.Error()))
return multistep.ActionHalt
}
ui.Say(fmt.Sprintf("Server OS is %s", os))
switch strings.ToLower(os) {
case "linux":
ui.Say("syncing file system changes")
if err := s.syncFs(ctx, comm); err != nil {
ui.Error(fmt.Sprintf("error syncing fs changes: %s", err.Error()))
return multistep.ActionHalt
}
}
snapshot := profitbricks.CreateSnapshot(dcId, volumeId, c.SnapshotName, "")
state.Put("snapshotname", c.SnapshotName)
if snapshot.StatusCode > 299 {
@@ -42,31 +68,123 @@ func (s *stepTakeSnapshot) Run(ctx context.Context, state multistep.StateBag) mu
return multistep.ActionHalt
}
s.waitTillProvisioned(snapshot.Headers.Get("Location"), *c)
ui.Say(fmt.Sprintf("Creating a snapshot for %s/volumes/%s", dcId, volumeId))
err = s.waitForRequest(snapshot.Headers.Get("Location"), *c, ui)
if err != nil {
ui.Error(fmt.Sprintf("An error occurred while waiting for the request to be done: %s", err.Error()))
return multistep.ActionHalt
}
err = s.waitTillSnapshotAvailable(snapshot.Id, *c, ui)
if err != nil {
ui.Error(fmt.Sprintf("An error occurred while waiting for the snapshot to be created: %s", err.Error()))
return multistep.ActionHalt
}
return multistep.ActionContinue
}
func (s *stepTakeSnapshot) Cleanup(state multistep.StateBag) {
func (s *stepTakeSnapshot) Cleanup(_ multistep.StateBag) {
}
func (d *stepTakeSnapshot) waitTillProvisioned(path string, config Config) {
d.setPB(config.PBUsername, config.PBPassword, config.PBUrl)
func (s *stepTakeSnapshot) waitForRequest(path string, config Config, ui packersdk.Ui) error {
ui.Say(fmt.Sprintf("Watching request %s", path))
s.setPB(config.PBUsername, config.PBPassword, config.PBUrl)
waitCount := 50
var waitInterval = 10 * time.Second
if config.Retries > 0 {
waitCount = config.Retries
}
done := false
for i := 0; i < waitCount; i++ {
request := profitbricks.GetRequestStatus(path)
ui.Say(fmt.Sprintf("request status = %s", request.Metadata.Status))
if request.Metadata.Status == "DONE" {
done = true
break
}
time.Sleep(10 * time.Second)
if request.Metadata.Status == "FAILED" {
return fmt.Errorf("Request failed: %s", request.Response)
}
time.Sleep(waitInterval)
i++
}
if done == false {
return fmt.Errorf("request not fulfilled after waiting %d seconds",
int64(waitCount)*int64(waitInterval)/int64(time.Second))
}
return nil
}
func (d *stepTakeSnapshot) setPB(username string, password string, url string) {
func (s *stepTakeSnapshot) waitTillSnapshotAvailable(id string, config Config, ui packersdk.Ui) error {
s.setPB(config.PBUsername, config.PBPassword, config.PBUrl)
waitCount := 50
var waitInterval = 10 * time.Second
if config.Retries > 0 {
waitCount = config.Retries
}
done := false
ui.Say(fmt.Sprintf("waiting for snapshot %s to become available", id))
for i := 0; i < waitCount; i++ {
snap := profitbricks.GetSnapshot(id)
ui.Say(fmt.Sprintf("snapshot status = %s", snap.Metadata.State))
if snap.StatusCode != 200 {
return fmt.Errorf("%s", snap.Response)
}
if snap.Metadata.State == "AVAILABLE" {
done = true
break
}
time.Sleep(waitInterval)
i++
ui.Say(fmt.Sprintf("... still waiting, %d seconds have passed", int64(waitInterval)*int64(i)))
}
if done == false {
return fmt.Errorf("snapshot not created after waiting %d seconds",
int64(waitCount)*int64(waitInterval)/int64(time.Second))
}
ui.Say("snapshot created")
return nil
}
func (s *stepTakeSnapshot) syncFs(ctx context.Context, comm packersdk.Communicator) error {
cmd := &packersdk.RemoteCmd{
Command: "sync",
}
if err := comm.Start(ctx, cmd); err != nil {
return err
}
if cmd.Wait() != 0 {
return fmt.Errorf("sync command exited with code %d", cmd.ExitStatus())
}
return nil
}
func (s *stepTakeSnapshot) getOs(dcId string, serverId string) (string, error) {
server := profitbricks.GetServer(dcId, serverId)
if server.StatusCode != 200 {
return "", errors.New(server.Response)
}
if server.Properties.BootVolume == nil {
return "", errors.New("no boot volume found on server")
}
volumeId := server.Properties.BootVolume.Id
volume := profitbricks.GetVolume(dcId, volumeId)
if volume.StatusCode != 200 {
return "", errors.New(volume.Response)
}
return volume.Properties.LicenceType, nil
}
func (s *stepTakeSnapshot) setPB(username string, password string, url string) {
profitbricks.SetAuth(username, password)
profitbricks.SetEndpoint(url)
}
+219 -46
View File
@@ -74,9 +74,12 @@ const (
# All generated input variables will be of 'string' type as this is how Packer JSON
# views them; you can change their type later on. Read the variables type
# constraints documentation
# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
`
# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.`
localsVarHeader = `
# All locals variables are generated from variables that uses expressions
# that are not allowed in HCL2 variables.
# Read the documentation for locals blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/locals`
packerBlockHeader = `
# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
`
@@ -93,15 +96,28 @@ const (
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
build {
`
amazonAmiDataHeader = `
# The amazon-ami data block is generated from your amazon builder source_ami_filter; a data
# from this block can be referenced in source and locals blocks.
# Read the documentation for data blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/data`
# https://www.packer.io/docs/templates/hcl_templates/blocks/data
# Read the documentation for the Amazon AMI Data Source here:
# https://www.packer.io/docs/datasources/amazon/ami`
amazonSecretsManagerDataHeader = `
# The amazon-secretsmanager data block is generated from your aws_secretsmanager template function; a data
# from this block can be referenced in source and locals blocks.
# Read the documentation for data blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/data
# Read the documentation for the Amazon Secrets Manager Data Source here:
# https://www.packer.io/docs/datasources/amazon/secretsmanager`
)
var amazonSecretsManagerMap = map[string]map[string]interface{}{}
var localsVariableMap = map[string]string{}
func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2UpgradeArgs) int {
out := &bytes.Buffer{}
var output io.Writer
if err := os.MkdirAll(filepath.Dir(cla.OutputFile), 0); err != nil {
c.Ui.Error(fmt.Sprintf("Failed to create output directory: %v", err))
@@ -131,20 +147,16 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
}
tpl := core.Template
// Packer section
if tpl.MinVersion != "" {
out.Write([]byte(packerBlockHeader))
fileContent := hclwrite.NewEmptyFile()
body := fileContent.Body()
packerBody := body.AppendNewBlock("packer", nil).Body()
packerBody.SetAttributeValue("required_version", cty.StringVal(fmt.Sprintf(">= %s", tpl.MinVersion)))
out.Write(fileContent.Bytes())
}
// OutPut Locals and Local blocks
localsContent := hclwrite.NewEmptyFile()
localsBody := localsContent.Body()
localsBody.AppendNewline()
localBody := localsBody.AppendNewBlock("locals", nil).Body()
out.Write([]byte(inputVarHeader))
localsOut := []byte{}
// Output variables section
variablesOut := []byte{}
variables := []*template.Variable{}
{
// sort variables to avoid map's randomness
@@ -157,27 +169,47 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
})
}
hasLocals := false
for _, variable := range variables {
variablesContent := hclwrite.NewEmptyFile()
variablesBody := variablesContent.Body()
variablesBody.AppendNewline()
variableBody := variablesBody.AppendNewBlock("variable", []string{variable.Key}).Body()
variableBody.SetAttributeRaw("type", hclwrite.Tokens{&hclwrite.Token{Bytes: []byte("string")}})
if variable.Default != "" || !variable.Required {
variableBody.SetAttributeValue("default", hcl2shim.HCL2ValueFromConfigValue(variable.Default))
}
sensitive := false
if isSensitiveVariable(variable.Key, tpl.SensitiveVariables) {
sensitive = true
variableBody.SetAttributeValue("sensitive", cty.BoolVal(true))
}
variablesBody.AppendNewline()
out.Write(transposeTemplatingCalls(variablesContent.Bytes()))
isLocal, out := variableTransposeTemplatingCalls(variablesContent.Bytes())
if isLocal {
if sensitive {
// Create Local block because this is sensitive
localContent := hclwrite.NewEmptyFile()
body := localContent.Body()
body.AppendNewline()
localBody := body.AppendNewBlock("local", []string{variable.Key}).Body()
localBody.SetAttributeValue("sensitive", cty.BoolVal(true))
localBody.SetAttributeValue("expression", hcl2shim.HCL2ValueFromConfigValue(variable.Default))
localsOut = append(localsOut, transposeTemplatingCalls(localContent.Bytes())...)
localsVariableMap[variable.Key] = "local"
continue
}
localBody.SetAttributeValue(variable.Key, hcl2shim.HCL2ValueFromConfigValue(variable.Default))
localsVariableMap[variable.Key] = "locals"
hasLocals = true
continue
}
variablesOut = append(variablesOut, out...)
}
fmt.Fprintln(out, `# "timestamp" template function replacement`)
fmt.Fprintln(out, `locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }`)
// Output sources section
if hasLocals {
localsOut = append(localsOut, transposeTemplatingCalls(localsContent.Bytes())...)
}
builders := []*template.Builder{}
{
@@ -187,7 +219,9 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
}
}
if err := c.writeAmazonAmiDatasource(builders, out); err != nil {
// Output amazon-ami data source section
amazonAmiOut, err := c.writeAmazonAmiDatasource(builders)
if err != nil {
return 1
}
@@ -195,8 +229,8 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
return builders[i].Type+builders[i].Name < builders[j].Type+builders[j].Name
})
out.Write([]byte(sourcesHeader))
// Output sources section
sourcesOut := []byte{}
for i, builderCfg := range builders {
sourcesContent := hclwrite.NewEmptyFile()
body := sourcesContent.Body()
@@ -209,16 +243,16 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
if builderCfg.Name == "" || builderCfg.Name == builderCfg.Type {
builderCfg.Name = fmt.Sprintf("autogenerated_%d", i+1)
}
builderCfg.Name = strings.ReplaceAll(strings.TrimSpace(builderCfg.Name), " ", "_")
sourceBody := body.AppendNewBlock("source", []string{builderCfg.Type, builderCfg.Name}).Body()
jsonBodyToHCL2Body(sourceBody, builderCfg.Config)
_, _ = out.Write(transposeTemplatingCalls(sourcesContent.Bytes()))
sourcesOut = append(sourcesOut, transposeTemplatingCalls(sourcesContent.Bytes())...)
}
// Output build section
out.Write([]byte(buildHeader))
buildContent := hclwrite.NewEmptyFile()
buildBody := buildContent.Body()
if tpl.Description != "" {
@@ -232,8 +266,10 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
}
buildBody.SetAttributeValue("sources", hcl2shim.HCL2ValueFromConfigValue(sourceNames))
buildBody.AppendNewline()
_, _ = buildContent.WriteTo(out)
buildOut := buildContent.Bytes()
// Output provisioners section
provisionersOut := []byte{}
for _, provisioner := range tpl.Provisioners {
provisionerContent := hclwrite.NewEmptyFile()
body := provisionerContent.Body()
@@ -255,8 +291,11 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
}
jsonBodyToHCL2Body(block.Body(), cfg)
out.Write(transposeTemplatingCalls(provisionerContent.Bytes()))
provisionersOut = append(provisionersOut, transposeTemplatingCalls(provisionerContent.Bytes())...)
}
// Output post-processors section
postProcessorsOut := []byte{}
for _, pps := range tpl.PostProcessors {
postProcessorContent := hclwrite.NewEmptyFile()
body := postProcessorContent.Body()
@@ -286,9 +325,69 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
jsonBodyToHCL2Body(ppBody, cfg)
}
_, _ = out.Write(transposeTemplatingCalls(postProcessorContent.Bytes()))
postProcessorsOut = append(postProcessorsOut, transposeTemplatingCalls(postProcessorContent.Bytes())...)
}
// Output amazon-secretsmanager data source section
keys := make([]string, 0, len(amazonSecretsManagerMap))
for k := range amazonSecretsManagerMap {
keys = append(keys, k)
}
sort.Strings(keys)
amazonSecretsDataOut := []byte{}
for _, dataSourceName := range keys {
datasourceContent := hclwrite.NewEmptyFile()
body := datasourceContent.Body()
body.AppendNewline()
datasourceBody := body.AppendNewBlock("data", []string{"amazon-secretsmanager", dataSourceName}).Body()
jsonBodyToHCL2Body(datasourceBody, amazonSecretsManagerMap[dataSourceName])
amazonSecretsDataOut = append(amazonSecretsDataOut, datasourceContent.Bytes()...)
}
// Write file
out := &bytes.Buffer{}
// Packer section
if tpl.MinVersion != "" {
out.Write([]byte(packerBlockHeader))
fileContent := hclwrite.NewEmptyFile()
body := fileContent.Body()
packerBody := body.AppendNewBlock("packer", nil).Body()
packerBody.SetAttributeValue("required_version", cty.StringVal(fmt.Sprintf(">= %s", tpl.MinVersion)))
out.Write(fileContent.Bytes())
}
out.Write([]byte(inputVarHeader))
out.Write(variablesOut)
if len(amazonSecretsManagerMap) > 0 {
out.Write([]byte(amazonSecretsManagerDataHeader))
out.Write(amazonSecretsDataOut)
}
if len(amazonAmiOut) > 0 {
out.Write([]byte(amazonAmiDataHeader))
out.Write(amazonAmiOut)
}
_, _ = out.Write([]byte("\n"))
fmt.Fprintln(out, `# "timestamp" template function replacement`)
fmt.Fprintln(out, `locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }`)
if len(localsOut) > 0 {
out.Write([]byte(localsVarHeader))
out.Write(localsOut)
}
out.Write([]byte(sourcesHeader))
out.Write(sourcesOut)
out.Write([]byte(buildHeader))
out.Write(buildOut)
out.Write(provisionersOut)
out.Write(postProcessorsOut)
_, _ = out.Write([]byte("}\n"))
_, _ = output.Write(hclwrite.Format(out.Bytes()))
@@ -298,9 +397,9 @@ func (c *HCL2UpgradeCommand) RunContext(buildCtx context.Context, cla *HCL2Upgra
return 0
}
func (c *HCL2UpgradeCommand) writeAmazonAmiDatasource(builders []*template.Builder, out *bytes.Buffer) error {
func (c *HCL2UpgradeCommand) writeAmazonAmiDatasource(builders []*template.Builder) ([]byte, error) {
amazonAmiOut := []byte{}
amazonAmiFilters := []map[string]interface{}{}
first := true
i := 1
for _, builder := range builders {
if strings.HasPrefix(builder.Type, "amazon-") {
@@ -308,7 +407,7 @@ func (c *HCL2UpgradeCommand) writeAmazonAmiDatasource(builders []*template.Build
sourceAmiFilterCfg := map[string]interface{}{}
if err := mapstructure.Decode(sourceAmiFilter, &sourceAmiFilterCfg); err != nil {
c.Ui.Error(fmt.Sprintf("Failed to write amazon-ami data source: %v", err))
return err
return nil, err
}
duplicate := false
@@ -336,21 +435,17 @@ func (c *HCL2UpgradeCommand) writeAmazonAmiDatasource(builders []*template.Build
builder.Config["source_ami"] = sourceAmiDataRef
i++
if first {
out.Write([]byte(amazonAmiDataHeader))
first = false
}
datasourceContent := hclwrite.NewEmptyFile()
body := datasourceContent.Body()
body.AppendNewline()
sourceBody := body.AppendNewBlock("data", []string{"amazon-ami", dataSourceName}).Body()
jsonBodyToHCL2Body(sourceBody, sourceAmiFilterCfg)
_, _ = out.Write(transposeTemplatingCalls(datasourceContent.Bytes()))
amazonAmiOut = append(amazonAmiOut, transposeTemplatingCalls(datasourceContent.Bytes())...)
}
}
}
return nil
return amazonAmiOut, nil
}
type UnhandleableArgumentError struct {
@@ -377,14 +472,71 @@ func transposeTemplatingCalls(s []byte) []byte {
return append([]byte(fmt.Sprintf("\n# could not parse template for following block: %q\n", err)), s...)
}
funcMap := texttemplate.FuncMap{
"timestamp": func() string {
funcMap := templateCommonFunctionMap()
tpl, err := texttemplate.New("hcl2_upgrade").
Funcs(funcMap).
Parse(string(s))
if err != nil {
return fallbackReturn(err)
}
str := &bytes.Buffer{}
v := struct {
HTTPIP string
HTTPPort string
}{
HTTPIP: "{{ .HTTPIP }}",
HTTPPort: "{{ .HTTPPort }}",
}
if err := tpl.Execute(str, v); err != nil {
return fallbackReturn(err)
}
return str.Bytes()
}
func templateCommonFunctionMap() texttemplate.FuncMap {
return texttemplate.FuncMap{
"aws_secretsmanager": func(a ...string) string {
if len(a) == 2 {
for key, config := range amazonSecretsManagerMap {
nameOk := config["name"] == a[0]
keyOk := config["key"] == a[1]
if nameOk && keyOk {
return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", key)
}
}
id := fmt.Sprintf("autogenerated_%d", len(amazonSecretsManagerMap)+1)
amazonSecretsManagerMap[id] = map[string]interface{}{
"name": a[0],
"key": a[1],
}
return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", id)
}
for key, config := range amazonSecretsManagerMap {
nameOk := config["name"] == a[0]
if nameOk {
return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", key)
}
}
id := fmt.Sprintf("autogenerated_%d", len(amazonSecretsManagerMap)+1)
amazonSecretsManagerMap[id] = map[string]interface{}{
"name": a[0],
}
return fmt.Sprintf("${data.amazon-secretsmanager.%s.value}", id)
}, "timestamp": func() string {
return "${local.timestamp}"
},
"isotime": func() string {
return "${local.timestamp}"
},
"user": func(in string) string {
if _, ok := localsVariableMap[in]; ok {
// variable is now a local
return fmt.Sprintf("${local.%s}", in)
}
return fmt.Sprintf("${var.%s}", in)
},
"env": func(in string) string {
@@ -459,13 +611,34 @@ func transposeTemplatingCalls(s []byte) []byte {
return fmt.Sprintf("${build.type}")
},
}
}
// variableTransposeTemplatingCalls executes parts of blocks as go template files and replaces
// their result with their hcl2 variant for variables block only. If something goes wrong the template
// containing the go template string is returned.
// In variableTransposeTemplatingCalls the definition of aws_secretsmanager function will create a data source
// with the same name as the variable.
func variableTransposeTemplatingCalls(s []byte) (isLocal bool, body []byte) {
fallbackReturn := func(err error) []byte {
if strings.Contains(err.Error(), "unhandled") {
return append([]byte(fmt.Sprintf("\n# %s\n", err)), s...)
}
return append([]byte(fmt.Sprintf("\n# could not parse template for following block: %q\n", err)), s...)
}
funcMap := templateCommonFunctionMap()
funcMap["aws_secretsmanager"] = func(a ...string) string {
isLocal = true
return ""
}
tpl, err := texttemplate.New("hcl2_upgrade").
Funcs(funcMap).
Parse(string(s))
if err != nil {
return fallbackReturn(err)
return isLocal, fallbackReturn(err)
}
str := &bytes.Buffer{}
@@ -477,10 +650,10 @@ func transposeTemplatingCalls(s []byte) []byte {
HTTPPort: "{{ .HTTPPort }}",
}
if err := tpl.Execute(str, v); err != nil {
return fallbackReturn(err)
return isLocal, fallbackReturn(err)
}
return str.Bytes()
return isLocal, str.Bytes()
}
func jsonBodyToHCL2Body(out *hclwrite.Body, kvs map[string]interface{}) {
+5 -3
View File
@@ -19,14 +19,16 @@ func Test_hcl2_upgrade(t *testing.T) {
tc := []struct {
folder string
}{
{"hcl2_upgrade_basic"},
{"basic"},
{"minimal"},
{"source-name"},
}
for _, tc := range tc {
t.Run(tc.folder, func(t *testing.T) {
inputPath := filepath.Join(testFixture(tc.folder, "input.json"))
inputPath := filepath.Join(testFixture("hcl2_upgrade", tc.folder, "input.json"))
outputPath := inputPath + ".pkr.hcl"
expectedPath := filepath.Join(testFixture(tc.folder, "expected.pkr.hcl"))
expectedPath := filepath.Join(testFixture("hcl2_upgrade", tc.folder, "expected.pkr.hcl"))
p := helperCommand(t, "hcl2_upgrade", inputPath)
bs, err := p.CombinedOutput()
if err != nil {
+145 -56
View File
@@ -1,10 +1,9 @@
package command
import (
"io/ioutil"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"sort"
"testing"
@@ -14,27 +13,46 @@ import (
"golang.org/x/mod/sumdb/dirhash"
)
type testCaseInit struct {
checkSkip func(*testing.T)
name string
Meta Meta
inPluginFolder map[string]string
expectedPackerConfigDirHashBeforeInit string
inConfigFolder map[string]string
packerConfigDir string
packerUserFolder string
want int
dirFiles []string
expectedPackerConfigDirHashAfterInit string
moreTests []func(*testing.T, testCaseInit)
}
type testBuild struct {
want int
}
func (tb testBuild) fn(t *testing.T, tc testCaseInit) {
bc := BuildCommand{
Meta: tc.Meta,
}
args := []string{tc.packerUserFolder}
want := tb.want
if got := bc.Run(args); got != want {
t.Errorf("BuildCommand.Run() = %v, want %v", got, want)
}
}
func TestInitCommand_Run(t *testing.T) {
// These tests will try to optimise for doing the least amount of github api
// requests whilst testing the max amount of things at once. Hopefully they
// don't require a GH token just yet. Acc tests are run on linux, darwin and
// windows, so requests are done 3 times.
type testCase struct {
checkSkip func(*testing.T)
name string
inPluginFolder map[string]string
expectedPackerConfigDirHashBeforeInit string
hclFile string
packerConfigDir string
want int
dirFiles []string
expectedPackerConfigDirHashAfterInit string
}
cfg := &configDirSingleton{map[string]string{}}
tests := []testCase{
tests := []testCaseInit{
{
nil,
// here we pre-write plugins with valid checksums, Packer will
@@ -43,6 +61,7 @@ func TestInitCommand_Run(t *testing.T) {
// that's a no-op. This also should do no GH query, so it is best
// to always run it.
"already-installed-no-op",
testMetaFile(t),
map[string]string{
"github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
"github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
@@ -52,19 +71,27 @@ func TestInitCommand_Run(t *testing.T) {
"github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
},
"h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
`# cfg.pkr.hcl
packer {
required_plugins {
comment = {
source = "github.com/sylviamoss/comment"
version = "v0.2.018"
}
}
}`,
cfg.dir("1"),
map[string]string{
`cfg.pkr.hcl`: `
packer {
required_plugins {
comment = {
source = "github.com/sylviamoss/comment"
version = "v0.2.018"
}
}
}`,
},
cfg.dir("1_pkr_config"),
cfg.dir("1_pkr_user_folder"),
0,
nil,
"h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
[]func(t *testing.T, tc testCaseInit){
// test that a build will not work since plugins are broken for
// this tests (they are not binaries).
testBuild{want: 1}.fn,
},
},
{
func(t *testing.T) {
@@ -76,6 +103,7 @@ func TestInitCommand_Run(t *testing.T) {
// see those as valid installations it did.
// But because we require version 0.2.19, we will upgrade.
"already-installed-upgrade",
testMetaFile(t),
map[string]string{
"github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64": "1",
"github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64_SHA256SUM": "6b86b273ff34fce19d6b804eff5a3f5747ada4eaa22f1d49c01e52ddb7875b4b",
@@ -85,16 +113,34 @@ func TestInitCommand_Run(t *testing.T) {
"github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_linux_amd64_SHA256SUM": "59031c50e0dfeedfde2b4e9445754804dce3f29e4efa737eead0ca9b4f5b85a5",
},
"h1:Q5qyAOdD43hL3CquQdVfaHpOYGf0UsZ/+wVA9Ry6cbA=",
`# cfg.pkr.hcl
packer {
required_plugins {
comment = {
source = "github.com/sylviamoss/comment"
version = "v0.2.019"
map[string]string{
`cfg.pkr.hcl`: `
packer {
required_plugins {
comment = {
source = "github.com/sylviamoss/comment"
version = "v0.2.019"
}
}
}`,
`source.pkr.hcl`: `
source "null" "test" {
communicator = "none"
}
`,
`build.pkr.hcl`: `
build {
sources = ["source.null.test"]
provisioner "comment" {
comment = "Begin ¡"
ui = true
bubble_text = true
}
}
}`,
cfg.dir("2"),
`,
},
cfg.dir("2_pkr_config"),
cfg.dir("2_pkr_user_folder"),
0,
[]string{
"github.com/sylviamoss/comment/packer-plugin-comment_v0.2.18_x5.0_darwin_amd64",
@@ -119,6 +165,10 @@ func TestInitCommand_Run(t *testing.T) {
"linux": "h1:CGym0+Nd0LEANgzqL0wx/LDjRL8bYwlpZ0HajPJo/hs=",
"windows": "h1:ag0/C1YjP7KoEDYOiJHE0K+lhFgs0tVgjriWCXVT1fg=",
}[runtime.GOOS],
[]func(t *testing.T, tc testCaseInit){
// test that a build will work as the plugin was just installed
testBuild{want: 0}.fn,
},
},
{
func(t *testing.T) {
@@ -127,21 +177,61 @@ func TestInitCommand_Run(t *testing.T) {
}
},
"release-with-no-binary",
testMetaFile(t),
nil,
"h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
`# cfg.pkr.hcl
packer {
required_plugins {
comment = {
source = "github.com/sylviamoss/comment"
version = "v0.2.20"
}
}
}`,
cfg.dir("3"),
map[string]string{
`cfg.pkr.hcl`: `
packer {
required_plugins {
comment = {
source = "github.com/sylviamoss/comment"
version = "v0.2.20"
}
}
}`,
},
cfg.dir("3_pkr_config"),
cfg.dir("3_pkr_user_folder"),
1,
nil,
"h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
nil,
},
{
func(t *testing.T) {
if os.Getenv(acctest.TestEnvVar) == "" {
t.Skipf("Acceptance test skipped unless env '%s' set", acctest.TestEnvVar)
}
tc := testCaseInit{}
if err := getBinary(getBinaryOptions{
GetZip: "https://github.com/azr/packer-provisioner-comment/releases/download/v1.0.0/packer-provisioner-comment_v1.0.0_" + runtime.GOOS + "_" + runtime.GOARCH + ".tar.gz",
UnzipIn: tc.inPluginFolder,
}); err != nil {
t.Fatal("getBinary: %v", err)
}
},
"release-with-no-binary",
testMetaFile(t),
nil,
"h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
map[string]string{
`cfg.pkr.hcl`: `
packer {
required_plugins {
comment = {
source = "github.com/sylviamoss/comment"
version = "v0.2.20"
}
}
}`,
},
cfg.dir("3_pkr_config"),
cfg.dir("3_pkr_user_folder"),
1,
nil,
"h1:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=",
nil,
},
}
for _, tt := range tests {
@@ -157,6 +247,10 @@ func TestInitCommand_Run(t *testing.T) {
t.Cleanup(func() {
_ = os.RemoveAll(tt.packerConfigDir)
})
createFiles(tt.packerUserFolder, tt.inConfigFolder)
t.Cleanup(func() {
_ = os.RemoveAll(tt.packerUserFolder)
})
hash, err := dirhash.HashDir(tt.packerConfigDir, "", dirhash.DefaultHash)
if err != nil {
@@ -166,21 +260,10 @@ func TestInitCommand_Run(t *testing.T) {
t.Errorf("unexpected dir hash before init: %s", diff)
}
cfgDir, err := ioutil.TempDir("", "pkr-test-init-file-folder")
if err != nil {
t.Fatalf("TempDir: %v", err)
}
if err := ioutil.WriteFile(filepath.Join(cfgDir, "cfg.pkr.hcl"), []byte(tt.hclFile), 0666); err != nil {
t.Fatalf("WriteFile: %v", err)
}
t.Cleanup(func() {
_ = os.RemoveAll(cfgDir)
})
args := []string{cfgDir}
args := []string{tt.packerUserFolder}
c := &InitCommand{
Meta: testMetaFile(t),
Meta: tt.Meta,
}
c.CoreConfig.Components.PluginConfig.KnownPluginFolders = []string{tt.packerConfigDir}
@@ -207,6 +290,12 @@ func TestInitCommand_Run(t *testing.T) {
if diff := cmp.Diff(tt.expectedPackerConfigDirHashAfterInit, hash); diff != "" {
t.Errorf("unexpected dir hash after init: %s", diff)
}
for i, subTest := range tt.moreTests {
t.Run(fmt.Sprintf("-subtest-%d", i), func(t *testing.T) {
subTest(t, tt)
})
}
})
}
}
@@ -47,13 +47,36 @@ variable "secret_account" {
sensitive = true
}
# "timestamp" template function replacement
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
# The amazon-secretsmanager data block is generated from your aws_secretsmanager template function; a data
# from this block can be referenced in source and locals blocks.
# Read the documentation for data blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/data
# Read the documentation for the Amazon Secrets Manager Data Source here:
# https://www.packer.io/docs/datasources/amazon/secretsmanager
data "amazon-secretsmanager" "autogenerated_1" {
name = "sample/app/password"
}
data "amazon-secretsmanager" "autogenerated_2" {
key = "api_key"
name = "sample/app/passwords"
}
data "amazon-secretsmanager" "autogenerated_3" {
name = "some_secret"
}
data "amazon-secretsmanager" "autogenerated_4" {
key = "with_key"
name = "some_secret"
}
# The amazon-ami data block is generated from your amazon builder source_ami_filter; a data
# from this block can be referenced in source and locals blocks.
# Read the documentation for data blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/data
# Read the documentation for the Amazon AMI Data Source here:
# https://www.packer.io/docs/datasources/amazon/ami
data "amazon-ami" "autogenerated_1" {
filters = {
name = "ubuntu/images/*/ubuntu-xenial-16.04-amd64-server-*"
@@ -64,6 +87,22 @@ data "amazon-ami" "autogenerated_1" {
owners = ["099720109477"]
}
# "timestamp" template function replacement
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
# All locals variables are generated from variables that uses expressions
# that are not allowed in HCL2 variables.
# Read the documentation for locals blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/locals
local "password" {
sensitive = true
expression = "${data.amazon-secretsmanager.autogenerated_1.value}"
}
locals {
password_key = "MY_KEY_${data.amazon-secretsmanager.autogenerated_2.value}"
}
# source blocks are generated from your builders; a source can be referenced in
# build blocks. A build block runs provisioner and post-processors on a
# source. Read the documentation for source blocks here:
@@ -135,6 +174,12 @@ build {
inline = ["echo ${var.secret_account}", "echo ${build.ID}", "echo ${build.SSHPublicKey} | head -c 14", "echo ${path.root} is not ${path.cwd}", "echo ${packer.version}", "echo ${uuidv4()}"]
max_retries = "5"
}
provisioner "shell" {
inline = ["echo ${local.password}", "echo ${data.amazon-secretsmanager.autogenerated_1.value}", "echo ${local.password_key}", "echo ${data.amazon-secretsmanager.autogenerated_2.value}"]
}
provisioner "shell" {
inline = ["echo ${data.amazon-secretsmanager.autogenerated_3.value}", "echo ${data.amazon-secretsmanager.autogenerated_4.value}"]
}
# template: hcl2_upgrade:2:38: executing "hcl2_upgrade" at <clean_resource_name>: error calling clean_resource_name: unhandled "clean_resource_name" call:
# there is no way to automatically upgrade the "clean_resource_name" call.
@@ -5,13 +5,16 @@
"aws_region": null,
"aws_secondary_region": "{{ env `AWS_DEFAULT_REGION` }}",
"aws_secret_key": "",
"aws_access_key": ""
"aws_access_key": "",
"password": "{{ aws_secretsmanager `sample/app/password` }}",
"password_key": "MY_KEY_{{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
},
"sensitive-variables": [
"aws_secret_key",
"aws_access_key",
"secret_account",
"potato"
"potato",
"password"
],
"builders": [
{
@@ -128,6 +131,22 @@
"echo {{ uuid }}"
]
},
{
"type": "shell",
"inline": [
"echo {{ user `password` }}",
"echo {{ aws_secretsmanager `sample/app/password` }}",
"echo {{ user `password_key` }}",
"echo {{ aws_secretsmanager `sample/app/passwords` `api_key` }}"
]
},
{
"type": "shell",
"inline": [
"echo {{ aws_secretsmanager `some_secret` }}",
"echo {{ aws_secretsmanager `some_secret` `with_key` }}"
]
},
{
"type": "shell",
"inline": [
@@ -0,0 +1,78 @@
# This file was autogenerated by the 'packer hcl2_upgrade' command. We
# recommend double checking that everything is correct before going forward. We
# also recommend treating this file as disposable. The HCL2 blocks in this
# file can be moved to other files. For example, the variable blocks could be
# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
# once they also need to be in the same folder. 'packer inspect folder/'
# will describe to you what is in that folder.
# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
# executed together and the outcome will be unknown.
# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
packer {
required_version = ">= 1.6.0"
}
# All generated input variables will be of 'string' type as this is how Packer JSON
# views them; you can change their type later on. Read the variables type
# constraints documentation
# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
variable "aws_access_key" {
type = string
default = ""
}
variable "aws_region" {
type = string
}
variable "aws_secret_key" {
type = string
default = ""
}
# "timestamp" template function replacement
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
# source blocks are generated from your builders; a source can be referenced in
# build blocks. A build block runs provisioner and post-processors on a
# source. Read the documentation for source blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/source
source "amazon-ebs" "autogenerated_1" {
access_key = "${var.aws_access_key}"
ami_description = "Ubuntu 16.04 LTS - expand root partition"
ami_name = "ubuntu-16-04-test-${local.timestamp}"
encrypt_boot = true
launch_block_device_mappings {
delete_on_termination = true
device_name = "/dev/sda1"
volume_size = 48
volume_type = "gp2"
}
region = "${var.aws_region}"
secret_key = "${var.aws_secret_key}"
source_ami = "ami1234567"
spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
spot_price = "0.0075"
ssh_interface = "session_manager"
ssh_username = "ubuntu"
temporary_iam_instance_profile_policy_document {
Statement {
Action = ["*"]
Effect = "Allow"
Resource = ["*"]
}
Version = "2012-10-17"
}
}
# a build block invokes sources and runs provisioning steps on them. The
# documentation for build blocks can be found here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
build {
sources = ["source.amazon-ebs.autogenerated_1"]
}
@@ -0,0 +1,48 @@
{
"min_packer_version": "1.6.0",
"variables": {
"aws_region": null,
"aws_secret_key": "",
"aws_access_key": ""
},
"builders": [
{
"type": "amazon-ebs",
"region": "{{ user `aws_region` }}",
"secret_key": "{{ user `aws_secret_key` }}",
"access_key": "{{ user `aws_access_key` }}",
"ami_name": "ubuntu-16-04-test-{{ timestamp }}",
"ami_description": "Ubuntu 16.04 LTS - expand root partition",
"source_ami": "ami1234567",
"launch_block_device_mappings": [
{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"volume_type": "gp2",
"volume_size": 48
}
],
"spot_price": "0.0075",
"spot_instance_types": [
"t2.small",
"t2.medium",
"t2.large"
],
"encrypt_boot": true,
"ssh_username": "ubuntu",
"temporary_iam_instance_profile_policy_document": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"*"
],
"Resource": ["*"]
}
]
},
"ssh_interface": "session_manager"
}
]
}
@@ -0,0 +1,78 @@
# This file was autogenerated by the 'packer hcl2_upgrade' command. We
# recommend double checking that everything is correct before going forward. We
# also recommend treating this file as disposable. The HCL2 blocks in this
# file can be moved to other files. For example, the variable blocks could be
# moved to their own 'variables.pkr.hcl' file, etc. Those files need to be
# suffixed with '.pkr.hcl' to be visible to Packer. To use multiple files at
# once they also need to be in the same folder. 'packer inspect folder/'
# will describe to you what is in that folder.
# Avoid mixing go templating calls ( for example ```{{ upper(`string`) }}``` )
# and HCL2 calls (for example '${ var.string_value_example }' ). They won't be
# executed together and the outcome will be unknown.
# See https://www.packer.io/docs/templates/hcl_templates/blocks/packer for more info
packer {
required_version = ">= 1.6.0"
}
# All generated input variables will be of 'string' type as this is how Packer JSON
# views them; you can change their type later on. Read the variables type
# constraints documentation
# https://www.packer.io/docs/templates/hcl_templates/variables#type-constraints for more info.
variable "aws_access_key" {
type = string
default = ""
}
variable "aws_region" {
type = string
}
variable "aws_secret_key" {
type = string
default = ""
}
# "timestamp" template function replacement
locals { timestamp = regex_replace(timestamp(), "[- TZ:]", "") }
# source blocks are generated from your builders; a source can be referenced in
# build blocks. A build block runs provisioner and post-processors on a
# source. Read the documentation for source blocks here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/source
source "amazon-ebs" "party_parrot" {
access_key = "${var.aws_access_key}"
ami_description = "Ubuntu 16.04 LTS - expand root partition"
ami_name = "ubuntu-16-04-test-${local.timestamp}"
encrypt_boot = true
launch_block_device_mappings {
delete_on_termination = true
device_name = "/dev/sda1"
volume_size = 48
volume_type = "gp2"
}
region = "${var.aws_region}"
secret_key = "${var.aws_secret_key}"
source_ami = "ami1234567"
spot_instance_types = ["t2.small", "t2.medium", "t2.large"]
spot_price = "0.0075"
ssh_interface = "session_manager"
ssh_username = "ubuntu"
temporary_iam_instance_profile_policy_document {
Statement {
Action = ["*"]
Effect = "Allow"
Resource = ["*"]
}
Version = "2012-10-17"
}
}
# a build block invokes sources and runs provisioning steps on them. The
# documentation for build blocks can be found here:
# https://www.packer.io/docs/templates/hcl_templates/blocks/build
build {
sources = ["source.amazon-ebs.party_parrot"]
}
@@ -0,0 +1,49 @@
{
"min_packer_version": "1.6.0",
"variables": {
"aws_region": null,
"aws_secret_key": "",
"aws_access_key": ""
},
"builders": [
{
"type": "amazon-ebs",
"name": " party parrot ",
"region": "{{ user `aws_region` }}",
"secret_key": "{{ user `aws_secret_key` }}",
"access_key": "{{ user `aws_access_key` }}",
"ami_name": "ubuntu-16-04-test-{{ timestamp }}",
"ami_description": "Ubuntu 16.04 LTS - expand root partition",
"source_ami": "ami1234567",
"launch_block_device_mappings": [
{
"delete_on_termination": true,
"device_name": "/dev/sda1",
"volume_type": "gp2",
"volume_size": 48
}
],
"spot_price": "0.0075",
"spot_instance_types": [
"t2.small",
"t2.medium",
"t2.large"
],
"encrypt_boot": true,
"ssh_username": "ubuntu",
"temporary_iam_instance_profile_policy_document": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"*"
],
"Resource": ["*"]
}
]
},
"ssh_interface": "session_manager"
}
]
}
-2
View File
@@ -100,6 +100,4 @@ require (
google.golang.org/grpc v1.32.0
)
// replace github.com/hashicorp/packer-plugin-sdk => /Users/azr/go/src/github.com/hashicorp/packer-plugin-sdk
go 1.13
+1
View File
@@ -530,6 +530,7 @@ github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZX
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=
+2 -1
View File
@@ -97,7 +97,8 @@ func (cfg *PackerConfig) detectPluginBinaries() hcl.Diagnostics {
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: fmt.Sprintf("Failed to discover plugin %s", pluginRequirement.Identifier.ForDisplay()),
Summary: fmt.Sprintf("Error discovering plugin %s", pluginRequirement.Identifier.ForDisplay()),
Detail: err.Error(),
})
continue
}
+4 -3
View File
@@ -59,9 +59,10 @@ func (cfg *PackerConfig) startPostProcessor(source SourceUseBlock, pp *PostProce
postProcessor, err := cfg.parser.PluginConfig.PostProcessors.Start(pp.PType)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("Failed loading %s", pp.PType),
Subject: pp.DefRange.Ptr(),
Detail: err.Error(),
Severity: hcl.DiagError,
Summary: fmt.Sprintf("Failed loading %s", pp.PType),
Subject: pp.DefRange.Ptr(),
Detail: err.Error(),
})
return nil, diags
}
+4 -3
View File
@@ -146,9 +146,10 @@ func (cfg *PackerConfig) startProvisioner(source SourceUseBlock, pb *Provisioner
provisioner, err := cfg.parser.PluginConfig.Provisioners.Start(pb.PType)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("failed loading %s", pb.PType),
Subject: pb.HCL2Ref.LabelsRanges[0].Ptr(),
Detail: err.Error(),
Severity: hcl.DiagError,
Summary: fmt.Sprintf("failed loading %s", pb.PType),
Subject: pb.HCL2Ref.LabelsRanges[0].Ptr(),
Detail: err.Error(),
})
return nil, diags
}
+3 -2
View File
@@ -101,8 +101,9 @@ func (cfg *PackerConfig) startBuilder(source SourceUseBlock, ectx *hcl.EvalConte
builder, err := cfg.parser.PluginConfig.Builders.Start(source.Type)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: "Failed to load " + sourceLabel + " type",
Detail: err.Error(),
Severity: hcl.DiagError,
Summary: "Failed to load " + sourceLabel + " type",
Detail: err.Error(),
})
return builder, diags, nil
}
-27
View File
@@ -8,33 +8,6 @@
},
{
"pattern": "^https://www.linode.com"
},
{
"pattern": "^https://github.com/hashicorp/packer-plugin-scaffolding"
},
{
"pattern": "^https://www.packer.io/docs/templates/hcl_templates/"
},
{
"pattern": "^https://packer.io/docs/templates/hcl_templates/"
},
{
"pattern": "^/docs/templates/hcl_templates/"
},
{
"pattern": "^/commands/init"
},
{
"pattern": "^/docs/datasources"
},
{
"pattern": "^/docs/extending/custom-datasources"
},
{
"pattern": "^/docs/templates/legacy_json_templates"
},
{
"pattern": "^https://packer.io/docs/templates/legacy_json_templates"
}
],
"replacementPatterns": [
+13 -4
View File
@@ -121,7 +121,9 @@ func (c *PluginConfig) discoverExternalComponents(path string) error {
}
for pluginName, pluginPath := range pluginPaths {
newPath := pluginPath // this needs to be stored in a new variable for the func below
c.Builders.Set(pluginName, c.Client(newPath).Builder)
c.Builders.Set(pluginName, func() (packersdk.Builder, error) {
return c.Client(newPath).Builder()
})
externallyUsed = append(externallyUsed, pluginName)
}
if len(externallyUsed) > 0 {
@@ -136,7 +138,9 @@ func (c *PluginConfig) discoverExternalComponents(path string) error {
}
for pluginName, pluginPath := range pluginPaths {
newPath := pluginPath // this needs to be stored in a new variable for the func below
c.PostProcessors.Set(pluginName, c.Client(newPath).PostProcessor)
c.PostProcessors.Set(pluginName, func() (packersdk.PostProcessor, error) {
return c.Client(newPath).PostProcessor()
})
externallyUsed = append(externallyUsed, pluginName)
}
if len(externallyUsed) > 0 {
@@ -151,12 +155,15 @@ func (c *PluginConfig) discoverExternalComponents(path string) error {
}
for pluginName, pluginPath := range pluginPaths {
newPath := pluginPath // this needs to be stored in a new variable for the func below
c.Provisioners.Set(pluginName, c.Client(newPath).Provisioner)
c.Provisioners.Set(pluginName, func() (packersdk.Provisioner, error) {
return c.Client(newPath).Provisioner()
})
externallyUsed = append(externallyUsed, pluginName)
}
if len(externallyUsed) > 0 {
sort.Strings(externallyUsed)
log.Printf("using external provisioners %v", externallyUsed)
externallyUsed = nil
}
pluginPaths, err = c.discoverSingle(filepath.Join(path, "packer-datasource-*"))
@@ -165,7 +172,9 @@ func (c *PluginConfig) discoverExternalComponents(path string) error {
}
for pluginName, pluginPath := range pluginPaths {
newPath := pluginPath // this needs to be stored in a new variable for the func below
c.DataSources.Set(pluginName, c.Client(newPath).Datasource)
c.DataSources.Set(pluginName, func() (packersdk.Datasource, error) {
return c.Client(newPath).Datasource()
})
externallyUsed = append(externallyUsed, pluginName)
}
if len(externallyUsed) > 0 {
@@ -9,6 +9,7 @@ sidebar_title: Alicloud ECS
# Alicloud Image Builder
Type: `alicloud-ecs`
Artifact BuilderId: `alibaba.alicloud`
The `alicloud-ecs` Packer builder plugin provide the capability to build
customized images based on an existing base images.
@@ -17,7 +18,7 @@ customized images based on an existing base images.
The following configuration options are available for building Alicloud images.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
@@ -15,6 +15,7 @@ sidebar_title: chroot
# AMI Builder (chroot)
Type: `amazon-chroot`
Artifact BuilderId: `mitchellh.amazon.chroot`
The `amazon-chroot` Packer builder is able to create Amazon AMIs backed by an
EBS volume as the root device. For more information on the difference between
@@ -11,6 +11,7 @@ sidebar_title: EBS
# AMI Builder (EBS backed)
Type: `amazon-ebs`
Artifact BuilderId: `mitchellh.amazonebs`
The `amazon-ebs` Packer builder is able to create Amazon AMIs backed by EBS
volumes for use in [EC2](https://aws.amazon.com/ec2/). For more information on
@@ -90,6 +91,64 @@ necessary for this build to succeed and can be found further down the page.
@include 'builder/amazon/common/RunConfig-not-required.mdx'
#### Metadata Settings
@include 'builder/amazon/common/MetadataOptions.mdx'
@include 'builder/amazon/common/MetadataOptions-not-required.mdx'
Usage Example
<Tabs>
<Tab heading="HCL2">
```hcl
source "amazon-ebs" "basic-example" {
region = "us-east-1"
source_ami = "ami-fce3c696"
instance_type = "t2.micro"
ssh_username = "ubuntu"
ami_name = "packer_AWS_example_{{timestamp}}"
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
}
```
</Tab>
<Tab heading="JSON">
```json
{
"variables": {
"aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
"aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}"
},
"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "us-east-1",
"source_ami": "ami-fce3c696",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer_AWS {{timestamp}}",
"metadata_options": {
"http_endpoint": "enabled",
"http_tokens": "required",
"http_put_response_hop_limit": 1
}
}
]
}
```
</Tab>
</Tabs>
@include 'builders/aws-session-manager.mdx'
### Block Devices Configuration
@@ -11,6 +11,7 @@ sidebar_title: EBS Surrogate
# EBS Surrogate Builder
Type: `amazon-ebssurrogate`
Artifact BuilderId: `mitchellh.amazon.ebssurrogate`
The `amazon-ebssurrogate` Packer builder is able to create Amazon AMIs by
running a source instance with an attached volume, provisioning the attached
@@ -86,6 +87,64 @@ necessary for this build to succeed and can be found further down the page.
@include 'builder/amazon/common/RunConfig-not-required.mdx'
#### Metadata Settings
@include 'builder/amazon/common/MetadataOptions.mdx'
@include 'builder/amazon/common/MetadataOptions-not-required.mdx'
Usage Example
<Tabs>
<Tab heading="HCL2">
```hcl
source "amazon-ebs" "basic-example" {
region = "us-east-1"
source_ami = "ami-fce3c696"
instance_type = "t2.micro"
ssh_username = "ubuntu"
ami_name = "packer_AWS_example_{{timestamp}}"
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
}
```
</Tab>
<Tab heading="JSON">
```json
{
"variables": {
"aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
"aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}"
},
"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "us-east-1",
"source_ami": "ami-fce3c696",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer_AWS {{timestamp}}",
"metadata_options": {
"http_endpoint": "enabled",
"http_tokens": "required",
"http_put_response_hop_limit": 1
}
}
]
}
```
</Tab>
</Tabs>
@include 'builders/aws-session-manager.mdx'
### Block Devices Configuration
@@ -9,6 +9,7 @@ sidebar_title: EBS Volume
# EBS Volume Builder
Type: `amazon-ebsvolume`
Artifact BuilderId: `mitchellh.amazon.ebsvolume`
The `amazon-ebsvolume` Packer builder is able to create Amazon Elastic Block
Store volumes which are prepopulated with filesystems or data.
@@ -105,6 +106,64 @@ Block devices can be nested in the
@include 'builder/amazon/common/RunConfig-not-required.mdx'
#### Metadata Settings
@include 'builder/amazon/common/MetadataOptions.mdx'
@include 'builder/amazon/common/MetadataOptions-not-required.mdx'
Usage Example
<Tabs>
<Tab heading="HCL2">
```hcl
source "amazon-ebs" "basic-example" {
region = "us-east-1"
source_ami = "ami-fce3c696"
instance_type = "t2.micro"
ssh_username = "ubuntu"
ami_name = "packer_AWS_example_{{timestamp}}"
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
http_put_response_hop_limit = 1
}
}
```
</Tab>
<Tab heading="JSON">
```json
{
"variables": {
"aws_access_key": "{{env `AWS_ACCESS_KEY_ID`}}",
"aws_secret_key": "{{env `AWS_SECRET_ACCESS_KEY`}}"
},
"builders": [
{
"type": "amazon-ebs",
"access_key": "{{user `aws_access_key`}}",
"secret_key": "{{user `aws_secret_key`}}",
"region": "us-east-1",
"source_ami": "ami-fce3c696",
"instance_type": "t2.micro",
"ssh_username": "ubuntu",
"ami_name": "packer_AWS {{timestamp}}",
"metadata_options": {
"http_endpoint": "enabled",
"http_tokens": "required",
"http_put_response_hop_limit": 1
}
}
]
}
```
</Tab>
</Tabs>
@include 'builders/aws-session-manager.mdx'
### Communicator Configuration
@@ -15,6 +15,7 @@ sidebar_title: Instance
# AMI Builder (instance-store)
Type: `amazon-instance`
Artifact BuilderId: `mitchellh.amazon.instance`
The `amazon-instance` Packer builder is able to create Amazon AMIs backed by
instance storage as the root device. For more information on the difference
+2 -1
View File
@@ -7,6 +7,7 @@ sidebar_title: ARM
# Azure Resource Manager Builder
Type: `azure-arm`
Artifact BuilderId: `Azure.ResourceManagement.VMImage`
Packer supports building Virtual Hard Disks (VHDs) and Managed Images in [Azure Resource
Manager](https://azure.microsoft.com/en-us/documentation/articles/resource-group-overview/).
@@ -25,7 +26,7 @@ CLI](https://azure.microsoft.com/en-us/documentation/articles/xplat-cli-install/
There are many configuration options available for the builder. We'll start
with authentication parameters, then go over the Azure ARM builder specific
options. In addition to the options listed here, a [communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this builder.
options. In addition to the options listed here, a [communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this builder.
### Authentication options
@@ -11,6 +11,7 @@ sidebar_title: chroot
# Azure Builder (chroot)
Type: `azure-chroot`
Artifact BuilderId: `azure.chroot`
The `azure-chroot` builder is able to build Azure managed disk (MD) images. For
more information on managed disks, see [Azure Managed Disks Overview](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/managed-disks-overview).
+2 -1
View File
@@ -11,6 +11,7 @@ sidebar_title: CloudStack
# CloudStack Builder
Type: `cloudstack`
Artifact BuilderId: `packer.cloudstack`
The `cloudstack` Packer builder is able to create new templates for use with
[CloudStack](https://cloudstack.apache.org/). The builder takes either an ISO
@@ -27,7 +28,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
@@ -17,6 +17,7 @@ sidebar_title: DigitalOcean
# DigitalOcean Builder
Type: `digitalocean`
Artifact BuilderId: `pearkes.digitalocean`
The `digitalocean` Packer builder is able to create new images for use with
[DigitalOcean](https://www.digitalocean.com). The builder takes a source image,
@@ -36,7 +37,7 @@ each category, the available configuration keys are alphabetized.
### Communicator Config
In addition to the builder options, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this builder.
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this builder.
@include 'packer-plugin-sdk/communicator/Config-not-required.mdx'
+2 -1
View File
@@ -13,6 +13,7 @@ sidebar_title: Docker
# Docker Builder
Type: `docker`
Artifact BuilderId: `packer.docker`
The `docker` Packer builder builds [Docker](https://www.docker.io) images using
Docker. The builder starts a Docker container, runs provisioners within this
@@ -200,7 +201,7 @@ optional. Within each category, the available options are alphabetized and
described.
The Docker builder uses a special Docker communicator _and will not use_ the
standard [communicators](/docs/templates/legacy_json_templates/communicators).
standard [communicators](/docs/templates/legacy_json_templates/communicator).
### Required:
+2 -1
View File
@@ -10,6 +10,7 @@ sidebar_title: File
# File Builder
Type: `file`
Artifact BuilderId: `packer.file`
The `file` Packer builder is not really a builder, it just creates an artifact
from a file. It can be used to debug post-processors without incurring high
@@ -54,7 +55,7 @@ Configuration options are organized below into two categories: required and
optional. Within each category, the available options are alphabetized and
described.
Any [communicator](/docs/templates/legacy_json_templates/communicators) defined is ignored.
Any [communicator](/docs/templates/legacy_json_templates/communicator) defined is ignored.
### Required:
@@ -9,6 +9,7 @@ sidebar_title: Google Cloud
# Google Compute Builder
Type: `googlecompute`
Artifact BuilderId: `packer.googlecompute`
The `googlecompute` Packer builder is able to create
[images](https://developers.google.com/compute/docs/images) for use with
@@ -342,7 +343,7 @@ optional. Within each category, the available options are alphabetized and
described.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Communicator Configuration
@@ -12,6 +12,7 @@ sidebar_title: Hetzner Cloud
# Hetzner Cloud Builder
Type: `hcloud`
Artifact BuilderId: `hcloud.builder`
The `hcloud` Packer builder is able to create new images for use with [Hetzner
Cloud](https://www.hetzner.cloud). The builder takes a source image, runs any
@@ -29,7 +30,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required Builder Configuration options:
+2 -1
View File
@@ -10,6 +10,7 @@ sidebar_title: HyperOne
# HyperOne Builder
Type: `hyperone`
Artifact BuilderId: `hyperone.builder`
The `hyperone` Packer builder is able to create new images on the [HyperOne
platform](http://www.hyperone.com/). The builder takes a source image, runs
@@ -86,7 +87,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
+2 -1
View File
@@ -11,6 +11,7 @@ sidebar_title: ISO
# Hyper-V Builder (from an ISO)
Type: `hyperv-iso`
Artifact BuilderId: `MSOpenTech.hyperv`
The Hyper-V Packer builder is able to create
[Hyper-V](https://www.microsoft.com/en-us/server-cloud/solutions/virtualization.aspx)
@@ -65,7 +66,7 @@ are organized below into two categories: required and optional. Within each
category, the available options are alphabetized and described.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Optional:
@@ -11,6 +11,7 @@ sidebar_title: VMCX
# Hyper-V Builder (from a vmcx)
Type: `hyperv-vmcx`
Artifact BuilderId: `MSOpenTech.hyperv`
The Hyper-V Packer builder is able to use exported virtual machines or clone
existing
@@ -66,7 +67,7 @@ are organized below into two categories: required and optional. Within each
category, the available options are alphabetized and described.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
## ISO Configuration Reference
@@ -9,6 +9,7 @@ sidebar_title: JDCloud
# JDCloud Image Builder
Type: `jdcloud`
Artifact BuilderId: `hashicorp.jdcloud`
The `jdcloud` Packer builder helps you to build instance images
based on an existing image
+2 -1
View File
@@ -17,6 +17,7 @@ sidebar_title: Linode
# Linode Builder
Type: `linode`
Artifact BuilderId: `packer.linode`
The `linode` Packer builder is able to create [Linode
Images](https://www.linode.com/docs/platform/disk-images/linode-images/) for
@@ -35,7 +36,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
+1
View File
@@ -10,6 +10,7 @@ sidebar_title: LXC
# LXC Builder
Type: `lxc`
Artifact BuilderId: `ustream.lxc`
The `lxc` Packer builder builds containers for lxc1. The builder starts an LXC
container, runs provisioners within this container, then exports the container
+1
View File
@@ -13,6 +13,7 @@ sidebar_title: LXD
# LXD Builder
Type: `lxd`
Artifact BuilderId: `lxd`
The `lxd` Packer builder builds containers for LXD. The builder starts an LXD
container, runs provisioners within this container, then saves the container as
+3
View File
@@ -8,6 +8,9 @@ sidebar_title: NAVER Cloud
# NAVER CLOUD PLATFORM Builder
Type: `ncloud`
Artifact BuilderId: `ncloud.server.image`
The `ncloud` builder allows you to create server images using the [NAVER Cloud
Platform](https://www.ncloud.com/).
+1 -1
View File
@@ -55,4 +55,4 @@ build {
## Configuration Reference
The null builder has no configuration parameters other than the
[communicator](/docs/templates/legacy_json_templates/communicators) settings.
[communicator](/docs/templates/legacy_json_templates/communicator) settings.
+2 -1
View File
@@ -7,6 +7,7 @@ sidebar_title: 1&amp;1
# 1&1 Builder
Type: `oneandone`
Artifact BuilderId: `packer.oneandone`
The 1&1 Builder is able to create virtual machines for
[1&1](https://www.1and1.com/).
@@ -18,7 +19,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
+3 -2
View File
@@ -17,6 +17,7 @@ sidebar_title: OpenStack
# OpenStack Builder
Type: `openstack`
Artifact BuilderId: `mitchellh.openstack`
The `openstack` Packer builder is able to create new images for use with
[OpenStack](http://www.openstack.org). The builder takes a source image, runs
@@ -51,7 +52,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
@@ -140,7 +141,7 @@ Here is a basic example. This is a working example to build a Ubuntu 12.04 LTS
(Precise Pangolin) on Rackspace OpenStack cloud offering.
<Tabs>
<Tab heading="JSON">
<Tab heading="JSON">
```json
{
@@ -9,6 +9,7 @@ sidebar_title: Oracle Classic
# Oracle Cloud Infrastructure Classic Compute Builder
Type: `oracle-classic`
Artifact BuilderId: `packer.oracle.classic`
The `oracle-classic` Packer builder is able to create custom images for use
with [Oracle Cloud Infrastructure Classic
+2 -1
View File
@@ -9,6 +9,7 @@ sidebar_title: Oracle OCI
# Oracle Cloud Infrastructure (OCI) Builder
Type: `oracle-oci`
Artifact BuilderId: `packer.oracle.oci`
The `oracle-oci` Packer builder is able to create new custom images for use
with [Oracle Cloud Infrastructure](https://cloud.oracle.com) (OCI). The builder
@@ -40,7 +41,7 @@ in which case you don't need the above user authorization.
There are many configuration options available for the `oracle-oci` builder. In
addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
In addition to the options defined there, a private key file
@@ -13,6 +13,7 @@ sidebar_title: BSU
# OMI Builder (BSU backed)
Type: `osc-bsu`
Artifact BuilderId: `oapi.outscale.bsu`
The `osc-bsu` Packer builder is able to create Outscale OMIs backed by BSU
volumes for use in [Flexible Compute Unit](https://wiki.outscale.net/pages/viewpage.action?pageId=43060893). For more information on
@@ -41,7 +42,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
@@ -9,6 +9,7 @@ sidebar_title: BSU Surrogate
# BSU Surrogate Builder
Type: `osc-bsusurrogate`
Artifact BuilderId: `oapi.outscale.bsusurrogate`
The `osc-bsusurrogate` Packer builder is able to create Outscale OMIs by
running a source virtual machine with an attached volume, provisioning the attached
@@ -29,7 +30,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
@@ -9,6 +9,7 @@ sidebar_title: BSU Volume
# BSU Volume Builder
Type: `osc-bsuvolume`
Artifact BuilderId: `oapi.outscale.bsuvolume`
The `osc-bsuvolume` Packer builder is able to create Ouscale Block Stogate Unit
volumes which are prepopulated with filesystems or data.
@@ -35,7 +36,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
@@ -15,6 +15,7 @@ sidebar_title: chroot
# OMI Builder (chroot)
Type: `osc-chroot`
Artifact BuilderId: `oapi.outscale.chroot`
The `osc-chroot` Packer builder is able to create Outscale Machine Images (OMIs) backed by an
BSU volume as the root device. For more information on the difference between
@@ -12,6 +12,7 @@ sidebar_title: ISO
# Parallels Builder (from an ISO)
Type: `parallels-iso`
Artifact BuilderId: `packer.parallels`
The Parallels Packer builder is able to create [Parallels Desktop for
Mac](https://www.parallels.com/products/desktop/) virtual machines and export
@@ -53,7 +54,7 @@ are organized below into two categories: required and optional. Within each
category, the available options are alphabetized and described.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
@@ -12,6 +12,7 @@ sidebar_title: PVM
# Parallels Builder (from a PVM)
Type: `parallels-pvm`
Artifact BuilderId: `packer.parallels`
This Parallels builder is able to create [Parallels Desktop for
Mac](https://www.parallels.com/products/desktop/) virtual machines and export
@@ -50,7 +51,7 @@ are organized below into two categories: required and optional. Within each
category, the available options are alphabetized and described.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
@@ -7,6 +7,7 @@ sidebar_title: ProfitBricks
# ProfitBricks Builder
Type: `profitbricks`
Artifact BuilderId: `packer.profitbricks`
The ProfitBricks Builder is able to create virtual machines for
[ProfitBricks](https://www.profitbricks.com).
@@ -18,7 +19,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
@@ -11,6 +11,7 @@ sidebar_title: Clone
# Proxmox Builder (from an image)
Type: `proxmox-clone`
Artifact BuilderId: `proxmox.clone`
The `proxmox-clone` Packer builder is able to create new images for use with
[Proxmox](https://www.proxmox.com/en/proxmox-ve). The builder takes a virtual
@@ -28,7 +29,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
If no communicator is defined, an SSH key is generated for use, and is used
@@ -11,6 +11,7 @@ sidebar_title: ISO
# Proxmox Builder (from an ISO)
Type: `proxmox-iso`
Artifact BuilderId: `proxmox.iso`
The `proxmox-iso` Packer builder is able to create new images for use with
[Proxmox](https://www.proxmox.com/en/proxmox-ve). The builder takes an ISO
@@ -28,7 +29,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
+1
View File
@@ -10,6 +10,7 @@ sidebar_title: QEMU
# QEMU Builder
Type: `qemu`
Artifact BuilderId: `transcend.qemu`
The Qemu Packer builder is able to create [KVM](http://www.linux-kvm.org) virtual
machine images.
+2 -1
View File
@@ -17,6 +17,7 @@ sidebar_title: Scaleway
# Scaleway Builder
Type: `scaleway`
Artifact BuilderId: `hashicorp.scaleway`
The `scaleway` Packer builder is able to create new images for use with
[Scaleway](https://www.scaleway.com). The builder takes a source image, runs
@@ -34,7 +35,7 @@ segmented below into two categories: required and optional parameters. Within
each category, the available configuration keys are alphabetized.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
@@ -9,6 +9,7 @@ sidebar_title: Tencent Cloud
# Tencentcloud Image Builder
Type: `tencentcloud-cvm`
Artifact BuilderId: `tencent.cloud`
The `tencentcloud-cvm` Packer builder plugin provide the capability to build
customized images based on an existing base images.
@@ -17,7 +18,7 @@ customized images based on an existing base images.
The following configuration options are available for building Tencentcloud images.
In addition to the options listed here,
a [communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this builder.
a [communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this builder.
### Required:
+2 -1
View File
@@ -16,6 +16,7 @@ sidebar_title: Triton
# Triton Builder
Type: `triton`
Artifact BuilderId: `joyent.triton`
The `triton` Packer builder is able to create new images for use with Triton.
These images can be used with both the [Joyent public
@@ -47,7 +48,7 @@ There are many configuration options available for the builder. They are
segmented below into two categories: required and optional parameters.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
@@ -9,6 +9,7 @@ sidebar_title: UCloud
# UCloud Image Builder
Type: `ucloud-uhost`
Artifact BuilderId: `ucloud.uhost`
The `ucloud-uhost` Packer builder plugin provides the capability to build
customized images based on an existing base image for use in UHost Instance.
@@ -22,7 +23,7 @@ The following configuration options are available for building UCloud images. Th
segmented below into two categories: required and optional parameters.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
~> **Note:** The builder doesn't support Windows images for now and only supports CentOS and Ubuntu images via SSH authentication with `ssh_username` (Required) and `ssh_password` (Optional). The `ssh_username` must be `root` for CentOS images and `ubuntu` for Ubuntu images. The `ssh_password` may contain 8-30 characters, and must consist of at least 2 items out of the capital letters, lower case letters, numbers and special characters. The special characters include `()~!@#\$%^&\*-+=\_|{}\[]:;'<>,.?/`.
@@ -8,6 +8,9 @@ sidebar_title: Vagrant
# Vagrant Builder
Type: `vagrant`
Artifact BuilderId: `vagrant`
The Vagrant builder is intended for building new boxes from already-existing
boxes. Your source should be a URL or path to a .box file or a Vagrant Cloud
box name such as `hashicorp/precise64`.
@@ -11,6 +11,7 @@ sidebar_title: ISO
# VirtualBox Builder (from an ISO)
Type: `virtualbox-iso`
Artifact BuilderId: `mitchellh.virtualbox`
The VirtualBox Packer builder is able to create
[VirtualBox](https://www.virtualbox.org/) virtual machines and export them in
@@ -12,6 +12,7 @@ sidebar_title: OVF
# VirtualBox Builder (from an OVF/OVA)
Type: `virtualbox-ovf`
Artifact BuilderId: `mitchellh.virtualbox`
This VirtualBox Packer builder is able to create
[VirtualBox](https://www.virtualbox.org/) virtual machines and export them in
@@ -13,6 +13,7 @@ sidebar_title: VM
# VirtualBox Builder (from an existing VM)
Type: `virtualbox-vm`
Artifact BuilderId: `mitchellh.virtualbox`
The VirtualBox Packer builder is able to create
[VirtualBox](https://www.virtualbox.org/) virtual machines snapshots and
@@ -100,7 +101,7 @@ references for [ISO](#iso-configuration),
configuration references, which are
necessary for this build to succeed and can be found further down the page.
In addition to the options listed here, a
[communicator](/docs/templates/legacy_json_templates/communicators) can be configured for this
[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this
builder.
### Required:
@@ -14,6 +14,8 @@ sidebar_title: VMWare ISO
# VMware Builder (from ISO)
Type: `vmware-iso`
Artifact BuilderId: `mitchellh.vmware`
If remote_type is esx: Artifact BuilderId: `mitchellh.vmware-esx`
This VMware Packer builder is able to create VMware virtual machines from an ISO
file as a source. It currently supports building virtual machines on hosts
@@ -13,6 +13,8 @@ sidebar_title: VMWare VMX
# VMware Builder (from VMX)
Type: `vmware-vmx`
Artifact BuilderId: `mitchellh.vmware`
If remote_type is esx: Artifact BuilderId: `mitchellh.vmware-esx`
This VMware Packer builder is able to create VMware virtual machines from an
existing VMware virtual machine (a VMX file). It currently supports building
@@ -11,6 +11,7 @@ sidebar_title: VSphere Clone
# VMWare Vsphere Clone Builder
Type: `vsphere-clone`
Artifact BuilderId: `jetbrains.vsphere`
This builder clones VMs from existing templates.
@@ -11,6 +11,7 @@ sidebar_title: VSphere ISO
# Packer Builder for VMware vSphere
Type: `vsphere-iso`
Artifact BuilderId: `jetbrains.vsphere`
This builder uses the vSphere API, and creates virtual machines remotely. It
starts from an ISO file and creates new VMs from scratch.
+2 -1
View File
@@ -9,6 +9,7 @@ sidebar_title: Yandex.Cloud
# Yandex Compute Builder
Type: `yandex`
Artifact BuilderId: `packer.yandex`
The `yandex` Packer builder is able to create
[images](https://cloud.yandex.com/docs/compute/concepts/images) for use with
@@ -64,7 +65,7 @@ Configuration options are organized below into two categories: required and
optional. Within each category, the available options are alphabetized and
described.
In addition to the options listed here, a [communicator](/docs/templates/legacy_json_templates/communicators)
In addition to the options listed here, a [communicator](/docs/templates/legacy_json_templates/communicator)
can be configured for this builder. In addition to the options defined there, a private key file
can also be supplied to override the typical auto-generated key:
+16 -21
View File
@@ -7,23 +7,6 @@ sidebar_title: <tt>init</tt>
# `init` Command
-> **Note:** Packer does not currently have the notion of a state like Terraform
has. In other words, currently `packer init` is only in charge of installing
packer plugins.
-> **Note:** Currently, `packer init` can only fetch binaries from public
projects on *Github*.
-> **Note:** Currently, `packer init` only fetches binaries using Github's
public API, which [limits the number of unauthenticated requests per hour one IP
can
do](https://docs.github.com/en/developers/apps/rate-limits-for-github-apps#normal-user-to-server-rate-limits).
Packer will do its best to avoid hitting those limits and in an average local
usage this should not be an issue. Otherwise you can set the
`PKR_GITHUB_API_TOKEN` env var in order to get more requests per hour. Go to
your personal [access token page](https://github.com/settings/tokens) to
generate a new token.
-> **Note:** Packer init does not work with legacy JSON templates. You can
upgrade your JSON config files to HCL using the hcl2ugprade command.
@@ -32,10 +15,22 @@ that are named `packer-plugin-*` -- to install a single plugin binary -- that is
`packer-provisioner-*`, `packer-builder-*`, etc. -- nothing changes, you will
have to [install the plugin manually](/docs/plugins#installing-plugins).
The `packer init` command is used to download Packer plugin binaries.
This is the first command that should be executed when working with a new or
existing template. This command is always safe to run multiple times. Though
subsequent runs may give errors, this command will never delete anything.
The `packer init` command is used to download Packer plugin binaries. This is
the first command that should be executed when working with a new or existing
template. This command is always safe to run multiple times. Though subsequent
runs may give errors, this command will never delete anything.
Packer does not currently have the notion of a state like Terraform has. In other words,
currently `packer init` is only in charge of installing packer plugins.
Currently, `packer init` can only fetch binaries from public projects on **GitHub**. GitHub's public API, [limits the number of unauthenticated requests
per hour one IP can
do](https://docs.github.com/en/developers/apps/rate-limits-for-github-apps#normal-user-to-server-rate-limits).
Packer will do its best to avoid hitting those limits and in an average local
usage this should not be an issue. Otherwise you can set the
`PKR_GITHUB_API_TOKEN` env var in order to get more requests per hour. Go to
your personal [access token page](https://github.com/settings/tokens) to
generate a new token.
`packer init` will list all installed plugins then download the latest versions
for the ones that are missing.
+4
View File
@@ -110,6 +110,10 @@ each can be found below:
- `PACKER_CONFIG_DIR` - The location for the home directory of Packer. See
[Packer's home directory](#packer-s-home-directory) for more.
- `PKR_GITHUB_API_TOKEN` - When using Packer init on HCL2 templates, Packer
queries the public API from Github which limits the ammount of queries on can
set the `PKR_GITHUB_API_TOKEN` with a Github Token to make it higher.
- `PACKER_LOG` - Setting this to any value other than "" (empty string) or
"0" will enable the logger. See the [debugging
page](/docs/other/debugging).
@@ -173,7 +173,11 @@ builder, followed by the platform it is building for. For example, the builder
ID of the VMware builder is "hashicorp.vmware".
Post-processors use the builder ID value in order to make some assumptions
about the artifact results, so it is important it never changes.
about the artifact results and to determine whether they are even able to run
against a given artifact, so it is important that this ID never changes once
the builder is published.
The builder ID for each builder is documented on its website docs page.
## Provisioning
@@ -9,6 +9,7 @@ sidebar_title: Alicloud Import
# Alicloud Import Post-Processor
Type: `alicloud-import`
Artifact BuilderId: `packer.post-processor.alicloud-import`
The Packer Alicloud Import post-processor takes a RAW or VHD artifact from
various builders and imports it to an Alicloud ECS Image.
@@ -9,6 +9,7 @@ sidebar_title: Amazon Import
# Amazon Import Post-Processor
Type: `amazon-import`
Artifact BuilderId: `packer.post-processor.amazon-import`
The Packer Amazon Import post-processor takes an OVA artifact from various
builders and imports it to an AMI available to Amazon Web Services EC2.
@@ -19,6 +19,7 @@ sidebar_title: Artifice
# Artifice Post-Processor
Type: `artifice`
Artifact BuilderId: `packer.post-processor.artifice`
The artifice post-processor overrides the artifact list from an upstream
builder or post-processor. All downstream post-processors will see the new
@@ -13,6 +13,7 @@ sidebar_title: Checksum
# Checksum Post-Processor
Type: `checksum`
Artifact BuilderId: `packer.post-processor.checksum`
The checksum post-processor computes specified checksum for the artifact list
from an upstream builder or post-processor. All downstream post-processors will
@@ -9,6 +9,7 @@ sidebar_title: Compress
# Compress Post-Processor
Type: `compress`
Artifact BuilderId: `packer.post-processor.compress`
The Packer compress post-processor takes an artifact with files (such as from
VMware or VirtualBox) and compresses the artifact into a single archive.
@@ -9,6 +9,7 @@ sidebar_title: DigitalOcean Import
# DigitalOcean Import Post-Processor
Type: `digitalocean-import`
Artifact BuilderId: `packer.post-processor.digitalocean-import`
The Packer DigitalOcean Import post-processor is used to import images created by other Packer builders to DigitalOcean.
@@ -11,6 +11,7 @@ sidebar_title: Docker Import
# Docker Import Post-Processor
Type: `docker-import`
Artifact BuilderId: `packer.post-processor.docker-import`
The Packer Docker import post-processor takes an artifact from the [docker
builder](/docs/builders/docker) and imports it with Docker locally. This
@@ -9,6 +9,7 @@ sidebar_title: Docker Push
# Docker Push Post-Processor
Type: `docker-push`
Artifact BuilderId: `packer.post-processor.docker-import`
The Packer Docker push post-processor takes an artifact from the
[docker-import](/docs/post-processors/docker-import) post-processor and
@@ -15,6 +15,7 @@ sidebar_title: Docker Save
# Docker Save Post-Processor
Type: `docker-save`
Artifact BuilderId: `packer.post-processor.docker-save`
The Packer Docker Save post-processor takes an artifact from the [docker
builder](/docs/builders/docker) that was committed and saves it to a file.
@@ -11,6 +11,7 @@ sidebar_title: Docker Tag
# Docker Tag Post-Processor
Type: `docker-tag`
Artifact BuilderId: `packer.post-processor.docker-tag`
The Packer Docker Tag post-processor takes an artifact from the [docker
builder](/docs/builders/docker) that was committed and tags it into a
@@ -9,6 +9,7 @@ sidebar_title: Exoscale Import
# Exoscale Import Post-Processor
Type: `exoscale-import`
Artifact BuilderId: `packer.post-processor.exoscale-import`
The Packer Exoscale Import post-processor takes an image artifact from
the QEMU, Artifice, or File builders and imports it to Exoscale.
@@ -11,6 +11,7 @@ sidebar_title: Google Compute Export
# Google Compute Image Exporter Post-Processor
Type: `googlecompute-export`
Artifact BuilderId: `packer.post-processor.googlecompute-export`
The Google Compute Image Exporter post-processor exports the resultant image
from a googlecompute build as a gzipped tarball to Google Cloud Storage (GCS).
@@ -9,6 +9,7 @@ sidebar_title: Google Compute Import
# Google Compute Image Import Post-Processor
Type: `googlecompute-import`
Artifact BuilderId: `packer.post-processor.googlecompute-import`
The Google Compute Image Import post-processor takes a compressed raw disk
image and imports it to a GCE image available to Google Compute Engine.
@@ -9,6 +9,7 @@ sidebar_title: Manifest
# Manifest Post-Processor
Type: `manifest`
Artifact BuilderId: `packer.post-processor.manifest`
The manifest post-processor writes a JSON file with a list of all of the
artifacts packer produces during a run. If your packer template includes
@@ -10,6 +10,7 @@ sidebar_title: UCloud Import
# UCloud Import Post-Processor
Type: `ucloud-import`
Artifact BuilderId: `packer.post-processor.ucloud-import`
The Packer UCloud Import post-processor takes the RAW, VHD, VMDK, or qcow2 artifact from various builders and imports it to UCloud customized image list for UHost Instance.
@@ -9,6 +9,7 @@ sidebar_title: Vagrant Cloud
# Vagrant Cloud Post-Processor
Type: `vagrant-cloud`
Artifact BuilderId: `pearkes.post-processor.vagrant-cloud`
[Vagrant Cloud](https://app.vagrantup.com/boxes/search) hosts and serves boxes
to Vagrant, allowing you to version and distribute boxes to an organization in a
@@ -15,6 +15,7 @@ sidebar_title: Vagrant
# Vagrant Post-Processor
Type: `vagrant`
Artifact BuilderId: `mitchellh.post-processor.vagrant`
The Packer Vagrant post-processor takes a build and converts the artifact into
a valid [Vagrant](https://www.vagrantup.com) box, if it can. This lets you use

Some files were not shown because too many files have changed in this diff Show More