|
| 1 | +# Go-VCR |
| 2 | + |
| 3 | +The Terraform AWS provider utilizes [`go-vcr`](https://github.com/dnaeon/go-vcr) to improve acceptance test performance and reduce costs. |
| 4 | + |
| 5 | +`go-vcr` is a Go library for recording and replaying HTTP requests. |
| 6 | +In the context of [Terraform provider acceptance testing](https://developer.hashicorp.com/terraform/plugin/framework/acctests), replaying recorded interactions allows core provider logic to be exercised without provisioning real infrastructure. |
| 7 | +The benefits are more pronounced for long-running tests[^1] as the built-in polling mechanisms which would typically wait for resource creation or modification can be by-passed, resulting in quicker feedback loops for developers. |
| 8 | + |
| 9 | +!!! Note |
| 10 | + Maintainers are actively rolling out `go-vcr` support across service packages. |
| 11 | + Not all service will support recording and replaying interactions, and those that do may still have gaps for certain styles of tests. |
| 12 | + Subscribe to this [meta issue](https://github.com/hashicorp/terraform-provider-aws/issues/25602) for progress updates. |
| 13 | + |
| 14 | +## Using `go-vcr` |
| 15 | + |
| 16 | +The AWS provider supports two VCR modes - record and replay. |
| 17 | + |
| 18 | +To enable `go-vcr`, the `VCR_MODE` and `VCR_PATH` environment variables must both be set. |
| 19 | +The valid values for `VCR_MODE` are `RECORD_ONLY` and `REPLAY_ONLY`. |
| 20 | +`VCR_PATH` can point to any path on the local filesystem. |
| 21 | + |
| 22 | +!!! tip |
| 23 | + Always use the same directory for recording and replaying acceptance tests. |
| 24 | + This will maximize re-use of recorded interactions and the corresponding cost savings. |
| 25 | + |
| 26 | +### Recording Tests |
| 27 | + |
| 28 | +`RECORD_ONLY` mode will intercept HTTP interactions made by the provider and write request and response data to a YAML file at the configured path. |
| 29 | +A randomness seed is also stored in a separate file, allowing for replayed interactions to generate the same resource names and appropriately match recorded interaction payloads. |
| 30 | +The file names will match the test case with a `.yaml` and `.seed` extension, respectively. |
| 31 | + |
| 32 | +To record tests, set `VCR_MODE` to `RECORD_ONLY` and `VCR_PATH` to the test recording directory. |
| 33 | +For example, to record Log Group resource tests in the `logs` package: |
| 34 | + |
| 35 | +```sh |
| 36 | +make testacc PKG=logs TESTS=TestAccLogsLogGroup_ VCR_MODE=RECORD_ONLY VCR_PATH=/path/to/testdata/ |
| 37 | +``` |
| 38 | + |
| 39 | +### Replaying Tests |
| 40 | + |
| 41 | +`REPLAY_ONLY` mode replays recorded HTTP interactions by reading the local interaction and seed files. |
| 42 | +Each outbound request is matched with a recorded interaction based on the request headers and body. |
| 43 | +When a matching request is found, the recorded response is sent back. |
| 44 | +If no matching interaction can be found, an error is thrown and the test will fail. |
| 45 | + |
| 46 | +!!! tip |
| 47 | + A missing interaction likely represents a gap in `go-vcr` support. |
| 48 | + If the underlying cause is not already being tracked (check the open tasks in the [meta issue](https://github.com/hashicorp/terraform-provider-aws/issues/25602)) a new issue should be opened. |
| 49 | + |
| 50 | +To replay tests, set `VCR_MODE` to `REPLAY_ONLY` and `VCR_PATH` to the test recording directory. |
| 51 | +For example, to replay Log Group resource tests in the `logs` package: |
| 52 | + |
| 53 | +```sh |
| 54 | +make testacc PKG=logs TESTS=TestAccLogsLogGroup_ VCR_MODE=REPLAY_ONLY VCR_PATH=/path/to/testdata/ |
| 55 | +``` |
| 56 | + |
| 57 | +## Enabling `go-vcr` |
| 58 | + |
| 59 | +Enabling `go-vcr` support for a service primarily involves replacing certain functions and data structures with "VCR-aware" equivalents. |
| 60 | +Broadly this includes service clients, acceptance test data structures, status check functionality (waiters), and any functionality which generates names. |
| 61 | + |
| 62 | +Semgrep rules have been written to automate the majority of these changes. |
| 63 | +The `vcr-enable` Make target will apply semgrep rules and then format code and imports for a given package. |
| 64 | + |
| 65 | +```sh |
| 66 | +make vcr-enable PKG=logs |
| 67 | +``` |
| 68 | + |
| 69 | +### Additional Changes |
| 70 | + |
| 71 | +The changes made by semgrep may leave the code in a state which will not compile or conflicts with code generation. |
| 72 | +When this occurs some manual intervention may be required before running acceptance tests. |
| 73 | + |
| 74 | +#### Test Check Helper Functions |
| 75 | + |
| 76 | +The most common manual changes required are to acceptance test check helper functions (similar to "check exists" or "check destroy", but not covered via semgrep), which might now reference a `*testing.T` argument within the function body. |
| 77 | +Adding a `*testing.T` argument to the function signature will resolve the missing reference. |
| 78 | + |
| 79 | +For example, this was the change applied to the `testAccCheckMetricFilterManyExists` helper function in the `logs` package: |
| 80 | + |
| 81 | +```diff |
| 82 | +-func testAccCheckMetricFilterManyExists(ctx context.Context, basename string, n int) resource.TestCheckFunc { |
| 83 | ++func testAccCheckMetricFilterManyExists(ctx context.Context, t *testing.T, basename string, n int) resource.TestCheckFunc { |
| 84 | +``` |
| 85 | + |
| 86 | +#### Generated Tagging Tests |
| 87 | + |
| 88 | +If the service includes resources with generated tags tests, two additional `@Tags` annotations will be required to ensure the generator does not replace the `*testing.T` argument added to the "check exists" and "check destroy" functions by semgrep. |
| 89 | +Add the following annotations to the resource definition: |
| 90 | + |
| 91 | +```go |
| 92 | +// @Testing(existsTakesT=true) |
| 93 | +// @Testing(destroyTakesT=true) |
| 94 | +``` |
| 95 | + |
| 96 | +### Validating Changes |
| 97 | + |
| 98 | +The most time consuming part of enabling `go-vcr` for a service is validating acceptance test results. |
| 99 | +**The full acceptance test suite should run in `RECORD_ONLY` mode with no errors.** |
| 100 | + |
| 101 | +There are known support gaps which may result in test failures when running in `REPLAY_ONLY` mode. |
| 102 | +This is not a blocker for enabling `go-vcr` in the service, though it is worth verifying the failures are caused by known gaps already documented in the meta-issue. |
| 103 | +A new issue should be opened for any failures that appear unrelated to those already being tracked. |
| 104 | + |
| 105 | +Once test validation is complete, a pull request can be opened with the changes and test results. |
| 106 | + |
| 107 | +[^1]: The full acceptance test suite for certain resources can take upwards of 4 hours to complete. These are typically resources which need to provision compute as part of their lifecycle, such as an [RDS](https://aws.amazon.com/rds/) database or [ElastiCache](https://aws.amazon.com/elasticache/) cluster. |
0 commit comments