Skip to content

Commit

Permalink
Merge pull request #236 from jamf/feature/simplify_server
Browse files Browse the repository at this point in the history
add: simplify server by removing maintenance API port
  • Loading branch information
coufalja committed Dec 27, 2023
2 parents 8c8f9d2 + 357a14f commit 77a1046
Show file tree
Hide file tree
Showing 11 changed files with 185 additions and 134 deletions.
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# syntax = docker/dockerfile:1.2
FROM golang:1.21.5-alpine3.18 as builder
FROM golang:1.21.5-alpine3.19 as builder

RUN apk add --update --no-cache build-base tzdata \
&& addgroup -g 1000 -S regatta && adduser -u 1000 -S regatta -G regatta
Expand All @@ -13,7 +13,7 @@ ARG VERSION
RUN --mount=type=cache,target=/go/pkg/mod --mount=type=cache,target=/root/.cache/go-build GOMODCACHE=/go/pkg/mod GOCACHE=/root/.cache/go-build VERSION=${VERSION} make regatta

# Runtime
FROM alpine:3.18
FROM alpine:3.19

ARG VERSION
LABEL org.opencontainers.image.authors="Regatta Developers <regatta@jamf.com>"
Expand Down
20 changes: 0 additions & 20 deletions cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,26 +56,6 @@ func createAPIServer() (*regattaserver.RegattaServer, error) {
return regattaserver.NewServer(addr, net, opts...), nil
}

func createMaintenanceServer() (*regattaserver.RegattaServer, error) {
addr, secure, net := resolveUrl(viper.GetString("maintenance.address"))
opts := []grpc.ServerOption{
grpc.ChainStreamInterceptor(grpc_prometheus.StreamServerInterceptor, grpc_auth.StreamServerInterceptor(authFunc(viper.GetString("maintenance.token")))),
grpc.ChainUnaryInterceptor(grpc_prometheus.UnaryServerInterceptor, grpc_auth.UnaryServerInterceptor(authFunc(viper.GetString("maintenance.token")))),
}
if secure {
c, err := cert.New(viper.GetString("maintenance.cert-filename"), viper.GetString("maintenance.key-filename"))
if err != nil {
return nil, fmt.Errorf("cannot load maintenance certificate: %w", err)
}
opts = append(opts, grpc.Creds(credentials.NewTLS(&tls.Config{
MinVersion: tls.VersionTLS12,
GetCertificate: c.GetCertificate,
})))
}
// Create regatta maintenance server
return regattaserver.NewServer(addr, net, opts...), nil
}

