Skip to content

Commit

Permalink
fix(config): fix issues created by config overhaul
Browse files Browse the repository at this point in the history
changes to config introduced a number of problems that need addressing. Namely
profile mismatches between fsrepo & the config profile storage, port mismatches,
a few default configuration errors, and some missing / bad error reporting
around configuration loading.

closes #328, closes #329
  • Loading branch information
b5 committed Apr 3, 2018
1 parent 190f96b commit 501cf9a
Show file tree
Hide file tree
Showing 13 changed files with 191 additions and 78 deletions.
30 changes: 9 additions & 21 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,26 +77,10 @@ func New(r repo.Repo, options ...func(*config.Config)) (s *Server, err error) {
return s, nil
}

// Serve starts the server. It will block while the server
// is running
// Serve starts the server. It will block while the server is running
func (s *Server) Serve() (err error) {
server := &http.Server{}
server.Handler = NewServerRoutes(s)
p, err := s.qriNode.Repo.Profile()
if err != nil {
return err
}

if s.cfg.API.Enabled {
// log.Info("qri profile id:", s.qriNode.Identity.Pretty())
info := fmt.Sprintf("connecting to qri:\n peername: %s\n QRI ID: %s\n API port: %s\n IPFS Addreses:", p.Peername, p.ID, s.cfg.API.Port)
for _, a := range s.qriNode.EncapsulatedAddresses() {
info = fmt.Sprintf("%s\n %s", info, a.String())
}
log.Info(info)
} else {
log.Info("running qri in offline mode, no peer-2-peer connections")
}

go s.ServeRPC()
go s.ServeWebapp()
Expand All @@ -111,6 +95,13 @@ func (s *Server) Serve() (err error) {
}()
}

info := s.cfg.SummaryString()
info += "IPFS Addresses:"
for _, a := range s.qriNode.EncapsulatedAddresses() {
info = fmt.Sprintf("%s\n %s", info, a.String())
}
log.Info(info)

// http.ListenAndServe will not return unless there's an error
return StartServer(s.cfg.API, server)
}
Expand All @@ -134,7 +125,6 @@ func (s *Server) ServeRPC() {
}
}

log.Infof("accepting RPC requests on port %s", s.cfg.RPC.Port)
rpc.Accept(listener)
return
}
Expand All @@ -156,8 +146,6 @@ func (s *Server) ServeWebapp() {
m := http.NewServeMux()
m.Handle("/", s.middleware(s.WebappHandler))
webappserver := &http.Server{Handler: m}

log.Infof("webapp available on port %s", s.cfg.Webapp.Port)
webappserver.Serve(listener)
return
}
Expand All @@ -176,7 +164,7 @@ func (s *Server) resolveWebappPath() {
}
log.Debugf("webapp path: %s", p.String())
s.cfg.Webapp.Scripts = []string{
fmt.Sprintf("http://localhost:2503%s", p.String()),
fmt.Sprintf("http://localhost:%s%s", s.cfg.API.Port, p.String()),
}
}

Expand Down
33 changes: 28 additions & 5 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ import (
"gopkg.in/yaml.v2"
)

// cfg is the global configuration object for the CLI
var cfg *config.Config
var (
// cfg is the global configuration object for the CLI
cfg *config.Config
// setting ignoreCfg to true will prevent loadConfig from doing anything
ignoreCfg bool
)

