diff --git a/cli/commands/terraform/command.go b/cli/commands/terraform/command.go index c03b354a3..cdaf236c5 100644 --- a/cli/commands/terraform/command.go +++ b/cli/commands/terraform/command.go @@ -1,6 +1,8 @@ package terraform import ( + "strings" + "github.com/gruntwork-io/go-commons/errors" "github.com/gruntwork-io/gruntwork-cli/collections" "github.com/gruntwork-io/terragrunt/options" @@ -33,7 +35,12 @@ func action(opts *options.TerragruntOptions) cli.ActionFunc { } if !opts.DisableCommandValidation && !collections.ListContainsElement(nativeTerraformCommands, opts.TerraformCommand) { - return errors.WithStackTrace(WrongTerraformCommand(opts.TerraformCommand)) + if strings.HasSuffix(opts.TerraformPath, "terraform") { + return errors.WithStackTrace(WrongTerraformCommand(opts.TerraformCommand)) + } else { + // We default to tofu if the terraform path does not end in Terraform + return errors.WithStackTrace(WrongTofuCommand(opts.TerraformCommand)) + } } return Run(ctx.Context, opts.OptionsFromContext(ctx)) diff --git a/cli/commands/terraform/command_test.go b/cli/commands/terraform/command_test.go new file mode 100644 index 000000000..35b3bce9e --- /dev/null +++ b/cli/commands/terraform/command_test.go @@ -0,0 +1,53 @@ +package terraform + +import ( + "context" + "testing" + + "github.com/gruntwork-io/terragrunt/options" + "github.com/gruntwork-io/terragrunt/pkg/cli" + "github.com/stretchr/testify/require" +) + +func TestAction(t *testing.T) { + t.Parallel() + + tt := []struct { + name string + opts *options.TerragruntOptions + expectedErr error + }{ + { + name: "wrong tofu command", + opts: &options.TerragruntOptions{ + TerraformCommand: "foo", + TerraformPath: "tofu", + }, + expectedErr: WrongTofuCommand("foo"), + }, + { + name: "wrong terraform command", + opts: &options.TerragruntOptions{ + TerraformCommand: "foo", + TerraformPath: "terraform", + }, + expectedErr: WrongTerraformCommand("foo"), + }, + } + + for _, tc := range tt { + t.Run(tc.name, func(t *testing.T) { + fn := action(tc.opts) + + ctx := cli.Context{ + Context: context.Background(), + } + err := fn(&ctx) + if tc.expectedErr != nil { + require.ErrorIs(t, err, tc.expectedErr) + } else { + require.NoError(t, err) + } + }) + } +} diff --git a/cli/commands/terraform/errors.go b/cli/commands/terraform/errors.go index 91730ad37..eea2a6f9e 100644 --- a/cli/commands/terraform/errors.go +++ b/cli/commands/terraform/errors.go @@ -21,6 +21,12 @@ func (name WrongTerraformCommand) Error() string { return fmt.Sprintf("Terraform has no command named %q. To see all of Terraform's top-level commands, run: terraform -help", string(name)) } +type WrongTofuCommand string + +func (name WrongTofuCommand) Error() string { + return fmt.Sprintf("OpenTofu has no command named %q. To see all of OpenTofu's top-level commands, run: tofu -help", string(name)) +} + type BackendNotDefined struct { Opts *options.TerragruntOptions BackendType string diff --git a/test/integration_test.go b/test/integration_test.go index 0ba929176..7a79aebc9 100644 --- a/test/integration_test.go +++ b/test/integration_test.go @@ -1662,7 +1662,7 @@ func TestTerraformCommandCliArgs(t *testing.T) { { []string{"paln"}, "", - terraform.WrongTerraformCommand("paln"), + expectedWrongCommandErr("paln"), }, { []string{"paln", "--terragrunt-disable-command-validation"}, @@ -7433,6 +7433,14 @@ func wrappedBinary() string { return filepath.Base(value) } +// expectedWrongCommandErr - return expected error message for wrong command +func expectedWrongCommandErr(command string) error { + if wrappedBinary() == TOFU_BINARY { + return terraform.WrongTofuCommand(command) + } + return terraform.WrongTerraformCommand(command) +} + func isTerraform() bool { return wrappedBinary() == TERRAFORM_BINARY }