forked from kolesa-team/http-api-mock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
file_definition.go
160 lines (134 loc) · 3.63 KB
/
file_definition.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package definition
import (
"encoding/json"
"errors"
"io/ioutil"
"os"
"path/filepath"
"sort"
"github.com/fsnotify/fsnotify"
"github.com/vtrifonov/http-api-mock/logging"
)
//ErrNotFoundPath error from missing or configuration path
var ErrNotFoundPath = errors.New("Configuration path not found")
//NewFileDefinition file definition constructor
func NewFileDefinition(path string, updatesCh chan []Mock) *FileDefinition {
return &FileDefinition{
Path: path,
Updates: updatesCh,
ConfigReaders: []ConfigReader{},
}
}
//FileDefinition this struct contains the path of definition and some config readers
type FileDefinition struct {
Path string
Updates chan []Mock
ConfigReaders []ConfigReader
}
//PrioritySort mock array sorted by priority
type PrioritySort []Mock
func (s PrioritySort) Len() int {
return len(s)
}
func (s PrioritySort) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
func (s PrioritySort) Less(i, j int) bool {
return s[i].Control.Priority > s[j].Control.Priority
}
func (fd *FileDefinition) existsConfigPath(path string) bool {
_, err := os.Stat(path)
if err == nil {
return true
}
if os.IsNotExist(err) {
return false
}
return true
}
func (fd *FileDefinition) getConfigFiles(path string) []string {
filesList := []string{}
filepath.Walk(path, func(filePath string, fileInfo os.FileInfo, err error) error {
if !fileInfo.IsDir() {
filesList = append(filesList, filePath)
}
return nil
})
return filesList
}
func (fd *FileDefinition) readMock(filename string) (Mock, error) {
buf, err := ioutil.ReadFile(filename)
if err != nil {
return Mock{}, err
}
m := Mock{}
err = json.Unmarshal(buf, &m)
if err != nil {
logging.Printf("Invalid mock definition in: %s\n", filename)
return Mock{}, err
}
m.Name = filepath.Base(filename)
return m, nil
}
//WatchDir start the watching process to detect any change on defintions
func (fd *FileDefinition) WatchDir() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
logging.Println("Hot mock file changing not available.")
return
}
err = watcher.Add(fd.Path)
if err != nil {
logging.Printf("Hot mock file changing not available in folder: %s\n", fd.Path)
return
}
if err = filepath.Walk(fd.Path, func(path string, fileInfo os.FileInfo, err error) error {
if fileInfo.IsDir() {
err = watcher.Add(path)
if err != nil {
logging.Printf("Hot mock file changing not available in folder: %s\n", fd.Path)
return err
}
}
return nil
}); err != nil {
return
}
go func() {
for {
select {
case event := <-watcher.Events:
if event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Remove == fsnotify.Remove {
logging.Println("Changes detected in mock definitions")
fd.Updates <- fd.ReadMocksDefinition()
}
case err := <-watcher.Errors:
logging.Fatal(err)
}
}
}()
}
//AddConfigReader allows append new readers to able load different config files
func (fd *FileDefinition) AddConfigReader(reader ConfigReader) {
fd.ConfigReaders = append(fd.ConfigReaders, reader)
}
//ReadMocksDefinition reads all definitions and return an array of valid mocks
func (fd *FileDefinition) ReadMocksDefinition() []Mock {
if !fd.existsConfigPath(fd.Path) {
logging.Fatalf(ErrNotFoundPath.Error())
}
mocks := []Mock{}
for _, file := range fd.getConfigFiles(fd.Path) {
for _, reader := range fd.ConfigReaders {
if reader.CanRead(file) {
if mockDef, err := reader.Read(file); err == nil {
mockDef.Name = filepath.Base(file)
mocks = append(mocks, mockDef)
}
break
}
}
}
sort.Sort(PrioritySort(mocks))
return mocks
}