mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
OpenTofu will now attempt to create the configuration directory ~/.terraform.d on startup (#512)
Signed-off-by: Serhii Babak <s.babak@scalr.com>
This commit is contained in:
parent
f9d8b3ca2c
commit
0930a90822
@ -1,29 +1,33 @@
|
||||
## 1.6.0 (Unreleased)
|
||||
|
||||
UPGRADE NOTES:
|
||||
|
||||
* The `cloud` and `remote` backends will no longer default to `app.terraform.io` hostname and will require the hostname to be explicitly specified ([#291](https://github.com/opentofu/opentofu/pull/291));
|
||||
* The `login` and `logout` commands will no longer default to `app.terraform.io` hostname and will require the hostname to be explicitly provided as a command-line argument ([#291](https://github.com/opentofu/opentofu/pull/291));
|
||||
* prevent future possible incompatibility with states that include unknown `check` block result kinds. ([#355](https://github.com/opentofu/opentofu/pull/355));
|
||||
|
||||
NEW FEATURES:
|
||||
|
||||
* `tofu test`: The previously experimental `tofu test` command has been moved out of experimental. This comes with a significant change in how OpenTofu tests are written and executed.
|
||||
|
||||
OpenTofu tests are written within `.tftest.hcl` files, controlled by a series of `run` blocks. Each `run` block will execute an OpenTofu plan or apply command against the OpenTofu configuration under test and can execute conditions against the resultant plan and state.
|
||||
|
||||
ENHANCEMENTS:
|
||||
|
||||
* config: OpenTofu can now track some additional detail about values that won't be known until the apply step, such as the range of possible lengths for a collection or whether an unknown value can possibly be null. When this information is available, Terraform can potentially generate known results for some operations on unknown values. This doesn't mean that Terraform can immediately track that detail in all cases, but the type system now contains the facility for that and so over time we will improve the level of detail generated by built-in functions, language operators, Terraform providers, etc. ([#33234](https://github.com/hashicorp/terraform/issues/33234))
|
||||
* jsonplan: Added `errored` field to JSON plan output, indicating whether a plan errored. ([#33372](https://github.com/hashicorp/terraform/issues/33372))
|
||||
* cloud: Remote plans on cloud backends can now be saved using the `-out` flag, referenced in the `show` command, and applied by specifying the plan file name. ([#33492](https://github.com/hashicorp/terraform/issues/33492))
|
||||
* config: The `import` block `id` field now accepts an expression referencing other values such as resource attributes, as long as the value is a string known at plan time. ([#33618](https://github.com/hashicorp/terraform/issues/33618))
|
||||
|
||||
|
||||
BUG FIXES:
|
||||
|
||||
* The upstream dependency that OpenTofu uses for service discovery of OpenTofu-native services such as cloud backend state storage was previously not concurrency-safe, but OpenTofu was treating it as if it was in situations like when a configuration has multiple `terraform_remote_state` blocks all using the "remote" backend. OpenTofu is now using a newer version of that library which updates its internal caches in a concurrency-safe way. ([#33364](https://github.com/hashicorp/terraform/issues/33364))
|
||||
* Transitive dependencies were lost during apply when the referenced resource expanded into zero instances ([#33403](https://github.com/hashicorp/terraform/issues/33403))
|
||||
* OpenTofu will no longer override SSH settings in local git configuration when installing modules. ([#33592](https://github.com/hashicorp/terraform/issues/33592))
|
||||
* Handle file-operation errors in `internal/states/statemgr`. ([#278](https://github.com/opentofu/opentofu/issues/278))
|
||||
* `tofu init`: OpenTofu will no longer allow downloading remote modules to invalid paths. ([#356](https://github.com/opentofu/opentofu/issues/356))
|
||||
* tofu_remote_state: Fixed a potential unsafe read panic when reading from multiple tofu_remote_state data sources ([#357](https://github.com/opentofu/opentofu/issues/357))
|
||||
* OpenTofu will now attempt to create the configuration directory `~/.terraform.d` on startup. ([#442](https://github.com/opentofu/opentofu/issues/442))
|
||||
|
||||
## Previous Releases
|
||||
|
||||
|
27
main.go
27
main.go
@ -249,6 +249,14 @@ func realMain() int {
|
||||
initCommands(ctx, originalWd, streams, config, services, providerSrc, providerDevOverrides, unmanagedProviders)
|
||||
}
|
||||
|
||||
// Attempt to ensure the config directory exists.
|
||||
configDir, err := cliconfig.ConfigDir()
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed to find the path to the config directory: %v", err)
|
||||
} else if err := mkConfigDir(configDir); err != nil {
|
||||
log.Printf("[ERROR] Failed to create the config directory at path %s: %v", configDir, err)
|
||||
}
|
||||
|
||||
// Make sure we clean up any managed plugins at the end of this
|
||||
defer plugin.CleanupClients()
|
||||
|
||||
@ -491,3 +499,22 @@ func extractChdirOption(args []string) (string, []string, error) {
|
||||
copy(newArgs[argPos:], args[argPos+1:])
|
||||
return argValue, newArgs, nil
|
||||
}
|
||||
|
||||
// Creates the the configuration directory.
|
||||
// `configDir` should refer to `~/.terraform.d` or its equivalent
|
||||
// on non-UNIX platforms.
|
||||
func mkConfigDir(configDir string) error {
|
||||
err := os.Mkdir(configDir, os.ModePerm)
|
||||
|
||||
if err == nil {
|
||||
log.Printf("[DEBUG] Created the config directory: %s", configDir)
|
||||
return nil
|
||||
}
|
||||
|
||||
if os.IsExist(err) {
|
||||
log.Printf("[DEBUG] Found the config directory: %s", configDir)
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
56
main_test.go
56
main_test.go
@ -6,6 +6,7 @@ package main
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
@ -312,3 +313,58 @@ func TestWarnOutput(t *testing.T) {
|
||||
t.Fatalf("unexpected stdout: %q\n", stdout)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMkConfigDir_new(t *testing.T) {
|
||||
tmpConfigDir := filepath.Join(t.TempDir(), ".terraform.d")
|
||||
|
||||
err := mkConfigDir(tmpConfigDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create the new config directory: %v", err)
|
||||
}
|
||||
|
||||
info, err := os.Stat(tmpConfigDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Directory does not exist after creation: %v", err)
|
||||
}
|
||||
|
||||
if !info.IsDir() {
|
||||
t.Fatalf("%s should be a directory but it's not", tmpConfigDir)
|
||||
}
|
||||
|
||||
mode := int(info.Mode().Perm())
|
||||
expectedMode := 0755
|
||||
if mode != expectedMode {
|
||||
t.Fatalf("Expected mode: %04o, but got: %04o", expectedMode, mode)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMkConfigDir_exists(t *testing.T) {
|
||||
tmpConfigDir := filepath.Join(t.TempDir(), ".terraform.d")
|
||||
os.Mkdir(tmpConfigDir, os.ModePerm)
|
||||
|
||||
err := mkConfigDir(tmpConfigDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create the new config directory: %v", err)
|
||||
}
|
||||
|
||||
_, err = os.Stat(tmpConfigDir)
|
||||
if err != nil {
|
||||
t.Fatalf("Directory does not exist after creation: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestMkConfigDir_noparent(t *testing.T) {
|
||||
tmpConfigDir := filepath.Join(t.TempDir(), "nonexistenthomedir", ".terraform.d")
|
||||
|
||||
err := mkConfigDir(tmpConfigDir)
|
||||
if err == nil {
|
||||
t.Fatal("Expected an error, but got none")
|
||||
}
|
||||
|
||||
// We wouldn't dare creating the home dir. If the parent of our config dir
|
||||
// is missing, it's likely an issue with the system.
|
||||
expectedError := fmt.Sprintf("mkdir %s: no such file or directory", tmpConfigDir)
|
||||
if err.Error() != expectedError {
|
||||
t.Fatalf("Expected error: %s, but got: %v", expectedError, err)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user