Skip to content

Commit 0ca78b8

Browse files
authored
feat: Support config from YAML (#186)
* feat: Read config from YAML & env * fix: Update services to use the new config * chore: Remove unnecessary config * chore: Remove unused config parser * refactor: Config parsing logic * chore: Config use OS interface for easier mock * chore: Default config paths * test: Config test suite * chore: Improve config validation * fix: Validation & config parsing & make sure services are running * test: Extend e2e from default config * refactor: Group destinations & portal config * test: Mixed YAML & env * fix: API_PORT * fix: Support optional publishmq * chore: Rename destination config env
1 parent 5ad1e46 commit 0ca78b8

File tree

24 files changed

+1559
-685
lines changed

24 files changed

+1559
-685
lines changed

cmd/e2e/configs/basic.go

Lines changed: 45 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,69 +8,63 @@ import (
88
"github.com/google/uuid"
99
"github.com/hookdeck/outpost/internal/config"
1010
"github.com/hookdeck/outpost/internal/infra"
11-
"github.com/hookdeck/outpost/internal/mqs"
1211
"github.com/hookdeck/outpost/internal/util/testinfra"
1312
"github.com/hookdeck/outpost/internal/util/testutil"
1413
)
1514

16-
func Basic(t *testing.T) *config.Config {
17-
// Config
15+
func Basic(t *testing.T) config.Config {
16+
// Get test infrastructure configs
1817
redisConfig := testutil.CreateTestRedisConfig(t)
1918
clickHouseConfig := testinfra.NewClickHouseConfig(t)
2019
rabbitmqServerURL := testinfra.EnsureRabbitMQ()
21-
deliveryMQConfig := mqs.QueueConfig{
22-
RabbitMQ: &mqs.RabbitMQConfig{
23-
ServerURL: rabbitmqServerURL,
24-
Exchange: uuid.New().String(),
25-
Queue: uuid.New().String(),
26-
},
27-
Policy: mqs.Policy{
28-
RetryLimit: 5,
29-
},
30-
}
31-
logMQConfig := mqs.QueueConfig{
32-
RabbitMQ: &mqs.RabbitMQConfig{
33-
ServerURL: rabbitmqServerURL,
34-
Exchange: uuid.New().String(),
35-
Queue: uuid.New().String(),
36-
},
37-
Policy: mqs.Policy{
38-
RetryLimit: 5,
39-
},
40-
}
20+
21+
// Start with defaults
22+
c := &config.Config{}
23+
c.InitDefaults()
24+
25+
// Override only what's needed for e2e tests
26+
c.Service = config.ServiceTypeSingular.String()
27+
c.APIPort = testutil.RandomPortNumber()
28+
c.APIKey = "apikey"
29+
c.APIJWTSecret = "jwtsecret"
30+
c.AESEncryptionSecret = "encryptionsecret"
31+
c.Topics = testutil.TestTopics
32+
33+
// Infrastructure overrides
34+
c.Redis.Host = redisConfig.Host
35+
c.Redis.Port = redisConfig.Port
36+
c.Redis.Password = redisConfig.Password
37+
c.Redis.Database = redisConfig.Database
38+
39+
c.ClickHouse.Addr = clickHouseConfig.Addr
40+
c.ClickHouse.Username = clickHouseConfig.Username
41+
c.ClickHouse.Password = clickHouseConfig.Password
42+
c.ClickHouse.Database = clickHouseConfig.Database
43+
44+
// MQ overrides
45+
c.MQs.RabbitMQ.ServerURL = rabbitmqServerURL
46+
c.MQs.RabbitMQ.Exchange = uuid.New().String()
47+
c.MQs.RabbitMQ.DeliveryQueue = uuid.New().String()
48+
c.MQs.RabbitMQ.LogQueue = uuid.New().String()
49+
50+
// Test-specific overrides
51+
c.PublishMaxConcurrency = 3
52+
c.DeliveryMaxConcurrency = 3
53+
c.LogMaxConcurrency = 3
54+
c.RetryIntervalSeconds = 1
55+
c.RetryMaxLimit = 3
56+
c.LogBatcherDelayThresholdSeconds = 1
57+
c.LogBatcherItemCountThreshold = 100
58+
59+
// Setup cleanup
4160
t.Cleanup(func() {
4261
if err := infra.Teardown(context.Background(), infra.Config{
43-
DeliveryMQ: &deliveryMQConfig,
44-
LogMQ: &logMQConfig,
62+
DeliveryMQ: c.MQs.GetDeliveryQueueConfig(),
63+
LogMQ: c.MQs.GetLogQueueConfig(),
4564
}); err != nil {
4665
log.Println("Teardown failed:", err)
4766
}
4867
})
4968

50-
return &config.Config{
51-
Hostname: "outpost",
52-
Service: config.ServiceTypeSingular,
53-
Port: testutil.RandomPortNumber(),
54-
APIKey: "apikey",
55-
APIJWTSecret: "jwtsecret",
56-
AESEncryptionSecret: "encryptionsecret",
57-
PortalProxyURL: "",
58-
Topics: testutil.TestTopics,
59-
Redis: redisConfig,
60-
ClickHouse: &clickHouseConfig,
61-
OpenTelemetry: nil,
62-
PublishQueueConfig: nil,
63-
DeliveryQueueConfig: &deliveryMQConfig,
64-
LogQueueConfig: &logMQConfig,
65-
PublishMaxConcurrency: 3,
66-
DeliveryMaxConcurrency: 3,
67-
LogMaxConcurrency: 3,
68-
RetryIntervalSeconds: 1,
69-
RetryMaxLimit: 3,
70-
DeliveryTimeoutSeconds: 5,
71-
LogBatcherDelayThresholdSeconds: 1,
72-
LogBatcherItemCountThreshold: 100,
73-
MaxDestinationsPerTenant: 20,
74-
DestinationWebhookHeaderPrefix: "x-outpost-",
75-
}
69+
return *c
7670
}

cmd/e2e/suites_test.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,17 @@ import (
2222

2323
type e2eSuite struct {
2424
ctx context.Context
25-
config *config.Config
25+
config config.Config
2626
mockServerBaseURL string
2727
mockServerInfra *testinfra.MockServerInfra
2828
cleanup func()
2929
client httpclient.Client
3030
}
3131

3232
func (suite *e2eSuite) SetupSuite() {
33-
suite.client = httpclient.New(fmt.Sprintf("http://localhost:%d/api/v1", suite.config.Port), suite.config.APIKey)
33+
suite.client = httpclient.New(fmt.Sprintf("http://localhost:%d/api/v1", suite.config.APIPort), suite.config.APIKey)
3434
go func() {
35-
application := app.New(suite.config)
35+
application := app.New(&suite.config)
3636
if err := application.Run(suite.ctx); err != nil {
3737
log.Println("Application failed to run", err)
3838
}
@@ -122,9 +122,13 @@ func (suite *basicSuite) SetupSuite() {
122122
t.Cleanup(testinfra.Start(t))
123123
gin.SetMode(gin.TestMode)
124124
mockServerBaseURL := testinfra.GetMockServer(t)
125+
126+
cfg := configs.Basic(t)
127+
require.NoError(t, cfg.Validate(config.Flags{}))
128+
125129
suite.e2eSuite = e2eSuite{
126130
ctx: context.Background(),
127-
config: configs.Basic(t),
131+
config: cfg,
128132
mockServerBaseURL: mockServerBaseURL,
129133
mockServerInfra: testinfra.NewMockServerInfra(mockServerBaseURL),
130134
cleanup: func() {},

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/aws/aws-sdk-go-v2/credentials v1.17.27
1313
github.com/aws/aws-sdk-go-v2/service/sqs v1.34.3
1414
github.com/aws/smithy-go v1.20.3
15+
github.com/caarlos0/env/v9 v9.0.0
1516
github.com/gin-contrib/static v1.1.2
1617
github.com/gin-gonic/gin v1.10.0
1718
github.com/go-playground/validator/v10 v10.22.0
@@ -55,6 +56,7 @@ require (
5556
gocloud.dev v0.39.0
5657
gocloud.dev/pubsub/rabbitpubsub v0.39.0
5758
golang.org/x/sync v0.8.0
59+
gopkg.in/yaml.v3 v3.0.1
5860
)
5961

6062
require (
@@ -183,5 +185,4 @@ require (
183185
google.golang.org/grpc v1.65.0 // indirect
184186
google.golang.org/protobuf v1.34.2 // indirect
185187
gopkg.in/ini.v1 v1.67.0 // indirect
186-
gopkg.in/yaml.v3 v3.0.1 // indirect
187188
)

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ github.com/bytedance/sonic v1.11.9 h1:LFHENlIY/SLzDWverzdOvgMztTxcfcF+cqNsz9pK5z
7676
github.com/bytedance/sonic v1.11.9/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
7777
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
7878
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
79+
github.com/caarlos0/env/v9 v9.0.0 h1:SI6JNsOA+y5gj9njpgybykATIylrRMklbs5ch6wO6pc=
80+
github.com/caarlos0/env/v9 v9.0.0/go.mod h1:ye5mlCVMYh6tZ+vCgrs/B95sj88cg5Tlnc0XIzgZ020=
7981
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
8082
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
8183
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=

internal/app/app.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func run(mainContext context.Context, cfg *config.Config) error {
4343
otelzap.WithMinLevel(zap.InfoLevel), // TODO: allow configuration
4444
)
4545

46-
chDB, err := clickhouse.New(cfg.ClickHouse)
46+
chDB, err := clickhouse.New(cfg.ClickHouse.ToConfig())
4747
if err != nil {
4848
return err
4949
}
@@ -53,8 +53,8 @@ func run(mainContext context.Context, cfg *config.Config) error {
5353
}
5454

5555
if err := infra.Declare(mainContext, infra.Config{
56-
DeliveryMQ: cfg.DeliveryQueueConfig,
57-
LogMQ: cfg.LogQueueConfig,
56+
DeliveryMQ: cfg.MQs.GetDeliveryQueueConfig(),
57+
LogMQ: cfg.MQs.GetLogQueueConfig(),
5858
}); err != nil {
5959
return err
6060
}
@@ -63,8 +63,8 @@ func run(mainContext context.Context, cfg *config.Config) error {
6363
ctx, cancel := context.WithCancel(mainContext)
6464

6565
// Set up OpenTelemetry.
66-
if cfg.OpenTelemetry != nil {
67-
otelShutdown, err := otel.SetupOTelSDK(ctx, cfg.OpenTelemetry)
66+
if cfg.OpenTelemetry.ToConfig() != nil {
67+
otelShutdown, err := otel.SetupOTelSDK(ctx, cfg.OpenTelemetry.ToConfig())
6868
if err != nil {
6969
cancel()
7070
return err
@@ -121,23 +121,24 @@ func constructServices(
121121
wg *sync.WaitGroup,
122122
logger *otelzap.Logger,
123123
) ([]Service, error) {
124+
serviceType := cfg.MustGetService()
124125
services := []Service{}
125126

126-
if cfg.Service == config.ServiceTypeAPI || cfg.Service == config.ServiceTypeSingular {
127+
if serviceType == config.ServiceTypeAPI || serviceType == config.ServiceTypeSingular {
127128
service, err := api.NewService(ctx, wg, cfg, logger)
128129
if err != nil {
129130
return nil, err
130131
}
131132
services = append(services, service)
132133
}
133-
if cfg.Service == config.ServiceTypeDelivery || cfg.Service == config.ServiceTypeSingular {
134+
if serviceType == config.ServiceTypeDelivery || serviceType == config.ServiceTypeSingular {
134135
service, err := delivery.NewService(ctx, wg, cfg, logger, nil)
135136
if err != nil {
136137
return nil, err
137138
}
138139
services = append(services, service)
139140
}
140-
if cfg.Service == config.ServiceTypeLog || cfg.Service == config.ServiceTypeSingular {
141+
if serviceType == config.ServiceTypeLog || serviceType == config.ServiceTypeSingular {
141142
service, err := log.NewService(ctx, wg, cfg, logger, nil)
142143
if err != nil {
143144
return nil, err

0 commit comments

Comments
 (0)