Skip to content

Commit

Permalink
bootstrap single node cluster
Browse files Browse the repository at this point in the history
  • Loading branch information
gernest committed Mar 2, 2024
1 parent 82d9285 commit 5c6ca04
Show file tree
Hide file tree
Showing 9 changed files with 104 additions and 40 deletions.
73 changes: 46 additions & 27 deletions gen/go/vince/v1/config.pb.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions internal/cluster/auth/credential_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
package auth

import (
"encoding/base64"
"os"

v1 "github.com/vinceanalytics/vince/gen/go/vince/v1"
Expand All @@ -20,6 +21,11 @@ type BasicAuther interface {
BasicAuth() (string, string, bool)
}

func CreateBasicAuth(username, password string) (value string) {
a := base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
return "Basic " + a
}

// CredentialsStore stores authentication and authorization information for all users.
type CredentialsStore struct {
store map[string]string
Expand Down
8 changes: 3 additions & 5 deletions internal/cluster/events/event.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package events

import (
"context"
"log/slog"
"net"
"net/url"
"strings"
Expand All @@ -10,7 +10,6 @@ import (
"github.com/cespare/xxhash/v2"
v1 "github.com/vinceanalytics/vince/gen/go/vince/v1"
"github.com/vinceanalytics/vince/internal/geo"
"github.com/vinceanalytics/vince/internal/logger"
"github.com/vinceanalytics/vince/internal/ref"
"github.com/vinceanalytics/vince/ua"
"google.golang.org/protobuf/proto"
Expand Down Expand Up @@ -46,8 +45,7 @@ var True = ptr(true)

var False = ptr(false)

func Parse(ctx context.Context, req *v1.Event) *v1.Data {
log := logger.Get(ctx)
func Parse(log *slog.Logger, g *geo.Geo, req *v1.Event) *v1.Data {
if req.U == "" || req.N == "" || req.D == "" {
log.Error("invalid request")
return nil
Expand Down Expand Up @@ -82,7 +80,7 @@ func Parse(ctx context.Context, req *v1.Event) *v1.Data {
var city geo.Info
if req.Ip != "" {
ip := net.ParseIP(req.Ip)
city = geo.Get(ctx).Get(ip)
city = g.Get(ip)
}
var screenSize string
switch {
Expand Down
11 changes: 8 additions & 3 deletions internal/cluster/http/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"github.com/vinceanalytics/vince/internal/cluster/events"
"github.com/vinceanalytics/vince/internal/cluster/store"
"github.com/vinceanalytics/vince/internal/defaults"
"github.com/vinceanalytics/vince/internal/geo"
"github.com/vinceanalytics/vince/internal/guard"
"github.com/vinceanalytics/vince/internal/tenant"
"github.com/vinceanalytics/vince/version"
Expand Down Expand Up @@ -106,13 +107,16 @@ type Service struct {
start time.Time
lastBackup time.Time
creds CredentialStore
geo *geo.Geo
log *slog.Logger
}

// New returns an uninitialized HTTP service. If credentials is nil, then
// the service performs no authentication and authorization checks.
func New(store store.Storage, cluster Cluster, credentials CredentialStore, guard guard.Guard, tenants tenant.Loader) *Service {
func New(store store.Storage, cluster Cluster, credentials CredentialStore, guard guard.Guard,
tenants tenant.Loader, geo *geo.Geo) *Service {
return &Service{
geo: geo,
store: store,
cluster: cluster,
guard: guard,
Expand Down Expand Up @@ -453,6 +457,7 @@ func (s *Service) handleApiEvent(w http.ResponseWriter, r *http.Request, params
w.WriteHeader(http.StatusUnauthorized)
return
}

if r.Method != http.MethodPost {
w.WriteHeader(http.StatusMethodNotAllowed)
return
Expand All @@ -473,7 +478,7 @@ func (s *Service) handleApiEvent(w http.ResponseWriter, r *http.Request, params
w.WriteHeader(http.StatusBadRequest)
return
}
e := events.Parse(r.Context(), &ev)
e := events.Parse(s.log, s.geo, &ev)
if e == nil {
w.WriteHeader(http.StatusBadRequest)
return
Expand Down Expand Up @@ -561,7 +566,7 @@ func (s *Service) handleEvent(w http.ResponseWriter, r *http.Request, params Que
w.WriteHeader(http.StatusBadRequest)
return
}
e := events.Parse(r.Context(), &ev)
e := events.Parse(s.log, s.geo, &ev)
if e == nil {
w.WriteHeader(http.StatusBadRequest)
return
Expand Down
33 changes: 32 additions & 1 deletion internal/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/vinceanalytics/vince/internal/cluster/rtls"
"github.com/vinceanalytics/vince/internal/cluster/store"
"github.com/vinceanalytics/vince/internal/cluster/transport"
"github.com/vinceanalytics/vince/internal/geo"
"github.com/vinceanalytics/vince/internal/guard"
"github.com/vinceanalytics/vince/internal/load"
"github.com/vinceanalytics/vince/internal/logger"
Expand Down Expand Up @@ -288,7 +289,18 @@ func App() *cli.Command {
transit.Register(gSvr)
v1.RegisterInternalCLusterServer(gSvr, cluSvc)
cluCLient := cluster.NewClient(connMgr)
httpSvc := httpd.New(db, cluCLient, creds, xguard, tenants)
xg := geo.Open(base.GeoipDbPath)
httpSvc := httpd.New(db, cluCLient, creds, xguard, tenants, xg)

nodes, err := db.Nodes(ctx)
if err != nil {
return err
}
err = createCluster(ctx, log, base.Node, len(nodes.GetItems()) > 0,
cluCLient, db, httpSvc, creds)
if err != nil {
return fmt.Errorf("failed creating cluster %v", err)
}
svr := &http.Server{
Addr: base.Listen,
Handler: httpSvc,
Expand Down Expand Up @@ -349,3 +361,22 @@ func serverOptions(node *v1.RaftNode, creds cluster.CredentialStore) (o []grpc.S
o = append(o, grpc.Creds(credentials.NewTLS(tlsConfig)))
return
}

func createCluster(ctx context.Context, log *slog.Logger, node *v1.RaftNode, hasPeers bool, client *cluster.Client, str *store.Store, httpServ *httpd.Service, credStr *auth.CredentialsStore) error {
if len(node.Joins) == 0 && !hasPeers {
if node.NonVoter {
return fmt.Errorf("cannot create a new non-voting node without joining it to an existing cluster")
}
// Brand new node, told to bootstrap itself. So do it.
log.Info("bootstraping single new node")
if err := str.Bootstrap(ctx, &v1.Server_List{
Items: []*v1.Server{
{Id: node.Id, Addr: node.Advertise, Suffrage: v1.Server_Voter},
},
}); err != nil {
return fmt.Errorf("failed to bootstrap single new node: %s", err.Error())
}
return nil
}
return nil
}
3 changes: 1 addition & 2 deletions internal/db/persistance.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"fmt"
"io"
"log/slog"
"path/filepath"
"strings"
"time"

Expand Down Expand Up @@ -156,7 +155,7 @@ type KV struct {
}

func OpenBadger(path string) (*badger.DB, error) {
return badger.Open(badger.DefaultOptions(filepath.Join(path, "db")).
return badger.Open(badger.DefaultOptions(path).
WithLogger(&badgerLogger{
log: slog.Default().With(
slog.String("component", "key-value-store"),
Expand Down
6 changes: 5 additions & 1 deletion internal/load/load.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"github.com/dop251/goja"
"github.com/urfave/cli/v3"
v1 "github.com/vinceanalytics/vince/gen/go/vince/v1"
"github.com/vinceanalytics/vince/internal/cluster/auth"
"github.com/vinceanalytics/vince/internal/ref"
"github.com/vinceanalytics/vince/ua"
"google.golang.org/protobuf/encoding/protojson"
Expand Down Expand Up @@ -122,12 +123,15 @@ func (s *Session) send(name, path string, dump bool) error {
Ip: "127.0.0.1",
R: s.Referrer,
}
q := make(url.Values)
q.Add("site_id", s.Domain)
data, _ := protojson.Marshal(e)
req, err := http.NewRequest(http.MethodPost, s.Vince+apiPath, bytes.NewReader(data))
req, err := http.NewRequest(http.MethodPost, s.Vince+apiPath+"?"+q.Encode(), bytes.NewReader(data))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", auth.CreateBasicAuth("staples", ""))
if dump {
b, _ := httputil.DumpRequestOut(req, true)
fmt.Println(string(b))
Expand Down
2 changes: 1 addition & 1 deletion internal/load/testdata/page_view.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const site = "https://vinceanalytics.com"
for (let index = 0; index < limit; index++) {
const session = createSession(site);
session.Send("pageview", "/");
session.SendDebug("pageview", "/");
}
2 changes: 2 additions & 0 deletions proto/vince/v1/config.proto
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ message RaftNode {
bool verify_client = 6;
bool verify_server_name = 7;
string advertise = 8 [ (buf.validate.field).string.host_and_port = true ];
repeated string joins = 9;
bool non_voter = 10;
}

message Domain { string name = 1 [ (buf.validate.field).required = true ]; }
Expand Down

0 comments on commit 5c6ca04

Please sign in to comment.