Skip to content

Commit 33b149a

Browse files
committed
remove init changes
1 parent 1050f5e commit 33b149a

4 files changed

Lines changed: 148 additions & 318 deletions

File tree

internal/command/apply_policy_test.go

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package command
66
import (
77
"context"
88
"os"
9-
"strings"
109
"testing"
1110

1211
"github.com/hashicorp/hcl/v2"
@@ -141,10 +140,18 @@ func TestApply_WithPolicyDiagnosticsJSON(t *testing.T) {
141140
t.Fatalf("bad: %d\n\n%s", code, output.Stdout())
142141
}
143142

144-
all := output.All()
145-
if !strings.Contains(all, "policy denied") {
146-
t.Fatalf("expected %q in output, got:\n%s", "policy denied", all)
147-
}
143+
expected := `{"@level":"info","@message":"Terraform 1.15.0-dev","@module":"terraform.ui","terraform":"1.15.0-dev","type":"version","ui":"1.2"}
144+
{"@level":"info","@message":"data.test_data_source.a: Refreshing...","@module":"terraform.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read"},"type":"apply_start"}
145+
{"@level":"info","@message":"data.test_data_source.a: Refresh complete after 0s [id=zzzzz]","@module":"terraform.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read","id_key":"id","id_value":"zzzzz","elapsed_seconds":0},"type":"apply_complete"}
146+
{"@level":"info","@message":"test_instance.foo: Plan to create","@module":"terraform.ui","change":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"planned_change"}
147+
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","changes":{"add":1,"change":0,"import":0,"remove":0,"action_invocation":0,"operation":"plan"},"type":"change_summary"}
148+
{"@level":"info","@message":"test_instance.foo: Creating...","@module":"terraform.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"apply_start"}
149+
{"@level":"info","@message":"test_instance.foo: Creation complete after 0s","@module":"terraform.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create","elapsed_seconds":0},"type":"apply_complete"}
150+
{"@level":"error","@message":"Error: policy denied","@module":"terraform.ui","@policy":"true","target_address":"test_instance.foo","policy_diagnostic":{"severity":"error","summary":"policy denied","detail":"","range":{"filename":"main.tf","start":{"line":1,"column":1,"byte":0},"end":{"line":1,"column":31,"byte":30}},"snippet":{"context":null,"code":"resource \"test_instance\" \"foo\" {","start_line":1,"highlight_start_offset":0,"highlight_end_offset":30,"values":[]},"policy_range":{"filename":"policy_file.tfpolicy.hcl","start":{"line":1,"column":1,"byte":0},"end":{"line":2,"column":4,"byte":0}},"policy_snippet":{"context":null,"code":"\t\tresource_policy \"resource_type\" \"policy_name\" {\n\t\t enforce_attrs {\n\t\t key = attr.value == \"foo\"\n\t\t }\n\t\t}\n\t","start_line":1,"highlight_start_offset":1,"highlight_end_offset":100,"values":null}},"policy_metadata":{"enforce_index":1,"policy_set_path":"policy_file.tfpolicy.hcl","policy_name":"resource_policy.foo","file_name":"policy_file.tfpolicy.hcl","enforcement_level":"mandatory"},"result":"DenyResult","type":"policy_diagnostic"}
151+
{"@level":"info","@message":"Policy Result","@module":"terraform.ui","@policy":"true","policy_address":"resource_policy.foo","policy_metadata":{"policy_set_path":"policy_file.tfpolicy.hcl","policy_name":"resource_policy.foo","file_name":"policy_file.tfpolicy.hcl","enforcement_level":"mandatory"},"result":"DenyResult","target_address":"test_instance.foo","type":"policy_result"}
152+
{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"terraform.ui","changes":{"add":1,"change":0,"import":0,"remove":0,"action_invocation":0,"operation":"apply"},"type":"change_summary"}
153+
{"@level":"info","@message":"Outputs: 0","@module":"terraform.ui","outputs":{},"type":"outputs"}`
154+
checkGoldenReferenceStr(t, output, expected)
148155
}
149156

150157
// This tests that the plan policy diagnostic is superceded by the apply policy evaluation.
@@ -286,12 +293,18 @@ func TestApply_WithPlanPolicyDiagnosticsJSON(t *testing.T) {
286293
t.Fatalf("bad: %d\n\n%s", code, output.Stdout())
287294
}
288295

