Merge pull request #9239 from hashicorp/enable_artifice

Add Artifice postprocessor ID to valid artifacts for postprocessors t…
This commit is contained in:
Megan Marsh 2020-05-20 10:46:44 -07:00 committed by GitHub
commit 3c782e9d03
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 117 additions and 23 deletions

View File

@ -14,6 +14,7 @@ import (
"github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/post-processor/artifice"
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
"golang.org/x/oauth2/jwt" "golang.org/x/oauth2/jwt"
) )
@ -92,9 +93,12 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
} }
func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
if artifact.BuilderId() != googlecompute.BuilderId { switch artifact.BuilderId() {
case googlecompute.BuilderId, artifice.BuilderId:
break
default:
err := fmt.Errorf( err := fmt.Errorf(
"Unknown artifact type: %s\nCan only export from Google Compute Engine builder artifacts.", "Unknown artifact type: %s\nCan only export from Google Compute Engine builder and Artifice post-processor artifacts.",
artifact.BuilderId()) artifact.BuilderId())
return nil, false, false, err return nil, false, false, err
} }

View File

@ -19,6 +19,7 @@ import (
"github.com/hashicorp/packer/common" "github.com/hashicorp/packer/common"
"github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/post-processor/artifice"
"github.com/hashicorp/packer/post-processor/compress" "github.com/hashicorp/packer/post-processor/compress"
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
) )
@ -123,9 +124,12 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact
return nil, false, false, err return nil, false, false, err
} }
if artifact.BuilderId() != compress.BuilderId { switch artifact.BuilderId() {
err = fmt.Errorf( case compress.BuilderId, artifice.BuilderId:
"incompatible artifact type: %s\nCan only import from Compress post-processor artifacts", break
default:
err := fmt.Errorf(
"Unknown artifact type: %s\nCan only import from Compress post-processor and Artifice post-processor artifacts.",
artifact.BuilderId()) artifact.BuilderId())
return nil, false, false, err return nil, false, false, err
} }

View File

@ -130,7 +130,7 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
if _, ok := builtins[artifact.BuilderId()]; !ok { if _, ok := builtins[artifact.BuilderId()]; !ok {
return nil, false, false, fmt.Errorf( return nil, false, false, fmt.Errorf(
"Unknown artifact type, requires box from vagrant post-processor or vagrant builder: %s", artifact.BuilderId()) "Unknown artifact type: this post-processor requires an input artifact from the artifice post-processor, vagrant post-processor, or vagrant builder: %s", artifact.BuilderId())
} }
// We assume that there is only one .box file to upload // We assume that there is only one .box file to upload

View File

@ -12,6 +12,7 @@ import (
"io/ioutil" "io/ioutil"
"os" "os"
"path/filepath" "path/filepath"
"strings"
"text/template" "text/template"
"github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/hcl/v2/hcldec"
@ -19,6 +20,7 @@ import (
"github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/packer/tmp" "github.com/hashicorp/packer/packer/tmp"
"github.com/hashicorp/packer/post-processor/artifice"
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
"github.com/mitchellh/mapstructure" "github.com/mitchellh/mapstructure"
) )
@ -42,6 +44,21 @@ var builtins = map[string]string{
"packer.post-processor.docker-push": "docker", "packer.post-processor.docker-push": "docker",
} }
func availableProviders() []string {
dedupedProvidersMap := map[string]string{}
for _, v := range builtins {
dedupedProvidersMap[v] = v
}
dedupedProviders := []string{}
for k := range dedupedProvidersMap {
dedupedProviders = append(dedupedProviders, k)
}
return dedupedProviders
}
type Config struct { type Config struct {
common.PackerConfig `mapstructure:",squash"` common.PackerConfig `mapstructure:",squash"`
@ -51,6 +68,7 @@ type Config struct {
Override map[string]interface{} Override map[string]interface{}
VagrantfileTemplate string `mapstructure:"vagrantfile_template"` VagrantfileTemplate string `mapstructure:"vagrantfile_template"`
VagrantfileTemplateGenerated bool `mapstructure:"vagrantfile_template_generated"` VagrantfileTemplateGenerated bool `mapstructure:"vagrantfile_template_generated"`
ProviderOverride string `mapstructure:"provider_override"`
ctx interpolate.Context ctx interpolate.Context
} }
@ -67,6 +85,22 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
if err := p.configureSingle(&p.config, raws...); err != nil { if err := p.configureSingle(&p.config, raws...); err != nil {
return err return err
} }
if p.config.ProviderOverride != "" {
validOverride := false
providers := availableProviders()
for _, prov := range providers {
if prov == p.config.ProviderOverride {
validOverride = true
break
}
}
if !validOverride {
return fmt.Errorf("The given provider_override %s is not valid. "+
"Please choose from one of %s", p.config.ProviderOverride,
strings.Join(providers, ", "))
}
}
return nil return nil
} }
@ -168,18 +202,28 @@ func (p *PostProcessor) PostProcessProvider(name string, provider Provider, ui p
} }
func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
name := p.config.ProviderOverride
name, ok := builtins[artifact.BuilderId()] if name == "" {
n, ok := builtins[artifact.BuilderId()]
if !ok { if !ok {
return nil, false, false, fmt.Errorf( return nil, false, false, fmt.Errorf(
"Unknown artifact type, can't build box: %s", artifact.BuilderId()) "Unknown artifact type, can't build box: %s", artifact.BuilderId())
} }
name = n
}
provider := providerForName(name) provider := providerForName(name)
if provider == nil { if provider == nil {
if artifact.BuilderId() == artifice.BuilderId {
return nil, false, false, fmt.Errorf(
"Unknown provider type: When using an artifact created by " +
"the artifice post-processor, you need to set the " +
"provider_override option.")
} else {
// This shouldn't happen since we hard code all of these ourselves // This shouldn't happen since we hard code all of these ourselves
panic(fmt.Sprintf("bad provider name: %s", name)) panic(fmt.Sprintf("bad provider name: %s", name))
} }
}
artifact, keep, err := p.PostProcessProvider(name, provider, ui, artifact) artifact, keep, err := p.PostProcessProvider(name, provider, ui, artifact)

