Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changes/v1.13/NEW FEATURES-20250513-132953.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
kind: NEW FEATURES
body: 'The new command `terraform stacks` exposes some stack operations through the cli. The available subcommands depend on the stacks plugin implementation. Use `terraform stacks -help` to see available commands.'
time: 2025-05-13T13:29:53.189733-04:00
custom:
Issue: "36931"
6 changes: 6 additions & 0 deletions commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,12 @@ func initCommands(
}, nil
}

Commands["stacks"] = func() (cli.Command, error) {
return &command.StacksCommand{
Meta: meta,
}, nil
}

// "rpcapi" is handled a bit differently because the whole point of
// this interface is to bypass the CLI layer so wrapping automation can
// get as-direct-as-possible access to Terraform Core functionality,
Expand Down
10 changes: 7 additions & 3 deletions internal/cloud/backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ func (b *Cloud) ServiceDiscoveryAliases() ([]backendrun.HostAlias, error) {
}, nil
}

func (b *Cloud) Services() *disco.Disco {
return b.services
}

// Configure implements backend.Backend (which is embedded in backendrun.OperationsBackend).
func (b *Cloud) Configure(obj cty.Value) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
Expand Down Expand Up @@ -292,7 +296,7 @@ func (b *Cloud) Configure(obj cty.Value) tfdiags.Diagnostics {
// Get the token from the CLI Config File in the credentials section
// if no token was set in the configuration
if token == "" {
token, err = cliConfigToken(hostname, b.services)
token, err = CliConfigToken(hostname, b.services)
if err != nil {
diags = diags.Append(tfdiags.AttributeValue(
tfdiags.Error,
Expand Down Expand Up @@ -589,10 +593,10 @@ func resolveCloudConfig(obj cty.Value) (cloudConfig, tfdiags.Diagnostics) {
return ret, diags
}

// cliConfigToken returns the token for this host as configured in the credentials
// CliConfigToken returns the token for this host as configured in the credentials
// section of the CLI Config File. If no token was configured, an empty
// string will be returned instead.
func cliConfigToken(hostname svchost.Hostname, services *disco.Disco) (string, error) {
func CliConfigToken(hostname svchost.Hostname, services *disco.Disco) (string, error) {
creds, err := services.CredentialsForHost(hostname)
if err != nil {
log.Printf("[WARN] Failed to get credentials for %s: %s (ignoring)", hostname.ForDisplay(), err)
Expand Down
2 changes: 1 addition & 1 deletion internal/cloud/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ func (runner *TestSuiteRunner) client(addr tfaddr.Module, id tfe.RegistryModuleI
return nil, nil, diags
}

token, err := cliConfigToken(addr.Package.Host, runner.Services)
token, err := CliConfigToken(addr.Package.Host, runner.Services)
if err != nil {
diags = diags.Append(tfdiags.AttributeValue(
tfdiags.Error,
Expand Down
4 changes: 2 additions & 2 deletions internal/cloudplugin/cloudplugin1/grpc_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"io"
"log"

"github.com/hashicorp/terraform/internal/cloudplugin"
"github.com/hashicorp/terraform/internal/cloudplugin/cloudproto1"
"github.com/hashicorp/terraform/internal/pluginshared"
)

// GRPCCloudClient is the client interface for interacting with terraform-cloudplugin
Expand All @@ -20,7 +20,7 @@ type GRPCCloudClient struct {
}

// Proof that GRPCCloudClient fulfills the go-plugin interface
var _ cloudplugin.Cloud1 = GRPCCloudClient{}
var _ pluginshared.CustomPluginClient = GRPCCloudClient{}

// Execute sends the client Execute request and waits for the plugin to return
// an exit code response before returning
Expand Down
4 changes: 2 additions & 2 deletions internal/cloudplugin/cloudplugin1/grpc_plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"net/rpc"

"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/internal/cloudplugin"
"github.com/hashicorp/terraform/internal/cloudplugin/cloudproto1"
"github.com/hashicorp/terraform/internal/pluginshared"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
)
Expand All @@ -19,7 +19,7 @@ import (
// implementation exists in this package.
type GRPCCloudPlugin struct {
plugin.GRPCPlugin
Impl cloudplugin.Cloud1
Impl pluginshared.CustomPluginClient
// Any configuration metadata that the plugin executable needs in order to
// do something useful, which will be passed along via gRPC metadata headers.
Metadata metadata.MD
Expand Down
6 changes: 3 additions & 3 deletions internal/command/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ import (

"github.com/hashicorp/go-plugin"
"github.com/hashicorp/terraform/internal/cloud"
"github.com/hashicorp/terraform/internal/cloudplugin"
"github.com/hashicorp/terraform/internal/cloudplugin/cloudplugin1"
"github.com/hashicorp/terraform/internal/logging"
"github.com/hashicorp/terraform/internal/pluginshared"
"github.com/hashicorp/terraform/internal/tfdiags"
)

Expand Down Expand Up @@ -112,7 +112,7 @@ func (c *CloudCommand) realRun(args []string, stdout, stderr io.Writer) int {
// Proxy the request
// Note: future changes will need to determine the type of raw when
// multiple versions are possible.
cloud1, ok := raw.(cloudplugin.Cloud1)
cloud1, ok := raw.(pluginshared.CustomPluginClient)
if !ok {
c.Ui.Error("If more than one cloudplugin versions are available, they need to be added to the cloud command. This is a bug in Terraform.")
return ExitRPCError
Expand Down Expand Up @@ -217,7 +217,7 @@ func (c *CloudCommand) initPlugin() tfdiags.Diagnostics {

overridePath := os.Getenv("TF_CLOUD_PLUGIN_DEV_OVERRIDE")

bm, err := cloudplugin.NewBinaryManager(ctx, packagesPath, overridePath, c.pluginService, runtime.GOOS, runtime.GOARCH)
bm, err := pluginshared.NewCloudBinaryManager(ctx, packagesPath, overridePath, c.pluginService, runtime.GOOS, runtime.GOARCH)
if err != nil {
return diags.Append(tfdiags.Sourceless(tfdiags.Error, errorSummary, err.Error()))
}
Expand Down
Loading