packer: link to docs if a component is missing

When a user invokes packer for a build or validation, the template being
processed needs components to be present for Packer to process it
without error.

If the component cannot be found from the plugins loaded (or from the
components bundled with Packer), Packer errors, and the command fails.

This is expected, but the error message does not suggest anything to fix
the error, potantially leaving users confused at the problem.

This commit suggests either a replacement (in case of a typo), or points
to the web documentation for Packer, specifically the integrations, so
they can look for the plugin they're missing, and install it, so
subsequent invocations of Packer work.
update/missing_builder_warning
Lucas Bajolet 2 years ago committed by Lucas Bajolet
parent 9b2d9f4fb3
commit efe182b221

@ -133,10 +133,22 @@ func (cfg *PackerConfig) initializeBlocks() hcl.Diagnostics {
// its body.
srcUsage := &(build.Sources[i])
if !cfg.parser.PluginConfig.Builders.Has(srcUsage.Type) {
detail := fmt.Sprintf(
"The %s %s is unknown by Packer, and is likely part of a plugin that is not installed.\n"+
"You may find the needed plugin along with installation instructions documented on the Packer integrations page.\n\n"+
"https://developer.hashicorp.com/packer/integrations?filter=%s",
buildSourceLabel,
srcUsage.Type,
strings.Split(srcUsage.Type, "-")[0],
)
if sugg := didyoumean.NameSuggestion(srcUsage.Type, cfg.parser.PluginConfig.Builders.List()); sugg != "" {
detail = fmt.Sprintf("Did you mean to use %q?", sugg)
}
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + buildSourceLabel + " type " + srcUsage.Type,
Subject: &build.HCL2Ref.DefRange,
Detail: fmt.Sprintf("known builders: %v", cfg.parser.PluginConfig.Builders.List()),
Detail: detail,
Severity: hcl.DiagError,
})
continue
@ -169,10 +181,23 @@ func (cfg *PackerConfig) initializeBlocks() hcl.Diagnostics {
for _, provBlock := range build.ProvisionerBlocks {
if !cfg.parser.PluginConfig.Provisioners.Has(provBlock.PType) {
detail := fmt.Sprintf(
"The %s %s is unknown by Packer, and is likely part of a plugin that is not installed.\n"+
"You may find the needed plugin along with installation instructions documented on the Packer integrations page.\n\n"+
"https://developer.hashicorp.com/packer/integrations?filter=%s",
buildProvisionerLabel,
provBlock.PType,
strings.Split(provBlock.PType, "-")[0],
)
if sugg := didyoumean.NameSuggestion(provBlock.PType, cfg.parser.PluginConfig.Provisioners.List()); sugg != "" {
detail = fmt.Sprintf("Did you mean to use %q?", sugg)
}
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("Unknown "+buildProvisionerLabel+" type %q", provBlock.PType),
Subject: provBlock.HCL2Ref.TypeRange.Ptr(),
Detail: fmt.Sprintf("known "+buildProvisionerLabel+"s: %v", cfg.parser.PluginConfig.Provisioners.List()),
Detail: detail,
Severity: hcl.DiagError,
})
}
@ -180,10 +205,23 @@ func (cfg *PackerConfig) initializeBlocks() hcl.Diagnostics {
if build.ErrorCleanupProvisionerBlock != nil {
if !cfg.parser.PluginConfig.Provisioners.Has(build.ErrorCleanupProvisionerBlock.PType) {
detail := fmt.Sprintf(
"The %s %s is unknown by Packer, and is likely part of a plugin that is not installed.\n"+
"You may find the needed plugin along with installation instructions documented on the Packer integrations page.\n\n"+
"https://developer.hashicorp.com/packer/integrations?filter=%s",
buildErrorCleanupProvisionerLabel,
build.ErrorCleanupProvisionerBlock.PType,
strings.Split(build.ErrorCleanupProvisionerBlock.PType, "-")[0],
)
if sugg := didyoumean.NameSuggestion(build.ErrorCleanupProvisionerBlock.PType, cfg.parser.PluginConfig.Provisioners.List()); sugg != "" {
detail = fmt.Sprintf("Did you mean to use %q?", sugg)
}
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("Unknown "+buildErrorCleanupProvisionerLabel+" type %q", build.ErrorCleanupProvisionerBlock.PType),
Subject: build.ErrorCleanupProvisionerBlock.HCL2Ref.TypeRange.Ptr(),
Detail: fmt.Sprintf("known "+buildErrorCleanupProvisionerLabel+"s: %v", cfg.parser.PluginConfig.Provisioners.List()),
Detail: detail,
Severity: hcl.DiagError,
})
}
@ -192,10 +230,23 @@ func (cfg *PackerConfig) initializeBlocks() hcl.Diagnostics {
for _, ppList := range build.PostProcessorsLists {
for _, ppBlock := range ppList {
if !cfg.parser.PluginConfig.PostProcessors.Has(ppBlock.PType) {
detail := fmt.Sprintf(
"The %s %s is unknown by Packer, and is likely part of a plugin that is not installed.\n"+
"You may find the needed plugin along with installation instructions documented on the Packer integrations page.\n\n"+
"https://developer.hashicorp.com/packer/integrations?filter=%s",
buildPostProcessorLabel,
ppBlock.PType,
strings.Split(ppBlock.PType, "-")[0],
)
if sugg := didyoumean.NameSuggestion(ppBlock.PType, cfg.parser.PluginConfig.PostProcessors.List()); sugg != "" {
detail = fmt.Sprintf("Did you mean to use %q?", sugg)
}
diags = append(diags, &hcl.Diagnostic{
Summary: fmt.Sprintf("Unknown "+buildPostProcessorLabel+" type %q", ppBlock.PType),
Subject: ppBlock.HCL2Ref.TypeRange.Ptr(),
Detail: fmt.Sprintf("known "+buildPostProcessorLabel+"s: %v", cfg.parser.PluginConfig.PostProcessors.List()),
Detail: detail,
Severity: hcl.DiagError,
})
}

@ -18,6 +18,7 @@ import (
multierror "github.com/hashicorp/go-multierror"
version "github.com/hashicorp/go-version"
hcl "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/packer-plugin-sdk/didyoumean"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
"github.com/hashicorp/packer-plugin-sdk/template"
"github.com/hashicorp/packer-plugin-sdk/template/interpolate"
@ -218,15 +219,33 @@ func (c *Core) BuildNames(only, except []string) []string {
func (c *Core) generateCoreBuildProvisioner(rawP *template.Provisioner, rawName string) (CoreBuildProvisioner, error) {
// Get the provisioner
cbp := CoreBuildProvisioner{}
if !c.components.PluginConfig.Provisioners.Has(rawP.Type) {
err := fmt.Errorf(
"The provisioner %s is unknown by Packer, and is likely part of a plugin that is not installed.\n"+
"You may find the needed plugin along with installation instructions documented on the Packer integrations page.\n\n"+
"https://developer.hashicorp.com/packer/integrations?filter=%s",
rawP.Type,
strings.Split(rawP.Type, "-")[0],
)
if sugg := didyoumean.NameSuggestion(rawP.Type, c.components.PluginConfig.Builders.List()); sugg != "" {
err = fmt.Errorf("Did you mean to use %q?", sugg)
}
return cbp, err
}
provisioner, err := c.components.PluginConfig.Provisioners.Start(rawP.Type)
if err != nil {
return cbp, fmt.Errorf(
"error initializing provisioner '%s': %s",
rawP.Type, err)
}
// Seems unlikely that a provisioner doesn't start successfully without error
if provisioner == nil {
return cbp, fmt.Errorf(
"provisioner type not found: %s", rawP.Type)
"provisioner failed to be started and did not error: %s", rawP.Type)
}
// Get the configuration
@ -335,6 +354,22 @@ func (c *Core) Build(n string) (packersdk.Build, error) {
// For reference, the builtin BuilderStore is generated in
// packer/config.go in the Discover() func.
if !c.components.PluginConfig.Builders.Has(configBuilder.Type) {
err := fmt.Errorf(
"The builder %s is unknown by Packer, and is likely part of a plugin that is not installed.\n"+
"You may find the needed plugin along with installation instructions documented on the Packer integrations page.\n\n"+
"https://developer.hashicorp.com/packer/integrations?filter=%s",
configBuilder.Type,
strings.Split(configBuilder.Type, "-")[0],
)
if sugg := didyoumean.NameSuggestion(configBuilder.Type, c.components.PluginConfig.Builders.List()); sugg != "" {
err = fmt.Errorf("Did you mean to use %q?", sugg)
}
return nil, err
}
// the Start command launches the builder plugin of the given type without
// calling Prepare() or passing any build-specific details.
builder, err := c.components.PluginConfig.Builders.Start(configBuilder.Type)
@ -396,6 +431,22 @@ func (c *Core) Build(n string) (packersdk.Build, error) {
break
}
if !c.components.PluginConfig.PostProcessors.Has(rawP.Type) {
err := fmt.Errorf(
"The post-processor %s is unknown by Packer, and is likely part of a plugin that is not installed.\n"+
"You may find the needed plugin along with installation instructions documented on the Packer integrations page.\n\n"+
"https://developer.hashicorp.com/packer/integrations?filter=%s",
rawP.Type,
strings.Split(rawP.Type, "-")[0],
)
if sugg := didyoumean.NameSuggestion(rawP.Type, c.components.PluginConfig.PostProcessors.List()); sugg != "" {
err = fmt.Errorf("Did you mean to use %q?", sugg)
}
return nil, err
}
// Get the post-processor
postProcessor, err := c.components.PluginConfig.PostProcessors.Start(rawP.Type)
if err != nil {

Loading…
Cancel
Save