From 3d66e17110b20abc81ed3af9a4e735f453312a8c Mon Sep 17 00:00:00 2001 From: Benjamin Bollen <ben@erisindustries.com> Date: Wed, 25 May 2016 17:31:49 +0200 Subject: [PATCH] configure Do.DataDir as default WorkDir/data; introduce directory relates filesystem functions in /util; inspired by common but debugged --- cmd/serve.go | 67 +++++++++++++++++++++++++++++++---------------- definitions/do.go | 25 +++++++++++++++--- util/fs.go | 46 ++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 25 deletions(-) create mode 100644 util/fs.go diff --git a/cmd/serve.go b/cmd/serve.go index 91f3c41a..a8ad8187 100644 --- a/cmd/serve.go +++ b/cmd/serve.go @@ -17,11 +17,14 @@ package commands import ( + "fmt" "os" cobra "github.com/spf13/cobra" - log "github.com/eris-ltd/eris-logger" + log "github.com/eris-ltd/eris-logger" + + util "github.com/eris-ltd/eris-db/util" ) var ServeCmd = &cobra.Command { @@ -30,10 +33,28 @@ var ServeCmd = &cobra.Command { Long: `Eris-DB serve starts an eris-db node with client API enabled by default. The Eris-DB node is modularly configured for the consensus engine and application manager. The client API can be disabled.`, - Example: `$ eris-db serve -- will start the Eris-DB node based on the configuration file in the current working directory`, - Run: func(cmd *cobra.Command, args []string) { - serve() + Example: `$ eris-db serve -- will start the Eris-DB node based on the configuration file "server_config.toml" in the current working directory +$ eris-db serve --work-dir <path-to-working-directory> -- will start the Eris-DB node based on the configuration file "server_config.toml" in the provided working directory`, + PreRun: func(cmd *cobra.Command, args []string) { + // if WorkDir was not set by a flag or by $ERIS_DB_WORKDIR + // NOTE [ben]: we can consider an `Explicit` flag that eliminates + // the use of any assumptions while starting Eris-DB + if do.WorkDir == "" { + if currentDirectory, err := os.Getwd(); err != nil { + log.Fatalf("No directory provided and failed to get current working directory: %v", err) + os.Exit(1) + } else { + log.Warn("No working directory provided in ERIS_DB_WORKDIR or --work-dir\n" + + "Will use current working directory ", currentDirectory) + do.WorkDir = currentDirectory + } + } + if !util.IsDir(do.WorkDir) { + log.Fatalf("Provided working directory %s is not a directory", do.WorkDir) + } + log.Debug("Working directory is set as %s", do.WorkDir) }, + Run: Serve, } // build the serve subcommand @@ -44,12 +65,17 @@ func buildServeCommand() { func addServeFlags() { ServeCmd.PersistentFlags().StringVarP(&do.WorkDir, "work-dir", "w", defaultWorkDir(), "specify the working directory for the chain to run. If omitted, and no path set in $ERIS_DB_WORKDIR, the current working directory is taken.") + ServeCmd.PersistentFlags().StringVarP(&do.DataDir, "data-dir", "a", + defaultDataDir(), "specify the data directory. If omitted and not set in $ERIS_DB_DATADIR, <working_directory>/data is taken.") } //------------------------------------------------------------------------------ // functions -func serve() { +// serve() prepares the environment and sets up the core for Eris_DB to run. +// After the setup succeeds, serve() starts the core and halts for core to +// terminate. +func Serve(cmd *cobra.Command, args []string) { // load configuration from a single location to avoid a wrong configuration // file is loaded. if err := do.ReadConfig(do.WorkDir, "server_config", "toml"); err != nil { @@ -62,31 +88,28 @@ func serve() { log.Fatalf("Failed to read non-empty string for ChainId from config.") os.Exit(1) } - log.Info("Eris-DB serve initializing ", do.ChainId, " from ", do.WorkDir) -} + // Ensure data directory is set and accesible + if err := do.InitialiseDataDirectory(); err != nil { + log.Fatalf("Failed to initialise data directory (%s): %v", do.DataDir, err) + os.Exit(1) + } + log.Debug(fmt.Sprintf("Data directory is set at %s", do.DataDir)) + + +} //------------------------------------------------------------------------------ // Defaults func defaultWorkDir() string { // if ERIS_DB_WORKDIR environment variable is not set, keep do.WorkDir empty - providedDirectory := setDefaultString("ERIS_DB_WORKDIR", "") - if providedDirectory == "" { - if currentDirectory, err := os.Getwd(); err != nil { - log.Fatalf("No directory provided and failed to get current working directory: %v", err) - os.Exit(1) - } else { - log.Warn("No working directory provided in ERIS_DB_WORKDIR or --work-dir\n" + - "Will use current working directory ", currentDirectory) - return currentDirectory - } - } - return providedDirectory + return setDefaultString("ERIS_DB_WORKDIR", "") } -func defaultToCurrentWorkingDirectory() { - if do.WorkDir == "" { - } +func defaultDataDir() string { + // As the default data directory depends on the default working directory, + // wait setting a default value, and initialise the data directory from serve() + return setDefaultString("ERIS_DB_DATADIR", "") } diff --git a/definitions/do.go b/definitions/do.go index 5ecc2f1c..0410a456 100644 --- a/definitions/do.go +++ b/definitions/do.go @@ -17,7 +17,12 @@ package definitions import ( + "path" + "os" + viper "github.com/spf13/viper" + + util "github.com/eris-ltd/eris-db/util" ) type Do struct { @@ -25,7 +30,14 @@ type Do struct { // only set through command line flags or environment variables Debug bool // ERIS_DB_DEBUG Verbose bool // ERIS_DB_VERBOSE - WorkDir string + + // Work directory is the root directory for Eris-DB to act in + WorkDir string // ERIS_DB_WORKDIR + // Data directory is defaulted to WorkDir + `/data`. + // If Eris-CLI maps a data container, DataDir is intended to point + // to that mapped data directory. + DataDir string // ERIS_DB_DATADIR + // Capital configuration options explicitly extracted from the Viper config ChainId string // has to be set to non-empty string, // uniquely identifying the chain. @@ -43,9 +55,8 @@ func NowDo() *Do { do := new(Do) do.Debug = false do.Verbose = false - // the default value for output is set to true in cmd/eris-db.go; - // avoid double setting it here though do.WorkDir = "" + do.DataDir = "" do.ChainId = "" do.Config = viper.New() return do @@ -64,3 +75,11 @@ func (d *Do) ReadConfig(directory string, name string, configType string) error d.Config.AddConfigPath(directory) return d.Config.ReadInConfig() } + +// InitialiseDataDirectory will default to WorkDir/data if DataDir is empty +func (d *Do) InitialiseDataDirectory() error { + if d.DataDir == "" { + d.DataDir = path.Join(d.WorkDir, "data") + } + return util.EnsureDir(d.DataDir, os.ModePerm) +} diff --git a/util/fs.go b/util/fs.go new file mode 100644 index 00000000..b33450b3 --- /dev/null +++ b/util/fs.go @@ -0,0 +1,46 @@ +// Copyright 2015, 2016 Eris Industries (UK) Ltd. +// This file is part of Eris-RT + +// Eris-RT is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Eris-RT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Eris-RT. If not, see <http://www.gnu.org/licenses/>. + +package util + +import ( + "fmt" + "os" +) + +// Ensure the directory exists or create it if needed. +func EnsureDir(dir string, mode os.FileMode) error { + if fileOptions, err := os.Stat(dir); os.IsNotExist(err) { + err := os.MkdirAll(dir, mode) + if err != nil { + return fmt.Errorf("Could not create directory %v. %v\n", dir, err) + } + } else if err != nil { + return fmt.Errorf("Error asserting directory %s: %v", dir, err) + } else if !fileOptions.IsDir() { + return fmt.Errorf("Path already exists as a file: %s\n", dir) + } + return nil +} + +// Check whether the provided directory exists +func IsDir(directory string) bool { + fileInfo, err := os.Stat(directory) + if err != nil { + return false + } + return fileInfo.IsDir() +} -- GitLab