Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Fix for issue #418 #911

Merged
merged 4 commits into from
May 17, 2016
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions core/serror/serror.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ limitations under the License.

package serror

import (
"errors"
)

var (
ErrBadAddress = errors.New("Address for binding can not contain comma")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case I feel snapd and the rest package should use their own errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK just removing this part then.

)

type SnapError interface {
error
Fields() map[string]interface{}
Expand Down
3 changes: 2 additions & 1 deletion examples/configs/snap-config-sample.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@
"rest_auth_password": "changeme",
"rest_certificate": "/path/to/cert/file",
"rest_key": "/path/to/private/key",
"port": 8282
"port": 8282,
"addr": "127.0.0.1:12345"
},
"tribe": {
"enable": true,
Expand Down
3 changes: 3 additions & 0 deletions examples/configs/snap-config-sample.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ restapi:
# port sets the port to start the REST API server on. Default is 8181
port: 8282

# REST API in address[:port] format
addr: 127.0.0.1:12345

# tribe section contains all configuration items for the tribe module
tribe:
# enable controls enabling tribe for the snapd instance. Default value is false.
Expand Down
2 changes: 1 addition & 1 deletion mgmt/rest/client/client_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func startAPI() string {
}
log.Fatal(err)
}(r.Err())
r.SetAddress("127.0.0.1:0")
r.SetAddress("127.0.0.1", 0)
r.Start()
time.Sleep(100 * time.Millisecond)
return fmt.Sprintf("http://localhost:%d", r.Port())
Expand Down
3 changes: 1 addition & 2 deletions mgmt/rest/client/client_tribe_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"io/ioutil"
"net"
"net/http"
"strconv"
"sync"
"testing"
"time"
Expand Down Expand Up @@ -201,7 +200,7 @@ func startTribes(count int) []int {
r.BindMetricManager(c)
r.BindTaskManager(s)
r.BindTribeManager(t)
r.SetAddress(":" + strconv.Itoa(mgtPort))
r.SetAddress("", mgtPort)
r.Start()
wg.Add(1)
timer := time.After(10 * time.Second)
Expand Down
2 changes: 1 addition & 1 deletion mgmt/rest/rest_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ func startAPI(cfg *mockConfig) *restAPIInstance {
}
log.Fatal(err)
}(r.Err())
r.SetAddress("127.0.0.1:0")
r.SetAddress("127.0.0.1", 0)
r.Start()
time.Sleep(time.Millisecond * 100)
return &restAPIInstance{
Expand Down
26 changes: 24 additions & 2 deletions mgmt/rest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ const (
const (
defaultEnable bool = true
defaultPort int = 8181
defaultAddress string = ""
defaultHTTPS bool = false
defaultRestCertificate string = ""
defaultRestKey string = ""
Expand All @@ -73,6 +74,7 @@ var (
type Config struct {
Enable bool `json:"enable,omitempty"yaml:"enable,omitempty"`
Port int `json:"port,omitempty"yaml:"port,omitempty"`
Address string `json:"addr,omitempty"yaml:"addr,omitempty"`
HTTPS bool `json:"https,omitempty"yaml:"https,omitempty"`
RestCertificate string `json:"rest_certificate,omitempty"yaml:"rest_certificate,omitempty"`
RestKey string `json:"rest_key,omitempty"yaml:"rest_key,omitempty"`
Expand Down Expand Up @@ -107,6 +109,9 @@ const (
"type": "integer",
"minimum": 0,
"maximum": 65535
},
"addr" : {
"type": "string"
}
},
"additionalProperties": false
Expand Down Expand Up @@ -210,6 +215,7 @@ func GetDefaultConfig() *Config {
return &Config{
Enable: defaultEnable,
Port: defaultPort,
Address: defaultAddress,
HTTPS: defaultHTTPS,
RestCertificate: defaultRestCertificate,
RestKey: defaultRestKey,
Expand Down Expand Up @@ -240,6 +246,10 @@ func (c *Config) UnmarshalJSON(data []byte) error {
if err := json.Unmarshal(v, &(c.Port)); err != nil {
return fmt.Errorf("%v (while parsing 'restapi::port')", err)
}
case "addr":
if err := json.Unmarshal(v, &(c.Address)); err != nil {
return fmt.Errorf("%v (while parsing 'restapi::addr')", err)
}
case "https":
if err := json.Unmarshal(v, &(c.HTTPS)); err != nil {
return fmt.Errorf("%v (while parsing 'restapi::https')", err)
Expand Down Expand Up @@ -299,8 +309,20 @@ func (s *Server) Name() string {
return "REST"
}

func (s *Server) SetAddress(addrString string) {
s.addrString = addrString
func (s *Server) SetAddress(addrString string, dfltPort int) error {
restLogger.Info(fmt.Sprintf("Setting address to: [%v] Default port: %v", addrString, dfltPort))
// In the future, we could extend this to support multiple comma separated IP[:port] values
if strings.Index(addrString, ",") != -1 {
return serror.ErrBadAddress
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's consider returning errors.New("Invalid address") here.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error here isn't used anywhere. Remove it entirely since the func you added in snapd checkCmdLineFlags already checks for this?

Copy link
Contributor Author

@obourdon obourdon May 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood and agreed. However I will still run the test and call log.Fatal because we might enter this code when running tests like PluginRestCalls for instance which will not go through the main snapd.go code.

Considering this, I would therefore like to "factorize/refactor/modify" the checkCmdLineFlags and extract from it the address validation mechanisms so that this can be common to both snapd.go and server.go. However, where should I put such a code in the current code hierarchy ?

}
// If no port is specified, use default port
if strings.Index(addrString, ":") != -1 {
s.addrString = addrString
} else {
s.addrString = fmt.Sprintf("%s:%d", addrString, dfltPort)
}
restLogger.Info(fmt.Sprintf("Address used for binding: [%v]", s.addrString))
return nil
}

func (s *Server) Start() error {
Expand Down
9 changes: 9 additions & 0 deletions mgmt/rest/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ func TestRestAPIConfigJSON(t *testing.T) {
Convey("Port should be 8282", func() {
So(cfg.Port, ShouldEqual, 8282)
})
Convey("Address should equal 127.0.0.1:12345", func() {
So(cfg.Address, ShouldEqual, "127.0.0.1:12345")
})
Convey("RestAuth should be true", func() {
So(cfg.RestAuth, ShouldEqual, true)
})
Expand Down Expand Up @@ -92,6 +95,9 @@ func TestRestAPIConfigYaml(t *testing.T) {
Convey("Port should be 8282", func() {
So(cfg.Port, ShouldEqual, 8282)
})
Convey("Address should equal 127.0.0.1:12345", func() {
So(cfg.Address, ShouldEqual, "127.0.0.1:12345")
})
Convey("RestAuth should be true", func() {
So(cfg.RestAuth, ShouldEqual, true)
})
Expand Down Expand Up @@ -120,6 +126,9 @@ func TestRestAPIDefaultConfig(t *testing.T) {
Convey("Port should be 8181", func() {
So(cfg.Port, ShouldEqual, 8181)
})
Convey("Address should equal empty string", func() {
So(cfg.Address, ShouldEqual, "")
})
Convey("RestAuth should be false", func() {
So(cfg.RestAuth, ShouldEqual, false)
})
Expand Down
3 changes: 1 addition & 2 deletions mgmt/rest/tribe_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import (
"fmt"
"net"
"net/http"
"strconv"
"sync"
"sync/atomic"
"testing"
Expand Down Expand Up @@ -701,7 +700,7 @@ func startTribes(count int, seed string) ([]int, int) {
r.BindMetricManager(c)
r.BindTaskManager(s)
r.BindTribeManager(t)
r.SetAddress(":" + strconv.Itoa(mgtPort))
r.SetAddress("", mgtPort)
r.Start()
wg.Add(1)
timer := time.After(10 * time.Second)
Expand Down
43 changes: 40 additions & 3 deletions snapd.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package main

import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -54,8 +55,14 @@ var (
Usage: "Disable the agent REST API",
}
flAPIPort = cli.IntFlag{
Name: "api-port, p",
Usage: "API port (Default: 8181)",
Name: "api-port, p",
Usage: "API port (Default: 8181)",
EnvVar: "SNAP_PORT",
}
flAPIAddr = cli.StringFlag{
Name: "api-addr, b",
Usage: "API Address[:port] to bind to/listen on. Default: empty string => listen on all interfaces",
EnvVar: "SNAP_ADDR",
}
flMaxProcs = cli.IntFlag{
Name: "max-procs, c",
Expand Down Expand Up @@ -227,6 +234,7 @@ func main() {
app.Flags = []cli.Flag{
flAPIDisabled,
flAPIPort,
flAPIAddr,
flLogLevel,
flLogPath,
flMaxProcs,
Expand Down Expand Up @@ -354,7 +362,7 @@ func action(ctx *cli.Context) {
r.BindTribeManager(tr)
}
go monitorErrors(r.Err())
r.SetAddress(fmt.Sprintf(":%d", cfg.RestAPI.Port))
r.SetAddress(cfg.RestAPI.Address, cfg.RestAPI.Port)
coreModules = append(coreModules, r)
log.Info("REST API is enabled")
} else {
Expand Down Expand Up @@ -645,9 +653,37 @@ func setDurationVal(field time.Duration, ctx *cli.Context, flagName string) time
return field
}

//
func checkCmdLineFlags(ctx *cli.Context) error {
// Bind address is specified
if ctx.IsSet("api-addr") {
addr := ctx.String("api-addr")
// Contains a comma
if strings.Index(addr, ",") != -1 {
return serror.ErrBadAddress
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's consider returning errors.New("Invalid address") here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

}
idx := strings.Index(addr, ":")
// Port is specified in address string
if idx != -1 {
// Port is also specified on command line
if ctx.IsSet("api-port") {
return errors.New("Port can not be specified in both --api-addr and --port")
}
if idx == (len(addr) - 1) {
return errors.New("Empty port specified")
}
}
}
return nil
}

// Apply the command line flags set (if any) to override the values
// in the input configuration
func applyCmdLineFlags(cfg *Config, ctx *cli.Context) {
err := checkCmdLineFlags(ctx)
if err != nil {
panic(err)
Copy link
Collaborator

@jcooklin jcooklin May 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's remove the panic and call log.Fatal.

Calling log.Fatal calls os.Exit(1) after printing the log message.

Copy link
Contributor Author

@obourdon obourdon May 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure will. This answers one of my questions thanks. However coming from a Java world I am not used to have log.Fatal being "entitled" to also provide the exit mechanism ;-)

}
invertBoolean := true
// apply any command line flags that might have been set, first for the
// snapd-related flags
Expand All @@ -663,6 +699,7 @@ func applyCmdLineFlags(cfg *Config, ctx *cli.Context) {
// next for the RESTful server related flags
cfg.RestAPI.Enable = setBoolVal(cfg.RestAPI.Enable, ctx, "disable-api", invertBoolean)
cfg.RestAPI.Port = setIntVal(cfg.RestAPI.Port, ctx, "api-port")
cfg.RestAPI.Address = setStringVal(cfg.RestAPI.Address, ctx, "ip-addr")
Copy link
Collaborator

@jcooklin jcooklin May 13, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be "api-addr" not "ip-addr"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch thanks

cfg.RestAPI.HTTPS = setBoolVal(cfg.RestAPI.HTTPS, ctx, "rest-https")
cfg.RestAPI.RestCertificate = setStringVal(cfg.RestAPI.RestCertificate, ctx, "rest-cert")
cfg.RestAPI.RestKey = setStringVal(cfg.RestAPI.RestKey, ctx, "rest-key")
Expand Down