diff --git a/cmd/ipfs/daemon.go b/cmd/ipfs/daemon.go index ed4cf4f4672..70ace8036b7 100644 --- a/cmd/ipfs/daemon.go +++ b/cmd/ipfs/daemon.go @@ -13,6 +13,8 @@ import ( "sync" version "github.com/ipfs/go-ipfs" + config "github.com/ipfs/go-ipfs-config" + cserial "github.com/ipfs/go-ipfs-config/serialize" utilmain "github.com/ipfs/go-ipfs/cmd/ipfs/util" oldcmds "github.com/ipfs/go-ipfs/commands" "github.com/ipfs/go-ipfs/core" @@ -26,11 +28,11 @@ import ( migrate "github.com/ipfs/go-ipfs/repo/fsrepo/migrations" "github.com/hashicorp/go-multierror" - "github.com/ipfs/go-ipfs-cmds" + cmds "github.com/ipfs/go-ipfs-cmds" mprome "github.com/ipfs/go-metrics-prometheus" goprocess "github.com/jbenet/goprocess" ma "github.com/multiformats/go-multiaddr" - "github.com/multiformats/go-multiaddr-net" + manet "github.com/multiformats/go-multiaddr-net" "github.com/prometheus/client_golang/prometheus" ) @@ -38,6 +40,7 @@ const ( adjustFDLimitKwd = "manage-fdlimit" enableGCKwd = "enable-gc" initOptionKwd = "init" + initConfigOptionKwd = "init-config" initProfileOptionKwd = "init-profile" ipfsMountKwd = "mount-ipfs" ipnsMountKwd = "mount-ipns" @@ -154,6 +157,7 @@ Headers. Options: []cmds.Option{ cmds.BoolOption(initOptionKwd, "Initialize ipfs with default settings if not already initialized"), + cmds.StringOption(initConfigOptionKwd, "Path to existing configuration file to be loaded during --init"), cmds.StringOption(initProfileOptionKwd, "Configuration profiles to apply for --init. See ipfs init --help for more"), cmds.StringOption(routingOptionKwd, "Overrides the routing option").WithDefault(routingOptionDefaultKwd), cmds.BoolOption(mountKwd, "Mounts IPFS to the filesystem"), @@ -229,17 +233,20 @@ func daemonFunc(req *cmds.Request, re cmds.ResponseEmitter, env cmds.Environment // first, whether user has provided the initialization flag. we may be // running in an uninitialized state. initialize, _ := req.Options[initOptionKwd].(bool) - if initialize { + if initialize && !fsrepo.IsInitialized(cctx.ConfigRoot) { + cfgLocation, _ := req.Options[initConfigOptionKwd].(string) + profiles, _ := req.Options[initProfileOptionKwd].(string) + var conf *config.Config - cfg := cctx.ConfigRoot - if !fsrepo.IsInitialized(cfg) { - profiles, _ := req.Options[initProfileOptionKwd].(string) - - err := initWithDefaults(os.Stdout, cfg, profiles) - if err != nil { + if cfgLocation != "" { + if conf, err = cserial.Load(cfgLocation); err != nil { return err } } + + if err = doInit(os.Stdout, cctx.ConfigRoot, false, nBitsForKeypairDefault, profiles, conf); err != nil { + return err + } } // acquire the repo lock _before_ constructing a node. we need to make diff --git a/cmd/ipfs/init.go b/cmd/ipfs/init.go index 4fa5087fa6e..03851452087 100644 --- a/cmd/ipfs/init.go +++ b/cmd/ipfs/init.go @@ -7,7 +7,7 @@ import ( "fmt" "io" "os" - "path" + "path/filepath" "strings" assets "github.com/ipfs/go-ipfs/assets" @@ -16,9 +16,9 @@ import ( namesys "github.com/ipfs/go-ipfs/namesys" fsrepo "github.com/ipfs/go-ipfs/repo/fsrepo" - "github.com/ipfs/go-ipfs-cmds" - "github.com/ipfs/go-ipfs-config" - "github.com/ipfs/go-ipfs-files" + cmds "github.com/ipfs/go-ipfs-cmds" + config "github.com/ipfs/go-ipfs-config" + files "github.com/ipfs/go-ipfs-files" ) const ( @@ -28,6 +28,10 @@ const ( profileOptionName = "profile" ) +var errRepoExists = errors.New(`ipfs configuration file already exists! +Reinitializing would overwrite your keys. +`) + var initCmd = &cmds.Command{ Helptext: cmds.HelpText{ Tagline: "Initializes ipfs config file.", @@ -102,31 +106,30 @@ environment variable: } } - profile, _ := req.Options[profileOptionName].(string) - - var profiles []string - if profile != "" { - profiles = strings.Split(profile, ",") - } - + profiles, _ := req.Options[profileOptionName].(string) return doInit(os.Stdout, cctx.ConfigRoot, empty, nBitsForKeypair, profiles, conf) }, } -var errRepoExists = errors.New(`ipfs configuration file already exists! -Reinitializing would overwrite your keys. -`) - -func initWithDefaults(out io.Writer, repoRoot string, profile string) error { - var profiles []string - if profile != "" { - profiles = strings.Split(profile, ",") +func applyProfiles(conf *config.Config, profiles string) error { + if profiles == "" { + return nil } - return doInit(out, repoRoot, false, nBitsForKeypairDefault, profiles, nil) + for _, profile := range strings.Split(profiles, ",") { + transformer, ok := config.Profiles[profile] + if !ok { + return fmt.Errorf("invalid configuration profile: %s", profile) + } + + if err := transformer.Transform(conf); err != nil { + return err + } + } + return nil } -func doInit(out io.Writer, repoRoot string, empty bool, nBitsForKeypair int, confProfiles []string, conf *config.Config) error { +func doInit(out io.Writer, repoRoot string, empty bool, nBitsForKeypair int, confProfiles string, conf *config.Config) error { if _, err := fmt.Fprintf(out, "initializing IPFS node at %s\n", repoRoot); err != nil { return err } @@ -147,15 +150,8 @@ func doInit(out io.Writer, repoRoot string, empty bool, nBitsForKeypair int, con } } - for _, profile := range confProfiles { - transformer, ok := config.Profiles[profile] - if !ok { - return fmt.Errorf("invalid configuration profile: %s", profile) - } - - if err := transformer.Transform(conf); err != nil { - return err - } + if err := applyProfiles(conf, confProfiles); err != nil { + return err } if err := fsrepo.Init(repoRoot, conf); err != nil { @@ -175,7 +171,7 @@ func checkWritable(dir string) error { _, err := os.Stat(dir) if err == nil { // dir exists, make sure we can write to it - testfile := path.Join(dir, "test") + testfile := filepath.Join(dir, "test") fi, err := os.Create(testfile) if err != nil { if os.IsPermission(err) { diff --git a/test/sharness/lib/test-lib.sh b/test/sharness/lib/test-lib.sh index 687ae790498..c16118898a9 100644 --- a/test/sharness/lib/test-lib.sh +++ b/test/sharness/lib/test-lib.sh @@ -212,12 +212,12 @@ test_set_address_vars() { test_launch_ipfs_daemon() { - args="$@" + args=("$@") test "$TEST_ULIMIT_PRESET" != 1 && ulimit -n 2048 test_expect_success "'ipfs daemon' succeeds" ' - ipfs daemon $args >actual_daemon 2>daemon_err & + ipfs daemon "${args[@]}" >actual_daemon 2>daemon_err & IPFS_PID=$! ' diff --git a/test/sharness/t0020-init.sh b/test/sharness/t0020-init.sh index 040cea7ad0c..590afeeaa32 100755 --- a/test/sharness/t0020-init.sh +++ b/test/sharness/t0020-init.sh @@ -163,6 +163,20 @@ test_expect_success "'ipfs config Addresses.API' looks good" ' test $(cat actual_config) = "/ip4/127.0.0.1/tcp/0" ' +test_expect_success "ipfs init from existing config succeeds" ' + export ORIG_PATH=$IPFS_PATH + export IPFS_PATH=$(pwd)/.ipfs-clone + + ipfs init "$ORIG_PATH/config" && + ipfs config Addresses.API > actual_config && + test $(cat actual_config) = "/ip4/127.0.0.1/tcp/0" +' + +test_expect_success "clean up ipfs clone dir and reset IPFS_PATH" ' + rm -rf "$IPFS_PATH" && + export IPFS_PATH=$ORIG_PATH +' + test_expect_success "clean up ipfs dir" ' rm -rf "$IPFS_PATH" ' diff --git a/test/sharness/t0060-daemon.sh b/test/sharness/t0060-daemon.sh index 6f2445b3d9a..a6cdc962469 100755 --- a/test/sharness/t0060-daemon.sh +++ b/test/sharness/t0060-daemon.sh @@ -8,6 +8,43 @@ test_description="Test daemon command" . lib/test-lib.sh +test_expect_success "test environment initialized" ' + export ORIG_IPFS_PATH="$IPFS_PATH" + + export ORIG_PATH="$(pwd)/.ipfs" + export IPFS_PATH="$ORIG_PATH" + export CLONE_PATH="$(pwd)/.ipfs-clone" + ipfs init --profile=badgerds > /dev/null +' + +export IPFS_PATH=$CLONE_PATH +test_launch_ipfs_daemon --init --init-config="$ORIG_PATH/config" +test_kill_ipfs_daemon + +test_expect_success "daemon initialization with existing config works" ' + ipfs config "Datastore.Spec.child.path" >actual && + test $(cat actual) = "badgerds" +' + +test_expect_success "clean up daemon clone" ' + rm -rf "$CLONE_PATH" +' +test_launch_ipfs_daemon --init --init-config="$ORIG_PATH/config" --init-profile=randomports +test_kill_ipfs_daemon + +test_expect_failure "daemon initialization with existing config + profiles works" ' + ipfs config Addresses >clone_conf && + IPFS_PATH=$ORIG_PATH && + ipfs config Addresses >orig_conf && + test_cmp clone_conf orig_conf +' + +test_expect_success "clean up test environment" ' + rm -rf "$CLONE_PATH" + rm -rf "$ORIG_PATH" + + export IPFS_PATH=$ORIG_IPFS_PATH +' test_init_ipfs test_launch_ipfs_daemon