mirror of https://github.com/hashicorp/terraform
This doesn't actually do anything useful yet, but this does at least make the RPC server accessible to external callers where they can handshake and then get an error saying that nothing else is implemented.pull/34738/head
parent
38d66ea74d
commit
3bf1a5cf53
@ -0,0 +1,101 @@
|
||||
package rpcapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
// CLICommand is a command initialization callback for use with
|
||||
// github.com/mitchellh/cli, allowing Terraform's "package main" to
|
||||
// jump straight into the RPC plugin server without any interference
|
||||
// from the usual Terraform CLI machinery in package "command", which
|
||||
// is irrelevant here because this RPC API exists to bypass the
|
||||
// Terraform CLI layer as much as possible.
|
||||
func CLICommandFactory(opts CommandFactoryOpts) func() (cli.Command, error) {
|
||||
return func() (cli.Command, error) {
|
||||
return cliCommand{opts}, nil
|
||||
}
|
||||
}
|
||||
|
||||
type CommandFactoryOpts struct {
|
||||
ExperimentsAllowed bool
|
||||
ShutdownCh <-chan struct{}
|
||||
}
|
||||
|
||||
type cliCommand struct {
|
||||
opts CommandFactoryOpts
|
||||
}
|
||||
|
||||
// Help implements cli.Command.
|
||||
func (c cliCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: terraform [global options] rpcapi
|
||||
|
||||
Starts a gRPC server for programmatic access to Terraform Core from
|
||||
wrapping automation.
|
||||
|
||||
This interface is currently intended only for Terraform Cloud and is
|
||||
subject to breaking changes even in patch releases. Do not use this.
|
||||
`
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
// Run implements cli.Command.
|
||||
func (c cliCommand) Run(args []string) int {
|
||||
if len(args) != 0 {
|
||||
fmt.Fprintf(os.Stderr, "This command does not accept any arguments.\n")
|
||||
return 1
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
|
||||
go func() {
|
||||
// We'll adapt the caller's "shutdown channel" into a context
|
||||
// cancellation.
|
||||
for {
|
||||
select {
|
||||
case <-c.opts.ShutdownCh:
|
||||
cancel()
|
||||
case <-ctx.Done():
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
err := ServePlugin(ctx, ServerOpts{
|
||||
ExperimentsAllowed: c.opts.ExperimentsAllowed,
|
||||
})
|
||||
if err != nil {
|
||||
if err == ErrNotPluginClient {
|
||||
fmt.Fprintf(
|
||||
os.Stderr,
|
||||
`
|
||||
This subcommand is for use by Terraform Cloud and is not intended for direct use.
|
||||
Its behavior is not subject to Terraform compatibility promises. To interact
|
||||
with Terraform using the CLI workflow, refer to the main set of subcommands by
|
||||
running the following command:
|
||||
terraform help
|
||||
|
||||
`)
|
||||
} else {
|
||||
fmt.Fprintf(os.Stderr, "Failed to start RPC server: %s.\n", err)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
// NOTE: In practice it's impossible to get here, because if ServePlugin
|
||||
// doesn't error then it blocks forever and then eventually terminates
|
||||
// the process itself without returning.
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// Synopsis implements cli.Command.
|
||||
func (c cliCommand) Synopsis() string {
|
||||
return "An RPC server used for integration with wrapping automation"
|
||||
}
|
||||
Loading…
Reference in new issue