mirror of https://github.com/grafana/loki
Compactor: add per tenant compaction delete enabled flag (#6410)
* Add per tenant compaction delete enabled flag Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Remove changes in wrong place Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Add compactor deletion enabled field Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Use limit in compactor Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Use http middleware and add test Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Fix lint issue Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Add changelog Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Revert to default setting if no override Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Add default value command line option Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Update the docs Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Enable access to deletion API for integration test Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Rename flag to allow_deletes Signed-off-by: Michel Hollands <michel.hollands@grafana.com> * Update per review comments Signed-off-by: Michel Hollands <michel.hollands@grafana.com>pull/6415/head
parent
8ee0d62d9e
commit
b4e6c59936
@ -0,0 +1,133 @@ |
||||
package deletion |
||||
|
||||
import ( |
||||
"net/http" |
||||
"net/http/httptest" |
||||
"path/filepath" |
||||
"testing" |
||||
"time" |
||||
|
||||
"github.com/prometheus/common/model" |
||||
"github.com/stretchr/testify/require" |
||||
"github.com/weaveworks/common/user" |
||||
|
||||
"github.com/grafana/loki/pkg/storage/chunk/client/local" |
||||
"github.com/grafana/loki/pkg/storage/stores/shipper/storage" |
||||
"github.com/grafana/loki/pkg/validation" |
||||
) |
||||
|
||||
type retentionLimit struct { |
||||
compactorDeletionEnabled bool |
||||
retentionPeriod time.Duration |
||||
streamRetention []validation.StreamRetention |
||||
} |
||||
|
||||
func (r retentionLimit) convertToValidationLimit() *validation.Limits { |
||||
return &validation.Limits{ |
||||
CompactorDeletionEnabled: r.compactorDeletionEnabled, |
||||
RetentionPeriod: model.Duration(r.retentionPeriod), |
||||
StreamRetention: r.streamRetention, |
||||
} |
||||
} |
||||
|
||||
type fakeLimits struct { |
||||
defaultLimit retentionLimit |
||||
perTenant map[string]retentionLimit |
||||
} |
||||
|
||||
func (f fakeLimits) RetentionPeriod(userID string) time.Duration { |
||||
return f.perTenant[userID].retentionPeriod |
||||
} |
||||
|
||||
func (f fakeLimits) StreamRetention(userID string) []validation.StreamRetention { |
||||
return f.perTenant[userID].streamRetention |
||||
} |
||||
|
||||
func (f fakeLimits) CompactorDeletionEnabled(userID string) bool { |
||||
return f.perTenant[userID].compactorDeletionEnabled |
||||
} |
||||
|
||||
func (f fakeLimits) DefaultLimits() *validation.Limits { |
||||
return f.defaultLimit.convertToValidationLimit() |
||||
} |
||||
|
||||
func (f fakeLimits) AllByUserID() map[string]*validation.Limits { |
||||
res := make(map[string]*validation.Limits) |
||||
for userID, ret := range f.perTenant { |
||||
res[userID] = ret.convertToValidationLimit() |
||||
} |
||||
return res |
||||
} |
||||
|
||||
func TestDeleteRequestHandlerDeletionMiddleware(t *testing.T) { |
||||
// build the store
|
||||
tempDir := t.TempDir() |
||||
|
||||
workingDir := filepath.Join(tempDir, "working-dir") |
||||
objectStorePath := filepath.Join(tempDir, "object-store") |
||||
|
||||
objectClient, err := local.NewFSObjectClient(local.FSConfig{ |
||||
Directory: objectStorePath, |
||||
}) |
||||
require.NoError(t, err) |
||||
testDeleteRequestsStore, err := NewDeleteStore(workingDir, storage.NewIndexStorageClient(objectClient, "")) |
||||
require.NoError(t, err) |
||||
|
||||
// limits
|
||||
fl := &fakeLimits{ |
||||
perTenant: map[string]retentionLimit{ |
||||
"1": {compactorDeletionEnabled: true}, |
||||
"2": {compactorDeletionEnabled: false}, |
||||
}, |
||||
} |
||||
|
||||
// Setup handler
|
||||
drh := NewDeleteRequestHandler(testDeleteRequestsStore, 10*time.Second, fl, nil) |
||||
middle := drh.deletionMiddleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})) |
||||
|
||||
// User that has deletion enabled
|
||||
req := httptest.NewRequest(http.MethodGet, "http://www.your-domain.com", nil) |
||||
req = req.WithContext(user.InjectOrgID(req.Context(), "1")) |
||||
|
||||
res := httptest.NewRecorder() |
||||
middle.ServeHTTP(res, req) |
||||
|
||||
require.Equal(t, http.StatusOK, res.Result().StatusCode) |
||||
|
||||
// User that does not have deletion enabled
|
||||
req = httptest.NewRequest(http.MethodGet, "http://www.your-domain.com", nil) |
||||
req = req.WithContext(user.InjectOrgID(req.Context(), "2")) |
||||
|
||||
res = httptest.NewRecorder() |
||||
middle.ServeHTTP(res, req) |
||||
|
||||
require.Equal(t, http.StatusForbidden, res.Result().StatusCode) |
||||
|
||||
// User without override, this should use the default value which is false
|
||||
req = httptest.NewRequest(http.MethodGet, "http://www.your-domain.com", nil) |
||||
req = req.WithContext(user.InjectOrgID(req.Context(), "3")) |
||||
|
||||
res = httptest.NewRecorder() |
||||
middle.ServeHTTP(res, req) |
||||
|
||||
require.Equal(t, http.StatusForbidden, res.Result().StatusCode) |
||||
|
||||
// User without override, after the default value is set to true
|
||||
fl.defaultLimit.compactorDeletionEnabled = true |
||||
|
||||
req = httptest.NewRequest(http.MethodGet, "http://www.your-domain.com", nil) |
||||
req = req.WithContext(user.InjectOrgID(req.Context(), "3")) |
||||
|
||||
res = httptest.NewRecorder() |
||||
middle.ServeHTTP(res, req) |
||||
|
||||
require.Equal(t, http.StatusOK, res.Result().StatusCode) |
||||
|
||||
// User header is not given
|
||||
req = httptest.NewRequest(http.MethodGet, "http://www.your-domain.com", nil) |
||||
|
||||
res = httptest.NewRecorder() |
||||
middle.ServeHTTP(res, req) |
||||
|
||||
require.Equal(t, http.StatusBadRequest, res.Result().StatusCode) |
||||
} |
Loading…
Reference in new issue