Skip to content
This repository was archived by the owner on Feb 21, 2024. It is now read-only.

Commit e09aa84

Browse files
committed
Version checking: clean up code, add server flags
FB-1975 Cleaned up version checking, removed a race condition, and added error checking. Added server flags for check-in endpoint and UUID storage file. Incorporates Travis's changes to store UUID file in data directory and unexport most of verchk.go.
1 parent bff94ec commit e09aa84

File tree

6 files changed

+76
-36
lines changed

6 files changed

+76
-36
lines changed

ctl/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ func serverFlagSet(srv *server.Config, prefix string) *pflag.FlagSet {
4949
flags.DurationVar((*time.Duration)(&srv.LongQueryTime), pre("long-query-time"), time.Duration(srv.LongQueryTime), "Duration that will trigger log and stat messages for slow queries. Zero to disable.")
5050
flags.IntVar(&srv.QueryHistoryLength, pre("query-history-length"), srv.QueryHistoryLength, "Number of queries to remember in history.")
5151
flags.Int64Var(&srv.MaxQueryMemory, pre("max-query-memory"), srv.MaxQueryMemory, "Maximum memory allowed per Extract() or SELECT query.")
52+
flags.StringVar(&srv.VerChkAddress, pre("verchk-address"), srv.VerChkAddress, "Address to contact to check for latest version.")
53+
flags.StringVar(&srv.UUIDFile, pre("uuid-file"), srv.UUIDFile, "File to store UUID used in checking latest version. If this is a relative path, the file will be stored in the server's data directory.")
5254

5355
// TLS
5456
SetTLSConfig(flags, pre(""), &srv.TLS.CertificatePath, &srv.TLS.CertificateKeyPath, &srv.TLS.CACertPath, &srv.TLS.SkipVerify, &srv.TLS.EnableClientVerification)

ctl/server_test.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,10 @@ func TestBuildServerFlags(t *testing.T) {
2020
if cm.Flags().Lookup("log-path").Name == "" {
2121
t.Fatal("log-path flag is required")
2222
}
23+
if cm.Flags().Lookup("verchk-address").Name == "" {
24+
t.Fatal("verchk-address flag is required")
25+
}
26+
if cm.Flags().Lookup("uuid-file").Name == "" {
27+
t.Fatal("uuid-file flag is required")
28+
}
2329
}

server.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ type Server struct { // nolint: maligned
8989

9090
defaultClient *InternalClient
9191
dataDir string
92+
verChkAddress string
93+
uuidFile string
9294

9395
// Threshold for logging long-running queries
9496
longQueryTime time.Duration
@@ -167,6 +169,24 @@ func OptServerDataDir(dir string) ServerOption {
167169
}
168170
}
169171

172+
// OptServerVerChkAddress is a functional option on Server
173+
// used to set the address to check for the current version.
174+
func OptServerVerChkAddress(addr string) ServerOption {
175+
return func(s *Server) error {
176+
s.verChkAddress = addr
177+
return nil
178+
}
179+
}
180+
181+
// OptServerUUIDFile is a functional option on Server
182+
// used to set the file name for storing the checkin UUID.
183+
func OptServerUUIDFile(uf string) ServerOption {
184+
return func(s *Server) error {
185+
s.uuidFile = uf
186+
return nil
187+
}
188+
}
189+
170190
// OptServerViewsRemovalInterval is a functional option on Server
171191
// used to set the ttl removal interval.
172192
func OptServerViewsRemovalInterval(interval time.Duration) ServerOption {
@@ -608,13 +628,17 @@ func (s *Server) Open() error {
608628
// startup if the server endpoint is down/having issues.
609629
go func() {
610630
s.logger.Printf("Beginning featurebase version check-in")
611-
vc := newVersionChecker(s.cluster.Path, "https://analytics.featurebase.com/v2/featurebase/metrics")
631+
vc := newVersionChecker(s.cluster.Path, s.verChkAddress, s.uuidFile)
612632
resp, err := vc.checkIn()
613633
if err != nil {
614634
s.logger.Errorf("doing version checkin. Error was %s", err)
615635
return
616636
}
617-
s.logger.Printf("Version check-in complete. Latest version is %s", resp.Version)
637+
if resp.Error != "" {
638+
s.logger.Printf("Version check-in failed, endpoint response was %s", resp.Error)
639+
} else {
640+
s.logger.Printf("Version check-in complete. Latest version is %s", resp.Version)
641+
}
618642
}()
619643

620644
// Start DisCo.

server/config.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,15 @@ type Config struct {
152152
// Limits the total amount of memory to be used by Extract() & SELECT queries.
153153
MaxQueryMemory int64 `toml:"max-query-memory"`
154154

155+
// On startup, featurebase server contacts a web server to check the latest version.
156+
// This stores the address for that check
157+
VerChkAddress string `toml:"verchk-address"`
158+
159+
// When checking version, server sends a UUID so that we can keep track of
160+
// how many unique Featurebase installs are out there. The file is stored in
161+
// the data directory; this stores the filename to use.
162+
UUIDFile string `toml:"uuid-file"`
163+
155164
Cluster struct {
156165
ReplicaN int `toml:"replicas"`
157166
Name string `toml:"name"`
@@ -383,6 +392,8 @@ func NewConfig() *Config {
383392
LongQueryTime: toml.Duration(-time.Minute),
384393

385394
CheckInInterval: 60 * time.Second,
395+
VerChkAddress: "https://analytics.featurebase.com/v2/featurebase/metrics",
396+
UUIDFile: ".client_id.txt",
386397
}
387398

388399
// Cluster config.

server/server.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,8 @@ func (m *Command) setupServer() error {
596596
pilosa.OptServerServerlessStorage(m.serverlessStorage),
597597
pilosa.OptServerIsDataframeEnabled(m.Config.Dataframe.Enable),
598598
pilosa.OptServerDataframeUseParquet(m.Config.Dataframe.UseParquet),
599+
pilosa.OptServerVerChkAddress(m.Config.VerChkAddress),
600+
pilosa.OptServerUUIDFile(m.Config.UUIDFile),
599601
}
600602

601603
if m.isComputeNode {

verchk.go

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,17 @@ import (
1212
"github.com/google/uuid"
1313
)
1414

15-
const (
16-
versionCheckerFilename = ".client_id.txt"
17-
)
18-
1915
type versionChecker struct {
20-
path string
21-
url string
16+
path string
17+
url string
18+
idfile string
2219
}
2320

24-
func newVersionChecker(path, endpoint string) *versionChecker {
21+
func newVersionChecker(path, endpoint, idfile string) *versionChecker {
2522
v := versionChecker{
26-
path: path,
27-
url: endpoint,
23+
path: path,
24+
url: endpoint,
25+
idfile: idfile,
2826
}
2927
return &v
3028
}
@@ -62,7 +60,6 @@ func (v *versionChecker) checkIn() (*verCheckResponse, error) {
6260

6361
return nil, err
6462
}
65-
6663
return &jsonResp, nil
6764
}
6865

@@ -73,31 +70,15 @@ func (v *versionChecker) generateClientUUID() (string, error) {
7370
}
7471

7572
func (v *versionChecker) writeClientUUID() (string, error) {
76-
filename := filepath.Join(v.path, versionCheckerFilename)
77-
if _, err := os.Stat(filename); err != nil {
78-
if os.IsNotExist(err) {
79-
fh, err := os.Create(filename)
80-
if err != nil {
81-
return "", err
82-
}
83-
defer fh.Close()
84-
85-
id, err := v.generateClientUUID()
86-
if err != nil {
87-
return "", err
88-
}
89-
90-
if _, err := fh.WriteString(id); err != nil {
91-
return "", err
92-
}
93-
94-
return id, nil
95-
} else {
96-
return "", err
97-
}
73+
var filename string
74+
// if v.idfile starts with a path separator then it's an absolute path
75+
// otherwise it's a relative path and the file goes in the data directory
76+
if v.idfile[0] == os.PathSeparator {
77+
filename = v.idfile
78+
} else {
79+
filename = filepath.Join(v.path, v.idfile)
9880
}
99-
100-
fh, err := os.Open(filename)
81+
fh, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0744)
10182
if err != nil {
10283
return "", err
10384
}
@@ -107,10 +88,24 @@ func (v *versionChecker) writeClientUUID() (string, error) {
10788
if err != nil {
10889
return "", err
10990
}
91+
// this just checks to see if there was anything at all in the file.
92+
// we should probably check to make sure it's a valid UUID
93+
if string(buf) == "" {
94+
id, err := v.generateClientUUID()
95+
if err != nil {
96+
return "", err
97+
}
98+
_, err = fh.WriteString(id)
99+
if err != nil {
100+
return "", err
101+
}
102+
return id, nil
103+
}
110104

111105
return string(buf), nil
112106
}
113107

114108
type verCheckResponse struct {
115109
Version string `json:"latest_version"`
110+
Error string `json:"error"`
116111
}

0 commit comments

Comments
 (0)