Skip to content

Commit

Permalink
feat(registry): use registry at setup to claim peername
Browse files Browse the repository at this point in the history
Now we can finally avoid peers accidentally claiming the same peername.
To get this to work I've moved setup into the core package. Setup is going
to get a little more sophisticated in the future, and I'd prefer to have
the core method in a place where it can be tested independent of the CLI,
even if the only way to access this codepath from userland is through the
CLI.
  • Loading branch information
b5 committed Apr 17, 2018
1 parent 81a4020 commit 5b3c2ee
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 47 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ build: require-gopath
@echo ""
@echo "1/5 install non-gx deps:"
@echo ""
<<<<<<< HEAD
go get -v -u $(GOPACKAGES)
=======
go get -v -u github.com/briandowns/spinner github.com/datatogether/api/apiutil github.com/fatih/color github.com/ipfs/go-datastore github.com/olekukonko/tablewriter github.com/qri-io/analytics github.com/qri-io/bleve github.com/qri-io/dataset github.com/qri-io/doggos github.com/sirupsen/logrus github.com/spf13/cobra github.com/spf13/viper github.com/qri-io/varName github.com/qri-io/dsdiff github.com/datatogether/cdxj github.com/ugorji/go/codec github.com/qri-io/registry/regclient github.com/qri-io/registry/regserver/handlers
>>>>>>> feat(registry): use registry at setup to claim peername
@echo ""
@echo "2/5 install gx:"
@echo ""
Expand Down
8 changes: 7 additions & 1 deletion cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import (
"fmt"
"io/ioutil"
"net"
"net/http/httptest"
"os"
"path/filepath"
"strings"
"testing"

"github.com/qri-io/qri/config"
"github.com/qri-io/registry"
"github.com/qri-io/registry/regserver/handlers"
"github.com/spf13/cobra"
)

Expand Down Expand Up @@ -97,7 +100,10 @@ func TestCommandsIntegration(t *testing.T) {
t.Skip(err.Error())
}

registryServer := httptest.NewServer(handlers.NewRoutes(registry.NewProfiles()))

path := filepath.Join(os.TempDir(), "qri_test_commands_integration")
t.Logf("test filepath: %s", path)

