Skip to content

Commit b97b9af

Browse files
Merge branch 'master' into throttler-updateMySQLClusterProbes-log-typo
2 parents 50f5425 + 1c44ebc commit b97b9af

File tree

10 files changed

+168
-36
lines changed

10 files changed

+168
-36
lines changed

.github/workflows/release.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: goreleaser
2+
3+
on:
4+
push:
5+
tags:
6+
- '*'
7+
8+
jobs:
9+
goreleaser:
10+
runs-on: ubuntu-latest
11+
steps:
12+
-
13+
name: Checkout
14+
uses: actions/checkout@v2
15+
with:
16+
fetch-depth: 0
17+
-
18+
name: Set up Go
19+
uses: actions/setup-go@v2
20+
with:
21+
go-version: 1.14
22+
-
23+
name: Run GoReleaser
24+
uses: goreleaser/goreleaser-action@v2
25+
with:
26+
version: latest
27+
args: release --rm-dist
28+
env:
29+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
.gopath/
22
bin/
3+
dist/
34
main
45
conf/freno.local.conf.json
56
.vendor/

.goreleaser.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
before:
2+
hooks:
3+
- go mod download
4+
- go test -v -covermode=atomic ./pkg/...
5+
builds:
6+
- env:
7+
- CGO_ENABLED=0
8+
goos:
9+
- linux
10+
- darwin
11+
ldflags:
12+
- -w -s
13+
- -X main.AppVersion={{.Version}} -X main.GitCommit={{.Commit}}
14+
main: ./cmd/freno/main.go
15+
checksum:
16+
name_template: 'checksums.txt'
17+
changelog:
18+
sort: asc
19+
nfpms:
20+
- vendor: GitHub
21+
homepage: https://github.com/github/freno
22+
description: Cooperative, highly available throttler service
23+
license: MIT
24+
bindir: /usr/bin
25+
config_files:
26+
"resources/freno.conf.skeleton.json": "/etc/freno.conf.json"
27+
files:
28+
"resources/etc/init.d/freno": "/etc/init.d/freno"
29+
empty_folders:
30+
- "/var/lib/freno"
31+
formats:
32+
- deb
33+
- rpm
34+
release:
35+
github:
36+
owner: github
37+
name: freno

.travis.yml

Lines changed: 0 additions & 14 deletions
This file was deleted.

build.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ function oinstall() {
100100
prefix="$2"
101101

102102
cd $mydir
103-
gofmt -s -w go/
103+
gofmt -s -w pkg/
104104
cp ./resources/etc/init.d/freno $builddir/freno/etc/init.d/freno
105105
chmod +x $builddir/freno/etc/init.d/freno
106106
cp ./resources/freno.conf.skeleton.json $builddir/freno/etc/freno.conf.json
@@ -143,7 +143,7 @@ function build() {
143143
prefix="$4"
144144
ldflags="-X main.AppVersion=${RELEASE_VERSION} -X main.GitCommit=${GIT_COMMIT}"
145145
echo "Building via $(go version)"
146-
gobuild="go build -i ${opt_race} -ldflags \"$ldflags\" -o $builddir/freno${prefix}/freno go/cmd/freno/main.go"
146+
gobuild="go build -i ${opt_race} -ldflags \"$ldflags\" -o $builddir/freno${prefix}/freno cmd/freno/main.go"
147147

148148
case $os in
149149
'linux')

pkg/config/mysql_config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type MySQLConfigurationSettings struct {
5858
HttpCheckPort int // port for HTTP check. -1 to disable.
5959
HttpCheckPath string // If non-empty, requires HttpCheckPort
6060
IgnoreHosts []string // If non empty, substrings to indicate hosts to be ignored/skipped
61+
VitessCells []string // Name of the Vitess cells for polling tablet hosts
6162

6263
Clusters map[string](*MySQLClusterConfigurationSettings) // cluster name -> cluster config
6364
}
@@ -114,6 +115,9 @@ func (settings *MySQLConfigurationSettings) postReadAdjustments() error {
114115
if len(clusterSettings.IgnoreHosts) == 0 {
115116
clusterSettings.IgnoreHosts = settings.IgnoreHosts
116117
}
118+
if !clusterSettings.VitessSettings.IsEmpty() && len(clusterSettings.VitessSettings.Cells) < 1 {
119+
clusterSettings.VitessSettings.Cells = settings.VitessCells
120+
}
117121
}
118122
return nil
119123
}

pkg/config/vitess_config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package config
66

