mirror of
https://github.com/hashicorp/terraform.git
synced 2026-02-03 20:50:59 -05:00
- The cloud plugin wants a go-tfe client to get stuff from TFC. - Terraform knows how to find all the info you need in order to configure a go-tfe client, but it's sometimes scattered across configs and env vars and credentials helpers, and trying to re-implement the resolution logic identically in another codebase would be error-prone. - Therefore, it'd be best if Terraform did that resolution and just passed the plugin all the config info it needs. There are two options for that handoff: 1. Adding it as an additional argument to the primary Execute RPC interface. 2. Passing it as gRPC metadata, which is a pile of arbitrary key => list-of-strings pairs transmitted via HTTP/2 headers. The crux of the decision here is whether a proliferation of plugin protocol versions whenever we need to add more config data is better or worse than a fuzzy and typeless key/value bag. This PR is an implementation of option 2, for discussion and evaluation. (And after all, this is considered an experimental feature anyway.) It assembles the necessary information, translates it to the required metadata format, and attaches it to the request at the proper moment to get everything over to the plugin. As previous commits foreshadowed, we're leaning on the existing logic in the Cloud backend for pretty much all of this.
53 lines
1.8 KiB
Go
53 lines
1.8 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package cloudplugin1
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net/rpc"
|
|
|
|
"github.com/hashicorp/go-plugin"
|
|
"github.com/hashicorp/terraform/internal/cloudplugin"
|
|
"github.com/hashicorp/terraform/internal/cloudplugin/cloudproto1"
|
|
"google.golang.org/grpc"
|
|
"google.golang.org/grpc/metadata"
|
|
)
|
|
|
|
// GRPCCloudPlugin is the go-plugin implementation, but only the client
|
|
// implementation exists in this package.
|
|
type GRPCCloudPlugin struct {
|
|
plugin.GRPCPlugin
|
|
Impl cloudplugin.Cloud1
|
|
// 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
|
|
}
|
|
|
|
// Server always returns an error; we're only implementing the GRPCPlugin
|
|
// interface, not the Plugin interface.
|
|
func (p *GRPCCloudPlugin) Server(*plugin.MuxBroker) (interface{}, error) {
|
|
return nil, errors.New("cloudplugin only implements gRPC clients")
|
|
}
|
|
|
|
// Client always returns an error; we're only implementing the GRPCPlugin
|
|
// interface, not the Plugin interface.
|
|
func (p *GRPCCloudPlugin) Client(*plugin.MuxBroker, *rpc.Client) (interface{}, error) {
|
|
return nil, errors.New("cloudplugin only implements gRPC clients")
|
|
}
|
|
|
|
// GRPCServer always returns an error; we're only implementing the client
|
|
// interface, not the server.
|
|
func (p *GRPCCloudPlugin) GRPCServer(broker *plugin.GRPCBroker, s *grpc.Server) error {
|
|
return errors.New("cloudplugin only implements gRPC clients")
|
|
}
|
|
|
|
// GRPCClient returns a new GRPC client for interacting with the cloud plugin server.
|
|
func (p *GRPCCloudPlugin) GRPCClient(ctx context.Context, broker *plugin.GRPCBroker, c *grpc.ClientConn) (interface{}, error) {
|
|
ctx = metadata.NewOutgoingContext(ctx, p.Metadata)
|
|
return &GRPCCloudClient{
|
|
client: cloudproto1.NewCommandServiceClient(c),
|
|
context: ctx,
|
|
}, nil
|
|
}
|