Skip to content

Commit

Permalink
Merge pull request #249 from jamf/feature/table_api
Browse files Browse the repository at this point in the history
feature: tables API docs
  • Loading branch information
coufalja committed Jan 23, 2024
2 parents 46bb9ab + 84afc1a commit 4374a0e
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 48 deletions.
13 changes: 11 additions & 2 deletions cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"sync"
"time"

grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
grpc_prometheus "github.com/grpc-ecosystem/go-grpc-prometheus"
"github.com/jamf/regatta/cert"
Expand Down Expand Up @@ -41,8 +42,14 @@ func createAPIServer() (*regattaserver.RegattaServer, error) {
addr, secure, net := resolveUrl(viper.GetString("api.address"))
opts := []grpc.ServerOption{
grpc.KeepaliveParams(keepalive.ServerParameters{MaxConnectionAge: 60 * time.Second}),
grpc.StreamInterceptor(grpc_prometheus.StreamServerInterceptor),
grpc.UnaryInterceptor(grpc_prometheus.UnaryServerInterceptor),
grpc.StreamInterceptor(grpc_middleware.ChainStreamServer(
grpc_auth.StreamServerInterceptor(defaultAuthFunc),
grpc_prometheus.StreamServerInterceptor,
)),
grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
grpc_prometheus.UnaryServerInterceptor,
grpc_auth.UnaryServerInterceptor(defaultAuthFunc),
)),
}
if secure {
c, err := cert.New(viper.GetString("api.cert-filename"), viper.GetString("api.key-filename"))
Expand Down Expand Up @@ -104,6 +111,8 @@ func authFunc(token string) func(ctx context.Context) (context.Context, error) {
}
}

var defaultAuthFunc = authFunc("")

type tokenCredentials string

