Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

terraform test: allow computed/mocked values override during planning #36227

Merged
merged 21 commits into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 19 additions & 5 deletions internal/command/test_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -219,12 +219,25 @@ func TestTest_Runs(t *testing.T) {
code: 0,
},
"mocking": {
expectedOut: []string{"6 passed, 0 failed."},
expectedOut: []string{"9 passed, 0 failed."},
code: 0,
},
"mocking-invalid": {
expectedErr: []string{"Invalid outputs attribute"},
initCode: 1,
expectedErr: []string{
"Invalid outputs attribute",
"The override_during attribute must be a value of plan or apply.",
},
initCode: 1,
},
"mocking-error": {
expectedErr: []string{
"Unknown condition value",
"plan_mocked_overridden.tftest.hcl",
"test_resource.primary[0].id",
"plan_mocked_provider.tftest.hcl",
"test_resource.secondary[0].id",
},
code: 1,
},
"dangling_data_block": {
expectedOut: []string{"2 passed, 0 failed."},
Expand Down Expand Up @@ -1748,8 +1761,9 @@ Condition expression could not be evaluated at this time. This means you have
executed a %s block with %s and one of the values your
condition depended on is not known until after the plan has been applied.
Either remove this value from your condition, or execute an %s command
from this %s block.
`, "`run`", "`command = plan`", "`apply`", "`run`"),
from this %s block. Alternatively, if there is an override for this value,
you can make it available during the plan phase by setting %s in the %s block.
`, "`run`", "`command = plan`", "`apply`", "`run`", "`override_during =\nplan`", "`override_`"),
},
"unknown_value_in_vars": {
code: 1,
Expand Down
30 changes: 30 additions & 0 deletions internal/command/testdata/test/mocking-error/child/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
terraform {
required_providers {
test = {
source = "hashicorp/test"
configuration_aliases = [test.primary, test.secondary]
}
}
}

variable "instances" {
type = number
}

resource "test_resource" "primary" {
provider = test.primary
count = var.instances
}

resource "test_resource" "secondary" {
provider = test.secondary
count = var.instances
}

output "primary" {
value = test_resource.primary
}

output "secondary" {
value = test_resource.secondary
}
46 changes: 46 additions & 0 deletions internal/command/testdata/test/mocking-error/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
terraform {
required_providers {
test = {
source = "hashicorp/test"
}
}
}

provider "test" {
alias = "primary"
}

provider "test" {
alias = "secondary"
}

variable "instances" {
type = number
}

variable "child_instances" {
type = number
}

resource "test_resource" "primary" {
provider = test.primary
count = var.instances
}

resource "test_resource" "secondary" {
provider = test.secondary
count = var.instances
}

module "child" {
count = var.instances

source = "./child"

providers = {
test.primary = test.primary
test.secondary = test.secondary
}

instances = var.child_instances
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
mock_provider "test" {
alias = "primary"

mock_resource "test_resource" {
defaults = {
id = "aaaa"
}
}

override_resource {
target = test_resource.primary
values = {
id = "bbbb"
}
}
}

variables {
instances = 1
child_instances = 1
}

// This test will fail because the plan command does not use the
// overridden values for computed properties,
// making the left-hand side of the condition unknown.
run "test" {
command = plan

assert {
condition = test_resource.primary[0].id == "bbbb"
error_message = "plan should not have the overridden value"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
mock_provider "test" {
alias = "secondary"

mock_resource "test_resource" {
defaults = {
id = "ffff"
}
}
}


variables {
instances = 2
child_instances = 1
}

run "test" {
command = plan

assert {
condition = test_resource.secondary[0].id == "ffff"
error_message = "plan should use the mocked provider value when override_during is plan"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
mock_provider "test" {
alias = "primary"
override_during = baz // This should either be plan or apply, therefore this test should fail

mock_resource "test_resource" {
defaults = {
id = "aaaa"
}
}

override_resource {
target = test_resource.primary
values = {
id = "bbbb"
}
}
}

variables {
instances = 1
child_instances = 1
}

run "test" {

assert {
condition = test_resource.primary[0].id == "bbbb"
error_message = "mock not applied"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
mock_provider "test" {
alias = "primary"

mock_resource "test_resource" {
defaults = {
id = "aaaa"
}
}

override_resource {
target = test_resource.primary
override_during = plan
values = {
id = "bbbb"
}
}
}

variables {
instances = 1
child_instances = 1
}

run "test" {
command = plan

assert {
condition = test_resource.primary[0].id == "bbbb"
error_message = "plan should override the value when override_during is plan"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
mock_provider "test" {
alias = "secondary"
override_during = plan

mock_resource "test_resource" {
defaults = {
id = "ffff"
}
}
}


variables {
instances = 2
child_instances = 1
}

run "test" {
command = plan

assert {
condition = test_resource.secondary[0].id == "ffff"
error_message = "plan should use the mocked provider value when override_during is plan"
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
mock_provider "test" {
alias = "primary"
override_during = plan

mock_resource "test_resource" {
defaults = {
id = "aaaa"
}
}

override_resource {
target = test_resource.primary
values = {
id = "bbbb"
}
}

override_resource {
target = test_resource.primary[1]
override_during = apply // this should take precedence over the provider-level override_during
values = {
id = "bbbb"
}
}
}


override_resource {
target = test_resource.secondary[0]
override_during = plan
values = {
id = "ssss"
}
}


variables {
instances = 2
child_instances = 1
}

run "test" {
command = plan

assert {
condition = test_resource.primary[0].id == "bbbb"
error_message = "plan should override the value when override_during is plan"
}

assert {
condition = test_resource.secondary[0].id == "ssss"
error_message = "plan should override the value when override_during is plan"
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,16 @@ run "test" {
error_message = "did not apply mocks"
}

assert {
// Override should not affect the other instances
condition = !contains(["aaaa", "cccc"], test_resource.secondary[0].id)
error_message = "override from another instance affected this instance"
}

assert {
// Provider Override should propagate to the child module
condition = module.child[0].primary[0].id == "aaaa"
error_message = "did not apply mocks"
}

}
Loading
Loading