github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/command/workdir/dir.go (about) 1 package workdir 2 3 import ( 4 "fmt" 5 "os" 6 "path/filepath" 7 ) 8 9 // Dir represents a single Terraform working directory. 10 // 11 // "Working directory" is unfortunately a slight misnomer, because non-default 12 // options can potentially stretch the definition such that multiple working 13 // directories end up appearing to share a data directory, or other similar 14 // anomolies, but we continue to use this terminology both for historical 15 // reasons and because it reflects the common case without any special 16 // overrides. 17 // 18 // The naming convention for methods on this type is that methods whose names 19 // begin with "Override" affect only characteristics of the particular object 20 // they're called on, changing where it looks for data, while methods whose 21 // names begin with "Set" will write settings to disk such that other instances 22 // referring to the same directories will also see them. Given that, the 23 // "Override" methods should be used only during the initialization steps 24 // for a Dir object, typically only inside "package main", so that all 25 // subsequent work elsewhere will access consistent locations on disk. 26 // 27 // We're gradually transitioning to using this type to manage working directory 28 // settings, and so not everything in the working directory "data dir" is 29 // encapsulated here yet, but hopefully we'll gradually migrate all of those 30 // settings here over time. The working directory state not yet managed in here 31 // is typically managed directly in the "command" package, either directly 32 // inside commands or in methods of the giant command.Meta type. 33 type Dir struct { 34 // mainDir is the path to the directory that we present as the 35 // "working directory" in the user model, which is typically the 36 // current working directory when running Terraform CLI, or the 37 // directory explicitly chosen by the user using the -chdir=... 38 // global option. 39 mainDir string 40 41 // originalDir is the path to the working directory that was 42 // selected when creating the Terraform CLI process, regardless of 43 // -chdir=... being set. This is only for very limited purposes 44 // related to backward compatibility; most functionality should 45 // use mainDir instead. 46 originalDir string 47 48 // dataDir is the path to the directory where we will store our 49 // working directory settings and artifacts. This is typically a 50 // directory named ".terraform" within mainDir, but users may 51 // override it. 52 dataDir string 53 } 54 55 // NewDir constructs a new working directory, anchored at the given path. 56 // 57 // In normal use, mainPath should be "." to reflect the current working 58 // directory, with "package main" having switched the process's current 59 // working directory if necessary prior to calling this function. However, 60 // unusual situations in tests may set mainPath to a temporary directory, or 61 // similar. 62 // 63 // WARNING: Although the logic in this package is intended to work regardless 64 // of whether mainPath is actually the current working directory, we're 65 // currently in a transitional state where this package shares responsibility 66 // for the working directory with various command.Meta methods, and those 67 // often assume that the main path of the working directory will always be 68 // ".". If you're writing test code that spans across both areas of 69 // responsibility then you must ensure that the test temporarily changes the 70 // test process's working directory to the directory returned by RootModuleDir 71 // before using the result inside a command.Meta. 72 func NewDir(mainPath string) *Dir { 73 mainPath = filepath.Clean(mainPath) 74 return &Dir{ 75 mainDir: mainPath, 76 originalDir: mainPath, 77 dataDir: filepath.Join(mainPath, ".terraform"), 78 } 79 } 80 81 // OverrideOriginalWorkingDir records a different path as the 82 // "original working directory" for the reciever. 83 // 84 // Use this only to record the original working directory when Terraform is run 85 // with the -chdir=... global option. In that case, the directory given in 86 // -chdir=... is the "main path" to pass in to NewDir, while the original 87 // working directory should be sent to this method. 88 func (d *Dir) OverrideOriginalWorkingDir(originalPath string) { 89 d.originalDir = filepath.Clean(originalPath) 90 } 91 92 // OverrideDataDir chooses a specific alternative directory to read and write 93 // the persistent working directory settings. 94 // 95 // "package main" can call this if it detects that the user has overridden 96 // the default location by setting the relevant environment variable. Don't 97 // call this when that environment variable isn't set, in order to preserve 98 // the default setting of a dot-prefixed directory directly inside the main 99 // working directory. 100 func (d *Dir) OverrideDataDir(dataDir string) { 101 d.dataDir = filepath.Clean(dataDir) 102 } 103 104 // RootModuleDir returns the directory where we expect to find the root module 105 // configuration for this working directory. 106 func (d *Dir) RootModuleDir() string { 107 // The root module configuration is just directly inside the main directory. 108 return d.mainDir 109 } 110 111 // OriginalWorkingDir returns the true, operating-system-originated working 112 // directory that the current Terraform process was launched from. 113 // 114 // This is usually the same as the main working directory, but differs in the 115 // special case where the user ran Terraform with the global -chdir=... 116 // option. This is here only for a few backward compatibility affordances 117 // from before we had the -chdir=... option, so should typically not be used 118 // for anything new. 119 func (d *Dir) OriginalWorkingDir() string { 120 return d.originalDir 121 } 122 123 // DataDir returns the base path where the reciever keeps all of the settings 124 // and artifacts that must persist between consecutive commands in a single 125 // session. 126 // 127 // This is exported only to allow the legacy behaviors in command.Meta to 128 // continue accessing this directory directly. Over time we should replace 129 // all of those direct accesses with methods on this type, and then remove 130 // this method. Avoid using this method for new use-cases. 131 func (d *Dir) DataDir() string { 132 return d.dataDir 133 } 134 135 // ensureDataDir creates the data directory and all of the necessary parent 136 // directories that lead to it, if they don't already exist. 137 // 138 // For directories that already exist ensureDataDir will preserve their 139 // permissions, while it'll create any new directories to be owned by the user 140 // running Terraform, readable and writable by that user, and readable by 141 // all other users, or some approximation of that on non-Unix platforms which 142 // have a different permissions model. 143 func (d *Dir) ensureDataDir() error { 144 err := os.MkdirAll(d.dataDir, 0755) 145 if err != nil { 146 return fmt.Errorf("failed to prepare working directory: %w", err) 147 } 148 return nil 149 }