2016-04-05 04:11:11 +02:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
2016-04-26 00:33:53 +02:00
|
|
|
"fmt"
|
2016-04-05 04:11:11 +02:00
|
|
|
"log"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/plugin"
|
|
|
|
"github.com/kardianos/osext"
|
|
|
|
)
|
|
|
|
|
|
|
|
// InternalPluginCommand is a Command implementation that allows plugins to be
|
|
|
|
// compiled into the main Terraform binary and executed via a subcommand.
|
|
|
|
type InternalPluginCommand struct {
|
|
|
|
Meta
|
|
|
|
}
|
|
|
|
|
|
|
|
const TFSPACE = "-TFSPACE-"
|
|
|
|
|
|
|
|
// BuildPluginCommandString builds a special string for executing internal
|
|
|
|
// plugins. It has the following format:
|
|
|
|
//
|
|
|
|
// /path/to/terraform-TFSPACE-internal-plugin-TFSPACE-terraform-provider-aws
|
|
|
|
//
|
|
|
|
// We split the string on -TFSPACE- to build the command executor. The reason we
|
|
|
|
// use -TFSPACE- is so we can support spaces in the /path/to/terraform part.
|
|
|
|
func BuildPluginCommandString(pluginType, pluginName string) (string, error) {
|
|
|
|
terraformPath, err := osext.Executable()
|
|
|
|
if err != nil {
|
|
|
|
return "", err
|
|
|
|
}
|
|
|
|
parts := []string{terraformPath, "internal-plugin", pluginType, pluginName}
|
|
|
|
return strings.Join(parts, TFSPACE), nil
|
|
|
|
}
|
|
|
|
|
2019-12-06 00:00:51 +01:00
|
|
|
// Internal plugins do not support any CLI args, but we do receive flags that
|
|
|
|
// main.go:mergeEnvArgs has merged in from EnvCLI. Instead of making main.go
|
|
|
|
// aware of this exception, we strip all flags from our args. Flags are easily
|
|
|
|
// identified by the '-' prefix, ensured by the cli package used.
|
|
|
|
func StripArgFlags(args []string) []string {
|
|
|
|
argsNoFlags := []string{}
|
|
|
|
for i := range args {
|
|
|
|
if !strings.HasPrefix(args[i], "-") {
|
|
|
|
argsNoFlags = append(argsNoFlags, args[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return argsNoFlags
|
|
|
|
}
|
|
|
|
|
2016-04-05 04:11:11 +02:00
|
|
|
func (c *InternalPluginCommand) Run(args []string) int {
|
2019-12-06 00:00:51 +01:00
|
|
|
// strip flags from args, only use subcommands.
|
|
|
|
args = StripArgFlags(args)
|
|
|
|
|
2016-04-05 04:11:11 +02:00
|
|
|
if len(args) != 2 {
|
|
|
|
log.Printf("Wrong number of args; expected: terraform internal-plugin pluginType pluginName")
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
pluginType := args[0]
|
|
|
|
pluginName := args[1]
|
|
|
|
|
2016-04-26 00:33:53 +02:00
|
|
|
log.SetPrefix(fmt.Sprintf("%s-%s (internal) ", pluginName, pluginType))
|
|
|
|
|
2016-04-05 04:11:11 +02:00
|
|
|
switch pluginType {
|
|
|
|
case "provisioner":
|
|
|
|
pluginFunc, found := InternalProvisioners[pluginName]
|
|
|
|
if !found {
|
|
|
|
log.Printf("[ERROR] Could not load provisioner: %s", pluginName)
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
log.Printf("[INFO] Starting provisioner plugin %s", pluginName)
|
|
|
|
plugin.Serve(&plugin.ServeOpts{
|
|
|
|
ProvisionerFunc: pluginFunc,
|
|
|
|
})
|
|
|
|
default:
|
|
|
|
log.Printf("[ERROR] Invalid plugin type %s", pluginType)
|
|
|
|
return 1
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *InternalPluginCommand) Help() string {
|
|
|
|
helpText := `
|
|
|
|
Usage: terraform internal-plugin pluginType pluginName
|
|
|
|
|
|
|
|
Runs an internally-compiled version of a plugin from the terraform binary.
|
|
|
|
|
|
|
|
NOTE: this is an internal command and you should not call it yourself.
|
|
|
|
`
|
|
|
|
|
|
|
|
return strings.TrimSpace(helpText)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *InternalPluginCommand) Synopsis() string {
|
|
|
|
return "internal plugin command"
|
|
|
|
}
|