mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-24 16:10:46 -06:00
Adds cloud
subcommand with some toy options
This commit is contained in:
parent
7111fd1170
commit
2c3d134705
@ -414,6 +414,14 @@ func initCommands(
|
||||
},
|
||||
}
|
||||
|
||||
if meta.AllowExperimentalFeatures {
|
||||
Commands["cloud"] = func() (cli.Command, error) {
|
||||
return &command.CloudCommand{
|
||||
Meta: meta,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
PrimaryCommands = []string{
|
||||
"init",
|
||||
"validate",
|
||||
|
102
internal/command/cloud.go
Normal file
102
internal/command/cloud.go
Normal file
@ -0,0 +1,102 @@
|
||||
package command
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
|
||||
"github.com/hashicorp/go-plugin"
|
||||
"github.com/hashicorp/terraform/internal/cloudplugin"
|
||||
"github.com/hashicorp/terraform/internal/cloudplugin/cloudplugin1"
|
||||
"github.com/hashicorp/terraform/internal/logging"
|
||||
)
|
||||
|
||||
// CloudCommand is a Command implementation that interacts with Terraform
|
||||
// Cloud for operations that are inherently planless. It delegates
|
||||
// all execution to an internal plugin.
|
||||
type CloudCommand struct {
|
||||
Meta
|
||||
}
|
||||
|
||||
const (
|
||||
// DefaultCloudPluginVersion is the implied protocol version, though all
|
||||
// historical versions are defined explicitly.
|
||||
DefaultCloudPluginVersion = 1
|
||||
|
||||
// ExitRPCError is the exit code that is returned if an plugin
|
||||
// communication error occurred.
|
||||
ExitRPCError = 99
|
||||
)
|
||||
|
||||
var (
|
||||
// Handshake is used to verify that the plugin is the appropriate plugin for
|
||||
// the client. This is not a security verification.
|
||||
Handshake = plugin.HandshakeConfig{
|
||||
MagicCookieKey: "TF_CLOUDPLUGIN_MAGIC_COOKIE",
|
||||
MagicCookieValue: "721fca41431b780ff3ad2623838faaa178d74c65e1cfdfe19537c31656496bf9f82d6c6707f71d81c8eed0db9043f79e56ab4582d013bc08ead14f57961461dc",
|
||||
ProtocolVersion: DefaultCloudPluginVersion,
|
||||
}
|
||||
)
|
||||
|
||||
func (c *CloudCommand) proxy(args []string, stdout, stderr io.Writer) int {
|
||||
client := plugin.NewClient(&plugin.ClientConfig{
|
||||
HandshakeConfig: Handshake,
|
||||
AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC},
|
||||
Cmd: exec.Command("./terraform-cloudplugin"),
|
||||
Logger: logging.NewCloudLogger(),
|
||||
VersionedPlugins: map[int]plugin.PluginSet{
|
||||
1: {
|
||||
"cloud": &cloudplugin1.GRPCCloudPlugin{},
|
||||
},
|
||||
},
|
||||
})
|
||||
defer client.Kill()
|
||||
|
||||
// Connect via RPC
|
||||
rpcClient, err := client.Client()
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "Failed to create cloud plugin client: %s", err)
|
||||
return ExitRPCError
|
||||
}
|
||||
|
||||
// Request the plugin
|
||||
raw, err := rpcClient.Dispense("cloud")
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "Failed to request cloud plugin interface: %s", err)
|
||||
return ExitRPCError
|
||||
}
|
||||
|
||||
// Proxy the request
|
||||
cloud1 := raw.(cloudplugin.Cloud1)
|
||||
return cloud1.Execute(args, stdout, stderr)
|
||||
}
|
||||
|
||||
// Run runs the cloud command with the given arguments.
|
||||
func (c *CloudCommand) Run(args []string) int {
|
||||
args = c.Meta.process(args)
|
||||
|
||||
// TODO: Download and verify the signing of the terraform-cloudplugin
|
||||
// release that is appropriate for this OS/Arch
|
||||
if _, err := os.Stat("./terraform-cloudplugin"); err != nil {
|
||||
c.Ui.Warn("terraform-cloudplugin not found. This plugin does not have an official release, yet.")
|
||||
return 1
|
||||
}
|
||||
|
||||
// TODO: Need to use some type of c.Meta handle here
|
||||
return c.proxy(args, os.Stdout, os.Stderr)
|
||||
}
|
||||
|
||||
// Help returns help text for the cloud command.
|
||||
func (c *CloudCommand) Help() string {
|
||||
helpText := new(bytes.Buffer)
|
||||
c.proxy([]string{}, helpText, io.Discard)
|
||||
|
||||
return helpText.String()
|
||||
}
|
||||
|
||||
// Synopsis returns a short summary of the cloud command.
|
||||
func (c *CloudCommand) Synopsis() string {
|
||||
return "Manage Terraform Cloud settings and metadata"
|
||||
}
|
@ -30,6 +30,7 @@ const (
|
||||
// to other loggers, like provisioners and remote-state backends.
|
||||
envLogCore = "TF_LOG_CORE"
|
||||
envLogProvider = "TF_LOG_PROVIDER"
|
||||
envLogCloud = "TF_LOG_CLOUD"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -134,6 +135,20 @@ func NewProviderLogger(prefix string) hclog.Logger {
|
||||
return l
|
||||
}
|
||||
|
||||
// NewCloudLogger returns a logger for the cloud plugin, possibly with a
|
||||
// different log level from the global logger.
|
||||
func NewCloudLogger() hclog.Logger {
|
||||
l := &logPanicWrapper{
|
||||
Logger: logger.Named("cloud"),
|
||||
}
|
||||
|
||||
level := cloudLogLevel()
|
||||
logger.Debug("created cloud logger", "level", level)
|
||||
|
||||
l.SetLevel(level)
|
||||
return l
|
||||
}
|
||||
|
||||
// CurrentLogLevel returns the current log level string based the environment vars
|
||||
func CurrentLogLevel() string {
|
||||
ll, _ := globalLogLevel()
|
||||
@ -149,6 +164,15 @@ func providerLogLevel() hclog.Level {
|
||||
return parseLogLevel(providerEnvLevel)
|
||||
}
|
||||
|
||||
func cloudLogLevel() hclog.Level {
|
||||
providerEnvLevel := strings.ToUpper(os.Getenv(envLogCloud))
|
||||
if providerEnvLevel == "" {
|
||||
providerEnvLevel = strings.ToUpper(os.Getenv(envLog))
|
||||
}
|
||||
|
||||
return parseLogLevel(providerEnvLevel)
|
||||
}
|
||||
|
||||
func globalLogLevel() (hclog.Level, bool) {
|
||||
var json bool
|
||||
envLevel := strings.ToUpper(os.Getenv(envLog))
|
||||
|
Loading…
Reference in New Issue
Block a user