Files
opentf/internal/command/meta_test.go
Andrei Ciobanu ce59943d99 Remove Ui from the Meta structure (#4000)
Signed-off-by: Andrei Ciobanu <andrei.ciobanu@opentofu.org>
Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
Co-authored-by: Christian Mesh <christianmesh1@gmail.com>
2026-04-07 13:38:46 -04:00

294 lines
6.8 KiB
Go

// Copyright (c) The OpenTofu Authors
// SPDX-License-Identifier: MPL-2.0
// Copyright (c) 2023 HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package command
import (
"flag"
"os"
"path/filepath"
"strings"
"testing"
"github.com/opentofu/opentofu/internal/command/arguments"
"github.com/opentofu/opentofu/internal/command/workdir"
"github.com/opentofu/opentofu/internal/backend"
"github.com/opentofu/opentofu/internal/backend/local"
"github.com/opentofu/opentofu/internal/tofu"
)
func TestMetaInputMode(t *testing.T) {
test = false
defer func() { test = true }()
m := &Meta{
WorkingDir: workdir.NewDir("."),
}
// TODO meta-refactor: these assignments are needed because the extendedFlagSet was used here before,
// which had these with defaults as "true". In a future iteration, once these are not needed, we need to remove them.
m.input = true
m.stateLock = true
args := []string{}
fs := flag.NewFlagSet("foo", flag.ContinueOnError)
if err := fs.Parse(args); err != nil {
t.Fatalf("err: %s", err)
}
if m.InputMode() != tofu.InputModeStd {
t.Fatalf("bad: %#v", m.InputMode())
}
}
func TestMetaInputMode_envVar(t *testing.T) {
test = false
defer func() { test = true }()
m := &Meta{
WorkingDir: workdir.NewDir("."),
}
// TODO meta-refactor: these assignments are needed because the extendedFlagSet was used here before,
// which had these with defaults as "true". In a future iteration, once these are not needed, we need to remove them.
m.input = true
m.stateLock = true
args := []string{}
fs := flag.NewFlagSet("foo", flag.ContinueOnError)
if err := fs.Parse(args); err != nil {
t.Fatalf("err: %s", err)
}
off := tofu.InputMode(0)
on := tofu.InputModeStd
cases := []struct {
EnvVar string
Expected tofu.InputMode
}{
{"false", off},
{"0", off},
{"true", on},
{"1", on},
}
for _, tc := range cases {
t.Setenv(InputModeEnvVar, tc.EnvVar)
if m.InputMode() != tc.Expected {
t.Fatalf("expected InputMode: %#v, got: %#v", tc.Expected, m.InputMode())
}
}
}
func TestMetaInputMode_disable(t *testing.T) {
test = false
defer func() { test = true }()
m := &Meta{
WorkingDir: workdir.NewDir("."),
}
// TODO meta-refactor: these assignments are needed because the extendedFlagSet was used here before,
// which had these with defaults as "true". In a future iteration, once these are not needed, we need to remove them.
m.input = true
m.stateLock = true
args := []string{"-input=false"}
fs := flag.NewFlagSet("foo", flag.ContinueOnError)
var viewOpts arguments.ViewOptions
viewOpts.AddFlags(fs, true)
if err := fs.Parse(args); err != nil {
t.Fatalf("err: %s", err)
}
if _, diags := viewOpts.Parse(); len(diags) > 0 {
t.Fatalf("unexpected diagnostics: %s", diags)
}
m.input = viewOpts.InputEnabled
if m.InputMode() > 0 {
t.Fatalf("bad: %#v", m.InputMode())
}
}
func TestMeta_initStatePaths(t *testing.T) {
m := &Meta{
WorkingDir: workdir.NewDir("."),
}
m.initStatePaths()
if m.statePath != arguments.DefaultStateFilename {
t.Fatalf("bad: %#v", m)
}
if m.stateOutPath != arguments.DefaultStateFilename {
t.Fatalf("bad: %#v", m)
}
if m.backupPath != arguments.DefaultStateFilename+DefaultBackupExtension {
t.Fatalf("bad: %#v", m)
}
m = &Meta{
WorkingDir: workdir.NewDir("."),
}
m.statePath = "foo"
m.initStatePaths()
if m.stateOutPath != "foo" {
t.Fatalf("bad: %#v", m)
}
if m.backupPath != "foo"+DefaultBackupExtension {
t.Fatalf("bad: %#v", m)
}
m = &Meta{
WorkingDir: workdir.NewDir("."),
}
m.stateOutPath = "foo"
m.initStatePaths()
if m.statePath != arguments.DefaultStateFilename {
t.Fatalf("bad: %#v", m)
}
if m.backupPath != "foo"+DefaultBackupExtension {
t.Fatalf("bad: %#v", m)
}
}
func TestMeta_Env(t *testing.T) {
td := t.TempDir()
t.Chdir(td)
m := &Meta{
WorkingDir: workdir.NewDir("."),
}
env, err := m.Workspace(t.Context())
if err != nil {
t.Fatal(err)
}
if env != backend.DefaultStateName {
t.Fatalf("expected env %q, got env %q", backend.DefaultStateName, env)
}
testEnv := "test_env"
if err := m.SetWorkspace(testEnv); err != nil {
t.Fatal("error setting env:", err)
}
env, _ = m.Workspace(t.Context())
if env != testEnv {
t.Fatalf("expected env %q, got env %q", testEnv, env)
}
if err := m.SetWorkspace(backend.DefaultStateName); err != nil {
t.Fatal("error setting env:", err)
}
env, _ = m.Workspace(t.Context())
if env != backend.DefaultStateName {
t.Fatalf("expected env %q, got env %q", backend.DefaultStateName, env)
}
}
func TestMeta_Workspace_override(t *testing.T) {
m := &Meta{
WorkingDir: workdir.NewDir("."),
}
testCases := map[string]struct {
workspace string
err error
}{
"": {
"default",
nil,
},
"development": {
"development",
nil,
},
"invalid name": {
"",
errInvalidWorkspaceNameEnvVar,
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
t.Setenv(WorkspaceNameEnvVar, name)
workspace, err := m.Workspace(t.Context())
if workspace != tc.workspace {
t.Errorf("Unexpected workspace\n got: %s\nwant: %s\n", workspace, tc.workspace)
}
if err != tc.err {
t.Errorf("Unexpected error\n got: %s\nwant: %s\n", err, tc.err)
}
})
}
}
func TestMeta_Workspace_invalidSelected(t *testing.T) {
td := t.TempDir()
t.Chdir(td)
// this is an invalid workspace name
workspace := "test workspace"
// create the workspace directories
if err := os.MkdirAll(filepath.Join(local.DefaultWorkspaceDir, workspace), 0755); err != nil {
t.Fatal(err)
}
// create the workspace file to select it
if err := os.MkdirAll(workdir.DefaultDataDir, 0755); err != nil {
t.Fatal(err)
}
if err := os.WriteFile(filepath.Join(workdir.DefaultDataDir, local.DefaultWorkspaceFile), []byte(workspace), 0644); err != nil {
t.Fatal(err)
}
m := &Meta{
WorkingDir: workdir.NewDir("."),
}
ws, err := m.Workspace(t.Context())
if ws != workspace {
t.Errorf("Unexpected workspace\n got: %s\nwant: %s\n", ws, workspace)
}
if err != nil {
t.Errorf("Unexpected error: %s", err)
}
}
func TestCommand_checkRequiredVersion(t *testing.T) {
// Create a temporary working directory that is empty
td := t.TempDir()
testCopyDir(t, testFixturePath("command-check-required-version"), td)
t.Chdir(td)
view, done := testView(t)
meta := Meta{
WorkingDir: workdir.NewDir("."),
View: view,
}
diags := meta.checkRequiredVersion(t.Context())
if diags == nil {
t.Fatalf("diagnostics should contain unmet version constraint, but is nil")
}
view.Diagnostics(diags)
// Required version diags are correct
output := done(t)
errStr := output.Stderr()
if !strings.Contains(errStr, `required_version = "~> 0.9.0"`) {
t.Fatalf("output should point to unmet version constraint, but is:\n\n%s", errStr)
}
if strings.Contains(errStr, `required_version = ">= 0.13.0"`) {
t.Fatalf("output should not point to met version constraint, but is:\n\n%s", errStr)
}
}