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

Commit 0c7e54c

Browse files
lorycloutiertravisturnerseebs
authored and
Vengata Krishnan
committed
Fb 1975 (#2254)
* Store version-check file in the configured data-directory This also fixes what I think is a bug. It also un-exports everything. I have questions. * 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. --------- Co-authored-by: Travis Turner <[email protected]> Co-authored-by: seebs <[email protected]>
1 parent b7c3c01 commit 0c7e54c

File tree

6 files changed

+93
-52
lines changed

6 files changed

+93
-52
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: 29 additions & 4 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 {
@@ -604,16 +624,21 @@ func (s *Server) Open() error {
604624
log.Println(errors.Wrap(err, "logging startup"))
605625
}
606626

607-
// Do version check in. This is in a goroutine so that we don't block server startup if the server endpoint is down/having issues.
627+
// Do version check in. This is in a goroutine so that we don't block server
628+
// startup if the server endpoint is down/having issues.
608629
go func() {
609630
s.logger.Printf("Beginning featurebase version check-in")
610-
vc := VersionChecker{URL: "https://analytics.featurebase.com/v2/featurebase/metrics"}
611-
resp, err := vc.CheckIn()
631+
vc := newVersionChecker(s.cluster.Path, s.verChkAddress, s.uuidFile)
632+
resp, err := vc.checkIn()
612633
if err != nil {
613634
s.logger.Errorf("doing version checkin. Error was %s", err)
614635
return
615636
}
616-
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+
}
617642
}()
618643

619644
// 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: 43 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,29 @@ import (
66
"io"
77
"net/http"
88
"os"
9+
"path/filepath"
910
"strings"
1011

1112
"github.com/google/uuid"
1213
)
1314

14-
type VersionChecker struct {
15-
URL string
15+
type versionChecker struct {
16+
path string
17+
url string
18+
idfile string
1619
}
1720

18-
func NewVersionChecker(endpoint string) *VersionChecker {
19-
v := VersionChecker{
20-
URL: endpoint,
21+
func newVersionChecker(path, endpoint, idfile string) *versionChecker {
22+
v := versionChecker{
23+
path: path,
24+
url: endpoint,
25+
idfile: idfile,
2126
}
2227
return &v
2328
}
2429

25-
func (v *VersionChecker) CheckIn() (*VerCheckResponse, error) {
26-
27-
id, err := v.WriteClientUUID()
30+
func (v *versionChecker) checkIn() (*verCheckResponse, error) {
31+
id, err := v.writeClientUUID()
2832
if err != nil {
2933
return nil, err
3034
}
@@ -38,79 +42,70 @@ func (v *VersionChecker) CheckIn() (*VerCheckResponse, error) {
3842
if err != nil {
3943
return nil, err
4044
}
41-
4245
wReq := bytes.NewReader(req)
4346

47+
var jsonResp verCheckResponse
48+
r, err := http.Post(v.url, "application/json", wReq)
4449
if err != nil {
4550
return nil, err
4651
}
4752

48-
var json_resp VerCheckResponse
49-
r, err := http.Post(v.URL, "application/json", wReq)
50-
if err != nil {
51-
return nil, err
52-
}
5353
data, err := io.ReadAll(r.Body)
54-
5554
if err != nil {
5655
return nil, err
5756
}
5857

59-
err = json.Unmarshal(data, &json_resp)
58+
err = json.Unmarshal(data, &jsonResp)
6059
if err != nil {
6160

6261
return nil, err
6362
}
64-
return &json_resp, nil
65-
63+
return &jsonResp, nil
6664
}
6765

68-
func (v *VersionChecker) GenerateClientUUID() (string, error) {
66+
func (v *versionChecker) generateClientUUID() (string, error) {
6967
clientUUID := uuid.New()
7068
cleanedUUID := strings.Replace(clientUUID.String(), "-", "", -1)
7169
return cleanedUUID, nil
7270
}
7371

74-
func (v *VersionChecker) WriteClientUUID() (string, error) {
75-
filename := ".client_id.txt"
76-
_, err := os.Stat(filename)
77-
if 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-
id, err := v.GenerateClientUUID()
85-
if err != nil {
86-
return "", err
87-
}
88-
89-
_, err = fh.WriteString(id)
90-
if err != nil {
91-
return "", err
92-
}
93-
94-
return "", err
95-
} else {
96-
return "", err
97-
}
72+
func (v *versionChecker) writeClientUUID() (string, error) {
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
}
10485
defer fh.Close()
105-
buf, err := os.ReadFile(filename)
10686

87+
buf, err := os.ReadFile(filename)
10788
if err != nil {
10889
return "", err
10990
}
110-
return string(buf), nil
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+
}
111104

105+
return string(buf), nil
112106
}
113107

114-
type VerCheckResponse struct {
108+
type verCheckResponse struct {
115109
Version string `json:"latest_version"`
110+
Error string `json:"error"`
116111
}

0 commit comments

Comments
 (0)