mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Cloud: Split private readRedactedPlan
func into two
Since `terraform show -json` needs to get a raw hunk of json bytes and sling it right back out again, it's going to be more convenient if plain `show` can ALSO take in raw json. In order for that to happen, I need a function that basically acts like `client.Plans.ReadJSONOutput()`, without eagerly unmarshalling that `jsonformat.Plan` struct. As a slight bonus, this also lets us make the tfe client mocks slightly stupider.
This commit is contained in:
parent
0df3c143bb
commit
2a08a5b46e
@ -5,6 +5,7 @@ package cloud
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
@ -550,11 +551,12 @@ func (b *Cloud) confirm(stopCtx context.Context, op *backend.Operation, opts *te
|
||||
return <-result
|
||||
}
|
||||
|
||||
// This method will fetch the redacted plan output and marshal the response into
|
||||
// a struct the jsonformat.Renderer expects.
|
||||
// This method will fetch the redacted plan output as a byte slice, mirroring
|
||||
// the behavior of the similar client.Plans.ReadJSONOutput method.
|
||||
//
|
||||
// Note: Apologies for the lengthy definition, this is a result of not being able to mock receiver methods
|
||||
var readRedactedPlan func(context.Context, url.URL, string, string) (*jsonformat.Plan, error) = func(ctx context.Context, baseURL url.URL, token string, planID string) (*jsonformat.Plan, error) {
|
||||
// Note: Apologies for the lengthy definition, this is a result of not being
|
||||
// able to mock receiver methods
|
||||
var readRedactedPlan func(context.Context, url.URL, string, string) ([]byte, error) = func(ctx context.Context, baseURL url.URL, token string, planID string) ([]byte, error) {
|
||||
client := retryablehttp.NewClient()
|
||||
client.RetryMax = 10
|
||||
client.RetryWaitMin = 100 * time.Millisecond
|
||||
@ -575,7 +577,6 @@ var readRedactedPlan func(context.Context, url.URL, string, string) (*jsonformat
|
||||
req.Header.Set("Authorization", "Bearer "+token)
|
||||
req.Header.Set("Accept", "application/json")
|
||||
|
||||
p := &jsonformat.Plan{}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -586,10 +587,17 @@ var readRedactedPlan func(context.Context, url.URL, string, string) (*jsonformat
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(p); err != nil {
|
||||
return io.ReadAll(resp.Body)
|
||||
}
|
||||
|
||||
// decodeRedactedPlan unmarshals a downloaded redacted plan into a struct the
|
||||
// jsonformat.Renderer expects.
|
||||
func decodeRedactedPlan(jsonBytes []byte) (*jsonformat.Plan, error) {
|
||||
r := bytes.NewReader(jsonBytes)
|
||||
p := &jsonformat.Plan{}
|
||||
if err := json.NewDecoder(r).Decode(p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
@ -509,10 +509,14 @@ func (b *Cloud) renderPlanLogs(ctx context.Context, op *backend.Operation, run *
|
||||
return err
|
||||
}
|
||||
if renderSRO || shouldGenerateConfig {
|
||||
redactedPlan, err = readRedactedPlan(ctx, b.client.BaseURL(), b.token, run.Plan.ID)
|
||||
jsonBytes, err := readRedactedPlan(ctx, b.client.BaseURL(), b.token, run.Plan.ID)
|
||||
if err != nil {
|
||||
return generalError("Failed to read JSON plan", err)
|
||||
}
|
||||
redactedPlan, err = decodeRedactedPlan(jsonBytes)
|
||||
if err != nil {
|
||||
return generalError("Failed to decode JSON plan", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Write any generated config before rendering the plan, so we can stop in case of errors
|
||||
|
@ -26,7 +26,6 @@ import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/backend"
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat"
|
||||
"github.com/hashicorp/terraform/internal/configs"
|
||||
"github.com/hashicorp/terraform/internal/configs/configschema"
|
||||
"github.com/hashicorp/terraform/internal/httpclient"
|
||||
@ -264,7 +263,7 @@ func testBackend(t *testing.T, obj cty.Value, handlers map[string]func(http.Resp
|
||||
}
|
||||
baseURL.Path = "/api/v2/"
|
||||
|
||||
readRedactedPlan = func(ctx context.Context, baseURL url.URL, token, planID string) (*jsonformat.Plan, error) {
|
||||
readRedactedPlan = func(ctx context.Context, baseURL url.URL, token, planID string) ([]byte, error) {
|
||||
return mc.RedactedPlans.Read(ctx, baseURL.Hostname(), token, planID)
|
||||
}
|
||||
|
||||
@ -332,7 +331,7 @@ func testUnconfiguredBackend(t *testing.T) (*Cloud, func()) {
|
||||
}
|
||||
baseURL.Path = "/api/v2/"
|
||||
|
||||
readRedactedPlan = func(ctx context.Context, baseURL url.URL, token, planID string) (*jsonformat.Plan, error) {
|
||||
readRedactedPlan = func(ctx context.Context, baseURL url.URL, token, planID string) ([]byte, error) {
|
||||
return mc.RedactedPlans.Read(ctx, baseURL.Hostname(), token, planID)
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,6 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
@ -22,7 +21,6 @@ import (
|
||||
tfe "github.com/hashicorp/go-tfe"
|
||||
"github.com/mitchellh/copystructure"
|
||||
|
||||
"github.com/hashicorp/terraform/internal/command/jsonformat"
|
||||
tfversion "github.com/hashicorp/terraform/version"
|
||||
)
|
||||
|
||||
@ -468,13 +466,13 @@ func (m *MockOrganizations) ReadRunQueue(ctx context.Context, name string, optio
|
||||
|
||||
type MockRedactedPlans struct {
|
||||
client *MockClient
|
||||
redactedPlans map[string]*jsonformat.Plan
|
||||
redactedPlans map[string][]byte
|
||||
}
|
||||
|
||||
func newMockRedactedPlans(client *MockClient) *MockRedactedPlans {
|
||||
return &MockRedactedPlans{
|
||||
client: client,
|
||||
redactedPlans: make(map[string]*jsonformat.Plan),
|
||||
redactedPlans: make(map[string][]byte),
|
||||
}
|
||||
}
|
||||
|
||||
@ -495,23 +493,17 @@ func (m *MockRedactedPlans) create(cvID, workspaceID, planID string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
raw, err := ioutil.ReadAll(redactedPlanFile)
|
||||
raw, err := io.ReadAll(redactedPlanFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
redactedPlan := &jsonformat.Plan{}
|
||||
err = json.Unmarshal(raw, redactedPlan)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
m.redactedPlans[planID] = redactedPlan
|
||||
m.redactedPlans[planID] = raw
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MockRedactedPlans) Read(ctx context.Context, hostname, token, planID string) (*jsonformat.Plan, error) {
|
||||
func (m *MockRedactedPlans) Read(ctx context.Context, hostname, token, planID string) ([]byte, error) {
|
||||
if p, ok := m.redactedPlans[planID]; ok {
|
||||
return p, nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user