Skip to content

Commit

Permalink
Node add/delete/list
Browse files Browse the repository at this point in the history
  • Loading branch information
pierotofy committed Dec 21, 2018
1 parent 211245f commit 3bdafd7
Show file tree
Hide file tree
Showing 6 changed files with 154 additions and 29 deletions.
47 changes: 36 additions & 11 deletions internal/cmd/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
package cmd

import (
"fmt"
"github.com/OpenDroneMap/CloudODM/internal/logger"

"github.com/OpenDroneMap/CloudODM/internal/config"
"github.com/spf13/cobra"
Expand All @@ -29,20 +29,45 @@ var nodeCmd = &cobra.Command{
Run: func(cmd *cobra.Command, args []string) {
config.Initialize()

fmt.Println("node called")
for k, n := range config.User.Nodes {
if logger.Verbose {
logger.Info(k + " - " + n.String())
} else {
logger.Info(k)
}
}
},
}

func init() {
rootCmd.AddCommand(nodeCmd)
var addCmd = &cobra.Command{
Use: "add <name> <url>",
Short: "Add a new processing node",
Args: cobra.ExactValidArgs(2),
Run: func(cmd *cobra.Command, args []string) {
config.Initialize()

// Here you will define your flags and configuration settings.
if err := config.User.AddNode(args[0], args[1]); err != nil {
logger.Error(err)
}
},
}

// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// nodeCmd.PersistentFlags().String("foo", "", "A help for foo")
var removeCmd = &cobra.Command{
Use: "remove <name>",
Short: "Remove a processing node",
Aliases: []string{"delete", "rm", "del"},
Args: cobra.ExactValidArgs(1),
Run: func(cmd *cobra.Command, args []string) {
config.Initialize()

if !config.User.RemoveNode(args[0]) {
logger.Error("Cannot remove node " + args[0] + " (does it exist?)")
}
},
}

// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// nodeCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
func init() {
nodeCmd.AddCommand(addCmd)
nodeCmd.AddCommand(removeCmd)
rootCmd.AddCommand(nodeCmd)
}
1 change: 1 addition & 0 deletions internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,5 @@ func Execute() {

func init() {
rootCmd.PersistentFlags().BoolVarP(&logger.Verbose, "verbose", "v", false, "show verbose output")
rootCmd.PersistentFlags().BoolVar(&logger.Verbose, "debug", false, "show debug output")
}
46 changes: 30 additions & 16 deletions internal/config/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,36 @@ import (
homedir "github.com/mitchellh/go-homedir"
)

var cfgPath string
// User contains the user's configuration
var User Configuration

func NewConfiguration() Configuration {
// NewConfiguration creates a new configuration from a specified file path
func NewConfiguration(filePath string) Configuration {
conf := Configuration{}
conf.Nodes = map[string]Node{}
conf.filePath = filePath
return conf
}

func (c Configuration) Save() {
saveToFile(c, c.filePath)
}

type Configuration struct {
Nodes map[string]Node `json:"nodes"`

filePath string
}

type Node struct {
Url string `json:"url"`
Token string `json:"token"`
}

func (n Node) String() string {
return n.Url
}

// Initialize the configuration
func Initialize() {
// Find home directory.
Expand All @@ -41,14 +54,15 @@ func Initialize() {
os.Exit(1)
}

cfgPath = filepath.Join(home, ".odm.json")
cfgPath := filepath.Join(home, ".odm.json")

if exists, _ := fs.FileExists(cfgPath); exists {
// Read existing config
loadFromFile()
User = loadFromFile(cfgPath)
} else {
// Download public nodes, choose a default
nodes := GetPublicNodes()
defaultConfig := NewConfiguration()
User := NewConfiguration(cfgPath)

logger.Info("Found " + strconv.Itoa(len(nodes)) + " public nodes")

Expand All @@ -58,45 +72,45 @@ func Initialize() {
randomNode := nodes[rand.Intn(len(nodes))]

logger.Info("Setting default node to " + randomNode.String())
defaultConfig.Nodes["default"] = Node{Url: randomNode.Url, Token: ""}
}
User.AddNode("default", randomNode.Url)

saveToFile(defaultConfig)
logger.Info("Initialized configuration at " + cfgPath)
}
}
}

func saveToFile(conf Configuration) {
func saveToFile(conf Configuration, filePath string) {
jsonData, err := json.MarshalIndent(conf, "", " ")
if err != nil {
logger.Error(err)
}

jsonFile, err := os.Create(cfgPath)
jsonFile, err := os.Create(filePath)
if err != nil {
logger.Error(err)
}
defer jsonFile.Close()

jsonFile.Write(jsonData)

logger.Info("Wrote default configuration in " + cfgPath)
logger.Debug("Wrote default configuration in " + filePath)
}

func loadFromFile() Configuration {
jsonFile, err := os.Open(cfgPath)
func loadFromFile(filePath string) Configuration {
jsonFile, err := os.Open(filePath)
if err != nil {
logger.Error(err)
}
logger.Debug("Loaded configuration from " + cfgPath)
logger.Debug("Loaded configuration from " + filePath)

defer jsonFile.Close()

jsonData, err := ioutil.ReadAll(jsonFile)
if err != nil {
logger.Error("Cannot read configuration file: " + cfgPath)
logger.Error("Cannot read configuration file: " + filePath)
}

conf := Configuration{}
conf := NewConfiguration(filePath)
err = json.Unmarshal([]byte(jsonData), &conf)
if err != nil {
logger.Error("Cannot parse configuration file: " + err.Error())
Expand Down
33 changes: 33 additions & 0 deletions internal/config/nodes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package config

import (
"errors"
"net/url"
)

// AddNode adds a new node to the configuration
func (c Configuration) AddNode(name string, nodeURL string) error {
if _, ok := c.Nodes[name]; ok {
return errors.New("node" + name + " already exists. Remove it first.")
}

u, err := url.ParseRequestURI(nodeURL)
if err != nil {
return errors.New(nodeURL + " is not a valid URL. A valid URL looks like: http://hostname:port/?token=optional")
}

c.Nodes[name] = Node{Url: u.Scheme + "://" + u.Host, Token: u.Query().Get("token")}
c.Save()

return nil
}

// RemoveNode removes a node from the configuration
func (c Configuration) RemoveNode(name string) bool {
_, ok := c.Nodes[name]
if ok {
delete(c.Nodes, name)
c.Save()
}
return ok
}
49 changes: 49 additions & 0 deletions internal/config/nodes_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package config

import (
"os"
"testing"
)

func TestNodes(t *testing.T) {
os.Remove("test.json")
c := NewConfiguration("test.json")

c.AddNode("default", "http://localhost")
if value, ok := c.Nodes["default"]; ok {
if value.Token != "" {
t.Error("Token should not have been set")
}
} else {
t.Error("Default has not been added")
}

if c.AddNode("default", "http://test123") == nil {
t.Error("Should not be able to add an existing node")
}

c.AddNode("test1", "https://localhost:8080/?token=123")
value, _ := c.Nodes["test1"]
if value.Token != "123" {
t.Error("Token should be 123")
}
if value.Url != "https://localhost:8080" {
t.Error("URL is not properly set")
}

if c.AddNode("test2", "invalid-url") == nil {
t.Error("We shouldn't be able to add invalid URLs")
}

if !c.RemoveNode("test1") {
t.Error("Function should have returned true")
}

if _, ok := c.Nodes["test1"]; ok {
t.Error("test1 should have been removed")
}

if c.RemoveNode("test1") {
t.Error("Function should have returned false (already deleted)")
}
}
7 changes: 5 additions & 2 deletions internal/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import (
// Verbose output
var Verbose bool

// Debug message (if verbose is enabled)
// DebugFlag sets debug output
var DebugFlag bool

// Debug message (if DebugFlag is enabled)
func Debug(a ...interface{}) {
if Verbose {
if DebugFlag {
fmt.Println(a...)
}
}
Expand Down

0 comments on commit 3bdafd7

Please sign in to comment.