mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
73 lines
2.0 KiB
Go
73 lines
2.0 KiB
Go
package cloudplugin1
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
|
|
"github.com/opentofu/opentofu/internal/cloudplugin"
|
|
"github.com/opentofu/opentofu/internal/cloudplugin/cloudproto1"
|
|
)
|
|
|
|
// GRPCCloudClient is the client interface for interacting with terraform-cloudplugin
|
|
type GRPCCloudClient struct {
|
|
client cloudproto1.CommandServiceClient
|
|
context context.Context
|
|
}
|
|
|
|
// Proof that GRPCCloudClient fulfills the go-plugin interface
|
|
var _ cloudplugin.Cloud1 = GRPCCloudClient{}
|
|
|
|
// Execute sends the client Execute request and waits for the plugin to return
|
|
// an exit code response before returning
|
|
func (c GRPCCloudClient) Execute(args []string, stdout, stderr io.Writer) int {
|
|
client, err := c.client.Execute(c.context, &cloudproto1.CommandRequest{
|
|
Args: args,
|
|
})
|
|
|
|
if err != nil {
|
|
fmt.Fprint(stderr, err.Error())
|
|
return 1
|
|
}
|
|
|
|
for {
|
|
// cloudplugin streams output as multiple CommandResponse value. Each
|
|
// value will either contain stdout bytes, stderr bytes, or an exit code.
|
|
response, err := client.Recv()
|
|
if err == io.EOF {
|
|
log.Print("[DEBUG] received EOF from cloudplugin")
|
|
break
|
|
} else if err != nil {
|
|
fmt.Fprintf(stderr, "Failed to receive command response from cloudplugin: %s", err)
|
|
return 1
|
|
}
|
|
|
|
if bytes := response.GetStdout(); len(bytes) > 0 {
|
|
_, err := fmt.Fprint(stdout, string(bytes))
|
|
if err != nil {
|
|
log.Printf("[ERROR] Failed to write cloudplugin output to stdout: %s", err)
|
|
return 1
|
|
}
|
|
} else if bytes := response.GetStderr(); len(bytes) > 0 {
|
|
fmt.Fprint(stderr, string(bytes))
|
|
if err != nil {
|
|
log.Printf("[ERROR] Failed to write cloudplugin output to stderr: %s", err)
|
|
return 1
|
|
}
|
|
} else {
|
|
exitCode := response.GetExitCode()
|
|
log.Printf("[TRACE] received exit code: %d", exitCode)
|
|
if exitCode < 0 || exitCode > 255 {
|
|
log.Printf("[ERROR] cloudplugin returned an invalid error code %d", exitCode)
|
|
return 255
|
|
}
|
|
return int(exitCode)
|
|
}
|
|
}
|
|
|
|
// This should indicate a bug in the plugin
|
|
fmt.Fprint(stderr, "cloudplugin exited without responding with an error code")
|
|
return 1
|
|
}
|