// configCmd represents commands that read & modify configuration settings
var configCmd = &cobra.Command{
Expand Down Expand Up @@ -85,10 +89,29 @@ func init() {
RootCmd.AddCommand(configCmd)
}

func loadConfig() {
var err error
func loadConfig() (err error) {
if ignoreCfg {
return nil
}

cfg, err = config.ReadFromFile(configFilepath())

if err == nil && cfg.Profile == nil {
err = fmt.Errorf("missing profile")
}

if err != nil {
cfg = config.Config{}.Default()
str := `couldn't read config file. error
%s
if you've recently updated qri your config file may no longer be valid.
The easiest way to fix this is to delete your repository at:
%s
and start with a fresh qri install by running 'qri setup' again.
Sorry, we know this is not exactly a great experience, from this point forward
we won't be shipping changes that require starting over.
`
err = fmt.Errorf(str, err.Error(), QriRepoPath)
}

return err
}
19 changes: 7 additions & 12 deletions cmd/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

var (
connectCmdPort string
connectCmdAPIPort string
connectCmdRPCPort string
connectCmdWebappPort string

Expand All @@ -32,11 +32,7 @@ things:
- Start a local API server
When you run connect you are connecting to the distributed web, interacting with
peers & swapping data.
The default port for the local API server is 2503. We call port 2503,
“the qri port”. It’s a good port, lots of cool numbers in there. Some might even
call it a “prime” port number.`,
peers & swapping data.`,
Run: func(cmd *cobra.Command, args []string) {
var (
r repo.Repo
Expand All @@ -52,13 +48,13 @@ call it a “prime” port number.`,
s, err := api.New(r, func(c *config.Config) {
*c = *cfg

if connectCmdPort != config.DefaultAPIPort {
c.API.Enabled = connectCmdPort != ""
c.API.Port = connectCmdPort
if connectCmdAPIPort != config.DefaultAPIPort {
c.API.Enabled = connectCmdAPIPort != ""
c.API.Port = connectCmdAPIPort
}

if connectCmdRPCPort != config.DefaultRPCPort {
c.RPC.Enabled = connectCmdPort != ""
c.RPC.Enabled = connectCmdRPCPort != ""
c.RPC.Port = connectCmdRPCPort
}

Expand All @@ -67,7 +63,6 @@ call it a “prime” port number.`,
c.RPC.Port = connectCmdWebappPort
}
})

ExitIfErr(err)

err = s.Serve()
Expand All @@ -76,7 +71,7 @@ call it a “prime” port number.`,
}

func init() {
connectCmd.Flags().StringVarP(&connectCmdPort, "api-port", "", config.DefaultAPIPort, "port to start api on")
connectCmd.Flags().StringVarP(&connectCmdAPIPort, "api-port", "", config.DefaultAPIPort, "port to start api on")
connectCmd.Flags().StringVarP(&connectCmdRPCPort, "rpc-port", "", config.DefaultRPCPort, "port to start rpc listener on")
connectCmd.Flags().StringVarP(&connectCmdWebappPort, "webapp-port", "", config.DefaultWebappPort, "port to serve webapp on")
connectCmd.Flags().BoolVarP(&connectSetup, "setup", "", false, "run setup if necessary, reading options from enviornment variables")
Expand Down
8 changes: 4 additions & 4 deletions cmd/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,16 @@ func getRepo(online bool) repo.Repo {
ErrExit(fmt.Errorf("no qri repo found, please run `qri setup`"))
}

// cfg, err := readConfigFile()
// ExitIfErr(err)

pk, err := cfg.Profile.DecodePrivateKey()
ExitIfErr(err)

fs := getIpfsFilestore(online)
pro, err := cfg.Profile.DecodeProfile()
ExitIfErr(err)

fs := getIpfsFilestore(online)
r, err := fsrepo.NewRepo(fs, QriRepoPath, cfg.Profile.ID)
r.SetPrivateKey(pk)
r.SetProfile(pro)

ExitIfErr(err)

Expand Down
32 changes: 8 additions & 24 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ running setup. If setup has already been run, by default qri won’t let you
overwrite this info.`,
Example: ` run setup with a peername of your choosing:
$ qri setup --peername=your_great_peername`,
PreRun: func(cmd *cobra.Command, args []string) {
ignoreCfg = true
},
Run: func(cmd *cobra.Command, args []string) {
// var cfgData []byte

Expand All @@ -60,7 +63,7 @@ overwrite this info.`,
}
mapEnvVars(envVars)

// // if cfgFile is specified, override
// if cfgFile is specified, override
// if cfgFile != "" {
// f, err := os.Open(cfgFile)
// ExitIfErr(err)
Expand All @@ -77,11 +80,6 @@ overwrite this info.`,
ExitIfErr(err)
}

// cfg = &config.Config{}
// err := yaml.Unmarshal(cfgData, cfg)
// ExitIfErr(err)
// loadConfig()

// TODO - re-enable
// err = cfg.ensurePrivateKey()
// ExitIfErr(err)
Expand All @@ -92,9 +90,6 @@ overwrite this info.`,
err := cfg.WriteToFile(configFilepath())
ExitIfErr(err)

// err = viper.ReadInConfig()
// ExitIfErr(err)

if setupIPFS {

tmpIPFSConfigPath := ""
Expand Down Expand Up @@ -122,15 +117,6 @@ overwrite this info.`,
printWarning("no IPFS repo exists at %s, things aren't going to work properly", IpfsFsPath)
}

// p := &core.Profile{}
// if setupProfileData != "" {
// err = readAtFile(&setupProfileData)
// ExitIfErr(err)
// err = json.Unmarshal([]byte(setupProfileData), p)
// ExitIfErr(err)
// } else {
// }

anon, err := cmd.Flags().GetBool("anonymous")
ExitIfErr(err)
if setupPeername == "" && !anon {
Expand All @@ -141,12 +127,10 @@ overwrite this info.`,
err = cfg.WriteToFile(configFilepath())
ExitIfErr(err)

// loadConfig()
// pr, err := profileRequests(false)
// ExitIfErr(err)
// res := &core.Profile{}
// err = pr.SavePeername(p, res)
// err = pr.SaveProfile(p, res)
// call SetProfile to give repo a chance to save updated profile data
pro, err := cfg.Profile.DecodeProfile()
ExitIfErr(err)
getRepo(false).SetProfile(pro)

ExitIfErr(err)
},
Expand Down
2 changes: 1 addition & 1 deletion config/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (API) Default() *API {
return &API{
Enabled: true,
Port: DefaultAPIPort,
TLS: true,
TLS: false,
AllowedOrigins: []string{
"http://localhost:2505",
},
Expand Down
23 changes: 23 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,29 @@ func (Config) Default() *Config {
}
}

// SummaryString creates a pretty string summarizing the
// configuration, useful for log output
func (cfg Config) SummaryString() (summary string) {
summary = "\n"
if cfg.Profile != nil {
summary += fmt.Sprintf("peername:\t%s\nprofileID:\t%s\n", cfg.Profile.Peername, cfg.Profile.ID)
}

if cfg.API != nil && cfg.API.Enabled {
summary += fmt.Sprintf("API port:\t%s\n", cfg.API.Port)
}

if cfg.RPC != nil && cfg.RPC.Enabled {
summary += fmt.Sprintf("RPC port:\t%s\n", cfg.RPC.Port)
}

if cfg.Webapp != nil && cfg.Webapp.Enabled {
summary += fmt.Sprintf("Webapp port:\t%s\n", cfg.Webapp.Port)
}

return summary
}

// ReadFromFile reads a YAML configuration file from path
func ReadFromFile(path string) (cfg *Config, err error) {
var data []byte
Expand Down
9 changes: 9 additions & 0 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"os"
"path/filepath"
"reflect"
"strings"
"testing"
)

Expand Down Expand Up @@ -36,6 +37,14 @@ func TestWriteToFile(t *testing.T) {
}
}

func TestConfigSummaryString(t *testing.T) {
summary := Config{}.Default().SummaryString()
t.Log(summary)
if !strings.Contains(summary, "API") {
t.Errorf("expected summary to list API port")
}
}

func TestConfigGet(t *testing.T) {
cfg := Config{}.Default()
cases := []struct {
Expand Down
47 changes: 47 additions & 0 deletions config/profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"crypto/rand"
"encoding/base64"
"fmt"
"time"

"github.com/ipfs/go-datastore"
"github.com/libp2p/go-libp2p-crypto"
"github.com/libp2p/go-libp2p-peer"
"github.com/qri-io/doggos"
Expand All @@ -16,6 +18,10 @@ type Profile struct {
ID string
PrivKey string
Peername string
// Created timestamp
Created time.Time
// Updated timestamp
Updated time.Time
// specifies weather this is a user or an organization
Type string
// user's email address
Expand Down Expand Up @@ -61,6 +67,47 @@ func (Profile) Default() *Profile {
return p
}

// DecodeProfile turns a cfg.Profile into a profile.Profile
func (cfg *Profile) DecodeProfile() (*profile.Profile, error) {
id, err := profile.IDB58Decode(cfg.ID)
if err != nil {
return nil, err
}

t, err := profile.ParseType(cfg.Type)
if err != nil {
return nil, err
}

p := &profile.Profile{
ID: id,
Type: t,
Peername: cfg.Peername,
Created: cfg.Created,
Updated: cfg.Updated,
Email: cfg.Email,
Name: cfg.Name,
Description: cfg.Description,
HomeURL: cfg.HomeURL,
Color: cfg.Color,
Twitter: cfg.Twitter,
}

if cfg.Thumb != "" {
p.Thumb = datastore.NewKey(cfg.Thumb)
}

if cfg.Poster != "" {
p.Poster = datastore.NewKey(cfg.Poster)
}

if cfg.Profile != "" {
p.Profile = datastore.NewKey(cfg.Profile)
}

return p, nil
}

// DecodePrivateKey generates a PrivKey instance from base64-encoded config file bytes
func (cfg *Profile) DecodePrivateKey() (crypto.PrivKey, error) {
if cfg.PrivKey == "" {
Expand Down
Loading

0 comments on commit 501cf9a

Please sign in to comment.