-
Notifications
You must be signed in to change notification settings - Fork 2
/
config.go
195 lines (163 loc) · 5.09 KB
/
config.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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
package pgverify
import (
"fmt"
log "github.com/sirupsen/logrus"
)
const (
// A full test is the default test mode. It is the only test mode that checks all
// of the rows of a given table, guaranteeing equivalent values between targets.
TestModeFull = "full"
// The bookend test is similar to the full test mode, but it only checks a certain
// number of rows from the beginning and end of the table, sorted by primary key.
TestModeBookend = "bookend"
// The number of rows checked in the bookend test mode is configurable.
TestModeBookendDefaultLimit = 1000
// A sparse test checks a deterministic subset of the rows in a table.
TestModeSparse = "sparse"
// The number of rows checked in the sparse test mode is configurable,
// equalling approximately 1/mod of the total.
TestModeSparseDefaultMod = 10
// A rowcount test simply compares table row counts between targets.
TestModeRowCount = "rowcount"
TimestampPrecisionMilliseconds = "milliseconds"
)
// Config represents the configuration for running a verification.
type Config struct {
// Filters for which schemas and tables to run verification tests on.
// Exclude overrides Include.
IncludeTables []string
ExcludeTables []string
IncludeSchemas []string
ExcludeSchemas []string
IncludeColumns []string
ExcludeColumns []string
// TestModes is a list of test modes to run, executed in order.
TestModes []string
// BookendLimit is the number of rows to include when running a bookend test.
BookendLimit int
// SparseMod is used in the sparse test mode to deterministically select a
// subset of rows, approximately 1/mod of the total.
SparseMod int
// Aliases is a list of aliases to use for the target databases in reporting
// output. Is ignored if the number of aliases is not equal to the number of
// supplied targets.
Aliases []string
// TimestampPrecision is the precision level to use when comparing timestamp values.
TimestampPrecision string
Logger log.FieldLogger
}
// Option interface used for setting optional config properties.
type Option interface {
apply(*Config)
}
type optionFunc func(*Config)
func (o optionFunc) apply(c *Config) {
o(c)
}
// NewConfig returns a new Config with default values overridden
// by the supplied Options.
func NewConfig(opts ...Option) Config {
c := Config{}
defaultOpts := []Option{
WithLogger(log.StandardLogger()),
WithTests(TestModeFull),
WithBookendLimit(TestModeBookendDefaultLimit),
WithSparseMod(TestModeSparseDefaultMod),
WithTimestampPrecision(TimestampPrecisionMilliseconds),
}
for _, opt := range append(defaultOpts, opts...) {
opt.apply(&c)
}
return c
}
// Validate checks that the configuration contains valid values.
func (c Config) Validate() error {
for _, mode := range c.TestModes {
switch mode {
case TestModeBookend:
case TestModeFull:
case TestModeRowCount:
case TestModeSparse:
default:
return fmt.Errorf("invalid strategy: %s", c.TestModes)
}
}
return nil
}
// WithLogger sets the logger configuration.
func WithLogger(logger log.FieldLogger) optionFunc {
return func(c *Config) {
c.Logger = logger
}
}
// ExcludeSchemas sets the exclude schemas configuration.
func ExcludeSchemas(schemas ...string) optionFunc {
return func(c *Config) {
c.ExcludeSchemas = schemas
}
}
// IncludeSchemas sets the include schemas configuration.
func IncludeSchemas(schemas ...string) optionFunc {
return func(c *Config) {
c.IncludeSchemas = schemas
}
}
// ExcludeTables sets the exclude tables configuration.
func ExcludeTables(tables ...string) optionFunc {
return func(c *Config) {
c.ExcludeTables = tables
}
}
// IncludeTables sets the include tables configuration.
func IncludeTables(tables ...string) optionFunc {
return func(c *Config) {
c.IncludeTables = tables
}
}
// ExcludeColumns sets the exclude columns configuration.
func ExcludeColumns(columns ...string) optionFunc {
return func(c *Config) {
c.ExcludeColumns = columns
}
}
// IncludeColumns sets the include columns configuration.
func IncludeColumns(columns ...string) optionFunc {
return func(c *Config) {
c.IncludeColumns = columns
}
}
// WithTests defines the tests to run.
func WithTests(testModes ...string) optionFunc {
return func(c *Config) {
c.TestModes = testModes
}
}
// WithBookendLimit sets the bookend limit configuration used in
// the bookend test mode.
func WithBookendLimit(limit int) optionFunc {
return func(c *Config) {
c.BookendLimit = limit
}
}
// WithSparseMod sets the sparse mod configuration used in
// the sparse test mode.
func WithSparseMod(mod int) optionFunc {
return func(c *Config) {
c.SparseMod = mod
}
}
// WithAliases sets the aliases for the target databases. Is ignored if not equal
// to the number of targets.
func WithAliases(aliases []string) optionFunc {
return func(c *Config) {
c.Aliases = aliases
}
}
// WithTimestampPrecision sets the precision level to use when comparing
// timestamp values. This can be useful for addressing precision differences
// between engines, i.e. millisecond vs. microsecond.
func WithTimestampPrecision(precision string) optionFunc {
return func(c *Config) {
c.TimestampPrecision = precision
}
}