terraform/internal/command/arguments/test.go
Liam Cervante 551ba2e525
Implement controlling destroy functionality within Terraform Test (#37359)
* Add ability to parse backend blocks present in a test file's run blocks, validate configuration (#36541)

* Add ability to parse backend blocks from a run block

* Add validation to avoid multiple backend blocks across run blocks that use the same internal state file. Update tests.

* Add validation to avoid multiple backend blocks within a single run block. Update tests.

* Remove use of quotes in diagnostic messages

* Add validation to avoid backend blocks being used in plan run blocks. Update tests.

* Correct local backend blocks in new test fixtures

* Add test to show that different test files can use same backend block for same state key.

* Add validation to enforce state-storage backend types are used

* Remove TODO comment

We only need to consider one file at a time when checking if a state_key already has a backend associated with it; parallelism in `terraform test` is scoped down to individual files.

* Add validation to assert that the backend block must be in the first apply command for an internal state

* Consolidate backend block validation inside a single if statement

* Add initial version of validation that ensures a backend isn't re-used within a file

* Explicitly set the state_key at the point of parsing the config

TODO: What should be done with method (moduletest.Run).GetStateKey?

* Update test fixture now that reusing backend configs has been made invalid

* Add automated test showing validation of reused configuration blocks

* Skip test due to flakiness, minor change to test config naming

* Update test so it tolerates non-deterministic order run blocks are evaluated in

* Remove unnecessary value assignment to r.StateKey

* Replace use of GetStateKey() with accessing the state key that's now set during test config parsing

* Fix bug so that run blocks using child modules get the correct state key set at parsing time

* Update acceptance test to also cover scenario where root and child module state keys are in use

* Update test name

* Add newline to regex

* Ensure consistent place where repeat backend error is raised from

* Write leftover test state(s) to file (#36614)

* Add additional validation that the backend used in a run is a supported type (#36648)

* Prevent test run when leftover state data is present (#36685)

* `test`: Set the initial state for a state files from a backend, allow the run that defines a backend to write state to the backend (#36646)

* Allow use of backend block to set initial state for a state key

* Note about alternative place to keep 'backend factories'

* Allow the run block defining the backend to write state to it

* Fix rebase

* Change to accessing backend init functions via ContextOpts

* Add tests demonstrating how runs containing backend blocks use and update persisted state

* Fix test fixture

* Address test failure due to trouble opening the state file

This problem doesn't happen on MacOS, so I assume is due to the Linux environment of GitHub runners.

* Fix issue with paths properly

I hope

* Fix defect in test assertion

* Pivot back to approach introduced in 4afc3d7

* Let failing tests write to persistent state, add test case covering that.

I split the acceptance tests into happy/unhappy paths for this, which required some of the helper functions' declarations to be raised up to package-level.

* Change how we update internal state files, so that information about the associated backend is never lost

* Fix UpdateStateFile

* Ensure that the states map set by TestStateTransformer associates a backend with the correct run.

* Misc spelling fixes in comments and a log

* Replace state get/set functions with existing helpers (#36747)

* Replace state get/set functions with existing helpers

* Compare to string representation of state

* Compare to string representation of state

* Terraform Test: Allow skipping cleanup of entire test file or individual run blocks (#36729)

* Add validation to enforce skip_cleanup=false cannot be used with backend blocks (#36857)

* Integrate use of backend blocks in tests with skip_cleanup feature (#36848)

* Fix nil pointer error, update test to not be table-driven

* Make using a backend block implicitly set skip_cleanup to true

* Stop state artefacts being created when a backend is in use and no cleanup errors have occurred

* Return diagnostics so calling code knows if cleanup experienced issues or not

* Update tests to show that when cleanup fails a state artefact is created

* Add comment about why diag not returned

* Bug fix - actually pull in the state from the state manager!

* Split and simplify (?) tests to show the backend block can create and/or reuse prior state

* Update test to use new fixtures, assert about state artefact. Fix nil pointer

* Update test fixture in use, add guardrail for flakiness of forced error during cleanup

* Refactor so resource ID set in only one place

* Add documentation for using a `backend` block during `test` (#36832)

* Add backend as a documented block in a run block

* Add documentation about backend blocks in run blocks.

* Make the relationship between backends and state keys more clear, other improvements

* More test documentation (#36838)

* Terraform Test: cleanup command (#36847)

* Allow cleanup of states that depend on prior runs outputs (#36902)

* terraform test: refactor graph edge calculation

* create fake run block nodes during cleanup operation

* tidy up TODOs

* fix tests

* remove old changes

* Update internal/moduletest/graph/node_state_cleanup.go

Co-authored-by: Samsondeen <40821565+dsa0x@users.noreply.github.com>

* Improve diagnostics around skip_cleanup conflicts (#37385)

* Improve diagnostics around skip_cleanup conflicts

* remove unused dynamic node

* terraform test: refactor manifest file for simplicity (#37412)

* test: refactor apply and plan functions so no run block is needed

* terraform test: write and load state manifest files

* Terraform Test: Allow skipping cleanup of entire test file or individual run blocks (#36729)

* terraform test: add support for skip_cleanup attr

* terraform test: add cleanup command

* terraform test: add backend blocks

* pause

* fix tests

* remove commented code

* terraform test: make controlling destroy functionality experimental (#37419)

* address comments

* Update internal/moduletest/graph/node_state_cleanup.go

Co-authored-by: Samsondeen <40821565+dsa0x@users.noreply.github.com>

---------

Co-authored-by: Samsondeen <40821565+dsa0x@users.noreply.github.com>

* add experimental changelog entries

---------

Co-authored-by: Sarah French <15078782+SarahFrench@users.noreply.github.com>
Co-authored-by: Samsondeen <40821565+dsa0x@users.noreply.github.com>
Co-authored-by: Samsondeen Dare <samsondeen.dare@hashicorp.com>
2025-09-10 17:22:20 +02:00

110 lines
3.9 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package arguments
import (
"github.com/hashicorp/terraform/internal/configs"
"github.com/hashicorp/terraform/internal/tfdiags"
)
// Test represents the command-line arguments for the test command.
type Test struct {
// CloudRunSource specifies the remote private module that this test run
// should execute against in a remote HCP Terraform run.
CloudRunSource string
// Filter contains a list of test files to execute. If empty, all test files
// will be executed.
Filter []string
// OperationParallelism is the limit Terraform places on total parallel operations
// during the plan or apply command within a single test run.
OperationParallelism int
// RunParallelism is the limit Terraform places on parallel test runs. This
// is the number of test runs that can be executed in parallel within a file.
RunParallelism int
// TestDirectory allows the user to override the directory that the test
// command will use to discover test files, defaults to "tests". Regardless
// of the value here, test files within the configuration directory will
// always be discovered.
TestDirectory string
// ViewType specifies which output format to use: human or JSON.
ViewType ViewType
// JUnitXMLFile specifies an optional filename to write a JUnit XML test
// result report to, in addition to the information written to the selected
// view type.
JUnitXMLFile string
// You can specify common variables for all tests from the command line.
Vars *Vars
// Verbose tells the test command to print out the plan either in
// human-readable format or JSON for each run step depending on the
// ViewType.
Verbose bool
// DeferralAllowed enables deferrals during test operations. This matches
// the same-named flag in the Operation struct.
DeferralAllowed bool
// These flags are only relevant to the "test cleanup" command.
Repair bool
}
func ParseTest(args []string) (*Test, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
test := Test{
Vars: new(Vars),
}
var jsonOutput bool
cmdFlags := extendedFlagSet("test", nil, nil, test.Vars)
cmdFlags.Var((*FlagStringSlice)(&test.Filter), "filter", "filter")
cmdFlags.StringVar(&test.TestDirectory, "test-directory", configs.DefaultTestDirectory, "test-directory")
cmdFlags.BoolVar(&jsonOutput, "json", false, "json")
cmdFlags.StringVar(&test.JUnitXMLFile, "junit-xml", "", "junit-xml")
cmdFlags.BoolVar(&test.Verbose, "verbose", false, "verbose")
cmdFlags.IntVar(&test.OperationParallelism, "parallelism", DefaultParallelism, "parallelism")
cmdFlags.IntVar(&test.RunParallelism, "run-parallelism", DefaultParallelism, "run-parallelism")
cmdFlags.BoolVar(&test.DeferralAllowed, "allow-deferral", false, "allow-deferral")
cmdFlags.BoolVar(&test.Repair, "repair", false, "repair")
// TODO: Finalise the name of this flag.
cmdFlags.StringVar(&test.CloudRunSource, "cloud-run", "", "cloud-run")
if err := cmdFlags.Parse(args); err != nil {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Failed to parse command-line flags",
err.Error()))
}
if len(test.JUnitXMLFile) > 0 && len(test.CloudRunSource) > 0 {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Incompatible command-line flags",
"The -junit-xml option is currently not compatible with remote test execution via the -cloud-run flag. If you are interested in JUnit XML output for remotely-executed tests please open an issue in GitHub."))
}
// Only set the default parallelism if this is not a cloud-run test.
// A cloud-run test will eventually run its own local test, and if the
// user still hasn't set the parallelism, that run will use the default.
if test.OperationParallelism < 1 && len(test.CloudRunSource) == 0 {
test.OperationParallelism = DefaultParallelism
}
switch {
case jsonOutput:
test.ViewType = ViewJSON
default:
test.ViewType = ViewHuman
}
return &test, diags
}