fix: have terraform output adhere to authorization w/ cloud

Normally, `terraform output` refreshes and reads the entire state in the command package before pulling output values out of it. This doesn't give Terraform Cloud the opportunity to apply the read state outputs org permission and instead applies the read state versions permission.

I decided to expand the state manager interface to provide a separate GetRootOutputValues function in order to give the cloud backend a more nuanced opportunity to fetch just the outputs. This required moving state Refresh/Read code that was previously in the command into the shared backend state as well as the filesystem state packages.
This commit is contained in:
Brandon Croft
2022-03-16 22:47:06 -06:00
parent 5da30c2b65
commit c33c8b013f
16 changed files with 408 additions and 13 deletions

View File

@@ -30,6 +30,7 @@ type MockClient struct {
PolicyChecks *MockPolicyChecks
Runs *MockRuns
StateVersions *MockStateVersions
StateVersionOutputs *MockStateVersionOutputs
Variables *MockVariables
Workspaces *MockWorkspaces
}
@@ -44,6 +45,7 @@ func NewMockClient() *MockClient {
c.PolicyChecks = newMockPolicyChecks(c)
c.Runs = newMockRuns(c)
c.StateVersions = newMockStateVersions(c)
c.StateVersionOutputs = newMockStateVersionOutputs(c)
c.Variables = newMockVariables(c)
c.Workspaces = newMockWorkspaces(c)
return c
@@ -1029,6 +1031,49 @@ func (m *MockStateVersions) ListOutputs(ctx context.Context, svID string, option
panic("not implemented")
}
type MockStateVersionOutputs struct {
client *MockClient
outputs map[string]*tfe.StateVersionOutput
}
func newMockStateVersionOutputs(client *MockClient) *MockStateVersionOutputs {
return &MockStateVersionOutputs{
client: client,
outputs: make(map[string]*tfe.StateVersionOutput),
}
}
// This is a helper function in order to create mocks to be read later
func (m *MockStateVersionOutputs) create(id string, svo *tfe.StateVersionOutput) {
m.outputs[id] = svo
}
func (m *MockStateVersionOutputs) Read(ctx context.Context, outputID string) (*tfe.StateVersionOutput, error) {
result, ok := m.outputs[outputID]
if !ok {
return nil, tfe.ErrResourceNotFound
}
return result, nil
}
func (m *MockStateVersionOutputs) ReadCurrent(ctx context.Context, workspaceID string) (*tfe.StateVersionOutputsList, error) {
svl := &tfe.StateVersionOutputsList{}
for _, sv := range m.outputs {
svl.Items = append(svl.Items, sv)
}
svl.Pagination = &tfe.Pagination{
CurrentPage: 1,
NextPage: 1,
PreviousPage: 1,
TotalPages: 1,
TotalCount: len(svl.Items),
}
return svl, nil
}
type MockVariables struct {
client *MockClient
workspaces map[string]*tfe.VariableList