Skip to content

Commit cbe4a1a

Browse files
committed
Base structure for configuration
1 parent c2af3b5 commit cbe4a1a

File tree

5 files changed

+220
-14
lines changed

5 files changed

+220
-14
lines changed

config.go

Lines changed: 77 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,86 @@
11
package redkeep
22

3-
//
4-
//
5-
//
6-
//
7-
//
8-
//
3+
import (
4+
"encoding/json"
5+
"errors"
6+
7+
validator "gopkg.in/go-playground/validator.v8"
8+
)
9+
10+
//Configuration for red keep
11+
type Configuration struct {
12+
Mongo Mongo `json:"mongo" validate:"required"`
13+
Watches []Watch `json:"watches" validate:"required,gt=0,dive"`
14+
}
15+
16+
//Mongo is a config struct that changes the way the client
17+
//connects.
18+
//ConnectionURI should be a string identifying your cluster
19+
//if you have to slaves and one master it would be like
20+
//slave-01:27018,slave-02:27018,master:27018
21+
//where slave-01 is either a hostname or an ip
922
type Mongo struct {
10-
ListenDatabase string
11-
ConnectionURL string
23+
ConnectionURI string `json:"connectionURI" validate:"required,gt=0"`
1224
}
1325

26+
//Watch defines one watch that redkeep will do for you
1427
type Watch struct {
28+
TrackCollection string `json:"trackCollection" validate:"required,gt=0"`
29+
TrackFields []string `json:"trackFields" validate:"required,eq=1,dive,min=1"`
30+
TargetCollection string `json:"targetCollection" validate:"required,min=1"`
31+
TargetNormalizedField string `json:"targetNormalizedField" validate:"required,min=1"`
32+
TriggerReference string `json:"triggerReference" validate:"required,min=1"`
33+
BehaviourSettings BehaviourSettings `json:"behaviourSettings"`
1534
}
1635