// fmt.Printf("temp path: %s", path)
t.Logf("temp path: %s", path)
Expand Down Expand Up @@ -141,7 +147,7 @@ func TestCommandsIntegration(t *testing.T) {
commands := [][]string{
{"help"},
{"version"},
{"setup", "--peername=" + "alan"},
{"setup", "--peername=" + "alan", "--registry=" + registryServer.URL},
{"config", "get"},
{"config", "get", "profile"},
{"config", "set", "webapp.port", "3505"},
Expand Down
75 changes: 29 additions & 46 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
"strings"

ipfs "github.com/qri-io/cafs/ipfs"
"github.com/qri-io/doggos"
Expand All @@ -20,6 +19,7 @@ var (
setupOverwrite bool
setupIPFS bool
setupPeername string
setupRegistry string
setupIPFSConfigData string
setupConfigData string
)
Expand All @@ -44,7 +44,7 @@ overwrite this info.`,
$ qri setup --peername=your_great_peername`,
Run: func(cmd *cobra.Command, args []string) {
var (
cfg *config.Config
cfg = config.DefaultConfig()
err error
)

Expand All @@ -53,26 +53,13 @@ overwrite this info.`,
// this is usually a terrible idea
ErrExit(fmt.Errorf("repo already initialized"))
}
fmt.Printf("setting up qri repo at: %s\n", QriRepoPath)

cfg = config.DefaultConfig()

envVars := map[string]*string{
"QRI_SETUP_CONFIG_DATA": &setupConfigData,
"QRI_SETUP_IPFS_CONFIG_DATA": &setupIPFSConfigData,
}
mapEnvVars(envVars)

// if cfgFile is specified, override
// if cfgFile != "" {
// f, err := os.Open(cfgFile)
// ExitIfErr(err)
// cfgData, err = ioutil.ReadAll(f)
// ExitIfErr(err)
// } else {
// cfgData, _ = yaml.Marshal(config.Config{}.Default())
// }

if setupConfigData != "" {
err := readAtFile(&setupConfigData)
ExitIfErr(err)
Expand All @@ -91,46 +78,41 @@ overwrite this info.`,
cfg.Profile.Peername = setupPeername
} else if cfg.Profile.Peername == doggos.DoggoNick(cfg.Profile.ID) && !setupAnonymous {
cfg.Profile.Peername = inputText("choose a peername:", doggos.DoggoNick(cfg.Profile.ID))
printSuccess(cfg.Profile.Peername)
}

err = cfg.Validate()
ExitIfErr(err)

if err := os.MkdirAll(QriRepoPath, os.ModePerm); err != nil {
ErrExit(fmt.Errorf("error creating home dir: %s", err.Error()))
if setupRegistry != "" {
cfg.Registry.Location = setupRegistry
}

if setupIPFS {
tmpIPFSConfigPath := ""
if setupIPFSConfigData != "" {
err = readAtFile(&setupIPFSConfigData)
ExitIfErr(err)

// TODO - remove this temp file & instead adjust ipfs.InitRepo to accept an io.Reader
tmpIPFSConfigPath = filepath.Join(os.TempDir(), "ipfs_init_config")

err = ioutil.WriteFile(tmpIPFSConfigPath, []byte(setupIPFSConfigData), os.ModePerm)
ExitIfErr(err)

defer func() {
os.Remove(tmpIPFSConfigPath)
}()
}
p := core.SetupParams{
Config: cfg,
QriRepoPath: QriRepoPath,
ConfigFilepath: configFilepath(),
SetupIPFS: setupIPFS,
IPFSFsPath: IpfsFsPath,
}

err = ipfs.InitRepo(IpfsFsPath, tmpIPFSConfigPath)
if err != nil && strings.Contains(err.Error(), "already") {
err = nil
}
if setupIPFSConfigData != "" {
err = readAtFile(&setupIPFSConfigData)
ExitIfErr(err)
} else if _, err := os.Stat(IpfsFsPath); os.IsNotExist(err) {
printWarning("no IPFS repo exists at %s, things aren't going to work properly", IpfsFsPath)
p.SetupIPFSConfigData = []byte(setupIPFSConfigData)
}

err = cfg.WriteToFile(configFilepath())
ExitIfErr(err)
for {
err := core.Setup(p)
if err != nil {
if err == core.ErrHandleTaken {
printWarning("peername '%s' already taken", cfg.Profile.Peername)
cfg.Profile.Peername = inputText("choose a peername:", doggos.DoggoNick(cfg.Profile.ID))
continue
} else {
ErrExit(err)
}
}
break
}

core.Config = cfg
printSuccess("set up qri repo at: %s\n", QriRepoPath)
},
}

Expand All @@ -139,6 +121,7 @@ func init() {
setupCmd.Flags().BoolVarP(&setupAnonymous, "anonymous", "a", false, "use an auto-generated peername")
setupCmd.Flags().BoolVarP(&setupOverwrite, "overwrite", "", false, "overwrite repo if one exists")
setupCmd.Flags().BoolVarP(&setupIPFS, "init-ipfs", "", true, "initialize an IPFS repo if one isn't present")
setupCmd.Flags().StringVarP(&setupRegistry, "registry", "", "", "override default registry URL")
setupCmd.Flags().StringVarP(&setupPeername, "peername", "", "", "choose your desired peername")
setupCmd.Flags().StringVarP(&setupIPFSConfigData, "ipfs-config", "", "", "json-encoded configuration data, specify a filepath with '@' prefix")
setupCmd.Flags().StringVarP(&setupConfigData, "conifg-data", "", "", "json-encoded configuration data, specify a filepath with '@' prefix")
Expand Down
101 changes: 101 additions & 0 deletions core/setup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package core

import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

ipfs "github.com/qri-io/cafs/ipfs"
"github.com/qri-io/qri/config"
"github.com/qri-io/registry/regclient"
)

// ErrHandleTaken is for when a peername is already taken
var ErrHandleTaken = fmt.Errorf("handle is taken")

// SetupParams encapsulates arguments for Setup
type SetupParams struct {
Config *config.Config
QriRepoPath string
ConfigFilepath string
SetupIPFS bool
IPFSFsPath string
SetupIPFSConfigData []byte
}

// Setup provisions a new qri instance, it intentionally doesn't conform to the RPC function signature
// because remotely invoking setup doesn't make much sense
func Setup(p SetupParams) error {
cfg := p.Config
if cfg.Profile == nil {
cfg.Profile = config.DefaultProfile()
}

if err := cfg.Validate(); err != nil {
return fmt.Errorf("invalid configuration: %s", err.Error())
}

if cfg.Registry != nil {
privkey, err := cfg.Profile.DecodePrivateKey()
if err != nil {
return err
}

reg := regclient.NewClient(&regclient.Config{
Location: cfg.Registry.Location,
})

if err := reg.PutProfile(cfg.Profile.Peername, privkey); err != nil {
if strings.Contains(err.Error(), "taken") {
return ErrHandleTaken
}
return err
}
}

if err := os.MkdirAll(p.QriRepoPath, os.ModePerm); err != nil {
return fmt.Errorf("error creating home dir: %s", err.Error())
}

if p.SetupIPFS {
tmpIPFSConfigPath := ""
if p.SetupIPFSConfigData != nil {
// TODO - remove this temp file & instead adjust ipfs.InitRepo to accept an io.Reader
tmpIPFSConfigPath = filepath.Join(os.TempDir(), "ipfs_init_config")

if err := ioutil.WriteFile(tmpIPFSConfigPath, p.SetupIPFSConfigData, os.ModePerm); err != nil {
return err
}

defer func() {
os.Remove(tmpIPFSConfigPath)
}()
}

if err := ipfs.InitRepo(p.IPFSFsPath, tmpIPFSConfigPath); err != nil {
if !strings.Contains(err.Error(), "already") {
return fmt.Errorf("error creating IPFS repo: %s", err.Error())
}
}

if _, err := os.Stat(p.IPFSFsPath); os.IsNotExist(err) {
return fmt.Errorf("no IPFS repo exists at %s, things aren't going to work properly", p.IPFSFsPath)
}
}

if err := cfg.WriteToFile(p.ConfigFilepath); err != nil {
return fmt.Errorf("error writing config: %s", err.Error())
}

Config = cfg
ConfigFilepath = p.ConfigFilepath
return nil
}

// Teardown reverses the setup process, destroying a user's privateKey
// and removing local qri data
func Teardown() error {
return nil
}

0 comments on commit 5b3c2ee

Please sign in to comment.