Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(config): support fetching and watching configmaps for tunnel groups #20

Merged
merged 4 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 29 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,13 @@ USAGE
FLAGS
-l, --log LEVEL debug, info, warn or error (default: INFO)
-a, --tunnel-address STRING address for accepting tunnelling quic connections (default: 127.0.0.1:7171)
-s, --http-address STRING address for serving HTTP requests (default: 127.0.0.1:8181)
-g, --tunnel-groups STRING path to tunnel groups configuration file (default: groups.yml)
-s, --http-address STRING address for serving HTTP requests (default: 0.0.0.0:8181)
-n, --server-name STRING server name used to identify tunnel via TLS (required)
-k, --private-key-path STRING path to TLS private key PEM file (required)
-c, --certificate-path STRING path to TLS certificate PEM file (required)
-g, --tunnel-groups STRING path to file or k8s configmap identifier (default: groups.yml)
-w, --watch-groups watch tunnel groups sources for updates
--management-address STRING HTTP address for management API
--max-idle-timeout DURATION maximum time a connection can be idle (default: 1m0s)
--keep-alive-period DURATION period between keep-alive events (default: 30s)
```
Expand All @@ -136,6 +138,31 @@ For example, `--tunnel-address` becomes `REVERST_TUNNEL_ADDRESS`.

#### Tunnel Groups Configuration YAML

**configuring**

Currently, the tunnel groups configuration can be sourced from two different locations types (`file` and `k8s`).
Both tunnel group sources support watching sources for changes over time (see `-w` flag).

- Local filesystem (`file://[path]`)

The standard and simplest method is to point reverst at your configuration YAML file on your machine via its path.

```console
reverst -g path/to/configuration.yml
// alternatively:
reverst -g file:///path/to/configuration.yml
```

- Kubernetes ConfigMap `k8s://configmap/[namespace]/[name]/[key]`

Alternatively, you can configure reverst to connect to a Kubernetes API server and fetch / watch configuration from.

```console
reverst -g k8s://configmap/default/tunnelconfig/groups.yml
```

**defining**

The reverst server take a path to a YAML encoded file, which identifies the tunnel groups to be hosted.
A tunnel group is a load-balancer on which tunneled servers can register themselves.
The file contains a top-level key groups, under which each tunnel group is uniquely named.
Expand Down
68 changes: 12 additions & 56 deletions cmd/reverst/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ import (
"os"
"os/signal"
"syscall"
"time"

"github.com/fsnotify/fsnotify"
"github.com/peterbourgon/ff/v4"
"github.com/peterbourgon/ff/v4/ffhelp"
"go.flipt.io/reverst/internal/config"
Expand Down Expand Up @@ -38,62 +38,18 @@ func main() {
return err
}

groups, err := conf.TunnelGroups()
if err != nil {
return err
}

// start a subscription for tunnel group configuration
// this function should push at-least one tunnel groups
// instance on the channel before returning a non-nil error
groupsChan := make(chan *config.TunnelGroups, 1)
groupsChan <- groups

if conf.WatchTunnelGroups {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return err
}
defer watcher.Close()

go func() {
defer close(groupsChan)

for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}

slog.Debug("Watcher event", "event", event)

if !(event.Has(fsnotify.Remove)) {
continue
}

groups, err := conf.TunnelGroups()
if err != nil {
slog.Error("reading tunnel groups: %w", err)
continue
}

groupsChan <- groups

// remove and re-add as the file has been moved atomically
watcher.Remove(event.Name)
watcher.Add(conf.TunnelGroupsPath)

case err, ok := <-watcher.Errors:
if !ok {
return
}

slog.Error("watching tunnel groups", "error", err)
}
}
}()

if err := watcher.Add(conf.TunnelGroupsPath); err != nil {
return err
}
if err := func() error {
// this anonymous function allows us to defer a close
// and safely shadow the parent context
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
return conf.SubscribeTunnelGroups(ctx, groupsChan)
}(); err != nil {
return err
}

server, err := server.New(conf, groupsChan)
Expand Down
6 changes: 3 additions & 3 deletions dagger/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ func (m *Reverst) BuildContainer(
) (*Container, error) {
build := dag.
Go().
FromVersion("1.21-alpine3.18").
FromVersion("1.22-alpine3.18").
Build(source, dagger.GoBuildOpts{
Packages: []string{"./cmd/reverst/..."},
})
Expand All @@ -58,7 +58,7 @@ func (m *Reverst) TestUnit(
source *dagger.Directory,
) (string, error) {
out, err := dag.Container().
From("golang:1.21-alpine3.18").
From("golang:1.22-alpine3.18").
WithExec([]string{"apk", "add", "gcc", "build-base"}).
With(dag.Go().GlobalCache).
WithEnvVariable("CGO_ENABLED", "1").
Expand Down Expand Up @@ -128,7 +128,7 @@ func (m *Reverst) TestIntegration(
}

out, err := dag.Container().
From("golang:1.21-alpine3.18").
From("golang:1.22-alpine3.18").
WithServiceBinding("local.example", reverst).
With(dag.Go().GlobalCache).
WithMountedDirectory("/src", source).
Expand Down
36 changes: 34 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
module go.flipt.io/reverst

go 1.21.4
go 1.22.0

toolchain go1.22.2

require (
github.com/fsnotify/fsnotify v1.7.0
github.com/peterbourgon/ff/v4 v4.0.0-alpha.4
github.com/prometheus/client_golang v1.19.0
github.com/quic-go/quic-go v0.43.0
Expand All @@ -14,17 +17,34 @@ require (
go.opentelemetry.io/otel/sdk/metric v1.25.0
golang.org/x/sync v0.7.0
gopkg.in/yaml.v2 v2.4.0
k8s.io/apimachinery v0.30.0
k8s.io/client-go v0.30.0
)

require (
github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.7.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/pprof v0.0.0-20240430035430-e4905b036c4e // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/onsi/ginkgo/v2 v2.17.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
Expand All @@ -39,9 +59,21 @@ require (
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.16.0 // indirect
golang.org/x/sys v0.19.0 // indirect
golang.org/x/term v0.19.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.20.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.30.0 // indirect
k8s.io/klog/v2 v2.120.1 // indirect
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
Loading