77
type VitessConfigurationSettings struct {
88
API string
9+
Cells []string
910
Keyspace string
1011
Shard string
1112
TimeoutSecs uint

pkg/throttle/throttler.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,9 @@ func (throttler *Throttler) refreshMySQLInventory() error {
327327
if err != nil {
328328
return log.Errorf("Unable to get vitess hosts from %s, %s/%s: %+v", clusterSettings.VitessSettings.API, keyspace, shard, err)
329329
}
330-
log.Debugf("Read %+v hosts from vitess %s, %s/%s", len(tablets), clusterSettings.VitessSettings.API, keyspace, shard)
330+
log.Debugf("Read %+v hosts from vitess %s, %s/%s, cells=%s", len(tablets), clusterSettings.VitessSettings.API,
331+
keyspace, shard, strings.Join(vitess.ParseCells(clusterSettings.VitessSettings), ","),
332+
)
331333
clusterProbes := &mysql.ClusterProbes{
332334
ClusterName: clusterName,
333335
IgnoreHostsCount: clusterSettings.IgnoreHostsCount,

pkg/vitess/api_client.go

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,23 @@ const defaultTimeout = time.Duration(5) * time.Second
1616

1717
// Tablet represents information about a running instance of vttablet.
1818
type Tablet struct {
19-
MysqlHostname string `json:"mysql_hostname,omitempty"`
20-
MysqlPort int32 `json:"mysql_port,omitempty"`
21-
Type topodata.TabletType `json:"type,omitempty"`
19+
Alias *topodata.TabletAlias `json:"alias,omitempty"`
20+
MysqlHostname string `json:"mysql_hostname,omitempty"`
21+
MysqlPort int32 `json:"mysql_port,omitempty"`
22+
Type topodata.TabletType `json:"type,omitempty"`
23+
}
24+
25+
// HasValidCell returns a bool reflecting if a tablet is in a valid Vitess cell
26+
func (t Tablet) HasValidCell(validCells []string) bool {
27+
if len(validCells) == 0 {
28+
return true
29+
}
30+
for _, cell := range validCells {
31+
if t.Alias.GetCell() == cell {
32+
return true
33+
}
34+
}
35+
return false
2236
}
2337

2438
// IsValidReplica returns a bool reflecting if a tablet type is REPLICA
@@ -40,17 +54,29 @@ func constructAPIURL(settings config.VitessConfigurationSettings) (url string) {
4054
return url
4155
}
4256

57+
// ParseCells returns a slice of non-empty Vitess cell names
58+
func ParseCells(settings config.VitessConfigurationSettings) (cells []string) {
59+
for _, cell := range settings.Cells {
60+
cell = strings.TrimSpace(cell)
61+
if cell != "" {
62+
cells = append(cells, cell)
63+
}
64+
}
65+
return cells
66+
}
67+
4368
// filterReplicaTablets parses a list of tablets, returning replica tablets only
44-
func filterReplicaTablets(tablets []Tablet) (replicas []Tablet) {
69+
func filterReplicaTablets(settings config.VitessConfigurationSettings, tablets []Tablet) (replicas []Tablet) {
70+
validCells := ParseCells(settings)
4571
for _, tablet := range tablets {
46-
if tablet.IsValidReplica() {
72+
if tablet.HasValidCell(validCells) && tablet.IsValidReplica() {
4773
replicas = append(replicas, tablet)
4874
}
4975
}
5076
return replicas
5177
}
5278

53-
// ParseTablets reads from vitess /api/ks_tablets/<keyspace>/[shard] and returns a
79+
// ParseTablets reads from vitess /api/keyspace/<keyspace>/tablets/[shard] and returns a
5480
// listing (mysql_hostname, mysql_port, type) of REPLICA tablets
5581
func ParseTablets(settings config.VitessConfigurationSettings) (tablets []Tablet, err error) {
5682
if settings.TimeoutSecs == 0 {
@@ -64,13 +90,16 @@ func ParseTablets(settings config.VitessConfigurationSettings) (tablets []Tablet
6490
if err != nil {
6591
return tablets, err
6692
}
67-
6893
defer resp.Body.Close()
94+
95+
if resp.StatusCode != http.StatusOK {
96+
return tablets, fmt.Errorf("%v", resp.Status)
97+
}
98+
6999
body, err := ioutil.ReadAll(resp.Body)
70100
if err != nil {
71101
return tablets, err
72102
}
73-
74103
err = json.Unmarshal(body, &tablets)
75-
return filterReplicaTablets(tablets), err
104+
return filterReplicaTablets(settings, tablets), err
76105
}

pkg/vitess/api_client_test.go

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,35 +18,44 @@ func TestParseTablets(t *testing.T) {
1818
case "/api/keyspace/test/tablets/00":
1919
data, _ := json.Marshal([]Tablet{
2020
{
21+
Alias: &topodata.TabletAlias{Cell: "cell1"},
2122
MysqlHostname: "master",
2223
Type: topodata.TabletType_MASTER,
2324
},
2425
{
25-
MysqlHostname: "replica",
26+
Alias: &topodata.TabletAlias{Cell: "cell2"},
27+
MysqlHostname: "replica1",
2628
Type: topodata.TabletType_REPLICA,
2729
},
2830
{
31+
Alias: &topodata.TabletAlias{Cell: "cell3"},
32+
MysqlHostname: "replica2",
33+
Type: topodata.TabletType_REPLICA,
34+
},
35+
{
36+
Alias: &topodata.TabletAlias{Cell: "cell2"},
2937
MysqlHostname: "spare",
3038
Type: topodata.TabletType_SPARE,
3139
},
3240
{
41+
Alias: &topodata.TabletAlias{Cell: "cell3"},
3342
MysqlHostname: "batch",
3443
Type: topodata.TabletType_BATCH,
3544
},
3645
{
46+
Alias: &topodata.TabletAlias{Cell: "cell2"},
3747
MysqlHostname: "backup",
3848
Type: topodata.TabletType_BACKUP,
3949
},
4050
{
41-
51+
Alias: &topodata.TabletAlias{Cell: "cell1"},
4252
MysqlHostname: "restore",
4353
Type: topodata.TabletType_RESTORE,
4454
},
4555
})
4656
fmt.Fprint(w, string(data))
4757
default:
4858
w.WriteHeader(http.StatusNotFound)
49-
fmt.Fprint(w, "[]")
5059
}
5160
}))
5261
defer vitessApi.Close()
@@ -62,30 +71,64 @@ func TestParseTablets(t *testing.T) {
6271
t.Fatalf("Expected no error, got %q", err)
6372
}
6473

65-
if len(tablets) != 1 {
66-
t.Fatalf("Expected 1 tablet, got %d", len(tablets))
74+
if len(tablets) != 2 {
75+
t.Fatalf("Expected 2 tablets, got %d", len(tablets))
6776
}
6877

69-
if tablets[0].MysqlHostname != "replica" {
70-
t.Fatalf("Expected hostname %q, got %q", "replica", tablets[0].MysqlHostname)
78+
if tablets[0].MysqlHostname != "replica1" {
79+
t.Fatalf("Expected hostname %q, got %q", "replica1", tablets[0].MysqlHostname)
80+
}
81+
if tablets[1].MysqlHostname != "replica2" {
82+
t.Fatalf("Expected hostname %q, got %q", "replica2", tablets[1].MysqlHostname)
7183
}
7284

7385
if httpClient.Timeout != time.Second {
7486
t.Fatalf("Expected vitess client timeout of %v, got %v", time.Second, httpClient.Timeout)
7587
}
7688
})
7789

90+
t.Run("with-cell", func(t *testing.T) {
91+
settings := config.VitessConfigurationSettings{
92+
API: vitessApi.URL,
93+
Cells: []string{"cell2"},
94+
Keyspace: "test",
95+
Shard: "00",
96+
}
97+
tablets, err := ParseTablets(settings)
98+
if err != nil {
99+
t.Fatalf("Expected no error, got %q", err)
100+
}
101+
102+
if len(tablets) != 1 {
103+
t.Fatalf("Expected 1 tablet, got %d", len(tablets))
104+
}
105+
106+
if tablets[0].MysqlHostname != "replica1" {
107+
t.Fatalf("Expected hostname %q, got %q", "replica1", tablets[0].MysqlHostname)
108+
}
109+
if tablets[0].Alias.GetCell() != "cell2" {
110+
t.Fatalf("Expected vitess cell %s, got %s", "cell2", tablets[0].Alias.GetCell())
111+
}
112+
113+
// empty cell names should cause no filtering
114+
settings.Cells = []string{"", ""}
115+
tablets, _ = ParseTablets(settings)
116+
if len(tablets) != 2 {
117+
t.Fatalf("Expected 2 tablet, got %d", len(tablets))
118+
}
119+
})
120+
78121
t.Run("not-found", func(t *testing.T) {
79122
tablets, err := ParseTablets(config.VitessConfigurationSettings{
80123
API: vitessApi.URL,
81124
Keyspace: "not-found",
82125
Shard: "40-80",
83126
})
84-
if err != nil {
85-
t.Fatalf("Expected no error, got %q", err)
127+
if err == nil || err.Error() != "404 Not Found" {
128+
t.Fatalf("Expected %q error, got %q", "404 Not Found", err)
86129
}
87130

88-
if len(tablets) > 0 {
131+
if len(tablets) != 0 {
89132
t.Fatalf("Expected 0 tablets, got %d", len(tablets))
90133
}
91134

0 commit comments

Comments
 (0)