View File

@ -22,6 +22,7 @@ type FlatConfig struct {
Override map[string]interface{} `cty:"override"` Override map[string]interface{} `cty:"override"`
VagrantfileTemplate *string `mapstructure:"vagrantfile_template" cty:"vagrantfile_template"` VagrantfileTemplate *string `mapstructure:"vagrantfile_template" cty:"vagrantfile_template"`
VagrantfileTemplateGenerated *bool `mapstructure:"vagrantfile_template_generated" cty:"vagrantfile_template_generated"` VagrantfileTemplateGenerated *bool `mapstructure:"vagrantfile_template_generated" cty:"vagrantfile_template_generated"`
ProviderOverride *string `mapstructure:"provider_override" cty:"provider_override"`
} }
// FlatMapstructure returns a new FlatConfig. // FlatMapstructure returns a new FlatConfig.
@ -49,6 +50,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec {
"override": &hcldec.AttrSpec{Name: "override", Type: cty.Map(cty.String), Required: false}, "override": &hcldec.AttrSpec{Name: "override", Type: cty.Map(cty.String), Required: false},
"vagrantfile_template": &hcldec.AttrSpec{Name: "vagrantfile_template", Type: cty.String, Required: false}, "vagrantfile_template": &hcldec.AttrSpec{Name: "vagrantfile_template", Type: cty.String, Required: false},
"vagrantfile_template_generated": &hcldec.AttrSpec{Name: "vagrantfile_template_generated", Type: cty.Bool, Required: false}, "vagrantfile_template_generated": &hcldec.AttrSpec{Name: "vagrantfile_template_generated", Type: cty.Bool, Required: false},
"provider_override": &hcldec.AttrSpec{Name: "provider_override", Type: cty.String, Required: false},
} }
return s return s
} }

View File

