Add test coverage for Meta's determineInitReason method, fix error in diagnostic (#37303)

* Add test coverage for Meta's determineInitReason method, fix error in diagnostic when migrating away from HCP Terraform

* Add godoc comment to determineInitReason method
pull/37305/head
Sarah French 10 months ago committed by GitHub
parent d02a1ed1b7
commit 677e5ea276
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -715,13 +715,18 @@ func (m *Meta) backendFromConfig(opts *BackendOpts) (backend.Backend, tfdiags.Di
}
}
// determineInitReason is used in non-Init commands to interrupt the command early and prompt users to instead run an init command.
// That prompt needs to include the reason why init needs to be run, and it is determined here.
//
// Note: the calling code is responsible for determining that a change has occurred before invoking this
// method. This makes the default cases (config has changed) valid.
func (m *Meta) determineInitReason(previousBackendType string, currentBackendType string, cloudMode cloud.ConfigChangeMode) tfdiags.Diagnostics {
initReason := ""
switch cloudMode {
case cloud.ConfigMigrationIn:
initReason = fmt.Sprintf("Changed from backend %q to HCP Terraform", previousBackendType)
case cloud.ConfigMigrationOut:
initReason = fmt.Sprintf("Changed from HCP Terraform to backend %q", previousBackendType)
initReason = fmt.Sprintf("Changed from HCP Terraform to backend %q", currentBackendType)
case cloud.ConfigChangeInPlace:
initReason = "HCP Terraform configuration block has changed"
default:

@ -16,12 +16,15 @@ import (
"github.com/hashicorp/cli"
"github.com/hashicorp/terraform/internal/addrs"
"github.com/hashicorp/terraform/internal/backend"
"github.com/hashicorp/terraform/internal/cloud"
"github.com/hashicorp/terraform/internal/command/workdir"
"github.com/hashicorp/terraform/internal/configs"
"github.com/hashicorp/terraform/internal/copy"
"github.com/hashicorp/terraform/internal/plans"
"github.com/hashicorp/terraform/internal/states"
"github.com/hashicorp/terraform/internal/states/statefile"
"github.com/hashicorp/terraform/internal/states/statemgr"
"github.com/zclconf/go-cty/cty"
backendInit "github.com/hashicorp/terraform/internal/backend/init"
@ -1956,6 +1959,105 @@ func TestBackendFromState(t *testing.T) {
}
}
func Test_determineInitReason(t *testing.T) {
cases := map[string]struct {
cloudMode cloud.ConfigChangeMode
backendState workdir.BackendStateFile
backendConfig configs.Backend
wantErr string
}{
// All scenarios involving Cloud backend
"change in cloud config": {
cloudMode: cloud.ConfigChangeInPlace,
backendState: workdir.BackendStateFile{
Backend: &workdir.BackendConfigState{
Type: "cloud",
// Other fields unnecessary
},
},
backendConfig: configs.Backend{
Type: "cloud",
// Other fields unnecessary
},
wantErr: `HCP Terraform configuration block has changed`,
},
"migrate backend to cloud": {
cloudMode: cloud.ConfigMigrationIn,
backendState: workdir.BackendStateFile{
Backend: &workdir.BackendConfigState{
Type: "foobar",
// Other fields unnecessary
},
},
backendConfig: configs.Backend{
Type: "cloud",
// Other fields unnecessary
},
wantErr: `Changed from backend "foobar" to HCP Terraform`,
},
"migrate cloud to backend": {
cloudMode: cloud.ConfigMigrationOut,
backendState: workdir.BackendStateFile{
Backend: &workdir.BackendConfigState{
Type: "cloud",
// Other fields unnecessary
},
},
backendConfig: configs.Backend{
Type: "foobar",
// Other fields unnecessary
},
wantErr: `Changed from HCP Terraform to backend "foobar"`,
},
// Changes within the backend config block
"backend type changed": {
cloudMode: cloud.ConfigChangeIrrelevant,
backendState: workdir.BackendStateFile{
Backend: &workdir.BackendConfigState{
Type: "foobar1",
// Other fields unnecessary
},
},
backendConfig: configs.Backend{
Type: "foobar2",
// Other fields unnecessary
},
wantErr: `Backend type changed from "foobar1" to "foobar2`,
},
"backend config changed": {
// Note that we don't need to include differing config to trigger this
// scenario, as we're hitting the default case. If the types match, then
// only the config is left to differ.
// See the comment above determineInitReason for more info.
cloudMode: cloud.ConfigChangeIrrelevant,
backendState: workdir.BackendStateFile{
Backend: &workdir.BackendConfigState{
Type: "foobar",
// Other fields unnecessary
},
},
backendConfig: configs.Backend{
Type: "foobar",
// Other fields unnecessary
},
wantErr: `Backend configuration block has changed`,
},
}
for tn, tc := range cases {
t.Run(tn, func(t *testing.T) {
m := Meta{}
diags := m.determineInitReason(tc.backendState.Backend.Type, tc.backendConfig.Type, tc.cloudMode)
if !strings.Contains(diags.Err().Error(), tc.wantErr) {
t.Fatalf("expected error diagnostic detail to include \"%s\" but it's missing: %s", tc.wantErr, diags.Err())
}
})
}
}
func testMetaBackend(t *testing.T, args []string) *Meta {
var m Meta
m.Ui = new(cli.MockUi)

Loading…
Cancel
Save