func resolveUrl(urlStr string) (addr string, secure bool, network string) {
u, err := url.Parse(urlStr)
if err != nil {
Expand Down
3 changes: 0 additions & 3 deletions cmd/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,6 @@ At least one reachable Regatta instance is required to successfully bootstrap th

// Maintenance flags
maintenanceFlagSet.Bool("maintenance.enabled", true, "Whether maintenance API is enabled.")
maintenanceFlagSet.String("maintenance.address", "http://127.0.0.1:8445", "Replication API server address.")
maintenanceFlagSet.String("maintenance.cert-filename", "", "Path to the API server certificate.")
maintenanceFlagSet.String("maintenance.key-filename", "", "Path to the API server private key file.")
maintenanceFlagSet.String("maintenance.token", "", "Token to check for maintenance API access, if left empty (default) no token is checked.")
}

Expand Down
18 changes: 3 additions & 15 deletions cmd/follower.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,9 @@ func follower(_ *cobra.Command, _ []string) error {
regattapb.RegisterClusterServer(regatta, &regattaserver.ClusterServer{
Cluster: engine,
})
if viper.GetBool("maintenance.enabled") {
regattapb.RegisterMaintenanceServer(regatta, &regattaserver.ResetServer{Tables: engine, AuthFunc: authFunc(viper.GetString("maintenance.token"))})
}
// Start server
go func() {
if err := regatta.ListenAndServe(); err != nil {
Expand All @@ -206,21 +209,6 @@ func follower(_ *cobra.Command, _ []string) error {
defer regatta.Shutdown()
}

if viper.GetBool("maintenance.enabled") {
maintenance, err := createMaintenanceServer()
if err != nil {
return fmt.Errorf("failed to create Maintenance server: %w", err)
}
regattapb.RegisterMaintenanceServer(maintenance, &regattaserver.ResetServer{Tables: engine})
// Start server
go func() {
if err := maintenance.ListenAndServe(); err != nil {
log.Errorf("grpc listenAndServe failed: %v", err)
}
}()
defer maintenance.Shutdown()
}

// Create REST server
addr, _, _ := resolveUrl(viper.GetString("rest.address"))
hs := regattaserver.NewRESTServer(addr, viper.GetDuration("rest.read-timeout"))
Expand Down
19 changes: 3 additions & 16 deletions cmd/leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,9 @@ func leader(_ *cobra.Command, _ []string) error {
regattapb.RegisterClusterServer(regatta, &regattaserver.ClusterServer{
Cluster: engine,
})
if viper.GetBool("maintenance.enabled") {
regattapb.RegisterMaintenanceServer(regatta, &regattaserver.BackupServer{Tables: engine, AuthFunc: authFunc(viper.GetString("maintenance.token"))})
}
// Start server
go func() {
if err := regatta.ListenAndServe(); err != nil {
Expand Down Expand Up @@ -224,22 +227,6 @@ func leader(_ *cobra.Command, _ []string) error {
defer replication.Shutdown()
}

if viper.GetBool("maintenance.enabled") {
maintenance, err := createMaintenanceServer()
if err != nil {
return fmt.Errorf("failed to create Maintenance server: %w", err)
}
regattapb.RegisterMetadataServer(maintenance, &regattaserver.MetadataServer{Tables: engine})
regattapb.RegisterMaintenanceServer(maintenance, &regattaserver.BackupServer{Tables: engine})
// Start server
go func() {
if err := maintenance.ListenAndServe(); err != nil {
log.Errorf("grpc listenAndServe failed: %v", err)
}
}()
defer maintenance.Shutdown()
}

// Create REST server
addr, _, _ := resolveUrl(viper.GetString("rest.address"))
hs := regattaserver.NewRESTServer(addr, viper.GetDuration("rest.read-timeout"))
Expand Down
8 changes: 7 additions & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ nav_order: 999

# Changelog

## v0.3.3 (unreleased)
## v0.4.0 (unreleased)

### Breaking changes
* Remove maintenance server port, the API is now available on standard API port. It could still though be secured by a separate API token.

### Features
* Added `api.advertise-address` option to split address advertised to clients from the listen address.
* Removed `maintenance.address` config option.
* Removed `maintenance.cert-filename` config option.
* Removed `maintenance.key-filename` config option.

### Bugfixes
* Fix `KV/DeleteRange` `Count` erroneously returning `1` if no key was deleted.
Expand Down
3 changes: 0 additions & 3 deletions docs/operations_guide/cli/regatta_follower.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ regatta follower [flags]
--dev-mode Development mode enabled (verbose logging, human-friendly log format).
-h, --help help for follower
--log-level string Log level: DEBUG/INFO/WARN/ERROR. (default "INFO")
--maintenance.address string Replication API server address. (default "http://127.0.0.1:8445")
--maintenance.cert-filename string Path to the API server certificate.
--maintenance.enabled Whether maintenance API is enabled. (default true)
--maintenance.key-filename string Path to the API server private key file.
--maintenance.token string Token to check for maintenance API access, if left empty (default) no token is checked.
--memberlist.address string Address is the address for the gossip service to bind to and listen on. Both UDP and TCP ports are used by the gossip service.
The local gossip service should be able to receive gossip service related messages by binding to and listening on this address. BindAddress is usually in the format of IP:Port, Hostname:Port or DNS Name:Port. (default "0.0.0.0:7432")
Expand Down
3 changes: 0 additions & 3 deletions docs/operations_guide/cli/regatta_leader.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ regatta leader [flags]
--dev-mode Development mode enabled (verbose logging, human-friendly log format).
-h, --help help for leader
--log-level string Log level: DEBUG/INFO/WARN/ERROR. (default "INFO")
--maintenance.address string Replication API server address. (default "http://127.0.0.1:8445")
--maintenance.cert-filename string Path to the API server certificate.
--maintenance.enabled Whether maintenance API is enabled. (default true)
--maintenance.key-filename string Path to the API server private key file.
--maintenance.token string Token to check for maintenance API access, if left empty (default) no token is checked.
--memberlist.address string Address is the address for the gossip service to bind to and listen on. Both UDP and TCP ports are used by the gossip service.
The local gossip service should be able to receive gossip service related messages by binding to and listening on this address. BindAddress is usually in the format of IP:Port, Hostname:Port or DNS Name:Port. (default "0.0.0.0:7432")
Expand Down
18 changes: 13 additions & 5 deletions regattaserver/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,15 @@ import (
// ResetServer implements some Maintenance service methods from proto/regatta.proto.
type ResetServer struct {
regattapb.UnimplementedMaintenanceServer
Tables TableService
Tables TableService
AuthFunc func(ctx context.Context) (context.Context, error)
}

func (m *ResetServer) Reset(ctx context.Context, req *regattapb.ResetRequest) (*regattapb.ResetResponse, error) {
ctx, err := m.AuthFunc(ctx)
if err != nil {
return nil, err
}
reset := func(name string) error {
t, err := m.Tables.GetTable(name)
if err != nil {
Expand Down Expand Up @@ -53,8 +58,7 @@ func (m *ResetServer) Reset(ctx context.Context, req *regattapb.ResetRequest) (*
if len(req.Table) == 0 {
return nil, status.Errorf(codes.InvalidArgument, "table must be set")
}
err := reset(string(req.Table))
if err != nil {
if err := reset(string(req.Table)); err != nil {
return nil, err
}
return &regattapb.ResetResponse{}, nil
Expand All @@ -63,16 +67,20 @@ func (m *ResetServer) Reset(ctx context.Context, req *regattapb.ResetRequest) (*
// BackupServer implements some Maintenance service methods from proto/regatta.proto.
type BackupServer struct {
regattapb.UnimplementedMaintenanceServer
Tables TableService
Tables TableService
AuthFunc func(ctx context.Context) (context.Context, error)
}

func (m *BackupServer) Backup(req *regattapb.BackupRequest, srv regattapb.Maintenance_BackupServer) error {
ctx, err := m.AuthFunc(srv.Context())
if err != nil {
return err
}
table, err := m.Tables.GetTable(string(req.Table))
if err != nil {
return err
}

ctx := srv.Context()
if _, ok := ctx.Deadline(); !ok {
dctx, cancel := context.WithTimeout(srv.Context(), 1*time.Hour)
defer cancel()
Expand Down
20 changes: 9 additions & 11 deletions replication/backup/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@ type Manifest struct {
// ManifestTable a backup table descriptor.
type ManifestTable struct {
Name string `json:"name"`
Type string `json:"type"`
FileName string `json:"file_name"`
MD5 string `json:"md5"`
}
Expand Down Expand Up @@ -102,7 +101,7 @@ func (b *Backup) ensureDefaults() {
func (b *Backup) Backup() (Manifest, error) {
b.ensureDefaults()

mc := regattapb.NewMetadataClient(b.Conn)
mc := regattapb.NewClusterClient(b.Conn)
sc := regattapb.NewMaintenanceClient(b.Conn)

manifest := Manifest{
Expand All @@ -117,19 +116,19 @@ func (b *Backup) Backup() (Manifest, error) {
return manifest, err
}

meta, err := mc.Get(ctx, &regattapb.MetadataRequest{})
status, err := mc.Status(ctx, &regattapb.StatusRequest{})
if err != nil {
return manifest, err
}

b.Log.Infof("going to backup %v", meta.Tables)
for _, t := range meta.Tables {
b.Log.Infof("backing up table '%s'", t.Name)
stream, err := sc.Backup(ctx, &regattapb.BackupRequest{Table: []byte(t.Name)})
b.Log.Infof("starting backup")
for t := range status.Tables {
b.Log.Infof("backing up table '%s'", t)
stream, err := sc.Backup(ctx, &regattapb.BackupRequest{Table: []byte(t)})
if err != nil {
return manifest, err
}
fName := fmt.Sprintf("%s.bak", t.Name)
fName := fmt.Sprintf("%s.bak", t)
sf, err := os.Create(filepath.Join(b.Dir, fName))
if err != nil {
return manifest, err
Expand All @@ -147,12 +146,11 @@ func (b *Backup) Backup() (Manifest, error) {
}

manifest.Tables = append(manifest.Tables, ManifestTable{
Name: t.Name,
Type: t.Type.String(),
Name: t,
FileName: fName,
MD5: hex.EncodeToString(hash.Sum(nil)),
})
b.Log.Infof("backed up table '%s'", t.Name)
b.Log.Infof("backed up table '%s'", t)
}
sort.Sort(manifestTables(manifest.Tables))
manifest.Finished = b.clock.Now()
Expand Down
Loading

0 comments on commit 77a1046

Please sign in to comment.