github.com/opentofu/opentofu@v1.7.1/internal/command/workdir/plugin_dirs.go (about)

     1  // Copyright (c) The OpenTofu Authors
     2  // SPDX-License-Identifier: MPL-2.0
     3  // Copyright (c) 2023 HashiCorp, Inc.
     4  // SPDX-License-Identifier: MPL-2.0
     5  
     6  package workdir
     7  
     8  import (
     9  	"encoding/json"
    10  	"os"
    11  	"path/filepath"
    12  )
    13  
    14  const PluginPathFilename = "plugin_path"
    15  
    16  // ProviderLocalCacheDir returns the directory we'll use as the
    17  // working-directory-specific local cache of providers.
    18  //
    19  // The provider installer's job is to make sure that all providers needed for
    20  // a particular working directory are available in this cache directory. No
    21  // other component may write here, and in particular a Dir object itself
    22  // never reads or writes into this directory, instead just delegating all of
    23  // that responsibility to other components.
    24  //
    25  // Typically, the caller will ultimately pass the result of this method either
    26  // directly or indirectly into providercache.NewDir, to get an object
    27  // responsible for managing the contents.
    28  func (d *Dir) ProviderLocalCacheDir() string {
    29  	return filepath.Join(d.dataDir, "providers")
    30  }
    31  
    32  // ForcedPluginDirs returns a list of directories to use to find plugins,
    33  // instead of the default locations.
    34  //
    35  // Returns an zero-length list and no error in the normal case where there
    36  // are no overridden search directories. If ForcedPluginDirs returns a
    37  // non-empty list with no errors then the result totally replaces the default
    38  // search directories.
    39  func (d *Dir) ForcedPluginDirs() ([]string, error) {
    40  	raw, err := os.ReadFile(filepath.Join(d.dataDir, PluginPathFilename))
    41  	if os.IsNotExist(err) {
    42  		return nil, nil
    43  	}
    44  
    45  	if err != nil {
    46  		return nil, err
    47  	}
    48  
    49  	var pluginPath []string
    50  	if err := json.Unmarshal(raw, &pluginPath); err != nil {
    51  		return nil, err
    52  	}
    53  	return pluginPath, nil
    54  }
    55  
    56  // SetForcedPluginDirs records an overridden list of directories to search
    57  // to find plugins, instead of the default locations. See ForcePluginDirs
    58  // for more information.
    59  //
    60  // Pass a zero-length list to deactivate forced plugin directories altogether,
    61  // thus allowing the working directory to return to using the default
    62  // search directories.
    63  func (d *Dir) SetForcedPluginDirs(dirs []string) error {
    64  
    65  	filePath := filepath.Join(d.dataDir, PluginPathFilename)
    66  	switch {
    67  	case len(dirs) == 0:
    68  		err := os.Remove(filePath)
    69  		if !os.IsNotExist(err) {
    70  			return err
    71  		}
    72  		return nil
    73  	default:
    74  		// We'll ignore errors from this one, because if we fail to create
    75  		// the directory then we'll fail to create the file below too,
    76  		// and that subsequent error will more directly reflect what we
    77  		// are trying to do here.
    78  		d.ensureDataDir()
    79  
    80  		raw, err := json.MarshalIndent(dirs, "", "  ")
    81  		if err != nil {
    82  			return err
    83  		}
    84  
    85  		return os.WriteFile(filePath, raw, 0644)
    86  	}
    87  }