Skip to content

Commit 5e21b22

Browse files
committed
suggestions
Signed-off-by: Bogdan Stancu <stancu.bogdan.nicolae@gmail.com>
1 parent a2a7665 commit 5e21b22

File tree

6 files changed

+110
-244
lines changed

6 files changed

+110
-244
lines changed

integration/overrides_test.go

Lines changed: 38 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ func TestOverridesAPIWithRunningCortex(t *testing.T) {
5252
flags := map[string]string{
5353
"-target": "overrides",
5454

55-
"-overrides.runtime-config-file": "runtime.yaml",
56-
"-overrides.backend": "s3",
57-
"-overrides.s3.access-key-id": e2edb.MinioAccessKey,
58-
"-overrides.s3.secret-access-key": e2edb.MinioSecretKey,
59-
"-overrides.s3.bucket-name": "cortex",
60-
"-overrides.s3.endpoint": minio.NetworkHTTPEndpoint(),
61-
"-overrides.s3.insecure": "true",
55+
"-runtime-config.file": "runtime.yaml",
56+
"-runtime-config.backend": "s3",
57+
"-runtime-config.s3.access-key-id": e2edb.MinioAccessKey,
58+
"-runtime-config.s3.secret-access-key": e2edb.MinioSecretKey,
59+
"-runtime-config.s3.bucket-name": "cortex",
60+
"-runtime-config.s3.endpoint": minio.NetworkHTTPEndpoint(),
61+
"-runtime-config.s3.insecure": "true",
6262
}
6363

6464
cortexSvc := e2ecortex.NewSingleBinary("cortex-overrides", flags, "")
@@ -100,15 +100,15 @@ func TestOverridesAPIWithRunningCortex(t *testing.T) {
100100
assert.Empty(t, overrides)
101101
})
102102

