github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/command/internal_plugin.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"strings"
     7  
     8  	"github.com/hashicorp/terraform/plugin"
     9  	"github.com/kardianos/osext"
    10  )
    11  
    12  // InternalPluginCommand is a Command implementation that allows plugins to be
    13  // compiled into the main Terraform binary and executed via a subcommand.
    14  type InternalPluginCommand struct {
    15  	Meta
    16  }
    17  
    18  const TFSPACE = "-TFSPACE-"
    19  
    20  // BuildPluginCommandString builds a special string for executing internal
    21  // plugins. It has the following format:
    22  //
    23  // 	/path/to/terraform-TFSPACE-internal-plugin-TFSPACE-terraform-provider-aws
    24  //
    25  // We split the string on -TFSPACE- to build the command executor. The reason we
    26  // use -TFSPACE- is so we can support spaces in the /path/to/terraform part.
    27  func BuildPluginCommandString(pluginType, pluginName string) (string, error) {
    28  	terraformPath, err := osext.Executable()
    29  	if err != nil {
    30  		return "", err
    31  	}
    32  	parts := []string{terraformPath, "internal-plugin", pluginType, pluginName}
    33  	return strings.Join(parts, TFSPACE), nil
    34  }
    35  
    36  // Internal plugins do not support any CLI args, but we do receive flags that
    37  // main.go:mergeEnvArgs has merged in from EnvCLI. Instead of making main.go
    38  // aware of this exception, we strip all flags from our args. Flags are easily
    39  // identified by the '-' prefix, ensured by the cli package used.
    40  func StripArgFlags(args []string) []string {
    41  	argsNoFlags := []string{}
    42  	for i := range args {
    43  		if !strings.HasPrefix(args[i], "-") {
    44  			argsNoFlags = append(argsNoFlags, args[i])
    45  		}
    46  	}
    47  	return argsNoFlags
    48  }
    49  
    50  func (c *InternalPluginCommand) Run(args []string) int {
    51  	// strip flags from args, only use subcommands.
    52  	args = StripArgFlags(args)
    53  
    54  	if len(args) != 2 {
    55  		log.Printf("Wrong number of args; expected: terraform internal-plugin pluginType pluginName")
    56  		return 1
    57  	}
    58  
    59  	pluginType := args[0]
    60  	pluginName := args[1]
    61  
    62  	log.SetPrefix(fmt.Sprintf("%s-%s (internal) ", pluginName, pluginType))
    63  
    64  	switch pluginType {
    65  	case "provisioner":
    66  		pluginFunc, found := InternalProvisioners[pluginName]
    67  		if !found {
    68  			log.Printf("[ERROR] Could not load provisioner: %s", pluginName)
    69  			return 1
    70  		}
    71  		log.Printf("[INFO] Starting provisioner plugin %s", pluginName)
    72  		plugin.Serve(&plugin.ServeOpts{
    73  			ProvisionerFunc: pluginFunc,
    74  		})
    75  	default:
    76  		log.Printf("[ERROR] Invalid plugin type %s", pluginType)
    77  		return 1
    78  	}
    79  
    80  	return 0
    81  }
    82  
    83  func (c *InternalPluginCommand) Help() string {
    84  	helpText := `
    85  Usage: terraform internal-plugin pluginType pluginName
    86  
    87    Runs an internally-compiled version of a plugin from the terraform binary.
    88  
    89    NOTE: this is an internal command and you should not call it yourself.
    90  `
    91  
    92  	return strings.TrimSpace(helpText)
    93  }
    94  
    95  func (c *InternalPluginCommand) Synopsis() string {
    96  	return "internal plugin command"
    97  }