Skip to content

helper/resource: compatibility refresh after config mode test step #496

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

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions helper/resource/compatibility.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package resource

// Deprecated. This is an undocumented compatibility flag. When
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deprecated

This is about the flexibility to remove this flag some day. There is no timetable or specific urgency for that. If we get feedback that this flag is super effective & we do not come up with a better alternative in the future, then I have no desire to break it 😃

// `RefreshAfterApply` is set to non-empty, a `Config`-mode test step will
// invoke a refresh before successful completion. This is intended as a
// compatibility measure for test cases that have different -- but
// semantically-equal -- state representations in their test steps. When
// comparing two states, the testing framework is not aware of semantic
// equality or set equality, as that would rely on provider logic.
var RefreshAfterApply string
Copy link
Contributor Author

@bbasata bbasata May 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This acts as a build-time feature flag. The thought is that you'd add this as an ldflags value in a testacc Make target:

-X github.com/hashicorp/terraform-plugin-testing/helper/resource. RefreshAfterApply=unlocked

The ldflags bit is a weakly-held opinion. I would be receptive to using a TF_* environment variable instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I'd lean toward an environment variable, just being consistent with existing configuration options: TF_ACC_REFRESH_AFTER_APPLY or something of the like 😆

9 changes: 9 additions & 0 deletions helper/resource/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ type providerFactories struct {
protov6 protov6ProviderFactories
}

func runProviderCommandApplyRefreshOnly(ctx context.Context, t testing.T, wd *plugintest.WorkingDir, factories *providerFactories) error {
t.Helper()

fn := func() error {
return wd.Apply(ctx, tfexec.Refresh(true), tfexec.RefreshOnly(true))
}
return runProviderCommand(ctx, t, wd, factories, fn)
}

func runProviderCommandCreatePlan(ctx context.Context, t testing.T, wd *plugintest.WorkingDir, factories *providerFactories) error {
t.Helper()

Expand Down
15 changes: 15 additions & 0 deletions helper/resource/testing_new_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -442,5 +442,20 @@ func testStepNewConfig(ctx context.Context, t testing.T, c TestCase, wd *plugint
}
}

// I'm sorry, I'm afraid I can't do that. With one exception.
if RefreshAfterApply == "unlocked" && !step.Destroy && !step.PlanOnly {
if len(c.Steps) > stepIndex+1 {
// If the next step is a refresh, then we have no need to refresh here
if !c.Steps[stepIndex+1].RefreshState {
// Echo a searchable message to easily determine when this is no longer being used
fmt.Println("RefreshAfterApply: running apply -refresh-only -refresh=true")
err := runProviderCommandApplyRefreshOnly(ctx, t, wd, providers)
if err != nil {
return fmt.Errorf("Error running apply refresh-only: %w", err)
}
}
}
}

return nil
}
Loading