17-
type Configuration struct {
18-
Mongo Mongo `json:"mongo"`
19-
Watches []Watch `json:"watches"`
36+
//BehaviourSettings can define how one specific
37+
//watch handles special cases
38+
type BehaviourSettings struct {
39+
CascadeDelete bool `json:"cascadeDelete"`
40+
}
41+
42+
//NewConfiguration loads a configuration from data
43+
//if it is not valid json, it will return an error
44+
func NewConfiguration(configData []byte) (*Configuration, error) {
45+
var config Configuration
46+
err := json.Unmarshal(configData, &config)
47+
if err != nil {
48+
return nil, err
49+
}
50+
51+
validate := validator.New(&validator.Config{TagName: "validate"})
52+
err = validate.Struct(config)
53+
54+
if err != nil {
55+
return nil, getValidationError(err.(validator.ValidationErrors))
56+
}
57+
58+
return &config, err
59+
}
60+
61+
func getValidationError(allErrors validator.ValidationErrors) error {
62+
for _, e := range allErrors {
63+
switch e.Field {
64+
case "Watches":
65+
return errors.New("Please add atleast one entry in watches")
66+
case "ConnectionURI":
67+
return errors.New("Mongo configuration must be defined")
68+
case "TargetCollection":
69+
return errors.New("TargetCollection must not be empty")
70+
case "TriggerReference":
71+
return errors.New("TriggerReference must not be empty")
72+
case "TrackCollection":
73+
return errors.New("TrackCollection must not be empty")
74+
case "TrackFields":
75+
fallthrough
76+
case "TrackFields[0]":
77+
return errors.New("TrackFields must exactly have one non-empty field, more are currently not supported")
78+
case "TargetNormalizedField":
79+
return errors.New("TargetNormalizedField must not be empty")
80+
default:
81+
return allErrors
82+
}
83+
}
84+
85+
return errors.New("Something went wrong")
2086
}

config_test.go

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package redkeep_test
2+
3+
import (
4+
"io/ioutil"
5+
"strings"
6+
7+
. "github.com/manyminds/redkeep"
8+
9+
. "github.com/onsi/ginkgo"
10+
. "github.com/onsi/gomega"
11+
)
12+
13+
var mongoMissingConfig = `
14+
{
15+
"watches": [
16+
{
17+
"trackCollection": "live.user",
18+
"trackFields": ["username"],
19+
"targetCollection": "live.comment",
20+
"targetNormalizedField": "normalizedUser",
21+
"triggerReference": "user",
22+
"behaviourSettings": {
23+
"cascadeDelete": false
24+
}
25+
}
26+
]
27+
}`
28+
29+
var watchesMissingConfig = `
30+
{
31+
"mongo": {
32+
"connectionURI": "localhost:30000,localhost:30001,localhost:30002"
33+
},
34+
"watches": [
35+
]
36+
}
37+
`
38+
39+
var emptyConfig = `
40+
{
41+
}
42+
`
43+
44+
var templateForTestsConfig = `
45+
{
46+
"mongo": {
47+
"connectionURI": "localhost:30000,localhost:30001,localhost:30002"
48+
},
49+
"watches": [
50+
{
51+
"trackCollection": "xAx",
52+
"trackFields": ["xBx"],
53+
"targetCollection": "xCx",
54+
"targetNormalizedField": "xDx",
55+
"triggerReference": "xEx"
56+
}
57+
]
58+
}`
59+
60+
var _ = Describe("Config Testsuite", func() {
61+
Context("it will load and validate a config file", func() {
62+
It("will error with an empty config", func() {
63+
_, err := NewConfiguration([]byte(emptyConfig))
64+
Expect(err).To(HaveOccurred())
65+
})
66+
67+
It("will error with missing mongo key", func() {
68+
_, err := NewConfiguration([]byte(mongoMissingConfig))
69+
Expect(err).To(HaveOccurred())
70+
Expect(err.Error()).To(Equal("Mongo configuration must be defined"))
71+
})
72+
73+
It("will error with missing watches entries", func() {
74+
_, err := NewConfiguration([]byte(watchesMissingConfig))
75+
Expect(err).To(HaveOccurred())
76+
Expect(err.Error()).To(Equal("Please add atleast one entry in watches"))
77+
})
78+
79+
It("will error with correct data but empty trackCollection", func() {
80+
_, err := NewConfiguration([]byte(strings.Replace(templateForTestsConfig, "xAx", "", 1)))
81+
Expect(err).To(HaveOccurred())
82+
Expect(err.Error()).To(Equal("TrackCollection must not be empty"))
83+
})
84+
85+
It("will error with correct data but empty targetCollection", func() {
86+
_, err := NewConfiguration([]byte(strings.Replace(templateForTestsConfig, "xCx", "", 1)))
87+
Expect(err).To(HaveOccurred())
88+
Expect(err.Error()).To(Equal("TargetCollection must not be empty"))
89+
})
90+
91+
It("will error with correct data but empty targetNormalizedField", func() {
92+
_, err := NewConfiguration([]byte(strings.Replace(templateForTestsConfig, "xDx", "", 1)))
93+
Expect(err).To(HaveOccurred())
94+
Expect(err.Error()).To(Equal("TargetNormalizedField must not be empty"))
95+
})
96+
97+
It("will error with correct data but empty triggerReference", func() {
98+
_, err := NewConfiguration([]byte(strings.Replace(templateForTestsConfig, "xEx", "", 1)))
99+
Expect(err).To(HaveOccurred())
100+
Expect(err.Error()).To(Equal("TriggerReference must not be empty"))
101+
})
102+
103+
It("will error with correct data but empty trigger", func() {
104+
_, err := NewConfiguration([]byte(strings.Replace(templateForTestsConfig, "xBx", "", 1)))
105+
Expect(err).To(HaveOccurred())
106+
Expect(err.Error()).To(Equal("TrackFields must exactly have one non-empty field, more are currently not supported"))
107+
})
108+
109+
It("will error with correct data but multiple trackFields", func() {
110+
_, err := NewConfiguration([]byte(strings.Replace(templateForTestsConfig, `xBx"`, `", "xXx"`, 1)))
111+
Expect(err).To(HaveOccurred())
112+
Expect(err.Error()).To(Equal("TrackFields must exactly have one non-empty field, more are currently not supported"))
113+
})
114+
115+
It("will load correctly", func() {
116+
file, err := ioutil.ReadFile("./example-configuration.json")
117+
Expect(err).ToNot(HaveOccurred())
118+
119+
_, err = NewConfiguration(file)
120+
Expect(err).ToNot(HaveOccurred())
121+
})
122+
})
123+
})

example-configuration.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"mongo": {
3+
"connectionURI": "localhost:30000,localhost:30001,localhost:30002"
4+
},
5+
"watches": [
6+
{
7+
"trackCollection": "live.user",
8+
"trackFields": ["username"],
9+
"targetCollection": "live.comment",
10+
"targetNormalizedField": "normalizedUser",
11+
"triggerReference": "user",
12+
"behaviourSettings": {
13+
"cascadeDelete": false
14+
}
15+
}
16+
]
17+
}

tail.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ func (t TailAgent) Tail(quit chan bool) error {
144144

145145
func (t *TailAgent) connect() error {
146146
if !t.isConnected {
147-
session, err := mgo.Dial(t.config.Mongo.ConnectionURL)
147+
session, err := mgo.Dial(t.config.Mongo.ConnectionURI)
148148

149149
if err != nil {
150150
log.Println(err)

tail_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,10 @@ var _ = Describe("Tail", func() {
4949
})
5050

5151
Context("Test basic connectivity", func() {
52-
It("should connect to master", func() {
52+
PIt("should connect to master", func() {
5353
config := Configuration{
5454
Mongo: Mongo{
55-
ConnectionURL: "localhost:30002,localhost:30001,localhost:30000",
55+
ConnectionURI: "localhost:30002,localhost:30001,localhost:30000",
5656
},
5757
}
5858
running := make(chan bool)

0 commit comments

Comments
 (0)