289-
all := output.All()
290-
if !strings.Contains(all, "AllowResult") {
291-
t.Fatalf("expected %q in output, got:\n%s", "AllowResult", all)
292-
293-
}
294-
if strings.Contains(all, "policy denied") {
295-
t.Fatalf("expected apply-time policy result to supersede plan-time denial, got:\n%s", all)
296-
}
296+
// The resulting json only contains the policy result, because the object that
297+
// had a failed policy evaluation during the plan succeeded during apply.
298+
// This can occur when more references become known.
299+
expected := `{"@level":"info","@message":"Terraform 1.15.0-dev","@module":"terraform.ui","terraform":"1.15.0-dev","type":"version","ui":"1.2"}
300+
{"@level":"info","@message":"data.test_data_source.a: Refreshing...","@module":"terraform.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read"},"type":"apply_start"}
301+
{"@level":"info","@message":"data.test_data_source.a: Refresh complete after 0s [id=zzzzz]","@module":"terraform.ui","hook":{"resource":{"addr":"data.test_data_source.a","module":"","resource":"data.test_data_source.a","implied_provider":"test","resource_type":"test_data_source","resource_name":"a","resource_key":null},"action":"read","id_key":"id","id_value":"zzzzz","elapsed_seconds":0},"type":"apply_complete"}
302+
{"@level":"info","@message":"test_instance.foo: Plan to create","@module":"terraform.ui","change":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"planned_change"}
303+
{"@level":"info","@message":"Plan: 1 to add, 0 to change, 0 to destroy.","@module":"terraform.ui","changes":{"add":1,"change":0,"import":0,"remove":0,"action_invocation":0,"operation":"plan"},"type":"change_summary"}
304+
{"@level":"info","@message":"test_instance.foo: Creating...","@module":"terraform.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create"},"type":"apply_start"}
305+
{"@level":"info","@message":"test_instance.foo: Creation complete after 0s","@module":"terraform.ui","hook":{"resource":{"addr":"test_instance.foo","module":"","resource":"test_instance.foo","implied_provider":"test","resource_type":"test_instance","resource_name":"foo","resource_key":null},"action":"create","elapsed_seconds":0,"id_key":"id"},"type":"apply_complete"}
306+
{"@level":"info","@message":"Policy Result","@module":"terraform.ui","@policy":"true","policy_address":"resource_policy.foo","policy_metadata":{"policy_set_path":"policy_file.tfpolicy.hcl","policy_name":"resource_policy.foo","file_name":"policy_file.tfpolicy.hcl","enforcement_level":"mandatory"},"result":"AllowResult","target_address":"test_instance.foo","type":"policy_result"}
307+
{"@level":"info","@message":"Apply complete! Resources: 1 added, 0 changed, 0 destroyed.","@module":"terraform.ui","changes":{"add":1,"change":0,"import":0,"remove":0,"action_invocation":0,"operation":"apply"},"type":"change_summary"}
308+
{"@level":"info","@message":"Outputs: 0","@module":"terraform.ui","outputs":{},"type":"outputs"}`
309+
checkGoldenReferenceStr(t, output, expected)
297310
}

internal/command/meta_policy.go

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,11 @@ import (
77
"context"
88
"fmt"
99
"log"
10-
"maps"
11-
"slices"
1210

1311
"github.com/apparentlymart/go-versions/versions"
1412
"github.com/apparentlymart/go-versions/versions/constraints"
15-
"github.com/zclconf/go-cty/cty"
1613

17-
"github.com/hashicorp/terraform/internal/addrs"
18-
"github.com/hashicorp/terraform/internal/configs"
19-
"github.com/hashicorp/terraform/internal/initwd"
20-
"github.com/hashicorp/terraform/internal/plans"
2114
"github.com/hashicorp/terraform/internal/policy"
22-
"github.com/hashicorp/terraform/internal/policy/proto"
23-
"github.com/hashicorp/terraform/internal/tfdiags"
2415
"github.com/hashicorp/terraform/version"
2516
)
2617

