Skip to content

Commit

Permalink
modules: find module with TT_CLI_MODULES_PATH
Browse files Browse the repository at this point in the history
The TT_CLI_MODULES_PATH environment variable specifies a list of
module's paths separated by a colon “:”.
It can be set externally from tt and must contain a list of
folders where modules are located.
The logic of working with this variable is similar to the PATH
system variable.

Closes #1013
  • Loading branch information
dmyger committed Nov 27, 2024
1 parent 0e6bfb6 commit b36ea67
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ as a number or using [RFC3339/RFC3339Nano](https://go.dev/src/time/format.go) ti
- `tt connect`: add new `--evaler` option to support for customizing
the way user input is processed.
- `tt.yaml`: allows to specify a list of modules directories.
- Environment variable TT_CLI_MODULES_PATH can be used to specify
an extra path with modules.

### Changed

Expand Down
74 changes: 52 additions & 22 deletions cli/modules/modules.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,18 @@ func fillSubCommandsInfo(cmd *cobra.Command, modulesInfo *ModulesInfo) {
// GetModulesInfo collects information about available modules (both external and internal).
func GetModulesInfo(cmdCtx *cmdcontext.CmdCtx, rootCmd *cobra.Command,
cliOpts *config.CliOpts) (ModulesInfo, error) {
modulesDir, err := getExternalModulesDir(cmdCtx, cliOpts)
modulesDirs, err := getConfigModulesDirs(cmdCtx, cliOpts)
if err != nil {
return nil, err
}

externalModules, err := getExternalModules(modulesDir)
modulesEnvDirs, err := getEnvironmentModulesDirs()
if err != nil {
return nil, err
}
modulesDirs = append(modulesDirs, modulesEnvDirs...)

externalModules, err := getExternalModules(modulesDirs)
if err != nil {
return nil, fmt.Errorf(
"failed to get available external modules information: %s", err)
Expand All @@ -72,44 +78,68 @@ func GetModulesInfo(cmdCtx *cmdcontext.CmdCtx, rootCmd *cobra.Command,
return modulesInfo, nil
}

// getExternalModulesDir returns the directory where external modules are located.
func getExternalModulesDir(cmdCtx *cmdcontext.CmdCtx, cliOpts *config.CliOpts) (string, error) {
// collectDirectoriesList checks list to ensure that all items is directories.
func collectDirectoriesList(paths []string) ([]string, error) {
dirs := make([]string, 0, len(paths))
// We return an error only if the following conditions are met:
// 1. If a directory field is specified;
// 2. Specified path exists;
// 3. Path points to not a directory.
for _, dir := range paths {
info, err := os.Stat(dir)
if err != nil {
return dirs, fmt.Errorf("specified module path in configuration file not found")
}
// TODO: Add warning in next patches, discussion
// what if the file exists, but access is denied, etc.
// FIXME: resolve this question while prepare list:
// https://github.com/tarantool/tt/issues/1014
if !info.IsDir() {
return dirs, fmt.Errorf("specified path in configuration file is not a directory")
}
dirs = append(dirs, dir)
}

return dirs, nil
}

// getConfigModulesDirs returns from configuration the list of directories,
// where external modules are located.
func getConfigModulesDirs(cmdCtx *cmdcontext.CmdCtx, cliOpts *config.CliOpts) ([]string, error) {
// Configuration file not detected - ignore and work on.
// TODO: Add warning in next patches, discussion
// what if the file exists, but access is denied, etc.
if _, err := os.Stat(cmdCtx.Cli.ConfigPath); err != nil {
if !os.IsNotExist(err) {
return "", fmt.Errorf("failed to get access to configuration file: %s", err)
return []string{}, fmt.Errorf("failed to get access to configuration file: %s", err)
}

return "", nil
return []string{}, nil
}

// Unspecified `modules` field is not considered an error.
if cliOpts.Modules == nil {
return "", nil
return []string{}, nil
}

// We return an error only if the following conditions are met:
// 1. If a directory field is specified;
// 2. Specified path exists;
// 3. Path points to not a directory.
// FIXME: Add working with a list https://github.com/tarantool/tt/issues/1014
modulesDir := cliOpts.Modules.Directories[0]
if info, err := os.Stat(modulesDir); err == nil {
// TODO: Add warning in next patches, discussion
// what if the file exists, but access is denied, etc.
if !info.IsDir() {
return "", fmt.Errorf("specified path in configuration file is not a directory")
}
}
return collectDirectoriesList(cliOpts.Modules.Directories)
}

return modulesDir, nil
func getEnvironmentModulesDirs() ([]string, error) {
env_var := os.Getenv("TT_CLI_MODULES_PATH")
if env_var == "" {
return []string{}, nil
}
paths := strings.Split(env_var, ":")
return collectDirectoriesList(paths)
}

// getExternalModules returns map of available modules by
// parsing the contents of the path folder.
func getExternalModules(path string) (map[string]string, error) {
func getExternalModules(paths []string) (map[string]string, error) {
// FIXME: Work with list at https://github.com/tarantool/tt/issues/1014
path := paths[0]

modules := make(map[string]string)

// If the directory doesn't exist, it is not an error.
Expand Down
3 changes: 3 additions & 0 deletions cli/modules/modules_test.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// FIXME: Create new tests https://github.com/tarantool/tt/issues/1039
//go:build exclude

package modules

import (
Expand Down

0 comments on commit b36ea67

Please sign in to comment.