@ -164,6 +164,24 @@ func TestPostProcessorPrepare_vagrantfileTemplateExists(t *testing.T) {
} }
} }
func TestPostProcessorPrepare_ProviderOverrideExists(t *testing.T) {
c := testConfig()
c["provider_override"] = "foo"
var p PostProcessor
if err := p.Configure(c); err == nil {
t.Fatal("Should have errored since foo is not a valid vagrant provider")
}
c = testConfig()
c["provider_override"] = "aws"
if err := p.Configure(c); err != nil {
t.Fatal("Should not have errored since aws is a valid vagrant provider")
}
}
func TestPostProcessorPostProcess_badId(t *testing.T) { func TestPostProcessorPostProcess_badId(t *testing.T) {
artifact := &packer.MockArtifact{ artifact := &packer.MockArtifact{
BuilderIdValue: "invalid.packer", BuilderIdValue: "invalid.packer",

View File

@ -19,6 +19,7 @@ import (
"github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/post-processor/artifice"
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
"github.com/vmware/govmomi" "github.com/vmware/govmomi"
) )
@ -27,6 +28,7 @@ var builtins = map[string]string{
vspherepost.BuilderId: "vmware", vspherepost.BuilderId: "vmware",
vmwcommon.BuilderIdESX: "vmware", vmwcommon.BuilderIdESX: "vmware",
vsphere.BuilderId: "vsphere", vsphere.BuilderId: "vsphere",
artifice.BuilderId: "artifice",
} }
type Config struct { type Config struct {

View File

@ -16,6 +16,7 @@ import (
"github.com/hashicorp/packer/helper/config" "github.com/hashicorp/packer/helper/config"
"github.com/hashicorp/packer/helper/multistep" "github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/hashicorp/packer/post-processor/artifice"
"github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/template/interpolate"
) )
@ -106,9 +107,12 @@ func (p *PostProcessor) Configure(raws ...interface{}) error {
} }
func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) {
if artifact.BuilderId() != yandex.BuilderID { switch artifact.BuilderId() {
case yandex.BuilderID, artifice.BuilderId:
break
default:
err := fmt.Errorf( err := fmt.Errorf(
"Unknown artifact type: %s\nCan only export from Yandex Cloud builder artifacts.", "Unknown artifact type: %s\nCan only export from Yandex Cloud builder artifact or Artifice post-processor artifact.",
artifact.BuilderId()) artifact.BuilderId())
return nil, false, false, err return nil, false, false, err
} }

View File

@ -23,16 +23,18 @@ Type: `artifice`
The artifice post-processor overrides the artifact list from an upstream The artifice post-processor overrides the artifact list from an upstream
builder or post-processor. All downstream post-processors will see the new builder or post-processor. All downstream post-processors will see the new
artifacts you specify. The primary use-case is to build artifacts inside a artifacts you specify.
packer builder -- for example, spinning up an EC2 instance to build a docker
container -- and then extracting the docker container and throwing away the EC2
instance.
After overriding the artifact with artifice, you can use it with other After overriding the artifact with artifice, you can use it with other
post-processors like post-processors, including most of the core post-processors and third-party
[compress](/docs/post-processors/compress), post-processors.
[docker-push](/docs/post-processors/docker-push), or
a third-party post-processor. A major benefit of this is that you can modify builder
artifacts using shell-local and pass those modified artifacts into
post-processors that may not have worked with the original builder.
For example, maybe you want to export a docker container from an amazon-ebs
builder and then use Docker-push to put that Docker container into your Docker
Hub account.
Artifice allows you to use the familiar packer workflow to create a fresh, Artifice allows you to use the familiar packer workflow to create a fresh,
stateless build environment for each build on the infrastructure of your stateless build environment for each build on the infrastructure of your

View File

@ -94,6 +94,13 @@ more details about certain options in following sections.
By default, the value of this config is By default, the value of this config is
`packer_{{.BuildName}}_{{.Provider}}.box`. `packer_{{.BuildName}}_{{.Provider}}.box`.
- `provider_override` (string) - this option will override the internal logic
that decides which Vagrant provider to set for a particular Packer builder's
or post-processor's artifact. It is required when the artifact comes from the
Artifice post-processor, but is otherwise optional. Valid options are:
`digitalocean`, `virtualbox`, `azure`, `vmware`, `libvirt`, `docker`,
`lxc`, `scaleway`, `hyperv`, `parallels`, `aws`, or `google`.
- `vagrantfile_template` (string) - Path to a template to use for the - `vagrantfile_template` (string) - Path to a template to use for the
Vagrantfile that is packaged with the box. Vagrantfile that is packaged with the box.
@ -179,3 +186,10 @@ accelerators: none, kvm, tcg, or hvf.
If you are using the Vagrant post-processor with the `vmware-esxi` builder, you If you are using the Vagrant post-processor with the `vmware-esxi` builder, you
must export the builder artifact locally; the Vagrant post-processor will must export the builder artifact locally; the Vagrant post-processor will
not work on remote artifacts. not work on remote artifacts.
### Artifice
If you are using this post-processor after defining an artifact using the
Artifice post-processor, then you must set the "provider_override" template
option so that the Vagrant post-processor knows what provider to use to create
the Vagrant box.