103-
t.Run("PUT overrides for new user", func(t *testing.T) {
103+
t.Run("POST overrides for new user", func(t *testing.T) {
104104
newOverrides := map[string]interface{}{
105105
"ingestion_rate": 6000,
106106
"ingestion_burst_size": 7000,
107107
}
108108
requestBody, err := json.Marshal(newOverrides)
109109
require.NoError(t, err)
110110

111-
req, err := http.NewRequest("PUT", "http://"+cortexSvc.HTTPEndpoint()+"/api/v1/user-overrides", bytes.NewReader(requestBody))
111+
req, err := http.NewRequest("POST", "http://"+cortexSvc.HTTPEndpoint()+"/api/v1/user-overrides", bytes.NewReader(requestBody))
112112
require.NoError(t, err)
113113
req.Header.Set("X-Scope-OrgID", "user3")
114114
req.Header.Set("Content-Type", "application/json")
@@ -137,14 +137,14 @@ func TestOverridesAPIWithRunningCortex(t *testing.T) {
137137
assert.Equal(t, float64(7000), savedOverrides["ingestion_burst_size"])
138138
})
139139

140-
t.Run("PUT overrides with invalid limit", func(t *testing.T) {
140+
t.Run("POST overrides with invalid limit", func(t *testing.T) {
141141
invalidOverrides := map[string]interface{}{
142142
"invalid_limit": 5000,
143143
}
144144
requestBody, err := json.Marshal(invalidOverrides)
145145
require.NoError(t, err)
146146

147-
req, err := http.NewRequest("PUT", "http://"+cortexSvc.HTTPEndpoint()+"/api/v1/user-overrides", bytes.NewReader(requestBody))
147+
req, err := http.NewRequest("POST", "http://"+cortexSvc.HTTPEndpoint()+"/api/v1/user-overrides", bytes.NewReader(requestBody))
148148
require.NoError(t, err)
149149
req.Header.Set("X-Scope-OrgID", "user4")
150150
req.Header.Set("Content-Type", "application/json")
@@ -156,8 +156,8 @@ func TestOverridesAPIWithRunningCortex(t *testing.T) {
156156
assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
157157
})
158158

159-
t.Run("PUT overrides with invalid JSON", func(t *testing.T) {
160-
req, err := http.NewRequest("PUT", "http://"+cortexSvc.HTTPEndpoint()+"/api/v1/user-overrides", bytes.NewReader([]byte("invalid json")))
159+
t.Run("POST overrides with invalid JSON", func(t *testing.T) {
160+
req, err := http.NewRequest("POST", "http://"+cortexSvc.HTTPEndpoint()+"/api/v1/user-overrides", bytes.NewReader([]byte("invalid json")))
161161
require.NoError(t, err)
162162
req.Header.Set("X-Scope-OrgID", "user5")
163163
req.Header.Set("Content-Type", "application/json")
@@ -208,16 +208,34 @@ func TestOverridesAPITenantExtraction(t *testing.T) {
208208
minio := e2edb.NewMinio(9010, "cortex")
209209
require.NoError(t, s.StartAndWaitReady(minio))
210210

211+
// Upload an empty runtime config file to S3
212+
runtimeConfig := map[string]interface{}{
213+
"overrides": map[string]interface{}{},
214+
}
215+
runtimeConfigData, err := yaml.Marshal(runtimeConfig)
216+
require.NoError(t, err)
217+
218+
s3Client, err := s3.NewBucketWithConfig(nil, s3.Config{
219+
Endpoint: minio.HTTPEndpoint(),
220+
Insecure: true,
221+
Bucket: "cortex",
222+
AccessKey: e2edb.MinioAccessKey,
223+
SecretKey: e2edb.MinioSecretKey,
224+
}, "overrides-test-tenant", nil)
225+
require.NoError(t, err)
226+
227+
require.NoError(t, s3Client.Upload(context.Background(), "runtime.yaml", bytes.NewReader(runtimeConfigData)))
228+
211229
flags := map[string]string{
212230
"-target": "overrides",
213231

214-
"-overrides.runtime-config-file": "runtime.yaml",
215-
"-overrides.backend": "s3",
216-
"-overrides.s3.access-key-id": e2edb.MinioAccessKey,
217-
"-overrides.s3.secret-access-key": e2edb.MinioSecretKey,
218-
"-overrides.s3.bucket-name": "cortex",
219-
"-overrides.s3.endpoint": minio.NetworkHTTPEndpoint(),
220-
"-overrides.s3.insecure": "true",
232+
"-runtime-config.file": "runtime.yaml",
233+
"-runtime-config.backend": "s3",
234+
"-runtime-config.s3.access-key-id": e2edb.MinioAccessKey,
235+
"-runtime-config.s3.secret-access-key": e2edb.MinioSecretKey,
236+
"-runtime-config.s3.bucket-name": "cortex",
237+
"-runtime-config.s3.endpoint": minio.NetworkHTTPEndpoint(),
238+
"-runtime-config.s3.insecure": "true",
221239
}
222240

223241
cortexSvc := e2ecortex.NewSingleBinary("cortex-overrides-tenant", flags, "")
@@ -248,44 +266,3 @@ func TestOverridesAPITenantExtraction(t *testing.T) {
248266

249267
require.NoError(t, s.Stop(cortexSvc))
250268
}
251-
252-
func TestOverridesAPIFilesystemBackendRejected(t *testing.T) {
253-
s, err := e2e.NewScenario(networkName)
254-
require.NoError(t, err)
255-
defer s.Close()
256-
257-
t.Run("filesystem backend should be rejected", func(t *testing.T) {
258-
flags := map[string]string{
259-
"-target": "overrides",
260-
"-overrides.runtime-config-file": "runtime.yaml",
261-
"-overrides.backend": "filesystem",
262-
}
263-
264-
cortexSvc := e2ecortex.NewSingleBinary("cortex-overrides-filesystem", flags, "")
265-
266-
err = s.StartAndWaitReady(cortexSvc)
267-
if err == nil {
268-
t.Error("Expected Cortex to fail to start with filesystem backend, but it started successfully")
269-
require.NoError(t, s.Stop(cortexSvc))
270-
} else {
271-
t.Logf("Expected failure with filesystem backend: %v", err)
272-
}
273-
})
274-
275-
t.Run("no backend specified should be rejected", func(t *testing.T) {
276-
flags := map[string]string{
277-
"-target": "overrides",
278-
"-overrides.runtime-config-file": "runtime.yaml",
279-
}
280-
281-
cortexSvc := e2ecortex.NewSingleBinary("cortex-overrides-no-backend", flags, "")
282-
283-
err = s.StartAndWaitReady(cortexSvc)
284-
if err == nil {
285-
t.Error("Expected Cortex to fail to start with no backend specified, but it started successfully")
286-
require.NoError(t, s.Stop(cortexSvc))
287-
} else {
288-
t.Logf("Expected failure with no backend specified: %v", err)
289-
}
290-
})
291-
}

pkg/api/api.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -390,7 +390,7 @@ func (a *API) RegisterRulerAPI(r *ruler.API) {
390390
func (a *API) RegisterOverrides(o *overrides.API) {
391391
// Register individual overrides API routes with the main API
392392
a.RegisterRoute("/api/v1/user-overrides", http.HandlerFunc(o.GetOverrides), true, "GET")
393-
a.RegisterRoute("/api/v1/user-overrides", http.HandlerFunc(o.SetOverrides), true, "PUT")
393+
a.RegisterRoute("/api/v1/user-overrides", http.HandlerFunc(o.SetOverrides), true, "POST")
394394
a.RegisterRoute("/api/v1/user-overrides", http.HandlerFunc(o.DeleteOverrides), true, "DELETE")
395395

396396
// Add link to the index page

pkg/cortex/cortex.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,6 @@ type Config struct {
127127
RuntimeConfig runtimeconfig.Config `yaml:"runtime_config"`
128128
MemberlistKV memberlist.KVConfig `yaml:"memberlist"`
129129
QueryScheduler scheduler.Config `yaml:"query_scheduler"`
130-
Overrides overrides.Config `yaml:"overrides"`
131130

132131
Tracing tracing.Config `yaml:"tracing"`
133132
}
@@ -177,7 +176,6 @@ func (c *Config) RegisterFlags(f *flag.FlagSet) {
177176
c.RuntimeConfig.RegisterFlags(f)
178177
c.MemberlistKV.RegisterFlags(f)
179178
c.QueryScheduler.RegisterFlags(f)
180-
c.Overrides.RegisterFlags(f)
181179
c.Tracing.RegisterFlags(f)
182180
}
183181

pkg/cortex/modules.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ func (t *Cortex) initOverridesConfig() (services.Service, error) {
211211

212212
func (t *Cortex) initOverrides() (services.Service, error) {
213213

214-
overridesAPI, err := overrides.New(t.Cfg.Overrides, util_log.Logger, prometheus.DefaultRegisterer)
214+
overridesAPI, err := overrides.New(t.Cfg.RuntimeConfig, util_log.Logger, prometheus.DefaultRegisterer)
215215
if err != nil {
216216
return nil, fmt.Errorf("failed to create overrides API: %w", err)
217217
}

pkg/overrides/overrides.go

Lines changed: 8 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -2,154 +2,34 @@ package overrides
22

33
import (
44
"context"
5-
"errors"
6-
"flag"
75
"fmt"
8-
"time"
96

107
"github.com/go-kit/log"
118
"github.com/go-kit/log/level"
129
"github.com/prometheus/client_golang/prometheus"
1310
"github.com/thanos-io/objstore"
1411

1512
"github.com/cortexproject/cortex/pkg/storage/bucket"
13+
"github.com/cortexproject/cortex/pkg/util/runtimeconfig"
1614
"github.com/cortexproject/cortex/pkg/util/services"
1715
)
1816

1917
const (
20-
// Error messages
21-
ErrNoStorageBackendSpecified = "overrides module requires a storage backend to be specified"
22-
ErrFilesystemBackendNotSupported = "filesystem backend is not supported for overrides module; use S3, GCS, Azure, or Swift instead"
23-
ErrInvalidBucketConfiguration = "invalid bucket configuration"
2418
ErrInvalidOverridesConfiguration = "invalid overrides configuration"
2519
ErrFailedToCreateBucketClient = "failed to create bucket client for overrides"
2620
)
2721

28-
// Config holds configuration for the overrides module
29-
type Config struct {
30-
// Enable the overrides API module
31-
32-
// Path to the runtime configuration file that can be updated via the overrides API
33-
// CLI flag: -overrides.runtime-config-file
34-
RuntimeConfigFile string `yaml:"runtime_config_file"`
35-
36-
// Storage configuration for the runtime config file
37-
// All bucket backends (S3, GCS, Azure, Swift) are supported, but not filesystem
38-
bucket.Config `yaml:",inline"`
39-
}
40-
41-
// RegisterFlags registers the overrides module flags
42-
func (c *Config) RegisterFlags(f *flag.FlagSet) {
43-
44-
f.StringVar(&c.RuntimeConfigFile, "overrides.runtime-config-file", "runtime.yaml", "Path to the runtime configuration file that can be updated via the overrides API")
45-
46-
c.RegisterFlagsWithPrefix("overrides.", f)
47-
}
48-
49-
// Validate validates the configuration and returns an error if validation fails
50-
func (c *Config) Validate() error {
51-
52-
if c.RuntimeConfigFile == "" {
53-
c.RuntimeConfigFile = "runtime.yaml"
54-
}
55-
56-
if c.Backend == "" {
57-
c.Backend = bucket.S3
58-
}
59-
60-
if c.Backend == bucket.Filesystem {
61-
return errors.New(ErrFilesystemBackendNotSupported)
62-
}
63-
64-
if c.Backend == bucket.S3 {
65-
if c.S3.SignatureVersion == "" {
66-
c.S3.SignatureVersion = "v4"
67-
}
68-
if c.S3.BucketLookupType == "" {
69-
c.S3.BucketLookupType = "auto"
70-
}
71-
if !c.S3.SendContentMd5 {
72-
c.S3.SendContentMd5 = true
73-
}
74-
if c.S3.HTTP.IdleConnTimeout == 0 {
75-
c.S3.HTTP.IdleConnTimeout = 90 * time.Second
76-
}
77-
if c.S3.HTTP.ResponseHeaderTimeout == 0 {
78-
c.S3.HTTP.ResponseHeaderTimeout = 2 * time.Minute
79-
}
80-
if c.S3.HTTP.TLSHandshakeTimeout == 0 {
81-
c.S3.HTTP.TLSHandshakeTimeout = 10 * time.Second
82-
}
83-
if c.S3.HTTP.ExpectContinueTimeout == 0 {
84-
c.S3.HTTP.ExpectContinueTimeout = 1 * time.Second
85-
}
86-
if c.S3.HTTP.MaxIdleConns == 0 {
87-
c.S3.HTTP.MaxIdleConns = 100
88-
}
89-
if c.S3.HTTP.MaxIdleConnsPerHost == 0 {
90-
c.S3.HTTP.MaxIdleConnsPerHost = 100
91-
}
92-
}
93-
94-
if c.Backend == bucket.Azure {
95-
if c.Azure.MaxRetries == 0 {
96-
c.Azure.MaxRetries = 20
97-
}
98-
if c.Azure.IdleConnTimeout == 0 {
99-
c.Azure.IdleConnTimeout = 90 * time.Second
100-
}
101-
if c.Azure.ResponseHeaderTimeout == 0 {
102-
c.Azure.ResponseHeaderTimeout = 2 * time.Minute
103-
}
104-
if c.Azure.TLSHandshakeTimeout == 0 {
105-
c.Azure.TLSHandshakeTimeout = 10 * time.Second
106-
}
107-
if c.Azure.ExpectContinueTimeout == 0 {
108-
c.Azure.ExpectContinueTimeout = 1 * time.Second
109-
}
110-
if c.Azure.MaxIdleConns == 0 {
111-
c.Azure.MaxIdleConns = 100
112-
}
113-
if c.Azure.MaxIdleConnsPerHost == 0 {
114-
c.Azure.MaxIdleConnsPerHost = 100
115-
}
116-
}
117-
118-
if c.Backend == bucket.Swift {
119-
if c.Swift.AuthVersion == 0 {
120-
c.Swift.AuthVersion = 0
121-
}
122-
if c.Swift.MaxRetries == 0 {
123-
c.Swift.MaxRetries = 3
124-
}
125-
if c.Swift.ConnectTimeout == 0 {
126-
c.Swift.ConnectTimeout = 10 * time.Second
127-
}
128-
if c.Swift.RequestTimeout == 0 {
129-
c.Swift.RequestTimeout = 5 * time.Second
130-
}
131-
}
132-
133-
if err := c.Config.Validate(); err != nil {
134-
return fmt.Errorf("%s: %w", ErrInvalidBucketConfiguration, err)
135-
}
136-
137-
return nil
138-
}
139-
140-
// API represents the overrides API module
14122
type API struct {
14223
services.Service
143-
cfg Config
24+
cfg runtimeconfig.Config
14425
logger log.Logger
14526
registerer prometheus.Registerer
14627
bucketClient objstore.Bucket
14728
runtimeConfigPath string
14829
}
14930

150-
// New creates a new overrides API instance
151-
func New(cfg Config, logger log.Logger, registerer prometheus.Registerer) (*API, error) {
152-
if err := cfg.Validate(); err != nil {
31+
func New(cfg runtimeconfig.Config, logger log.Logger, registerer prometheus.Registerer) (*API, error) {
32+
if err := cfg.StorageConfig.Validate(); err != nil {
15333
return nil, fmt.Errorf("%s: %w", ErrInvalidOverridesConfiguration, err)
15434
}
15535

@@ -163,18 +43,18 @@ func New(cfg Config, logger log.Logger, registerer prometheus.Registerer) (*API,
16343
}
16444

16545
func (a *API) starting(ctx context.Context) error {
166-
level.Info(a.logger).Log("msg", "overrides API starting", "runtime_config_file", a.cfg.RuntimeConfigFile, "backend", a.cfg.Backend)
46+
level.Info(a.logger).Log("msg", "overrides API starting", "runtime_config_file", a.cfg.LoadPath, "backend", a.cfg.StorageConfig.Backend)
16747

168-
bucketClient, err := bucket.NewClient(ctx, a.cfg.Config, nil, "overrides", a.logger, a.registerer)
48+
bucketClient, err := bucket.NewClient(ctx, a.cfg.StorageConfig, nil, "overrides", a.logger, a.registerer)
16949
if err != nil {
17050
level.Error(a.logger).Log("msg", ErrFailedToCreateBucketClient, "err", err)
17151
return fmt.Errorf("%s: %w", ErrFailedToCreateBucketClient, err)
17252
}
17353
a.bucketClient = bucketClient
17454

175-
a.runtimeConfigPath = a.cfg.RuntimeConfigFile
55+
a.runtimeConfigPath = a.cfg.LoadPath
17656

177-
level.Info(a.logger).Log("msg", "overrides API started successfully", "backend", a.cfg.Backend)
57+
level.Info(a.logger).Log("msg", "overrides API started successfully", "backend", a.cfg.StorageConfig.Backend)
17858
return nil
17959
}
18060

0 commit comments

Comments
 (0)