Skip to content

Commit 334f0ba

Browse files
authored
ETOS SSE v2alpha (#91)
* Clean up configurations to utilize composition instead * Add v2alpha version of the SSE server * Create a streamer interface and add a file streamer * Review comments * Fix a rebase mistake * Add tests for these new endpoints
1 parent 31169af commit 334f0ba

File tree

22 files changed

+1671
-97
lines changed

22 files changed

+1671
-97
lines changed

cmd/keys/main.go

+135
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright Axis Communications AB.
2+
//
3+
// For a full list of individual contributors, please see the commit history.
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
package main
17+
18+
import (
19+
"context"
20+
"net/http"
21+
"os"
22+
"os/signal"
23+
"runtime/debug"
24+
"syscall"
25+
"time"
26+
27+
auth "github.com/eiffel-community/etos-api/internal/authorization"
28+
"github.com/eiffel-community/etos-api/internal/config"
29+
"github.com/eiffel-community/etos-api/internal/logging"
30+
"github.com/eiffel-community/etos-api/internal/server"
31+
"github.com/eiffel-community/etos-api/pkg/application"
32+
v1alpha "github.com/eiffel-community/etos-api/pkg/keys/v1alpha"
33+
"github.com/sirupsen/logrus"
34+
"github.com/snowzach/rotatefilehook"
35+
"go.elastic.co/ecslogrus"
36+
)
37+
38+
// main sets up logging and starts up the key webserver.
39+
func main() {
40+
cfg := config.NewKeyConfig()
41+
ctx := context.Background()
42+
43+
var hooks []logrus.Hook
44+
if fileHook := fileLogging(cfg); fileHook != nil {
45+
hooks = append(hooks, fileHook)
46+
}
47+
logger, err := logging.Setup(cfg.LogLevel(), hooks)
48+
if err != nil {
49+
logrus.Fatal(err.Error())
50+
}
51+
52+
hostname, err := os.Hostname()
53+
if err != nil {
54+
logrus.Fatal(err.Error())
55+
}
56+
log := logger.WithFields(logrus.Fields{
57+
"hostname": hostname,
58+
"application": "ETOS API Key Server",
59+
"version": vcsRevision(),
60+
"name": "ETOS API",
61+
})
62+
63+
pub, err := cfg.PublicKey()
64+
if err != nil {
65+
log.Fatal(err.Error())
66+
}
67+
priv, err := cfg.PrivateKey()
68+
if err != nil {
69+
log.Fatal(err.Error())
70+
}
71+
authorizer, err := auth.NewAuthorizer(pub, priv)
72+
if err != nil {
73+
log.Fatal(err.Error())
74+
}
75+
v1AlphaKeys := v1alpha.New(ctx, cfg, log, authorizer)
76+
defer v1AlphaKeys.Close()
77+
78+
log.Info("Loading Key routes")
79+
app := application.New(v1AlphaKeys)
80+
srv := server.NewWebService(cfg, log, app)
81+
82+
done := make(chan os.Signal, 1)
83+
signal.Notify(done, syscall.SIGINT, syscall.SIGTERM)
84+
85+
go func() {
86+
if err := srv.Start(); err != nil && err != http.ErrServerClosed {
87+
log.Errorf("Webserver shutdown: %+v", err)
88+
}
89+
}()
90+
91+
sig := <-done
92+
log.Infof("%s received", sig.String())
93+
94+
ctx, cancel := context.WithTimeout(ctx, 1*time.Minute)
95+
defer cancel()
96+
97+
if err := srv.Close(ctx); err != nil {
98+
log.Errorf("Webserver shutdown failed: %+v", err)
99+
}
100+
log.Info("Wait for shutdown to complete")
101+
}
102+
103+
// fileLogging adds a hook into a slice of hooks, if the filepath configuration is set
104+
func fileLogging(cfg config.Config) logrus.Hook {
105+
if filePath := cfg.LogFilePath(); filePath != "" {
106+
// TODO: Make these parameters configurable.
107+
// NewRotateFileHook cannot return an error which is why it's set to '_'.
108+
rotateFileHook, _ := rotatefilehook.NewRotateFileHook(rotatefilehook.RotateFileConfig{
109+
Filename: filePath,
110+
MaxSize: 10, // megabytes
111+
MaxBackups: 3,
112+
MaxAge: 0, // days
113+
Level: logrus.DebugLevel,
114+
Formatter: &ecslogrus.Formatter{
115+
DataKey: "labels",
116+
},
117+
})
118+
return rotateFileHook
119+
}
120+
return nil
121+
}
122+
123+
// vcsRevision returns vcs revision from build info, if any. Otherwise '(unknown)'.
124+
func vcsRevision() string {
125+
buildInfo, ok := debug.ReadBuildInfo()
126+
if !ok {
127+
return "(unknown)"
128+
}
129+
for _, val := range buildInfo.Settings {
130+
if val.Key == "vcs.revision" {
131+
return val.Value
132+
}
133+
}
134+
return "(unknown)"
135+
}

cmd/sse/main.go

+36-1
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,17 @@ import (
2424
"syscall"
2525
"time"
2626

27+
auth "github.com/eiffel-community/etos-api/internal/authorization"
2728
"github.com/eiffel-community/etos-api/internal/config"
2829
"github.com/eiffel-community/etos-api/internal/logging"
2930
"github.com/eiffel-community/etos-api/internal/server"
31+
"github.com/eiffel-community/etos-api/internal/stream"
3032
"github.com/eiffel-community/etos-api/pkg/application"
3133
v1 "github.com/eiffel-community/etos-api/pkg/sse/v1"
3234
v1alpha "github.com/eiffel-community/etos-api/pkg/sse/v1alpha"
35+
v2alpha "github.com/eiffel-community/etos-api/pkg/sse/v2alpha"
36+
"github.com/julienschmidt/httprouter"
37+
rabbitMQStream "github.com/rabbitmq/rabbitmq-stream-go-client/pkg/stream"
3338
"github.com/sirupsen/logrus"
3439
"github.com/snowzach/rotatefilehook"
3540
"go.elastic.co/ecslogrus"
@@ -66,7 +71,37 @@ func main() {
6671
v1SSE := v1.New(cfg, log, ctx)
6772
defer v1SSE.Close()
6873

69-
app := application.New(v1AlphaSSE, v1SSE)
74+
pub, err := cfg.PublicKey()
75+
if err != nil {
76+
log.Fatal(err.Error())
77+
}
78+
var app *httprouter.Router
79+
// Only load v2alpha if a public key exists.
80+
if pub != nil {
81+
authorizer, err := auth.NewAuthorizer(pub, nil)
82+
if err != nil {
83+
log.Fatal(err.Error())
84+
}
85+
86+
var streamer stream.Streamer
87+
if cfg.RabbitMQURI() != "" {
88+
log.Info("Starting up a RabbitMQStreamer")
89+
streamer, err = stream.NewRabbitMQStreamer(*rabbitMQStream.NewEnvironmentOptions().SetUri(cfg.RabbitMQURI()), log)
90+
} else {
91+
log.Warning("RabbitMQURI is not set, defaulting to FileStreamer")
92+
streamer, err = stream.NewFileStreamer(100*time.Millisecond, log)
93+
}
94+
if err != nil {
95+
log.Fatal(err.Error())
96+
}
97+
v2AlphaSSE := v2alpha.New(ctx, cfg, log, streamer, authorizer)
98+
defer v2AlphaSSE.Close()
99+
app = application.New(v1AlphaSSE, v1SSE, v2AlphaSSE)
100+
} else {
101+
log.Warning("Public key does not exist, won't enable v2alpha endpoint")
102+
app = application.New(v1AlphaSSE, v1SSE)
103+
}
104+
70105
srv := server.NewWebService(cfg, log, app)
71106

72107
done := make(chan os.Signal, 1)

go.mod

+19-16
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,27 @@ toolchain go1.22.1
77
require (
88
github.com/eiffel-community/eiffelevents-sdk-go v0.0.0-20240807115026-5ca5c194b7dc
99
github.com/fernet/fernet-go v0.0.0-20240119011108-303da6aec611
10+
github.com/golang-jwt/jwt/v5 v5.2.1
1011
github.com/google/uuid v1.6.0
1112
github.com/jmespath/go-jmespath v0.4.0
1213
github.com/julienschmidt/httprouter v1.3.0
13-
github.com/machinebox/graphql v0.2.2
1414
github.com/maxcnunes/httpfake v1.2.4
1515
github.com/package-url/packageurl-go v0.1.3
16+
github.com/rabbitmq/amqp091-go v1.10.0
17+
github.com/rabbitmq/rabbitmq-stream-go-client v1.4.10
1618
github.com/sethvargo/go-retry v0.3.0
1719
github.com/sirupsen/logrus v1.9.3
1820
github.com/snowzach/rotatefilehook v0.0.0-20220211133110-53752135082d
1921
github.com/stretchr/testify v1.9.0
2022
go.elastic.co/ecslogrus v1.0.0
21-
go.etcd.io/etcd/api/v3 v3.5.15
2223
go.etcd.io/etcd/client/v3 v3.5.15
2324
go.etcd.io/etcd/server/v3 v3.5.14
25+
go.opentelemetry.io/otel v1.20.0
26+
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0
27+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0
28+
go.opentelemetry.io/otel/sdk v1.20.0
29+
go.opentelemetry.io/otel/trace v1.20.0
30+
k8s.io/api v0.31.1
2431
k8s.io/apimachinery v0.31.1
2532
k8s.io/client-go v0.31.1
2633
)
@@ -46,6 +53,7 @@ require (
4653
github.com/gogo/protobuf v1.3.2 // indirect
4754
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
4855
github.com/golang/protobuf v1.5.4 // indirect
56+
github.com/golang/snappy v0.0.4 // indirect
4957
github.com/google/btree v1.0.1 // indirect
5058
github.com/google/gnostic-models v0.6.8 // indirect
5159
github.com/google/go-cmp v0.6.0 // indirect
@@ -59,21 +67,22 @@ require (
5967
github.com/jonboulle/clockwork v0.2.2 // indirect
6068
github.com/josharian/intern v1.0.0 // indirect
6169
github.com/json-iterator/go v1.1.12 // indirect
70+
github.com/klauspost/compress v1.17.9 // indirect
6271
github.com/magefile/mage v1.9.0 // indirect
6372
github.com/mailru/easyjson v0.7.7 // indirect
64-
github.com/matryer/is v1.4.1 // indirect
6573
github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
6674
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
6775
github.com/modern-go/reflect2 v1.0.2 // indirect
6876
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
77+
github.com/pierrec/lz4 v2.6.1+incompatible // indirect
6978
github.com/pkg/errors v0.9.1 // indirect
7079
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
7180
github.com/prometheus/client_golang v1.11.1 // indirect
7281
github.com/prometheus/client_model v0.2.0 // indirect
7382
github.com/prometheus/common v0.26.0 // indirect
7483
github.com/prometheus/procfs v0.6.0 // indirect
75-
github.com/rabbitmq/amqp091-go v1.10.0 // indirect
7684
github.com/soheilhy/cmux v0.1.5 // indirect
85+
github.com/spaolacci/murmur3 v1.1.0 // indirect
7786
github.com/spf13/pflag v1.0.5 // indirect
7887
github.com/tidwall/gjson v1.17.1 // indirect
7988
github.com/tidwall/match v1.1.1 // indirect
@@ -82,29 +91,24 @@ require (
8291
github.com/x448/float16 v0.8.4 // indirect
8392
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
8493
go.etcd.io/bbolt v1.3.10 // indirect
94+
go.etcd.io/etcd/api/v3 v3.5.15 // indirect
8595
go.etcd.io/etcd/client/pkg/v3 v3.5.15 // indirect
8696
go.etcd.io/etcd/client/v2 v2.305.14 // indirect
8797
go.etcd.io/etcd/pkg/v3 v3.5.14 // indirect
8898
go.etcd.io/etcd/raft/v3 v3.5.14 // indirect
8999
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.0 // indirect
90-
go.opentelemetry.io/otel v1.20.0 // indirect
91-
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 // indirect
92-
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 // indirect
93100
go.opentelemetry.io/otel/metric v1.20.0 // indirect
94-
go.opentelemetry.io/otel/sdk v1.20.0 // indirect
95-
go.opentelemetry.io/otel/trace v1.20.0 // indirect
96101
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
97102
go.uber.org/atomic v1.7.0 // indirect
98103
go.uber.org/multierr v1.6.0 // indirect
99104
go.uber.org/zap v1.17.0 // indirect
100-
golang.org/x/crypto v0.24.0 // indirect
101-
golang.org/x/net v0.26.0 // indirect
105+
golang.org/x/crypto v0.26.0 // indirect
106+
golang.org/x/net v0.28.0 // indirect
102107
golang.org/x/oauth2 v0.21.0 // indirect
103-
golang.org/x/sys v0.21.0 // indirect
104-
golang.org/x/term v0.21.0 // indirect
105-
golang.org/x/text v0.16.0 // indirect
108+
golang.org/x/sys v0.23.0 // indirect
109+
golang.org/x/term v0.23.0 // indirect
110+
golang.org/x/text v0.17.0 // indirect
106111
golang.org/x/time v0.3.0 // indirect
107-
google.golang.org/appengine v1.6.7 // indirect
108112
google.golang.org/genproto v0.0.0-20230822172742-b8732ec3820d // indirect
109113
google.golang.org/genproto/googleapis/api v0.0.0-20230822172742-b8732ec3820d // indirect
110114
google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect
@@ -114,7 +118,6 @@ require (
114118
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
115119
gopkg.in/yaml.v2 v2.4.0 // indirect
116120
gopkg.in/yaml.v3 v3.0.1 // indirect
117-
k8s.io/api v0.31.1 // indirect
118121
k8s.io/klog/v2 v2.130.1 // indirect
119122
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect
120123
k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect

0 commit comments

Comments
 (0)