func (t tokenCredentials) GetRequestMetadata(_ context.Context, _ ...string) (map[string]string, error) {
Expand Down
4 changes: 2 additions & 2 deletions cmd/leader.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ func init() {
// Tables flags
leaderCmd.PersistentFlags().StringSlice("tables.names", nil, "Create Regatta tables with given names.")
leaderCmd.PersistentFlags().StringSlice("tables.delete", nil, "Delete Regatta tables with given names.")
_ = leaderCmd.PersistentFlags().MarkHidden("tables.names")
_ = leaderCmd.PersistentFlags().MarkHidden("tables.delete")
_ = leaderCmd.PersistentFlags().MarkDeprecated("tables.names", "Use `regatta.v1.Tables/Create` API to create tables instead.")
_ = leaderCmd.PersistentFlags().MarkDeprecated("tables.delete", "Use `regatta.v1.Tables/Delete` API to delete tables instead.")

// Replication flags
leaderCmd.PersistentFlags().Bool("replication.enabled", true, "Whether replication API is enabled.")
Expand Down
16 changes: 14 additions & 2 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,28 @@ nav_order: 999
---

# Changelog
## v0.5.0 (unreleased)

## v0.4.1 (unreleased)
### Highlights
#### Dynamic tables management
* Tables now could be managed dynamically during the runtime of the server using newly provided `regatta.v1.Tables` API.
* Tables API could be secured by an API token using `tables.token` configuration value.

### Deprecations
* `tables.names` and `tables.delete` configuration values were deprecated and will be removed in future releases.

### Bugfixes
* Proper authentication of `maintenance.v1.Backup/Restore` API endpoint.
* When table is deleted in the leader cluster the followers will gracefully handle the situation by deleting the table locally and stopping the replication.
---
## v0.4.1

### Improvements
* Server now reports transient errors for requests that could be potentially retried as `codes.Unavailable`.

### Bugfixes
* Fixed the default timeout of `KV/IterateRange` operation.


---
## v0.4.0

Expand Down
3 changes: 0 additions & 3 deletions docs/operations_guide/deploying_to_kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,9 +63,6 @@ To deploy Regatta follower cluster and connect it to the leader cluster, let's s
mode: follower
replicas: 3

# Specify the tables.
tables: testing-table1,testing-table2

replication:
# Specify the address of the Regatta leader cluster to asynchronously replicate data from.
leaderAddress: "leader.regatta.example.com:8444"
Expand Down
25 changes: 11 additions & 14 deletions docs/quickstart.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,14 @@ tar -xf regatta-darwin-amd64.tar
./regatta leader \
--dev-mode \
--raft.address=127.0.0.1:5012 \
--raft.initial-members='1=127.0.0.1:5012' \
--tables.names=regatta-test
--raft.initial-members='1=127.0.0.1:5012'
```

This command will start a Regatta leader cluster with a single instance locally.

{: .note }
Mind the flags providing certificates and keys for the APIs. For testing purposes,
[certificate and key present in the repository](https://github.com/jamf/regatta/tree/cfc58f0205484b0c8a24c7cbcc0be8563b7cf6a5/hack)
can be used.
Create the `regatta-test` table using the API.
```bash
grpcurl -plaintext -d "{\"name\": \"regatta-test\"}" 127.0.0.1:8443 regatta.v1.Tables/Create
```

## Pull and run official Docker image

Expand All @@ -58,21 +56,20 @@ Just execute `docker run` with the following arguments:

```bash
docker run \
-p 8443:8443 \
ghcr.io/jamf/regatta:latest \
leader \
--dev-mode \
--raft.address=127.0.0.1:5012 \
--raft.initial-members='1=127.0.0.1:5012' \
--tables.names=regatta-test
--raft.initial-members='1=127.0.0.1:5012'
```

This command will start a Regatta leader cluster with a single instance in a Docker container.

{: .note }
Mind the `--mount` argument mounting the `/hack` directory to the container. This is the default location
where Regatta looks for certificates and keys for APIs. For testing purposes,
[certificate and key present in the repository](https://github.com/jamf/regatta/tree/cfc58f0205484b0c8a24c7cbcc0be8563b7cf6a5/hack)
can be used.
Create the `regatta-test` table using the API.
```bash
grpcurl -plaintext -d "{\"name\": \"regatta-test\"}" 127.0.0.1:8443 regatta.v1.Tables/Create
```

## Deploy to Kubernetes from Helm Chart

Expand Down
17 changes: 9 additions & 8 deletions regattaserver/maintenance.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,6 @@ type ResetServer struct {
}

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 @@ -64,6 +60,10 @@ func (m *ResetServer) Reset(ctx context.Context, req *regattapb.ResetRequest) (*
return &regattapb.ResetResponse{}, nil
}

func (m *ResetServer) AuthFuncOverride(ctx context.Context, _ string) (context.Context, error) {
return m.AuthFunc(ctx)
}

// BackupServer implements some Maintenance service methods from proto/regatta.proto.
type BackupServer struct {
regattapb.UnimplementedMaintenanceServer
Expand All @@ -72,10 +72,7 @@ type BackupServer struct {
}

func (m *BackupServer) Backup(req *regattapb.BackupRequest, srv regattapb.Maintenance_BackupServer) error {
ctx, err := m.AuthFunc(srv.Context())
if err != nil {
return err
}
ctx := srv.Context()
table, err := m.Tables.GetTable(string(req.Table))
if err != nil {
return err
Expand Down Expand Up @@ -149,6 +146,10 @@ func (m *BackupServer) Restore(srv regattapb.Maintenance_RestoreServer) error {
return srv.SendAndClose(&regattapb.RestoreResponse{})
}

func (m *BackupServer) AuthFuncOverride(ctx context.Context, _ string) (context.Context, error) {
return m.AuthFunc(ctx)
}

type backupReader struct {
stream regattapb.Maintenance_RestoreServer
}
Expand Down
16 changes: 4 additions & 12 deletions regattaserver/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ type TablesServer struct {
}

func (t *TablesServer) Create(ctx context.Context, req *regattapb.CreateTableRequest) (*regattapb.CreateTableResponse, error) {
_, err := t.AuthFunc(ctx)
if err != nil {
return nil, err
}
if len(req.Name) == 0 {
return nil, status.Errorf(codes.InvalidArgument, "name must be set")
}
Expand All @@ -40,10 +36,6 @@ func (t *TablesServer) Create(ctx context.Context, req *regattapb.CreateTableReq
}

func (t *TablesServer) Delete(ctx context.Context, req *regattapb.DeleteTableRequest) (*regattapb.DeleteTableResponse, error) {
_, err := t.AuthFunc(ctx)
if err != nil {
return nil, err
}
if len(req.Name) == 0 {
return nil, status.Errorf(codes.InvalidArgument, "name must be set")
}
Expand All @@ -57,10 +49,6 @@ func (t *TablesServer) Delete(ctx context.Context, req *regattapb.DeleteTableReq
}

func (t *TablesServer) List(ctx context.Context, _ *regattapb.ListTablesRequest) (*regattapb.ListTablesResponse, error) {
_, err := t.AuthFunc(ctx)
if err != nil {
return nil, err
}
ts, err := t.Tables.GetTables()
if err != nil {
if serrors.IsSafeToRetry(err) {
Expand All @@ -81,6 +69,10 @@ func (t *TablesServer) List(ctx context.Context, _ *regattapb.ListTablesRequest)
return resp, nil
}

func (t *TablesServer) AuthFuncOverride(ctx context.Context, _ string) (context.Context, error) {
return t.AuthFunc(ctx)
}

type ReadonlyTablesServer struct {
TablesServer
}
Expand Down
5 changes: 0 additions & 5 deletions regattaserver/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,11 +153,6 @@ func TestTablesServer_List(t *testing.T) {
},
}},
},
{
name: "deny all",
fields: fields{AuthFunc: denyAll},
wantErr: require.Error,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
Expand Down

0 comments on commit 4374a0e

Please sign in to comment.