Skip to content

Commit a9d04ec

Browse files
authored
helper/resource: Add TF_ACC_LOG, TF_LOG_CORE, and TF_LOG_PROVIDER environment variable handling for Terraform versions 0.15 and later (#993)
Reference: #992 This enables provider developers to have full control over Terraform CLI logging environment variables with the acceptance testing framework in `helper/resource`. In Terraform CLI 0.15 and later, the logging environment variables work as the following: | Environment Variable | Description | | - | - | | `TF_LOG` | Global logging level for core and providers. Overrides `TF_LOG_CORE` (but not `TF_LOG_PROVIDER`) if set. | | `TF_LOG_CORE` | Logging level for core functionality. No effect if `TF_LOG` is set. | | `TF_LOG_PROVIDER` | Logging level for provider logging sent over plugin file descriptors. | To execute Terraform CLI during acceptance testing, it uses `terraform-exec` for all interactions. `terraform-exec` has certain environment variable handling rules associated with it, to prevent issues with reading stdout/stderr output from calling Terraform CLI since it needs to be able to parse that information. It was recently updated to support setting `TF_LOG`, `TF_LOG_CORE`, and `TF_LOG_PROVIDER` environment variables when calling Terraform, in addition to the prior support for setting `TF_LOG_PATH`, which defaults to always setting `TF_LOG` to `TRACE` if unset. This enhancement allows the acceptance testing framework to accept the `TF_ACC_LOG` environment variable to appropriately set the `TF_LOG` environment variable in `terraform-exec`, if Terraform is version 0.15 or later. We could not change the behavior of the existing `TF_LOG` environment variable as it would cause undesirable side effects with the existing testing framework handling for the Go standard library `log` package. The `TF_ACC_LOG` naming follows the convention of `TF_ACC_LOG_PATH` setting `TF_LOG_PATH`. The `TF_LOG` value defaults to `TRACE`, similar to before, when `TF_ACC_LOG_PATH` or `TF_LOG_PATH_MASK` environment variables are set. This also enables the passthrough of `TF_LOG_CORE` and `TF_LOG_PROVIDER` environment variables to `terraform-exec`. This is required because `terraform-exec` will otherwise default `TF_LOG` to `TRACE` if `TF_LOG_PATH` is used, meaning that without this, provider developers could not disable Terraform core logging. This enhancement opts to not prefix the variables with `TF_ACC_` as there's no prior behaviors to protect and the differing environment variable names for acceptance testing is already confusing enough for everyone. They could still be prefixed for consistency with `TF_ACC_LOG` though, if desired. To summarize the state of logging environment variable with the acceptance testing framework after this change: | Environment Variable | Description | | - | - | | `TF_ACC_LOG` | Controls the Terraform CLI `TF_LOG` environment variable | | `TF_ACC_LOG_PATH` | Controls the Terraform CLI `TF_LOG_PATH` environment variable and where terraform-plugin-log SDK/provider loggers will write logs | | `TF_LOG` | Controls the Go standard library `log` package log level; Any level enables terraform-plugin-log SDK/provider loggers at `TRACE` currently (they have to be tuned down individually at the moment) | | `TF_LOG_CORE` | Controls the Terraform CLI `TF_LOG_CORE` environment variable | | `TF_LOG_PATH_MASK` | Act similar to `TF_ACC_LOG_PATH`, but replaces a `%s` placeholder in the value with individual test names (`(testing.T).Name()`) | | `TF_LOG_PROVIDER` | Controls the Terraform CLI `TF_LOG_PROVIDER` environment variable |
1 parent aad6301 commit a9d04ec

File tree

5 files changed

+166
-4
lines changed

5 files changed

+166
-4
lines changed

.changelog/993.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
helper/resource: Added `TF_ACC_LOG`, `TF_LOG_CORE`, and `TF_LOG_PROVIDER` environment variable handling for Terraform versions 0.15 and later
3+
```

internal/logging/keys.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,15 @@ const (
3131
// The TestStep number of the test being executed. Starts at 1.
3232
KeyTestStepNumber = "test_step_number"
3333

34+
// The Terraform CLI logging level (TF_LOG) used for an acceptance test.
35+
KeyTestTerraformLogLevel = "test_terraform_log_level"
36+
37+
// The Terraform CLI logging level (TF_LOG_CORE) used for an acceptance test.
38+
KeyTestTerraformLogCoreLevel = "test_terraform_log_core_level"
39+
40+
// The Terraform CLI logging level (TF_LOG_PROVIDER) used for an acceptance test.
41+
KeyTestTerraformLogProviderLevel = "test_terraform_log_provider_level"
42+
3443
// The path to the Terraform CLI logging file used for an acceptance test.
3544
//
3645
// This should match where the rest of the acceptance test logs are going

internal/plugintest/environment_variables.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,24 @@ const (
1010
// CLI installation, if installation is required.
1111
EnvTfAccTempDir = "TF_ACC_TEMP_DIR"
1212

13+
// Environment variable with level to filter Terraform logs during
14+
// acceptance testing. This value sets TF_LOG in a safe manner when
15+
// executing Terraform CLI commands, which would otherwise interfere
16+
// with the testing framework using TF_LOG to set the Go standard library
17+
// log package level.
18+
//
19+
// This value takes precedence over TF_LOG_CORE, due to precedence rules
20+
// in the Terraform core code, so it is not possible to set this to a level
21+
// and also TF_LOG_CORE=OFF. Use TF_LOG_CORE and TF_LOG_PROVIDER in that
22+
// case instead.
23+
//
24+
// If not set, but TF_ACC_LOG_PATH or TF_LOG_PATH_MASK is set, it defaults
25+
// to TRACE. If Terraform CLI is version 0.14 or earlier, it will have no
26+
// separate affect from the TF_ACC_LOG_PATH or TF_LOG_PATH_MASK behavior,
27+
// as those earlier versions of Terraform are unreliable with the logging
28+
// level being outside TRACE.
29+
EnvTfAccLog = "TF_ACC_LOG"
30+
1331
// Environment variable with path to save Terraform logs during acceptance
1432
// testing. This value sets TF_LOG_PATH in a safe manner when executing
1533
// Terraform CLI commands, which would otherwise be ignored since it could
@@ -18,6 +36,17 @@ const (
1836
// If TF_LOG_PATH_MASK is set, it takes precedence over this value.
1937
EnvTfAccLogPath = "TF_ACC_LOG_PATH"
2038

39+
// Environment variable with level to filter Terraform core logs during
40+
// acceptance testing. This value sets TF_LOG_CORE separate from
41+
// TF_LOG_PROVIDER when calling Terraform.
42+
//
43+
// This value has no affect when TF_ACC_LOG is set (which sets Terraform's
44+
// TF_LOG), due to precedence rules in the Terraform core code. Use
45+
// TF_LOG_CORE and TF_LOG_PROVIDER in that case instead.
46+
//
47+
// If not set, defaults to TF_ACC_LOG behaviors.
48+
EnvTfLogCore = "TF_LOG_CORE"
49+
2150
// Environment variable with path containing the string %s, which is
2251
// replaced with the test name, to save separate Terraform logs during
2352
// acceptance testing. This value sets TF_LOG_PATH in a safe manner when
@@ -27,6 +56,22 @@ const (
2756
// Takes precedence over TF_ACC_LOG_PATH.
2857
EnvTfLogPathMask = "TF_LOG_PATH_MASK"
2958

59+
// Environment variable with level to filter Terraform provider logs during
60+
// acceptance testing. This value sets TF_LOG_PROVIDER separate from
61+
// TF_LOG_CORE.
62+
//
63+
// During testing, this only affects external providers whose logging goes
64+
// through Terraform. The logging for the provider under test is controlled
65+
// by the testing framework as it is running the provider code. Provider
66+
// code using the Go standard library log package is controlled by TF_LOG
67+
// for historical compatibility.
68+
//
69+
// This value takes precedence over TF_ACC_LOG for external provider logs,
70+
// due to rules in the Terraform core code.
71+
//
72+
// If not set, defaults to TF_ACC_LOG behaviors.
73+
EnvTfLogProvider = "TF_LOG_PROVIDER"
74+
3075
// Environment variable with acceptance testing Terraform CLI version to
3176
// download from releases.hashicorp.com, checksum verify, and install. The
3277
// value can be any valid Terraform CLI version, such as 1.1.6, with or

internal/plugintest/helper.go

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,17 +139,102 @@ func (h *Helper) NewWorkingDir(ctx context.Context, t TestControl) (*WorkingDir,
139139
return nil, fmt.Errorf("unable to disable terraform-exec provider verification: %w", err)
140140
}
141141

142+
tfAccLog := os.Getenv(EnvTfAccLog)
143+
tfAccLogPath := os.Getenv(EnvTfAccLogPath)
144+
tfLogCore := os.Getenv(EnvTfLogCore)
145+
tfLogPathMask := os.Getenv(EnvTfLogPathMask)
146+
tfLogProvider := os.Getenv(EnvTfLogProvider)
147+
148+
if tfAccLog != "" && tfLogCore != "" {
149+
err = fmt.Errorf(
150+
"Invalid environment variable configuration. Cannot set both TF_ACC_LOG and TF_LOG_CORE. " +
151+
"Use TF_LOG_CORE and TF_LOG_PROVIDER to separately control the Terraform CLI logging subsystems. " +
152+
"To control the Go standard library log package for the provider under test, use TF_LOG.",
153+
)
154+
logging.HelperResourceError(ctx, err.Error())
155+
return nil, err
156+
}
157+
158+
if tfAccLog != "" {
159+
logging.HelperResourceTrace(
160+
ctx,
161+
fmt.Sprintf("Setting terraform-exec log level via %s environment variable, if Terraform CLI is version 0.15 or later", EnvTfAccLog),
162+
map[string]interface{}{logging.KeyTestTerraformLogLevel: tfAccLog},
163+
)
164+
165+
err := tf.SetLog(tfAccLog)
166+
167+
if err != nil {
168+
if !errors.As(err, new(*tfexec.ErrVersionMismatch)) {
169+
logging.HelperResourceError(
170+
ctx,
171+
"Unable to set terraform-exec log level",
172+
map[string]interface{}{logging.KeyError: err.Error()},
173+
)
174+
return nil, fmt.Errorf("unable to set terraform-exec log level (%s): %w", tfAccLog, err)
175+
}
176+
177+
logging.HelperResourceWarn(
178+
ctx,
179+
fmt.Sprintf("Unable to set terraform-exec log level via %s environment variable, as Terraform CLI is version 0.14 or earlier. It will default to TRACE.", EnvTfAccLog),
180+
map[string]interface{}{logging.KeyTestTerraformLogLevel: "TRACE"},
181+
)
182+
}
183+
}
184+
185+
if tfLogCore != "" {
186+
logging.HelperResourceTrace(
187+
ctx,
188+
fmt.Sprintf("Setting terraform-exec core log level via %s environment variable, if Terraform CLI is version 0.15 or later", EnvTfLogCore),
189+
map[string]interface{}{
190+
logging.KeyTestTerraformLogCoreLevel: tfLogCore,
191+
},
192+
)
193+
194+
err := tf.SetLogCore(tfLogCore)
195+
196+
if err != nil {
197+
logging.HelperResourceError(
198+
ctx,
199+
"Unable to set terraform-exec core log level",
200+
map[string]interface{}{logging.KeyError: err.Error()},
201+
)
202+
return nil, fmt.Errorf("unable to set terraform-exec core log level (%s): %w", tfLogCore, err)
203+
}
204+
}
205+
206+
if tfLogProvider != "" {
207+
logging.HelperResourceTrace(
208+
ctx,
209+
fmt.Sprintf("Setting terraform-exec provider log level via %s environment variable, if Terraform CLI is version 0.15 or later", EnvTfLogProvider),
210+
map[string]interface{}{
211+
logging.KeyTestTerraformLogCoreLevel: tfLogProvider,
212+
},
213+
)
214+
215+
err := tf.SetLogProvider(tfLogProvider)
216+
217+
if err != nil {
218+
logging.HelperResourceError(
219+
ctx,
220+
"Unable to set terraform-exec provider log level",
221+
map[string]interface{}{logging.KeyError: err.Error()},
222+
)
223+
return nil, fmt.Errorf("unable to set terraform-exec provider log level (%s): %w", tfLogProvider, err)
224+
}
225+
}
226+
142227
var logPath, logPathEnvVar string
143228

144-
if tfAccLogPath := os.Getenv(EnvTfAccLogPath); tfAccLogPath != "" {
229+
if tfAccLogPath != "" {
145230
logPath = tfAccLogPath
146231
logPathEnvVar = EnvTfAccLogPath
147232
}
148233

149234
// Similar to helper/logging.LogOutput() and
150235
// terraform-plugin-log/tfsdklog.RegisterTestSink(), the TF_LOG_PATH_MASK
151236
// environment variable should take precedence over TF_ACC_LOG_PATH.
152-
if tfLogPathMask := os.Getenv(EnvTfLogPathMask); tfLogPathMask != "" {
237+
if tfLogPathMask != "" {
153238
// Escape special characters which may appear if we have subtests
154239
testName := strings.Replace(t.Name(), "/", "__", -1)
155240
logPath = fmt.Sprintf(tfLogPathMask, testName)

website/docs/plugin/sdkv2/testing/acceptance-tests/index.mdx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -238,14 +238,34 @@ A number of environment variables are available to control aspects of acceptance
238238
| Environment Variable Name | Default | Description |
239239
|---------------------------|---------|-------------|
240240
| `TF_ACC` | N/A | Set to any value to enable acceptance testing via the [`helper/resource.ParallelTest()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource#ParallelTest) and [`helper/resource.Test()`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource#Test) functions. |
241-
| `TF_ACC_LOG_PATH` | N/A | Set a path for Terraform logs during testing. Refer to `TF_LOG_PATH_MASK` to configure individual log files per test. |
242241
| `TF_ACC_PROVIDER_HOST`: | `registry.terraform.io` | Set the hostname of the provider under test, such as `example.com` in the `example.com/myorg/myprovider` provider source address. This is only required if any [`TestStep.Config`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource#TestStep.Config) specifies a provider source address, such as in the [`terraform` configuration block `required_providers` attribute](https://www.terraform.io/language/settings#specifying-provider-requirements). |
243242
| `TF_ACC_PROVIDER_NAMESPACE` | `hashicorp` | Set the namespace of the provider under test, such as `myorg` in the `registry.terraform.io/myorg/myprovider` provider source address. This is only required if any [`TestStep.Config`](https://pkg.go.dev/github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource#TestStep.Config) specifies a provider source address, such as in the [`terraform` configuration block `required_providers` attribute](https://www.terraform.io/language/settings#specifying-provider-requirements). |
244243
| `TF_ACC_STATE_LINEAGE` | N/A | Set to `1` to enable state lineage debug logs, which are normally suppressed during acceptance testing. |
245244
| `TF_ACC_TEMP_DIR` | Operating system specific via [`os.TempDir()`](https://pkg.go.dev/os#TempDir) | Set a temporary directory used for testing files and installing Terraform CLI, if installation is required. |
246245
| `TF_ACC_TERRAFORM_PATH` | N/A | Set the path to a Terraform CLI binary on the local filesystem to be used during testing. It must be executable. If not found and `TF_ACC_TERRAFORM_VERSION` is not set, an error is returned. |
247246
| `TF_ACC_TERRAFORM_VERSION` | N/A | Set the exact version of Terraform CLI to automatically install into `TF_ACC_TEMP_DIR`. For example, `1.1.6` or `v1.0.11`. |
248-
| `TF_LOG_PATH_MASK` | N/A | Set a file path containing the string `%s`, which is replaced with the test name, to write a separate log file per test. Refer to `TF_ACC_LOG_PATH` to configure a single log file for all tests. |
247+
248+
### Logging Environment Variables
249+
250+
A number of environment variables available to control logging aspects during acceptance test execution. Some of these modify or replace the production behaviors defined in [managing provider log output](/plugin/log/managing) and [debugging Terraform](/internals/debugging).
251+
252+
#### Logging Levels
253+
254+
| Environment Variable Name | Default | Description |
255+
|---------------------------|---------|-------------|
256+
| `TF_ACC_LOG` | N/A | Set the `TF_LOG` environment variable used by Terraform CLI while testing. If set, overrides `TF_LOG_CORE`. Use `TF_LOG_CORE` and `TF_LOG_PROVIDER` to configure separate levels for Terraform CLI logging. |
257+
| `TF_LOG` | N/A | Set the log level for the Go standard library `log` package. If set to any level, sets the `TRACE` log level for any SDK and provider logs written by [`terraform-plugin-log`](/plugin/log/writing). Use the `TF_LOG_SDK*` and `TF_LOG_PROVIDER_*` environment variables described in [managing log output](/plugin/log/managing) to decrease or disable SDK and provider logs written by [`terraform-plugin-log`](/plugin/log/writing). Use `TF_ACC_LOG`, `TF_LOG_CORE`, or `TF_LOG_PROVIDER` environment variables to set the logging levels used by Terraform CLI while testing. |
258+
| `TF_LOG_CORE` | `TF_ACC_LOG` | Set the `TF_LOG_CORE` environment variable used by Terraform CLI logging of graph operations and other core functionality while testing. If `TF_ACC_LOG` is set, this setting has no effect. Use `TF_LOG_PROVIDER` to configure a separate level for Terraform CLI logging of external providers while testing (e.g. defined by the `TestCase` or `TestStep` type `ExternalProviders` field). |
259+
| `TF_LOG_PROVIDER` | `TF_ACC_LOG` | Set the `TF_LOG_PROVIDER` environment variable used by Terraform CLI logging of external providers while testing (e.g. defined by the `TestCase` or `TestStep` type `ExternalProviders` field). If set, overrides `TF_ACC_LOG`. Use `TF_LOG_CORE` to configure a separate level for Terraform CLI logging of graph operations and other core functionality while testing. |
260+
261+
#### Logging Output
262+
263+
By default, there is no logging output when running the `go test` command. Use one of the below environment variables to output logs to the local filesystem or use the `go test` command `-v` (verbose) flag to view logging without writing file(s).
264+
265+
| Environment Variable Name | Default | Description |
266+
|---------------------------|---------|-------------|
267+
| `TF_ACC_LOG_PATH` | N/A | Set a file path for all logs during testing. Use `TF_LOG_PATH_MASK` to configure individual log files per test. |
268+
| `TF_LOG_PATH_MASK` | N/A | Set a file path containing the string `%s`, which is replaced with the test name, to write a separate log file per test. Use `TF_ACC_LOG_PATH` to configure a single log file for all tests. |
249269

250270
## Troubleshooting
251271

0 commit comments

Comments
 (0)