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

Commit

Permalink
Merge pull request #899 from tjmcs/tb/fix-configFile-error-reporting
Browse files Browse the repository at this point in the history
Improves error handling when parsing the global config file
  • Loading branch information
IRCody committed May 5, 2016
2 parents 170c8d3 + 1e44f11 commit 5c1177e
Show file tree
Hide file tree
Showing 13 changed files with 361 additions and 47 deletions.
12 changes: 12 additions & 0 deletions Godeps/Godeps.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 41 additions & 5 deletions control/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,40 @@ type Config struct {
Plugins *pluginConfig `json:"plugins,omitempty"yaml:"plugins,omitempty"`
}

const (
CONFIG_CONSTRAINTS = `
"control" : {
"type": ["object", "null"],
"properties": {
"plugin_trust_level": {
"type": "integer",
"minimum": 0,
"maximum": 2
},
"auto_discover_path": {
"type": "string"
},
"cache_expiration": {
"type": "string"
},
"max_running_plugins": {
"type": "integer",
"minimum": 1
},
"keyring_paths" : {
"type": "string"
},
"plugins": {
"type": ["object", "null"],
"properties" : {},
"additionalProperties": true
}
},
"additionalProperties": false
}
`
)

// get the default snapd configuration
func GetDefaultConfig() *Config {
return &Config{
Expand Down Expand Up @@ -103,28 +137,30 @@ func (c *Config) UnmarshalJSON(data []byte) error {
switch k {
case "max_running_plugins":
if err := json.Unmarshal(v, &(c.MaxRunningPlugins)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'control::max_running_plugins')", err)
}
case "plugin_trust_level":
if err := json.Unmarshal(v, &(c.PluginTrust)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'control::plugin_trust_level')", err)
}
case "auto_discover_path":
if err := json.Unmarshal(v, &(c.AutoDiscoverPath)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'control::auto_discover_path')", err)
}
case "keyring_paths":
if err := json.Unmarshal(v, &(c.KeyringPaths)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'control::keyring_paths')", err)
}
case "cache_expiration":
if err := json.Unmarshal(v, &(c.CacheExpiration)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'control::cache_expiration')", err)
}
case "plugins":
if err := json.Unmarshal(v, c.Plugins); err != nil {
return err
}
default:
return fmt.Errorf("Unrecognized key '%v' in global config file while parsing 'control'", k)
}
}
return nil
Expand Down
24 changes: 21 additions & 3 deletions control/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,24 @@ import (
. "github.com/smartystreets/goconvey/convey"
)

const (
MOCK_CONSTRAINTS = `{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "snapd global config schema",
"type": ["object", "null"],
"properties": {
"control": { "$ref": "#/definitions/control" },
"scheduler": { "$ref": "#/definitions/scheduler"},
"restapi" : { "$ref": "#/definitions/restapi"},
"tribe": { "$ref": "#/definitions/tribe"}
},
"additionalProperties": true,
"definitions": { ` +
CONFIG_CONSTRAINTS + `,` + `"scheduler": {}, "restapi": {}, "tribe":{}` +
`}` +
`}`
)

