backend/remote: extend mocks and add sentinel tests
This commit is contained in:
parent
2bd1040bbd
commit
b28f47055d
|
@ -461,6 +461,9 @@ func (b *Remote) cancel(cancelCtx context.Context, r *tfe.Run) error {
|
|||
if err != nil {
|
||||
return generalError("error cancelling run", err)
|
||||
}
|
||||
if b.CLI != nil {
|
||||
b.CLI.Output(b.Colorize().Color(strings.TrimSpace(cancelPendingOperation)))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -511,6 +514,10 @@ connection problem, in which case you could retry the command. If the issue
|
|||
persists please open a support ticket to get help resolving the problem.
|
||||
`
|
||||
|
||||
const cancelPendingOperation = `[reset][red]
|
||||
Pending remote operation cancelled.[reset]
|
||||
`
|
||||
|
||||
var schemaDescriptions = map[string]string{
|
||||
"hostname": "The remote backend hostname to connect to (defaults to app.terraform.io).",
|
||||
"organization": "The name of the organization containing the targeted workspace(s).",
|
||||
|
|
|
@ -91,7 +91,7 @@ func TestRemote_applyWithVCS(t *testing.T) {
|
|||
<-run.Done()
|
||||
|
||||
if run.Err == nil {
|
||||
t.Fatalf("expected a apply error, got: %v", run.Err)
|
||||
t.Fatalf("expected an apply error, got: %v", run.Err)
|
||||
}
|
||||
if !strings.Contains(run.Err.Error(), "not allowed for workspaces with a VCS") {
|
||||
t.Fatalf("expected a VCS error, got: %v", run.Err)
|
||||
|
@ -116,7 +116,7 @@ func TestRemote_applyWithPlan(t *testing.T) {
|
|||
<-run.Done()
|
||||
|
||||
if run.Err == nil {
|
||||
t.Fatalf("expected a apply error, got: %v", run.Err)
|
||||
t.Fatalf("expected an apply error, got: %v", run.Err)
|
||||
}
|
||||
if !strings.Contains(run.Err.Error(), "saved plan is currently not supported") {
|
||||
t.Fatalf("expected a saved plan error, got: %v", run.Err)
|
||||
|
@ -141,7 +141,7 @@ func TestRemote_applyWithTarget(t *testing.T) {
|
|||
<-run.Done()
|
||||
|
||||
if run.Err == nil {
|
||||
t.Fatalf("expected a apply error, got: %v", run.Err)
|
||||
t.Fatalf("expected an apply error, got: %v", run.Err)
|
||||
}
|
||||
if !strings.Contains(run.Err.Error(), "targeting is currently not supported") {
|
||||
t.Fatalf("expected a targeting error, got: %v", run.Err)
|
||||
|
@ -162,7 +162,7 @@ func TestRemote_applyNoConfig(t *testing.T) {
|
|||
<-run.Done()
|
||||
|
||||
if run.Err == nil {
|
||||
t.Fatalf("expected a apply error, got: %v", run.Err)
|
||||
t.Fatalf("expected an apply error, got: %v", run.Err)
|
||||
}
|
||||
if !strings.Contains(run.Err.Error(), "configuration files found") {
|
||||
t.Fatalf("expected configuration files error, got: %v", run.Err)
|
||||
|
@ -218,10 +218,10 @@ func TestRemote_applyNoApprove(t *testing.T) {
|
|||
|
||||
<-run.Done()
|
||||
if run.Err == nil {
|
||||
t.Fatalf("expected a apply error, got: %v", run.Err)
|
||||
t.Fatalf("expected an apply error, got: %v", run.Err)
|
||||
}
|
||||
if !strings.Contains(run.Err.Error(), "Apply discarded") {
|
||||
t.Fatalf("expected a apply discarded error, got: %v", run.Err)
|
||||
t.Fatalf("expected an apply discarded error, got: %v", run.Err)
|
||||
}
|
||||
if len(input.answers) > 0 {
|
||||
t.Fatalf("expected no unused answers, got: %v", input.answers)
|
||||
|
@ -406,3 +406,175 @@ func TestRemote_applyDestroyNoConfig(t *testing.T) {
|
|||
t.Fatalf("expected no unused answers, got: %v", input.answers)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemote_applyPolicyPass(t *testing.T) {
|
||||
b := testBackendDefault(t)
|
||||
|
||||
mod, modCleanup := module.TestTree(t, "./test-fixtures/apply-policy-passed")
|
||||
defer modCleanup()
|
||||
|
||||
input := testInput(t, map[string]string{
|
||||
"approve": "yes",
|
||||
})
|
||||
|
||||
op := testOperationApply()
|
||||
op.Module = mod
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
t.Fatalf("error starting operation: %v", err)
|
||||
}
|
||||
|
||||
<-run.Done()
|
||||
if run.Err != nil {
|
||||
t.Fatalf("error running operation: %v", run.Err)
|
||||
}
|
||||
|
||||
if len(input.answers) > 0 {
|
||||
t.Fatalf("expected no unused answers, got: %v", input.answers)
|
||||
}
|
||||
|
||||
output := b.CLI.(*cli.MockUi).OutputWriter.String()
|
||||
if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
|
||||
t.Fatalf("missing plan summery in output: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "Sentinel Result: true") {
|
||||
t.Fatalf("missing Sentinel result in output: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
|
||||
t.Fatalf("missing apply summery in output: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemote_applyPolicyHardFail(t *testing.T) {
|
||||
b := testBackendDefault(t)
|
||||
|
||||
mod, modCleanup := module.TestTree(t, "./test-fixtures/apply-policy-hard-failed")
|
||||
defer modCleanup()
|
||||
|
||||
input := testInput(t, map[string]string{
|
||||
"approve": "yes",
|
||||
})
|
||||
|
||||
op := testOperationApply()
|
||||
op.Module = mod
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
t.Fatalf("error starting operation: %v", err)
|
||||
}
|
||||
|
||||
<-run.Done()
|
||||
if run.Err == nil {
|
||||
t.Fatalf("expected an apply error, got: %v", run.Err)
|
||||
}
|
||||
if !strings.Contains(run.Err.Error(), "hard failed") {
|
||||
t.Fatalf("expected a policy check error, got: %v", run.Err)
|
||||
}
|
||||
if len(input.answers) != 1 {
|
||||
t.Fatalf("expected an unused answers, got: %v", input.answers)
|
||||
}
|
||||
|
||||
output := b.CLI.(*cli.MockUi).OutputWriter.String()
|
||||
if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
|
||||
t.Fatalf("missing plan summery in output: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "Sentinel Result: false") {
|
||||
t.Fatalf("missing Sentinel result in output: %s", output)
|
||||
}
|
||||
if strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
|
||||
t.Fatalf("unexpected apply summery in output: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemote_applyPolicySoftFail(t *testing.T) {
|
||||
b := testBackendDefault(t)
|
||||
|
||||
mod, modCleanup := module.TestTree(t, "./test-fixtures/apply-policy-soft-failed")
|
||||
defer modCleanup()
|
||||
|
||||
input := testInput(t, map[string]string{
|
||||
"override": "override",
|
||||
"approve": "yes",
|
||||
})
|
||||
|
||||
op := testOperationApply()
|
||||
op.Module = mod
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
t.Fatalf("error starting operation: %v", err)
|
||||
}
|
||||
|
||||
<-run.Done()
|
||||
if run.Err != nil {
|
||||
t.Fatalf("error running operation: %v", run.Err)
|
||||
}
|
||||
|
||||
if len(input.answers) > 0 {
|
||||
t.Fatalf("expected no unused answers, got: %v", input.answers)
|
||||
}
|
||||
|
||||
output := b.CLI.(*cli.MockUi).OutputWriter.String()
|
||||
if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
|
||||
t.Fatalf("missing plan summery in output: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "Sentinel Result: false") {
|
||||
t.Fatalf("missing Sentinel result in output: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
|
||||
t.Fatalf("missing apply summery in output: %s", output)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemote_applyPolicySoftFailAutoApprove(t *testing.T) {
|
||||
b := testBackendDefault(t)
|
||||
|
||||
mod, modCleanup := module.TestTree(t, "./test-fixtures/apply-policy-soft-failed")
|
||||
defer modCleanup()
|
||||
|
||||
input := testInput(t, map[string]string{
|
||||
"override": "override",
|
||||
})
|
||||
|
||||
op := testOperationApply()
|
||||
op.AutoApprove = true
|
||||
op.Module = mod
|
||||
op.UIIn = input
|
||||
op.UIOut = b.CLI
|
||||
op.Workspace = backend.DefaultStateName
|
||||
|
||||
run, err := b.Operation(context.Background(), op)
|
||||
if err != nil {
|
||||
t.Fatalf("error starting operation: %v", err)
|
||||
}
|
||||
|
||||
<-run.Done()
|
||||
if run.Err != nil {
|
||||
t.Fatalf("error running operation: %v", run.Err)
|
||||
}
|
||||
|
||||
if len(input.answers) > 0 {
|
||||
t.Fatalf("expected no unused answers, got: %v", input.answers)
|
||||
}
|
||||
|
||||
output := b.CLI.(*cli.MockUi).OutputWriter.String()
|
||||
if !strings.Contains(output, "1 to add, 0 to change, 0 to destroy") {
|
||||
t.Fatalf("missing plan summery in output: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "Sentinel Result: false") {
|
||||
t.Fatalf("missing Sentinel result in output: %s", output)
|
||||
}
|
||||
if !strings.Contains(output, "1 added, 0 changed, 0 destroyed") {
|
||||
t.Fatalf("missing apply summery in output: %s", output)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ type mockClient struct {
|
|||
ConfigurationVersions *mockConfigurationVersions
|
||||
Organizations *mockOrganizations
|
||||
Plans *mockPlans
|
||||
PolicyChecks *mockPolicyChecks
|
||||
Runs *mockRuns
|
||||
StateVersions *mockStateVersions
|
||||
Workspaces *mockWorkspaces
|
||||
|
@ -34,6 +35,7 @@ func newMockClient() *mockClient {
|
|||
c.ConfigurationVersions = newMockConfigurationVersions(c)
|
||||
c.Organizations = newMockOrganizations(c)
|
||||
c.Plans = newMockPlans(c)
|
||||
c.PolicyChecks = newMockPolicyChecks(c)
|
||||
c.Runs = newMockRuns(c)
|
||||
c.StateVersions = newMockStateVersions(c)
|
||||
c.Workspaces = newMockWorkspaces(c)
|
||||
|
@ -55,8 +57,7 @@ func newMockApplies(client *mockClient) *mockApplies {
|
|||
}
|
||||
|
||||
// create is a helper function to create a mock apply that uses the configured
|
||||
// working directory to find the logfile. This enables us to test if we are
|
||||
// using the
|
||||
// working directory to find the logfile.
|
||||
func (m *mockApplies) create(cvID, workspaceID string) (*tfe.Apply, error) {
|
||||
c, ok := m.client.ConfigurationVersions.configVersions[cvID]
|
||||
if !ok {
|
||||
|
@ -320,8 +321,7 @@ func newMockPlans(client *mockClient) *mockPlans {
|
|||
}
|
||||
|
||||
// create is a helper function to create a mock plan that uses the configured
|
||||
// working directory to find the logfile. This enables us to test if we are
|
||||
// using the
|
||||
// working directory to find the logfile.
|
||||
func (m *mockPlans) create(cvID, workspaceID string) (*tfe.Plan, error) {
|
||||
id := generateID("plan-")
|
||||
url := fmt.Sprintf("https://app.terraform.io/_archivist/%s", id)
|
||||
|
@ -396,6 +396,133 @@ func (m *mockPlans) Logs(ctx context.Context, planID string) (io.Reader, error)
|
|||
}, nil
|
||||
}
|
||||
|
||||
type mockPolicyChecks struct {
|
||||
client *mockClient
|
||||
checks map[string]*tfe.PolicyCheck
|
||||
logs map[string]string
|
||||
}
|
||||
|
||||
func newMockPolicyChecks(client *mockClient) *mockPolicyChecks {
|
||||
return &mockPolicyChecks{
|
||||
client: client,
|
||||
checks: make(map[string]*tfe.PolicyCheck),
|
||||
logs: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
// create is a helper function to create a mock policy check that uses the
|
||||
// configured working directory to find the logfile.
|
||||
func (m *mockPolicyChecks) create(cvID, workspaceID string) (*tfe.PolicyCheck, error) {
|
||||
id := generateID("pc-")
|
||||
|
||||
pc := &tfe.PolicyCheck{
|
||||
ID: id,
|
||||
Actions: &tfe.PolicyActions{},
|
||||
Permissions: &tfe.PolicyPermissions{},
|
||||
Scope: tfe.PolicyScopeOrganization,
|
||||
Status: tfe.PolicyPending,
|
||||
}
|
||||
|
||||
w, ok := m.client.Workspaces.workspaceIDs[workspaceID]
|
||||
if !ok {
|
||||
return nil, tfe.ErrResourceNotFound
|
||||
}
|
||||
|
||||
logfile := filepath.Join(
|
||||
m.client.ConfigurationVersions.uploadPaths[cvID],
|
||||
w.WorkingDirectory,
|
||||
"policy.log",
|
||||
)
|
||||
|
||||
if _, err := os.Stat(logfile); os.IsNotExist(err) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
m.logs[pc.ID] = logfile
|
||||
m.checks[pc.ID] = pc
|
||||
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
func (m *mockPolicyChecks) List(ctx context.Context, runID string, options tfe.PolicyCheckListOptions) (*tfe.PolicyCheckList, error) {
|
||||
_, ok := m.client.Runs.runs[runID]
|
||||
if !ok {
|
||||
return nil, tfe.ErrResourceNotFound
|
||||
}
|
||||
|
||||
pcl := &tfe.PolicyCheckList{}
|
||||
for _, pc := range m.checks {
|
||||
pcl.Items = append(pcl.Items, pc)
|
||||
}
|
||||
|
||||
pcl.Pagination = &tfe.Pagination{
|
||||
CurrentPage: 1,
|
||||
NextPage: 1,
|
||||
PreviousPage: 1,
|
||||
TotalPages: 1,
|
||||
TotalCount: len(pcl.Items),
|
||||
}
|
||||
|
||||
return pcl, nil
|
||||
}
|
||||
|
||||
func (m *mockPolicyChecks) Read(ctx context.Context, policyCheckID string) (*tfe.PolicyCheck, error) {
|
||||
pc, ok := m.checks[policyCheckID]
|
||||
if !ok {
|
||||
return nil, tfe.ErrResourceNotFound
|
||||
}
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
func (m *mockPolicyChecks) Override(ctx context.Context, policyCheckID string) (*tfe.PolicyCheck, error) {
|
||||
pc, ok := m.checks[policyCheckID]
|
||||
if !ok {
|
||||
return nil, tfe.ErrResourceNotFound
|
||||
}
|
||||
pc.Status = tfe.PolicyOverridden
|
||||
return pc, nil
|
||||
}
|
||||
|
||||
func (m *mockPolicyChecks) Logs(ctx context.Context, policyCheckID string) (io.Reader, error) {
|
||||
pc, ok := m.checks[policyCheckID]
|
||||
if !ok {
|
||||
return nil, tfe.ErrResourceNotFound
|
||||
}
|
||||
|
||||
logfile, ok := m.logs[pc.ID]
|
||||
if !ok {
|
||||
return nil, tfe.ErrResourceNotFound
|
||||
}
|
||||
|
||||
if _, err := os.Stat(logfile); os.IsNotExist(err) {
|
||||
return bytes.NewBufferString("logfile does not exist"), nil
|
||||
}
|
||||
|
||||
logs, err := ioutil.ReadFile(logfile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch {
|
||||
case bytes.Contains(logs, []byte("Sentinel Result: true")):
|
||||
pc.Status = tfe.PolicyPasses
|
||||
case bytes.Contains(logs, []byte("Sentinel Result: false")):
|
||||
switch {
|
||||
case bytes.Contains(logs, []byte("hard-mandatory")):
|
||||
pc.Status = tfe.PolicyHardFailed
|
||||
case bytes.Contains(logs, []byte("soft-mandatory")):
|
||||
pc.Actions.IsOverridable = true
|
||||
pc.Permissions.CanOverride = true
|
||||
pc.Status = tfe.PolicySoftFailed
|
||||
}
|
||||
default:
|
||||
// As this is an unexpected state, we say the policy errored.
|
||||
pc.Status = tfe.PolicyErrored
|
||||
}
|
||||
|
||||
return bytes.NewBuffer(logs), nil
|
||||
}
|
||||
|
||||
type mockRuns struct {
|
||||
client *mockClient
|
||||
runs map[string]*tfe.Run
|
||||
|
@ -443,6 +570,11 @@ func (m *mockRuns) Create(ctx context.Context, options tfe.RunCreateOptions) (*t
|
|||
return nil, err
|
||||
}
|
||||
|
||||
pc, err := m.client.PolicyChecks.create(options.ConfigurationVersion.ID, options.Workspace.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
r := &tfe.Run{
|
||||
ID: generateID("run-"),
|
||||
Actions: &tfe.RunActions{},
|
||||
|
@ -453,6 +585,10 @@ func (m *mockRuns) Create(ctx context.Context, options tfe.RunCreateOptions) (*t
|
|||
Status: tfe.RunPending,
|
||||
}
|
||||
|
||||
if pc != nil {
|
||||
r.PolicyChecks = []*tfe.PolicyCheck{pc}
|
||||
}
|
||||
|
||||
if options.IsDestroy != nil {
|
||||
r.IsDestroy = *options.IsDestroy
|
||||
}
|
||||
|
|
|
@ -144,7 +144,12 @@ func (b *Remote) plan(stopCtx, cancelCtx context.Context, op *backend.Operation,
|
|||
if b.CLI != nil {
|
||||
b.CLI.Output(b.Colorize().Color(strings.TrimSpace(lockTimeoutErr)))
|
||||
}
|
||||
syscall.Kill(syscall.Getpid(), syscall.SIGINT)
|
||||
p, err := os.FindProcess(os.Getpid())
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] error searching process ID: %v", err)
|
||||
return
|
||||
}
|
||||
p.Signal(syscall.SIGINT)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
|
|
@ -1,11 +1,3 @@
|
|||
------------------------------------------------------------------------
|
||||
|
||||
Do you really want to destroy all resources in workspace "my-app-dev"?
|
||||
Terraform will destroy all your managed infrastructure, as shown above.
|
||||
There is no undo. Only 'yes' will be accepted to confirm.
|
||||
|
||||
Enter a value: yes
|
||||
|
||||
null_resource.hello: Destroying... (ID: 8657651096157629581)
|
||||
null_resource.hello: Destruction complete after 0s
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
resource "null_resource" "foo" {}
|
|
@ -0,0 +1,21 @@
|
|||
Terraform v0.11.7
|
||||
|
||||
Configuring remote state backend...
|
||||
Initializing Terraform configuration...
|
||||
Refreshing Terraform state in-memory prior to plan...
|
||||
The refreshed state will be used to calculate this plan, but will not be
|
||||
persisted to local or remote state storage.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
An execution plan has been generated and is shown below.
|
||||
Resource actions are indicated with the following symbols:
|
||||
+ create
|
||||
|
||||
Terraform will perform the following actions:
|
||||
|
||||
+ null_resource.foo
|
||||
id: <computed>
|
||||
|
||||
|
||||
Plan: 1 to add, 0 to change, 0 to destroy.
|
|
@ -0,0 +1,12 @@
|
|||
Sentinel Result: false
|
||||
|
||||
Sentinel evaluated to false because one or more Sentinel policies evaluated
|
||||
to false. This false was not due to an undefined value or runtime error.
|
||||
|
||||
1 policies evaluated.
|
||||
|
||||
## Policy 1: Passthrough.sentinel (hard-mandatory)
|
||||
|
||||
Result: false
|
||||
|
||||
FALSE - Passthrough.sentinel:1:1 - Rule "main"
|
|
@ -0,0 +1,4 @@
|
|||
null_resource.hello: Creating...
|
||||
null_resource.hello: Creation complete after 0s (ID: 8657651096157629581)
|
||||
|
||||
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
|
|
@ -0,0 +1 @@
|
|||
resource "null_resource" "foo" {}
|
|
@ -0,0 +1,21 @@
|
|||
Terraform v0.11.7
|
||||
|
||||
Configuring remote state backend...
|
||||
Initializing Terraform configuration...
|
||||
Refreshing Terraform state in-memory prior to plan...
|
||||
The refreshed state will be used to calculate this plan, but will not be
|
||||
persisted to local or remote state storage.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
An execution plan has been generated and is shown below.
|
||||
Resource actions are indicated with the following symbols:
|
||||
+ create
|
||||
|
||||
Terraform will perform the following actions:
|
||||
|
||||
+ null_resource.foo
|
||||
id: <computed>
|
||||
|
||||
|
||||
Plan: 1 to add, 0 to change, 0 to destroy.
|
|
@ -1,7 +1,3 @@
|
|||
------------------------------------------------------------------------
|
||||
|
||||
Organization policy check:
|
||||
|
||||
Sentinel Result: true
|
||||
|
||||
This result means that Sentinel policies returned true and the protected
|
|
@ -0,0 +1,4 @@
|
|||
null_resource.hello: Creating...
|
||||
null_resource.hello: Creation complete after 0s (ID: 8657651096157629581)
|
||||
|
||||
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
|
|
@ -0,0 +1 @@
|
|||
resource "null_resource" "foo" {}
|
|
@ -0,0 +1,21 @@
|
|||
Terraform v0.11.7
|
||||
|
||||
Configuring remote state backend...
|
||||
Initializing Terraform configuration...
|
||||
Refreshing Terraform state in-memory prior to plan...
|
||||
The refreshed state will be used to calculate this plan, but will not be
|
||||
persisted to local or remote state storage.
|
||||
|
||||
------------------------------------------------------------------------
|
||||
|
||||
An execution plan has been generated and is shown below.
|
||||
Resource actions are indicated with the following symbols:
|
||||
+ create
|
||||
|
||||
Terraform will perform the following actions:
|
||||
|
||||
+ null_resource.foo
|
||||
id: <computed>
|
||||
|
||||
|
||||
Plan: 1 to add, 0 to change, 0 to destroy.
|
|
@ -0,0 +1,12 @@
|
|||
Sentinel Result: false
|
||||
|
||||
Sentinel evaluated to false because one or more Sentinel policies evaluated
|
||||
to false. This false was not due to an undefined value or runtime error.
|
||||
|
||||
1 policies evaluated.
|
||||
|
||||
## Policy 1: Passthrough.sentinel (soft-mandatory)
|
||||
|
||||
Result: false
|
||||
|
||||
FALSE - Passthrough.sentinel:1:1 - Rule "main"
|
|
@ -1,11 +1,3 @@
|
|||
------------------------------------------------------------------------
|
||||
|
||||
Do you want to perform these actions in workspace "my-workspace-name"?
|
||||
Terraform will perform the actions described above.
|
||||
Only 'yes' will be accepted to approve.
|
||||
|
||||
Enter a value: yes
|
||||
|
||||
null_resource.hello: Creating...
|
||||
null_resource.hello: Creation complete after 0s (ID: 8657651096157629581)
|
||||
|
||||
|
|
|
@ -82,6 +82,7 @@ func testBackend(t *testing.T, c map[string]interface{}) *Remote {
|
|||
b.client.ConfigurationVersions = mc.ConfigurationVersions
|
||||
b.client.Organizations = mc.Organizations
|
||||
b.client.Plans = mc.Plans
|
||||
b.client.PolicyChecks = mc.PolicyChecks
|
||||
b.client.Runs = mc.Runs
|
||||
b.client.StateVersions = mc.StateVersions
|
||||
b.client.Workspaces = mc.Workspaces
|
||||
|
|
Loading…
Reference in New Issue