@@ -113,123 +104,3 @@ func (c *Meta) PolicyClient(ctx context.Context, policyPaths []string) (policy.C
113104
log.Printf("[INFO] backend/operation/policy: Policy engine initialized")
114105
return client, diags
115106
}
116-
117-
// policyModuleInstallHook implements initwd.ModuleInstallHook and
118-
// enables policy evaluation during module installation.
119-
type policyModuleInstallHook struct {
120-
initwd.ModuleInstallHooksImpl
121-
client policy.Client
122-
rootModule *configs.Module
123-
policyResults *plans.PolicyResults
124-
}
125-
126-
func (h *policyModuleInstallHook) EvaluatePolicy(ctx context.Context, req *configs.ModuleRequest, source, version string) tfdiags.Diagnostics {
127-
moduleAddr := req.Path.String()
128-
moduleCall := h.rootModule.ModuleCalls[req.Name]
129-
result := h.client.EvaluateModule(ctx, policy.EvaluationRequest[*proto.ModuleMetadata]{
130-
Attrs: cty.NilVal,
131-
Target: source,
132-
Meta: &proto.ModuleMetadata{
133-
Address: moduleAddr,
134-
Source: source,
135-
Version: version,
136-
},
137-
})
138-
139-
if moduleCall != nil && moduleCall.Config != nil {
140-
ptr := moduleCall.DeclRange.Ptr()
141-
for idx, diag := range result.Diagnostics {
142-
result.Diagnostics[idx] = diag.WithLocalRange(ptr)
143-
}
144-
for idx := range result.Enforcements {
145-
result.Enforcements[idx].LocalRange = ptr
146-
}
147-
}
148-
h.policyResults.AddModule(req.Path, result, moduleCall)
149-
150-
// return a generic error here that the init command returns to the CLI.
151-
// The detailed policy diagnostics are included in the policy results
152-
// and will be formatted in the CLI output.
153-
if len(result.Diagnostics) > 0 && result.Diagnostics.AsTerraformDiags().HasErrors() {
154-
return tfdiags.Diagnostics{
155-
policy.NewErrorDiagnostic(
156-
"Policy evaluation failed",
157-
"Module download blocked due to policy violations. Please review other diagnostics for details.",
158-
policy.SetupErrorResult,
159-
),
160-
}
161-
}
162-
return nil
163-
}
164-
165-
type providerInstallerHook struct {
166-
Reqs *configs.ModuleRequirements
167-
Client policy.Client
168-
moduleMap map[addrs.Provider]string
169-
policyResults *plans.PolicyResults
170-
config *configs.Config
171-
}
172-
173-
func (p *providerInstallerHook) moduleSources() map[addrs.Provider]string {
174-
if p.moduleMap != nil {
175-
return p.moduleMap
176-
}
177-
// We iterate through the module requirements to build a map of providers
178-
// to their module source addresses. The first module requirement we encounter
179-
// for each provider will be recorded as the provider's module.
180-
// This matches how Terraform adds providers to the graph.
181-
p.moduleMap = map[addrs.Provider]string{}
182-
moduleReqs := []*configs.ModuleRequirements{p.Reqs}
183-
for len(moduleReqs) != 0 {
184-
moduleReq := moduleReqs[0]
185-
for reqProvider := range moduleReq.Requirements {
186-
if _, ok := p.moduleMap[reqProvider]; ok {
187-
// if we already have a module for this provider, skip
188-
continue
189-
}
190-
191-
// The source is nil in the root module, so we use the root module address.
192-
if moduleReq.SourceAddr == nil {
193-
p.moduleMap[reqProvider] = addrs.RootModule.String()
194-
} else {
195-
p.moduleMap[reqProvider] = moduleReq.SourceAddr.String()
196-
}
197-
}
198-
199-
newReqs := slices.Collect(maps.Values(moduleReq.Children))
200-
moduleReqs = append(moduleReqs[1:], newReqs...)
201-
}
202-
return p.moduleMap
203-
}
204-
205-
func (p *providerInstallerHook) EvaluatePolicy(ctx context.Context, provider addrs.Provider, version string) policy.EvaluationResponse {
206-
// If the client is nil, then policy evaluation is disabled, so we can skip.
207-
if p.Client == nil {
208-
return policy.EvaluationResponse{}
209-
}
210-
moduleSources := p.moduleSources()
211-
log.Println("[DEBUG] init: evaluating policy for provider", provider.String(), version)
212-
result := p.Client.EvaluateProvider(ctx, policy.EvaluationRequest[*proto.ProviderMetadata]{
213-
Target: provider.Type,
214-
215-
// Configuration attributes may not be available during init, so we will not
216-
// send any attributes to the policy client.
217-
Attrs: cty.NilVal,
218-
Meta: &proto.ProviderMetadata{
219-
Name: provider.Type,
220-
Namespace: provider.Namespace,
221-
Type: provider.Type,
222-
Source: provider.String(),
223-
ModulePath: moduleSources[provider],
224-
Version: version,
225-
},
226-
})
227-
// We use the root module as the module for provider configs since the version resolution
228-
// is ambiguous, and we do not know which module the provider config belongs to.
229-
addr := addrs.AbsProviderConfig{Provider: provider, Module: addrs.RootModule}
230-
providerConfig := p.config.Module.ProviderConfigs[provider.Type]
231-
232-
p.policyResults.AddProvider(addr, result, providerConfig)
233-
234-
return result
235-
}

0 commit comments

Comments
 (0)