type mockConfig struct {
Control *Config
}
Expand Down Expand Up @@ -68,7 +86,7 @@ func TestPluginConfig(t *testing.T) {
Control: GetDefaultConfig(),
}
path := "../examples/configs/snap-config-sample.json"
err := cfgfile.Read(path, &config)
err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS)
So(err, ShouldBeNil)
cfg := config.Control
So(cfg.Plugins, ShouldNotBeNil)
Expand Down Expand Up @@ -124,7 +142,7 @@ func TestControlConfigJSON(t *testing.T) {
Control: GetDefaultConfig(),
}
path := "../examples/configs/snap-config-sample.json"
err := cfgfile.Read(path, &config)
err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS)
var cfg *Config
if err == nil {
cfg = config.Control
Expand Down Expand Up @@ -187,7 +205,7 @@ func TestControlConfigYaml(t *testing.T) {
Control: GetDefaultConfig(),
}
path := "../examples/configs/snap-config-sample.yaml"
err := cfgfile.Read(path, &config)
err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS)
var cfg *Config
if err == nil {
cfg = config.Control
Expand Down
20 changes: 19 additions & 1 deletion mgmt/rest/rest_func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,24 @@ var (
UploadCount = 0
)

const (
MOCK_CONSTRAINTS = `{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "snapd global config schema",
"type": ["object", "null"],
"properties": {
"control": { "$ref": "#/definitions/control" },
"scheduler": { "$ref": "#/definitions/scheduler"},
"restapi" : { "$ref": "#/definitions/restapi"},
"tribe": { "$ref": "#/definitions/tribe"}
},
"additionalProperties": true,
"definitions": { ` +
`"control": {}, "scheduler": {}, ` + CONFIG_CONSTRAINTS + `, "tribe":{}` +
`}` +
`}`
)

type restAPIInstance struct {
port int
server *Server
Expand Down Expand Up @@ -560,7 +578,7 @@ func TestPluginRestCalls(t *testing.T) {
})
Convey("Plugin config is set at startup", func() {
cfg := getDefaultMockConfig()
err := cfgfile.Read("../../examples/configs/snap-config-sample.json", &cfg)
err := cfgfile.Read("../../examples/configs/snap-config-sample.json", &cfg, MOCK_CONSTRAINTS)
So(err, ShouldBeNil)
r := startAPI(cfg)
port := r.port
Expand Down
50 changes: 43 additions & 7 deletions mgmt/rest/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,40 @@ type Config struct {
RestAuthPassword string `json:"rest_auth_password,omitempty"yaml:"rest_auth_password,omitempty"`
}

const (
CONFIG_CONSTRAINTS = `
"restapi" : {
"type": ["object", "null"],
"properties" : {
"enable": {
"type": "boolean"
},
"https" : {
"type": "boolean"
},
"rest_auth": {
"type": "boolean"
},
"rest_auth_password": {
"type": "string"
},
"rest_certificate": {
"type": "string"
},
"rest_key" : {
"type": "string"
},
"port" : {
"type": "integer",
"minimum": 0,
"maximum": 65535
}
},
"additionalProperties": false
}
`
)

type managesMetrics interface {
MetricCatalog() ([]core.CatalogedMetric, error)
FetchMetrics(core.Namespace, int) ([]core.CatalogedMetric, error)
Expand Down Expand Up @@ -200,32 +234,34 @@ func (c *Config) UnmarshalJSON(data []byte) error {
switch k {
case "enable":
if err := json.Unmarshal(v, &(c.Enable)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'restapi::enable')", err)
}
case "port":
if err := json.Unmarshal(v, &(c.Port)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'restapi::port')", err)
}
case "https":
if err := json.Unmarshal(v, &(c.HTTPS)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'restapi::https')", err)
}
case "rest_certificate":
if err := json.Unmarshal(v, &(c.RestCertificate)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'restapi::rest_certificate')", err)
}
case "rest_key":
if err := json.Unmarshal(v, &(c.RestKey)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'restapi::rest_key')", err)
}
case "rest_auth":
if err := json.Unmarshal(v, &(c.RestAuth)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'restapi::rest_auth')", err)
}
case "rest_auth_password":
if err := json.Unmarshal(v, &(c.RestAuthPassword)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'restapi::rest_auth_password')", err)
}
default:
return fmt.Errorf("Unrecognized key '%v' in global config file while parsing 'restapi'", k)
}
}
return nil
Expand Down
4 changes: 2 additions & 2 deletions mgmt/rest/server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func TestRestAPIConfigJSON(t *testing.T) {
RestAPI: GetDefaultConfig(),
}
path := "../../examples/configs/snap-config-sample.json"
err := cfgfile.Read(path, &config)
err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS)
var cfg *Config
if err == nil {
cfg = config.RestAPI
Expand Down Expand Up @@ -74,7 +74,7 @@ func TestRestAPIConfigYaml(t *testing.T) {
RestAPI: GetDefaultConfig(),
}
path := "../../examples/configs/snap-config-sample.yaml"
err := cfgfile.Read(path, &config)
err := cfgfile.Read(path, &config, MOCK_CONSTRAINTS)
var cfg *Config
if err == nil {
cfg = config.RestAPI
Expand Down
41 changes: 36 additions & 5 deletions mgmt/tribe/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package tribe

import (
"encoding/json"
"fmt"
"net"
"os"
"time"
Expand Down Expand Up @@ -58,6 +59,34 @@ type Config struct {
RestAPIInsecureSkipVerify string `json:"-"yaml:"-"`
}

const (
CONFIG_CONSTRAINTS = `
"tribe": {
"type": ["object", "null"],
"properties": {
"enable" : {
"type": "boolean"
},
"bind_addr": {
"type": "string"
},
"bind_port": {
"type": "integer",
"minimum": 0,
"maximum": 65535
},
"name": {
"type": "string"
},
"seed": {
"type" : "string"
}
},
"additionalProperties": false
}
`
)

// get the default snapd configuration
func GetDefaultConfig() *Config {
mlCfg := memberlist.DefaultLANConfig()
Expand Down Expand Up @@ -93,24 +122,26 @@ func (c *Config) UnmarshalJSON(data []byte) error {
switch k {
case "name":
if err := json.Unmarshal(v, &(c.Name)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'tribe::name')", err)
}
case "enable":
if err := json.Unmarshal(v, &(c.Enable)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'tribe::enable')", err)
}
case "bind_addr":
if err := json.Unmarshal(v, &(c.BindAddr)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'tribe::bind_addr')", err)
}
case "bind_port":
if err := json.Unmarshal(v, &(c.BindPort)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'tribe::bind_port')", err)
}
case "seed":
if err := json.Unmarshal(v, &(c.Seed)); err != nil {
return err
return fmt.Errorf("%v (while parsing 'tribe::seed')", err)
}
default:
return fmt.Errorf("Unrecognized key '%v' in global config file while parsing 'tribe'", k)
}
}
return nil
Expand Down
Loading

0 comments on commit 5c1177e

Please sign in to comment.