github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/ruler/base/ruler_test.go (about)

     1  package base
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/rand"
     8  	"net/http"
     9  	"net/http/httptest"
    10  	"os"
    11  	"reflect"
    12  	"sort"
    13  	"strings"
    14  	"sync"
    15  	"testing"
    16  	"time"
    17  	"unsafe"
    18  
    19  	"github.com/go-kit/log"
    20  	"github.com/go-kit/log/level"
    21  	"github.com/gorilla/mux"
    22  	"github.com/grafana/dskit/flagext"
    23  	"github.com/grafana/dskit/kv"
    24  	"github.com/grafana/dskit/kv/consul"
    25  	"github.com/grafana/dskit/ring"
    26  	"github.com/grafana/dskit/services"
    27  	"github.com/prometheus/client_golang/prometheus"
    28  	prom_testutil "github.com/prometheus/client_golang/prometheus/testutil"
    29  	"github.com/prometheus/common/model"
    30  	"github.com/prometheus/prometheus/model/labels"
    31  	"github.com/prometheus/prometheus/model/rulefmt"
    32  	"github.com/prometheus/prometheus/notifier"
    33  	"github.com/prometheus/prometheus/promql"
    34  	promRules "github.com/prometheus/prometheus/rules"
    35  	"github.com/prometheus/prometheus/storage"
    36  	"github.com/stretchr/testify/assert"
    37  	"github.com/stretchr/testify/require"
    38  	"github.com/weaveworks/common/user"
    39  	"go.uber.org/atomic"
    40  	"google.golang.org/grpc"
    41  	"gopkg.in/yaml.v2"
    42  
    43  	"github.com/grafana/dskit/tenant"
    44  
    45  	"github.com/grafana/loki/pkg/logproto"
    46  	"github.com/grafana/loki/pkg/querier/series"
    47  	"github.com/grafana/loki/pkg/ruler/rulespb"
    48  	"github.com/grafana/loki/pkg/ruler/rulestore"
    49  	"github.com/grafana/loki/pkg/ruler/rulestore/objectclient"
    50  	loki_storage "github.com/grafana/loki/pkg/storage"
    51  	"github.com/grafana/loki/pkg/storage/chunk/client/hedging"
    52  	"github.com/grafana/loki/pkg/storage/chunk/client/testutils"
    53  	"github.com/grafana/loki/pkg/util"
    54  )
    55  
    56  func defaultRulerConfig(t testing.TB, store rulestore.RuleStore) Config {
    57  	t.Helper()
    58  
    59  	// Create a new temporary directory for the rules, so that
    60  	// each test will run in isolation.
    61  	rulesDir := t.TempDir()
    62  
    63  	codec := ring.GetCodec()
    64  	consul, closer := consul.NewInMemoryClient(codec, log.NewNopLogger(), nil)
    65  	t.Cleanup(func() { assert.NoError(t, closer.Close()) })
    66  
    67  	cfg := Config{}
    68  	flagext.DefaultValues(&cfg)
    69  	cfg.RulePath = rulesDir
    70  	cfg.StoreConfig.mock = store
    71  	cfg.Ring.KVStore.Mock = consul
    72  	cfg.Ring.NumTokens = 1
    73  	cfg.Ring.ListenPort = 0
    74  	cfg.Ring.InstanceAddr = "localhost"
    75  	cfg.Ring.InstanceID = "localhost"
    76  	cfg.EnableQueryStats = false
    77  
    78  	return cfg
    79  }
    80  
    81  type ruleLimits struct {
    82  	evalDelay            time.Duration
    83  	tenantShard          int
    84  	maxRulesPerRuleGroup int
    85  	maxRuleGroups        int
    86  }
    87  
    88  func (r ruleLimits) EvaluationDelay(_ string) time.Duration {
    89  	return r.evalDelay
    90  }
    91  
    92  func (r ruleLimits) RulerTenantShardSize(_ string) int {
    93  	return r.tenantShard
    94  }
    95  
    96  func (r ruleLimits) RulerMaxRuleGroupsPerTenant(_ string) int {
    97  	return r.maxRuleGroups
    98  }
    99  
   100  func (r ruleLimits) RulerMaxRulesPerRuleGroup(_ string) int {
   101  	return r.maxRulesPerRuleGroup
   102  }
   103  
   104  func testQueryableFunc(q storage.Querier) storage.QueryableFunc {
   105  	if q != nil {
   106  		return func(ctx context.Context, mint, maxt int64) (storage.Querier, error) {
   107  			return q, nil
   108  		}
   109  	}
   110  
   111  	return func(ctx context.Context, mint, maxt int64) (storage.Querier, error) {
   112  		return storage.NoopQuerier(), nil
   113  	}
   114  }
   115  
   116  func testSetup(t *testing.T, q storage.Querier) (*promql.Engine, storage.QueryableFunc, Pusher, log.Logger, RulesLimits, prometheus.Registerer) {
   117  	dir := t.TempDir()
   118  
   119  	tracker := promql.NewActiveQueryTracker(dir, 20, log.NewNopLogger())
   120  
   121  	engine := promql.NewEngine(promql.EngineOpts{
   122  		MaxSamples:         1e6,
   123  		ActiveQueryTracker: tracker,
   124  		Timeout:            2 * time.Minute,
   125  	})
   126  
   127  	// Mock the pusher
   128  	pusher := newPusherMock()
   129  	pusher.MockPush(&logproto.WriteResponse{}, nil)
   130  
   131  	l := log.NewLogfmtLogger(os.Stdout)
   132  	l = level.NewFilter(l, level.AllowInfo())
   133  
   134  	reg := prometheus.NewRegistry()
   135  	queryable := testQueryableFunc(q)
   136  
   137  	return engine, queryable, pusher, l, ruleLimits{evalDelay: 0, maxRuleGroups: 20, maxRulesPerRuleGroup: 15}, reg
   138  }
   139  
   140  func newManager(t *testing.T, cfg Config, q storage.Querier) *DefaultMultiTenantManager {
   141  	engine, queryable, pusher, logger, overrides, reg := testSetup(t, q)
   142  	manager, err := NewDefaultMultiTenantManager(cfg, DefaultTenantManagerFactory(cfg, pusher, queryable, engine, overrides, nil), reg, logger)
   143  	require.NoError(t, err)
   144  
   145  	return manager
   146  }
   147  
   148  type mockRulerClientsPool struct {
   149  	ClientsPool
   150  	cfg           Config
   151  	rulerAddrMap  map[string]*Ruler
   152  	numberOfCalls atomic.Int32
   153  }
   154  
   155  type mockRulerClient struct {
   156  	ruler         *Ruler
   157  	numberOfCalls *atomic.Int32
   158  }
   159  
   160  func (c *mockRulerClient) Rules(ctx context.Context, in *RulesRequest, _ ...grpc.CallOption) (*RulesResponse, error) {
   161  	c.numberOfCalls.Inc()
   162  	return c.ruler.Rules(ctx, in)
   163  }
   164  
   165  func (p *mockRulerClientsPool) GetClientFor(addr string) (RulerClient, error) {
   166  	for _, r := range p.rulerAddrMap {
   167  		if r.lifecycler.GetInstanceAddr() == addr {
   168  			return &mockRulerClient{
   169  				ruler:         r,
   170  				numberOfCalls: &p.numberOfCalls,
   171  			}, nil
   172  		}
   173  	}
   174  
   175  	return nil, fmt.Errorf("unable to find ruler for add %s", addr)
   176  }
   177  
   178  func newMockClientsPool(cfg Config, logger log.Logger, reg prometheus.Registerer, rulerAddrMap map[string]*Ruler) *mockRulerClientsPool {
   179  	return &mockRulerClientsPool{
   180  		ClientsPool:  newRulerClientPool(cfg.ClientTLSConfig, logger, reg),
   181  		cfg:          cfg,
   182  		rulerAddrMap: rulerAddrMap,
   183  	}
   184  }
   185  
   186  func buildRuler(t *testing.T, rulerConfig Config, q storage.Querier, clientMetrics loki_storage.ClientMetrics, rulerAddrMap map[string]*Ruler) *Ruler {
   187  	engine, queryable, pusher, logger, overrides, reg := testSetup(t, q)
   188  	storage, err := NewLegacyRuleStore(rulerConfig.StoreConfig, hedging.Config{}, clientMetrics, promRules.FileLoader{}, log.NewNopLogger())
   189  	require.NoError(t, err)
   190  
   191  	managerFactory := DefaultTenantManagerFactory(rulerConfig, pusher, queryable, engine, overrides, reg)
   192  	manager, err := NewDefaultMultiTenantManager(rulerConfig, managerFactory, reg, log.NewNopLogger())
   193  	require.NoError(t, err)
   194  
   195  	ruler, err := newRuler(
   196  		rulerConfig,
   197  		manager,
   198  		reg,
   199  		logger,
   200  		storage,
   201  		overrides,
   202  		newMockClientsPool(rulerConfig, logger, reg, rulerAddrMap),
   203  	)
   204  	require.NoError(t, err)
   205  	return ruler
   206  }
   207  
   208  func newTestRuler(t *testing.T, rulerConfig Config) *Ruler {
   209  	m := loki_storage.NewClientMetrics()
   210  	defer m.Unregister()
   211  	ruler := buildRuler(t, rulerConfig, nil, m, nil)
   212  	require.NoError(t, services.StartAndAwaitRunning(context.Background(), ruler))
   213  
   214  	// Ensure all rules are loaded before usage
   215  	ruler.syncRules(context.Background(), rulerSyncReasonInitial)
   216  
   217  	return ruler
   218  }
   219  
   220  var _ MultiTenantManager = &DefaultMultiTenantManager{}
   221  
   222  func TestNotifierSendsUserIDHeader(t *testing.T) {
   223  	var wg sync.WaitGroup
   224  
   225  	// We do expect 1 API call for the user create with the getOrCreateNotifier()
   226  	wg.Add(1)
   227  	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   228  		userID, _, err := tenant.ExtractTenantIDFromHTTPRequest(r)
   229  		assert.NoError(t, err)
   230  		assert.Equal(t, userID, "1")
   231  		wg.Done()
   232  	}))
   233  	defer ts.Close()
   234  
   235  	// We create an empty rule store so that the ruler will not load any rule from it.
   236  	cfg := defaultRulerConfig(t, newMockRuleStore(nil))
   237  
   238  	cfg.AlertmanagerURL = ts.URL
   239  	cfg.AlertmanagerDiscovery = false
   240  
   241  	manager := newManager(t, cfg, nil)
   242  	defer manager.Stop()
   243  
   244  	n, err := manager.getOrCreateNotifier("1")
   245  	require.NoError(t, err)
   246  
   247  	// Loop until notifier discovery syncs up
   248  	for len(n.Alertmanagers()) == 0 {
   249  		time.Sleep(10 * time.Millisecond)
   250  	}
   251  	n.Send(&notifier.Alert{
   252  		Labels: labels.Labels{labels.Label{Name: "alertname", Value: "testalert"}},
   253  	})
   254  
   255  	wg.Wait()
   256  
   257  	// Ensure we have metrics in the notifier.
   258  	assert.NoError(t, prom_testutil.GatherAndCompare(manager.registry.(*prometheus.Registry), strings.NewReader(`
   259  		# HELP cortex_prometheus_notifications_dropped_total Total number of alerts dropped due to errors when sending to Alertmanager.
   260  		# TYPE cortex_prometheus_notifications_dropped_total counter
   261  		cortex_prometheus_notifications_dropped_total{user="1"} 0
   262  	`), "cortex_prometheus_notifications_dropped_total"))
   263  }
   264  
   265  func TestRuler_Rules(t *testing.T) {
   266  	cfg := defaultRulerConfig(t, newMockRuleStore(mockRules))
   267  
   268  	r := newTestRuler(t, cfg)
   269  	defer services.StopAndAwaitTerminated(context.Background(), r) //nolint:errcheck
   270  
   271  	// test user1
   272  	ctx := user.InjectOrgID(context.Background(), "user1")
   273  	rls, err := r.Rules(ctx, &RulesRequest{})
   274  	require.NoError(t, err)
   275  	require.Len(t, rls.Groups, 1)
   276  	rg := rls.Groups[0]
   277  	expectedRg := mockRules["user1"][0]
   278  	compareRuleGroupDescToStateDesc(t, expectedRg, rg)
   279  
   280  	// test user2
   281  	ctx = user.InjectOrgID(context.Background(), "user2")
   282  	rls, err = r.Rules(ctx, &RulesRequest{})
   283  	require.NoError(t, err)
   284  	require.Len(t, rls.Groups, 1)
   285  	rg = rls.Groups[0]
   286  	expectedRg = mockRules["user2"][0]
   287  	compareRuleGroupDescToStateDesc(t, expectedRg, rg)
   288  }
   289  
   290  func compareRuleGroupDescToStateDesc(t *testing.T, expected *rulespb.RuleGroupDesc, got *GroupStateDesc) {
   291  	require.Equal(t, got.Group.Name, expected.Name)
   292  	require.Equal(t, got.Group.Namespace, expected.Namespace)
   293  	require.Len(t, expected.Rules, len(got.ActiveRules))
   294  	for i := range got.ActiveRules {
   295  		require.Equal(t, expected.Rules[i].Record, got.ActiveRules[i].Rule.Record)
   296  		require.Equal(t, expected.Rules[i].Alert, got.ActiveRules[i].Rule.Alert)
   297  	}
   298  }
   299  
   300  func TestGetRules(t *testing.T) {
   301  	// ruler ID -> (user ID -> list of groups).
   302  	type expectedRulesMap map[string]map[string]rulespb.RuleGroupList
   303  
   304  	type testCase struct {
   305  		sharding         bool
   306  		shardingStrategy string
   307  		shuffleShardSize int
   308  	}
   309  
   310  	expectedRules := expectedRulesMap{
   311  		"ruler1": map[string]rulespb.RuleGroupList{
   312  			"user1": {
   313  				&rulespb.RuleGroupDesc{User: "user1", Namespace: "namespace", Name: "first", Interval: 10 * time.Second},
   314  				&rulespb.RuleGroupDesc{User: "user1", Namespace: "namespace", Name: "second", Interval: 10 * time.Second},
   315  			},
   316  			"user2": {
   317  				&rulespb.RuleGroupDesc{User: "user2", Namespace: "namespace", Name: "third", Interval: 10 * time.Second},
   318  			},
   319  		},
   320  		"ruler2": map[string]rulespb.RuleGroupList{
   321  			"user1": {
   322  				&rulespb.RuleGroupDesc{User: "user1", Namespace: "namespace", Name: "third", Interval: 10 * time.Second},
   323  			},
   324  			"user2": {
   325  				&rulespb.RuleGroupDesc{User: "user2", Namespace: "namespace", Name: "first", Interval: 10 * time.Second},
   326  				&rulespb.RuleGroupDesc{User: "user2", Namespace: "namespace", Name: "second", Interval: 10 * time.Second},
   327  			},
   328  		},
   329  		"ruler3": map[string]rulespb.RuleGroupList{
   330  			"user3": {
   331  				&rulespb.RuleGroupDesc{User: "user3", Namespace: "namespace", Name: "third", Interval: 10 * time.Second},
   332  			},
   333  			"user2": {
   334  				&rulespb.RuleGroupDesc{User: "user2", Namespace: "namespace", Name: "forth", Interval: 10 * time.Second},
   335  				&rulespb.RuleGroupDesc{User: "user2", Namespace: "namespace", Name: "fifty", Interval: 10 * time.Second},
   336  			},
   337  		},
   338  	}
   339  
   340  	testCases := map[string]testCase{
   341  		"No Sharding": {
   342  			sharding: false,
   343  		},
   344  		"Default Sharding": {
   345  			sharding:         true,
   346  			shardingStrategy: util.ShardingStrategyDefault,
   347  		},
   348  		"Shuffle Sharding and ShardSize = 2": {
   349  			sharding:         true,
   350  			shuffleShardSize: 2,
   351  			shardingStrategy: util.ShardingStrategyShuffle,
   352  		},
   353  	}
   354  
   355  	for name, tc := range testCases {
   356  		t.Run(name, func(t *testing.T) {
   357  			kvStore, cleanUp := consul.NewInMemoryClient(ring.GetCodec(), log.NewNopLogger(), nil)
   358  			t.Cleanup(func() { assert.NoError(t, cleanUp.Close()) })
   359  			allRulesByUser := map[string]rulespb.RuleGroupList{}
   360  			allRulesByRuler := map[string]rulespb.RuleGroupList{}
   361  			allTokensByRuler := map[string][]uint32{}
   362  			rulerAddrMap := map[string]*Ruler{}
   363  
   364  			createRuler := func(id string) *Ruler {
   365  				cfg := defaultRulerConfig(t, newMockRuleStore(allRulesByUser))
   366  
   367  				cfg.ShardingStrategy = tc.shardingStrategy
   368  				cfg.EnableSharding = tc.sharding
   369  
   370  				cfg.Ring = RingConfig{
   371  					InstanceID:   id,
   372  					InstanceAddr: id,
   373  					KVStore: kv.Config{
   374  						Mock: kvStore,
   375  					},
   376  				}
   377  				m := loki_storage.NewClientMetrics()
   378  				defer m.Unregister()
   379  				r := buildRuler(t, cfg, nil, m, rulerAddrMap)
   380  				r.limits = ruleLimits{evalDelay: 0, tenantShard: tc.shuffleShardSize}
   381  				rulerAddrMap[id] = r
   382  				if r.ring != nil {
   383  					require.NoError(t, services.StartAndAwaitRunning(context.Background(), r.ring))
   384  					t.Cleanup(r.ring.StopAsync)
   385  				}
   386  				return r
   387  			}
   388  
   389  			for rID, r := range expectedRules {
   390  				createRuler(rID)
   391  				for user, rules := range r {
   392  					allRulesByUser[user] = append(allRulesByUser[user], rules...)
   393  					allRulesByRuler[rID] = append(allRulesByRuler[rID], rules...)
   394  					allTokensByRuler[rID] = generateTokenForGroups(rules, 1)
   395  				}
   396  			}
   397  
   398  			if tc.sharding {
   399  				err := kvStore.CAS(context.Background(), ringKey, func(in interface{}) (out interface{}, retry bool, err error) {
   400  					d, _ := in.(*ring.Desc)
   401  					if d == nil {
   402  						d = ring.NewDesc()
   403  					}
   404  					for rID, tokens := range allTokensByRuler {
   405  						d.AddIngester(rID, rulerAddrMap[rID].lifecycler.GetInstanceAddr(), "", tokens, ring.ACTIVE, time.Now())
   406  					}
   407  					return d, true, nil
   408  				})
   409  				require.NoError(t, err)
   410  				// Wait a bit to make sure ruler's ring is updated.
   411  				time.Sleep(100 * time.Millisecond)
   412  			}
   413  
   414  			forEachRuler := func(f func(rID string, r *Ruler)) {
   415  				for rID, r := range rulerAddrMap {
   416  					f(rID, r)
   417  				}
   418  			}
   419  
   420  			// Sync Rules
   421  			forEachRuler(func(_ string, r *Ruler) {
   422  				r.syncRules(context.Background(), rulerSyncReasonInitial)
   423  			})
   424  
   425  			for u := range allRulesByUser {
   426  				ctx := user.InjectOrgID(context.Background(), u)
   427  				forEachRuler(func(_ string, r *Ruler) {
   428  					rules, err := r.GetRules(ctx)
   429  					require.NoError(t, err)
   430  					require.Equal(t, len(allRulesByUser[u]), len(rules))
   431  					if tc.sharding {
   432  						mockPoolClient := r.clientsPool.(*mockRulerClientsPool)
   433  
   434  						if tc.shardingStrategy == util.ShardingStrategyShuffle {
   435  							require.Equal(t, int32(tc.shuffleShardSize), mockPoolClient.numberOfCalls.Load())
   436  						} else {
   437  							require.Equal(t, int32(len(rulerAddrMap)), mockPoolClient.numberOfCalls.Load())
   438  						}
   439  						mockPoolClient.numberOfCalls.Store(0)
   440  					}
   441  				})
   442  			}
   443  
   444  			totalLoadedRules := 0
   445  			totalConfiguredRules := 0
   446  
   447  			forEachRuler(func(rID string, r *Ruler) {
   448  				localRules, err := r.listRules(context.Background())
   449  				require.NoError(t, err)
   450  				for _, rules := range localRules {
   451  					totalLoadedRules += len(rules)
   452  				}
   453  				totalConfiguredRules += len(allRulesByRuler[rID])
   454  			})
   455  
   456  			if tc.sharding {
   457  				require.Equal(t, totalConfiguredRules, totalLoadedRules)
   458  			} else {
   459  				// Not sharding means that all rules will be loaded on all rulers
   460  				numberOfRulers := len(rulerAddrMap)
   461  				require.Equal(t, totalConfiguredRules*numberOfRulers, totalLoadedRules)
   462  			}
   463  		})
   464  	}
   465  }
   466  
   467  func TestSharding(t *testing.T) {
   468  	const (
   469  		user1 = "user1"
   470  		user2 = "user2"
   471  		user3 = "user3"
   472  	)
   473  
   474  	user1Group1 := &rulespb.RuleGroupDesc{User: user1, Namespace: "namespace", Name: "first"}
   475  	user1Group2 := &rulespb.RuleGroupDesc{User: user1, Namespace: "namespace", Name: "second"}
   476  	user2Group1 := &rulespb.RuleGroupDesc{User: user2, Namespace: "namespace", Name: "first"}
   477  	user3Group1 := &rulespb.RuleGroupDesc{User: user3, Namespace: "namespace", Name: "first"}
   478  
   479  	// Must be distinct for test to work.
   480  	user1Group1Token := tokenForGroup(user1Group1)
   481  	user1Group2Token := tokenForGroup(user1Group2)
   482  	user2Group1Token := tokenForGroup(user2Group1)
   483  	user3Group1Token := tokenForGroup(user3Group1)
   484  
   485  	noRules := map[string]rulespb.RuleGroupList{}
   486  	allRules := map[string]rulespb.RuleGroupList{
   487  		user1: {user1Group1, user1Group2},
   488  		user2: {user2Group1},
   489  		user3: {user3Group1},
   490  	}
   491  
   492  	// ruler ID -> (user ID -> list of groups).
   493  	type expectedRulesMap map[string]map[string]rulespb.RuleGroupList
   494  
   495  	type testCase struct {
   496  		sharding         bool
   497  		shardingStrategy string
   498  		shuffleShardSize int
   499  		setupRing        func(*ring.Desc)
   500  		enabledUsers     []string
   501  		disabledUsers    []string
   502  
   503  		expectedRules expectedRulesMap
   504  	}
   505  
   506  	const (
   507  		ruler1     = "ruler-1"
   508  		ruler1Host = "1.1.1.1"
   509  		ruler1Port = 9999
   510  		ruler1Addr = "1.1.1.1:9999"
   511  
   512  		ruler2     = "ruler-2"
   513  		ruler2Host = "2.2.2.2"
   514  		ruler2Port = 9999
   515  		ruler2Addr = "2.2.2.2:9999"
   516  
   517  		ruler3     = "ruler-3"
   518  		ruler3Host = "3.3.3.3"
   519  		ruler3Port = 9999
   520  		ruler3Addr = "3.3.3.3:9999"
   521  	)
   522  
   523  	testCases := map[string]testCase{
   524  		"no sharding": {
   525  			sharding:      false,
   526  			expectedRules: expectedRulesMap{ruler1: allRules},
   527  		},
   528  
   529  		"no sharding, single user allowed": {
   530  			sharding:     false,
   531  			enabledUsers: []string{user1},
   532  			expectedRules: expectedRulesMap{ruler1: map[string]rulespb.RuleGroupList{
   533  				user1: {user1Group1, user1Group2},
   534  			}},
   535  		},
   536  
   537  		"no sharding, single user disabled": {
   538  			sharding:      false,
   539  			disabledUsers: []string{user1},
   540  			expectedRules: expectedRulesMap{ruler1: map[string]rulespb.RuleGroupList{
   541  				user2: {user2Group1},
   542  				user3: {user3Group1},
   543  			}},
   544  		},
   545  
   546  		"default sharding, single ruler": {
   547  			sharding:         true,
   548  			shardingStrategy: util.ShardingStrategyDefault,
   549  			setupRing: func(desc *ring.Desc) {
   550  				desc.AddIngester(ruler1, ruler1Addr, "", []uint32{0}, ring.ACTIVE, time.Now())
   551  			},
   552  			expectedRules: expectedRulesMap{ruler1: allRules},
   553  		},
   554  
   555  		"default sharding, single ruler, single enabled user": {
   556  			sharding:         true,
   557  			shardingStrategy: util.ShardingStrategyDefault,
   558  			enabledUsers:     []string{user1},
   559  			setupRing: func(desc *ring.Desc) {
   560  				desc.AddIngester(ruler1, ruler1Addr, "", []uint32{0}, ring.ACTIVE, time.Now())
   561  			},
   562  			expectedRules: expectedRulesMap{ruler1: map[string]rulespb.RuleGroupList{
   563  				user1: {user1Group1, user1Group2},
   564  			}},
   565  		},
   566  
   567  		"default sharding, single ruler, single disabled user": {
   568  			sharding:         true,
   569  			shardingStrategy: util.ShardingStrategyDefault,
   570  			disabledUsers:    []string{user1},
   571  			setupRing: func(desc *ring.Desc) {
   572  				desc.AddIngester(ruler1, ruler1Addr, "", []uint32{0}, ring.ACTIVE, time.Now())
   573  			},
   574  			expectedRules: expectedRulesMap{ruler1: map[string]rulespb.RuleGroupList{
   575  				user2: {user2Group1},
   576  				user3: {user3Group1},
   577  			}},
   578  		},
   579  
   580  		"default sharding, multiple ACTIVE rulers": {
   581  			sharding:         true,
   582  			shardingStrategy: util.ShardingStrategyDefault,
   583  			setupRing: func(desc *ring.Desc) {
   584  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{user1Group1Token + 1, user2Group1Token + 1}), ring.ACTIVE, time.Now())
   585  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{user1Group2Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   586  			},
   587  
   588  			expectedRules: expectedRulesMap{
   589  				ruler1: map[string]rulespb.RuleGroupList{
   590  					user1: {user1Group1},
   591  					user2: {user2Group1},
   592  				},
   593  
   594  				ruler2: map[string]rulespb.RuleGroupList{
   595  					user1: {user1Group2},
   596  					user3: {user3Group1},
   597  				},
   598  			},
   599  		},
   600  
   601  		"default sharding, multiple ACTIVE rulers, single enabled user": {
   602  			sharding:         true,
   603  			shardingStrategy: util.ShardingStrategyDefault,
   604  			enabledUsers:     []string{user1},
   605  			setupRing: func(desc *ring.Desc) {
   606  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{user1Group1Token + 1, user2Group1Token + 1}), ring.ACTIVE, time.Now())
   607  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{user1Group2Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   608  			},
   609  
   610  			expectedRules: expectedRulesMap{
   611  				ruler1: map[string]rulespb.RuleGroupList{
   612  					user1: {user1Group1},
   613  				},
   614  
   615  				ruler2: map[string]rulespb.RuleGroupList{
   616  					user1: {user1Group2},
   617  				},
   618  			},
   619  		},
   620  
   621  		"default sharding, multiple ACTIVE rulers, single disabled user": {
   622  			sharding:         true,
   623  			shardingStrategy: util.ShardingStrategyDefault,
   624  			disabledUsers:    []string{user1},
   625  			setupRing: func(desc *ring.Desc) {
   626  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{user1Group1Token + 1, user2Group1Token + 1}), ring.ACTIVE, time.Now())
   627  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{user1Group2Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   628  			},
   629  
   630  			expectedRules: expectedRulesMap{
   631  				ruler1: map[string]rulespb.RuleGroupList{
   632  					user2: {user2Group1},
   633  				},
   634  
   635  				ruler2: map[string]rulespb.RuleGroupList{
   636  					user3: {user3Group1},
   637  				},
   638  			},
   639  		},
   640  
   641  		"default sharding, unhealthy ACTIVE ruler": {
   642  			sharding:         true,
   643  			shardingStrategy: util.ShardingStrategyDefault,
   644  
   645  			setupRing: func(desc *ring.Desc) {
   646  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{user1Group1Token + 1, user2Group1Token + 1}), ring.ACTIVE, time.Now())
   647  				desc.Ingesters[ruler2] = ring.InstanceDesc{
   648  					Addr:      ruler2Addr,
   649  					Timestamp: time.Now().Add(-time.Hour).Unix(),
   650  					State:     ring.ACTIVE,
   651  					Tokens:    sortTokens([]uint32{user1Group2Token + 1, user3Group1Token + 1}),
   652  				}
   653  			},
   654  
   655  			expectedRules: expectedRulesMap{
   656  				// This ruler doesn't get rules from unhealthy ruler (RF=1).
   657  				ruler1: map[string]rulespb.RuleGroupList{
   658  					user1: {user1Group1},
   659  					user2: {user2Group1},
   660  				},
   661  				ruler2: noRules,
   662  			},
   663  		},
   664  
   665  		"default sharding, LEAVING ruler": {
   666  			sharding:         true,
   667  			shardingStrategy: util.ShardingStrategyDefault,
   668  
   669  			setupRing: func(desc *ring.Desc) {
   670  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{user1Group1Token + 1, user2Group1Token + 1}), ring.LEAVING, time.Now())
   671  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{user1Group2Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   672  			},
   673  
   674  			expectedRules: expectedRulesMap{
   675  				// LEAVING ruler doesn't get any rules.
   676  				ruler1: noRules,
   677  				ruler2: allRules,
   678  			},
   679  		},
   680  
   681  		"default sharding, JOINING ruler": {
   682  			sharding:         true,
   683  			shardingStrategy: util.ShardingStrategyDefault,
   684  
   685  			setupRing: func(desc *ring.Desc) {
   686  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{user1Group1Token + 1, user2Group1Token + 1}), ring.JOINING, time.Now())
   687  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{user1Group2Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   688  			},
   689  
   690  			expectedRules: expectedRulesMap{
   691  				// JOINING ruler has no rules yet.
   692  				ruler1: noRules,
   693  				ruler2: allRules,
   694  			},
   695  		},
   696  
   697  		"shuffle sharding, single ruler": {
   698  			sharding:         true,
   699  			shardingStrategy: util.ShardingStrategyShuffle,
   700  
   701  			setupRing: func(desc *ring.Desc) {
   702  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{0}), ring.ACTIVE, time.Now())
   703  			},
   704  
   705  			expectedRules: expectedRulesMap{
   706  				ruler1: allRules,
   707  			},
   708  		},
   709  
   710  		"shuffle sharding, multiple rulers, shard size 1": {
   711  			sharding:         true,
   712  			shardingStrategy: util.ShardingStrategyShuffle,
   713  			shuffleShardSize: 1,
   714  
   715  			setupRing: func(desc *ring.Desc) {
   716  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{userToken(user1, 0) + 1, userToken(user2, 0) + 1, userToken(user3, 0) + 1}), ring.ACTIVE, time.Now())
   717  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{user1Group1Token + 1, user1Group2Token + 1, user2Group1Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   718  			},
   719  
   720  			expectedRules: expectedRulesMap{
   721  				ruler1: allRules,
   722  				ruler2: noRules,
   723  			},
   724  		},
   725  
   726  		// Same test as previous one, but with shard size=2. Second ruler gets all the rules.
   727  		"shuffle sharding, two rulers, shard size 2": {
   728  			sharding:         true,
   729  			shardingStrategy: util.ShardingStrategyShuffle,
   730  			shuffleShardSize: 2,
   731  
   732  			setupRing: func(desc *ring.Desc) {
   733  				// Exact same tokens setup as previous test.
   734  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{userToken(user1, 0) + 1, userToken(user2, 0) + 1, userToken(user3, 0) + 1}), ring.ACTIVE, time.Now())
   735  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{user1Group1Token + 1, user1Group2Token + 1, user2Group1Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   736  			},
   737  
   738  			expectedRules: expectedRulesMap{
   739  				ruler1: noRules,
   740  				ruler2: allRules,
   741  			},
   742  		},
   743  
   744  		"shuffle sharding, two rulers, shard size 1, distributed users": {
   745  			sharding:         true,
   746  			shardingStrategy: util.ShardingStrategyShuffle,
   747  			shuffleShardSize: 1,
   748  
   749  			setupRing: func(desc *ring.Desc) {
   750  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{userToken(user1, 0) + 1}), ring.ACTIVE, time.Now())
   751  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{userToken(user2, 0) + 1, userToken(user3, 0) + 1}), ring.ACTIVE, time.Now())
   752  			},
   753  
   754  			expectedRules: expectedRulesMap{
   755  				ruler1: map[string]rulespb.RuleGroupList{
   756  					user1: {user1Group1, user1Group2},
   757  				},
   758  				ruler2: map[string]rulespb.RuleGroupList{
   759  					user2: {user2Group1},
   760  					user3: {user3Group1},
   761  				},
   762  			},
   763  		},
   764  		"shuffle sharding, three rulers, shard size 2": {
   765  			sharding:         true,
   766  			shardingStrategy: util.ShardingStrategyShuffle,
   767  			shuffleShardSize: 2,
   768  
   769  			setupRing: func(desc *ring.Desc) {
   770  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{userToken(user1, 0) + 1, user1Group1Token + 1}), ring.ACTIVE, time.Now())
   771  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{userToken(user1, 1) + 1, user1Group2Token + 1, userToken(user2, 1) + 1, userToken(user3, 1) + 1}), ring.ACTIVE, time.Now())
   772  				desc.AddIngester(ruler3, ruler3Addr, "", sortTokens([]uint32{userToken(user2, 0) + 1, userToken(user3, 0) + 1, user2Group1Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   773  			},
   774  
   775  			expectedRules: expectedRulesMap{
   776  				ruler1: map[string]rulespb.RuleGroupList{
   777  					user1: {user1Group1},
   778  				},
   779  				ruler2: map[string]rulespb.RuleGroupList{
   780  					user1: {user1Group2},
   781  				},
   782  				ruler3: map[string]rulespb.RuleGroupList{
   783  					user2: {user2Group1},
   784  					user3: {user3Group1},
   785  				},
   786  			},
   787  		},
   788  		"shuffle sharding, three rulers, shard size 2, ruler2 has no users": {
   789  			sharding:         true,
   790  			shardingStrategy: util.ShardingStrategyShuffle,
   791  			shuffleShardSize: 2,
   792  
   793  			setupRing: func(desc *ring.Desc) {
   794  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{userToken(user1, 0) + 1, userToken(user2, 1) + 1, user1Group1Token + 1, user1Group2Token + 1}), ring.ACTIVE, time.Now())
   795  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{userToken(user1, 1) + 1, userToken(user3, 1) + 1, user2Group1Token + 1}), ring.ACTIVE, time.Now())
   796  				desc.AddIngester(ruler3, ruler3Addr, "", sortTokens([]uint32{userToken(user2, 0) + 1, userToken(user3, 0) + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   797  			},
   798  
   799  			expectedRules: expectedRulesMap{
   800  				ruler1: map[string]rulespb.RuleGroupList{
   801  					user1: {user1Group1, user1Group2},
   802  				},
   803  				ruler2: noRules, // Ruler2 owns token for user2group1, but user-2 will only be handled by ruler-1 and 3.
   804  				ruler3: map[string]rulespb.RuleGroupList{
   805  					user2: {user2Group1},
   806  					user3: {user3Group1},
   807  				},
   808  			},
   809  		},
   810  
   811  		"shuffle sharding, three rulers, shard size 2, single enabled user": {
   812  			sharding:         true,
   813  			shardingStrategy: util.ShardingStrategyShuffle,
   814  			shuffleShardSize: 2,
   815  			enabledUsers:     []string{user1},
   816  
   817  			setupRing: func(desc *ring.Desc) {
   818  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{userToken(user1, 0) + 1, user1Group1Token + 1}), ring.ACTIVE, time.Now())
   819  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{userToken(user1, 1) + 1, user1Group2Token + 1, userToken(user2, 1) + 1, userToken(user3, 1) + 1}), ring.ACTIVE, time.Now())
   820  				desc.AddIngester(ruler3, ruler3Addr, "", sortTokens([]uint32{userToken(user2, 0) + 1, userToken(user3, 0) + 1, user2Group1Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   821  			},
   822  
   823  			expectedRules: expectedRulesMap{
   824  				ruler1: map[string]rulespb.RuleGroupList{
   825  					user1: {user1Group1},
   826  				},
   827  				ruler2: map[string]rulespb.RuleGroupList{
   828  					user1: {user1Group2},
   829  				},
   830  				ruler3: map[string]rulespb.RuleGroupList{},
   831  			},
   832  		},
   833  
   834  		"shuffle sharding, three rulers, shard size 2, single disabled user": {
   835  			sharding:         true,
   836  			shardingStrategy: util.ShardingStrategyShuffle,
   837  			shuffleShardSize: 2,
   838  			disabledUsers:    []string{user1},
   839  
   840  			setupRing: func(desc *ring.Desc) {
   841  				desc.AddIngester(ruler1, ruler1Addr, "", sortTokens([]uint32{userToken(user1, 0) + 1, user1Group1Token + 1}), ring.ACTIVE, time.Now())
   842  				desc.AddIngester(ruler2, ruler2Addr, "", sortTokens([]uint32{userToken(user1, 1) + 1, user1Group2Token + 1, userToken(user2, 1) + 1, userToken(user3, 1) + 1}), ring.ACTIVE, time.Now())
   843  				desc.AddIngester(ruler3, ruler3Addr, "", sortTokens([]uint32{userToken(user2, 0) + 1, userToken(user3, 0) + 1, user2Group1Token + 1, user3Group1Token + 1}), ring.ACTIVE, time.Now())
   844  			},
   845  
   846  			expectedRules: expectedRulesMap{
   847  				ruler1: map[string]rulespb.RuleGroupList{},
   848  				ruler2: map[string]rulespb.RuleGroupList{},
   849  				ruler3: map[string]rulespb.RuleGroupList{
   850  					user2: {user2Group1},
   851  					user3: {user3Group1},
   852  				},
   853  			},
   854  		},
   855  	}
   856  
   857  	for name, tc := range testCases {
   858  		t.Run(name, func(t *testing.T) {
   859  			kvStore, closer := consul.NewInMemoryClient(ring.GetCodec(), log.NewNopLogger(), nil)
   860  			t.Cleanup(func() { assert.NoError(t, closer.Close()) })
   861  
   862  			setupRuler := func(id string, host string, port int, forceRing *ring.Ring) *Ruler {
   863  				cfg := Config{
   864  					StoreConfig:      RuleStoreConfig{mock: newMockRuleStore(allRules)},
   865  					EnableSharding:   tc.sharding,
   866  					ShardingStrategy: tc.shardingStrategy,
   867  					Ring: RingConfig{
   868  						InstanceID:   id,
   869  						InstanceAddr: host,
   870  						InstancePort: port,
   871  						KVStore: kv.Config{
   872  							Mock: kvStore,
   873  						},
   874  						HeartbeatTimeout: 1 * time.Minute,
   875  					},
   876  					FlushCheckPeriod: 0,
   877  					EnabledTenants:   tc.enabledUsers,
   878  					DisabledTenants:  tc.disabledUsers,
   879  				}
   880  
   881  				m := loki_storage.NewClientMetrics()
   882  				defer m.Unregister()
   883  				r := buildRuler(t, cfg, nil, m, nil)
   884  				r.limits = ruleLimits{evalDelay: 0, tenantShard: tc.shuffleShardSize}
   885  
   886  				if forceRing != nil {
   887  					r.ring = forceRing
   888  				}
   889  				return r
   890  			}
   891  
   892  			r1 := setupRuler(ruler1, ruler1Host, ruler1Port, nil)
   893  
   894  			rulerRing := r1.ring
   895  
   896  			// We start ruler's ring, but nothing else (not even lifecycler).
   897  			if rulerRing != nil {
   898  				require.NoError(t, services.StartAndAwaitRunning(context.Background(), rulerRing))
   899  				t.Cleanup(rulerRing.StopAsync)
   900  			}
   901  
   902  			var r2, r3 *Ruler
   903  			if rulerRing != nil {
   904  				// Reuse ring from r1.
   905  				r2 = setupRuler(ruler2, ruler2Host, ruler2Port, rulerRing)
   906  				r3 = setupRuler(ruler3, ruler3Host, ruler3Port, rulerRing)
   907  			}
   908  
   909  			if tc.setupRing != nil {
   910  				err := kvStore.CAS(context.Background(), ringKey, func(in interface{}) (out interface{}, retry bool, err error) {
   911  					d, _ := in.(*ring.Desc)
   912  					if d == nil {
   913  						d = ring.NewDesc()
   914  					}
   915  
   916  					tc.setupRing(d)
   917  
   918  					return d, true, nil
   919  				})
   920  				require.NoError(t, err)
   921  				// Wait a bit to make sure ruler's ring is updated.
   922  				time.Sleep(100 * time.Millisecond)
   923  			}
   924  
   925  			// Always add ruler1 to expected rulers, even if there is no ring (no sharding).
   926  			loadedRules1, err := r1.listRules(context.Background())
   927  			require.NoError(t, err)
   928  
   929  			expected := expectedRulesMap{
   930  				ruler1: loadedRules1,
   931  			}
   932  
   933  			addToExpected := func(id string, r *Ruler) {
   934  				// Only expect rules from other rulers when using ring, and they are present in the ring.
   935  				if r != nil && rulerRing != nil && rulerRing.HasInstance(id) {
   936  					loaded, err := r.listRules(context.Background())
   937  					require.NoError(t, err)
   938  					// Normalize nil map to empty one.
   939  					if loaded == nil {
   940  						loaded = map[string]rulespb.RuleGroupList{}
   941  					}
   942  					expected[id] = loaded
   943  				}
   944  			}
   945  
   946  			addToExpected(ruler2, r2)
   947  			addToExpected(ruler3, r3)
   948  
   949  			require.Equal(t, tc.expectedRules, expected)
   950  		})
   951  	}
   952  }
   953  
   954  // User shuffle shard token.
   955  func userToken(user string, skip int) uint32 {
   956  	r := rand.New(rand.NewSource(util.ShuffleShardSeed(user, "")))
   957  
   958  	for ; skip > 0; skip-- {
   959  		_ = r.Uint32()
   960  	}
   961  	return r.Uint32()
   962  }
   963  
   964  func sortTokens(tokens []uint32) []uint32 {
   965  	sort.Slice(tokens, func(i, j int) bool {
   966  		return tokens[i] < tokens[j]
   967  	})
   968  	return tokens
   969  }
   970  
   971  func TestDeleteTenantRuleGroups(t *testing.T) {
   972  	ruleGroups := []ruleGroupKey{
   973  		{user: "userA", namespace: "namespace", group: "group"},
   974  		{user: "userB", namespace: "namespace1", group: "group"},
   975  		{user: "userB", namespace: "namespace2", group: "group"},
   976  	}
   977  
   978  	obj, rs := setupRuleGroupsStore(t, ruleGroups)
   979  	require.Equal(t, 3, obj.GetObjectCount())
   980  
   981  	api, err := NewRuler(Config{}, nil, nil, log.NewNopLogger(), rs, nil)
   982  	require.NoError(t, err)
   983  
   984  	{
   985  		req := &http.Request{}
   986  		resp := httptest.NewRecorder()
   987  		api.DeleteTenantConfiguration(resp, req)
   988  
   989  		require.Equal(t, http.StatusUnauthorized, resp.Code)
   990  	}
   991  
   992  	{
   993  		callDeleteTenantAPI(t, api, "user-with-no-rule-groups")
   994  		require.Equal(t, 3, obj.GetObjectCount())
   995  
   996  		verifyExpectedDeletedRuleGroupsForUser(t, api, "user-with-no-rule-groups", true) // Has no rule groups
   997  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userA", false)
   998  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userB", false)
   999  	}
  1000  
  1001  	{
  1002  		callDeleteTenantAPI(t, api, "userA")
  1003  		require.Equal(t, 2, obj.GetObjectCount())
  1004  
  1005  		verifyExpectedDeletedRuleGroupsForUser(t, api, "user-with-no-rule-groups", true) // Has no rule groups
  1006  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userA", true)                    // Just deleted.
  1007  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userB", false)
  1008  	}
  1009  
  1010  	// Deleting same user again works fine and reports no problems.
  1011  	{
  1012  		callDeleteTenantAPI(t, api, "userA")
  1013  		require.Equal(t, 2, obj.GetObjectCount())
  1014  
  1015  		verifyExpectedDeletedRuleGroupsForUser(t, api, "user-with-no-rule-groups", true) // Has no rule groups
  1016  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userA", true)                    // Already deleted before.
  1017  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userB", false)
  1018  	}
  1019  
  1020  	{
  1021  		callDeleteTenantAPI(t, api, "userB")
  1022  		require.Equal(t, 0, obj.GetObjectCount())
  1023  
  1024  		verifyExpectedDeletedRuleGroupsForUser(t, api, "user-with-no-rule-groups", true) // Has no rule groups
  1025  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userA", true)                    // Deleted previously
  1026  		verifyExpectedDeletedRuleGroupsForUser(t, api, "userB", true)                    // Just deleted
  1027  	}
  1028  }
  1029  
  1030  func generateTokenForGroups(groups []*rulespb.RuleGroupDesc, offset uint32) []uint32 {
  1031  	var tokens []uint32
  1032  
  1033  	for _, g := range groups {
  1034  		tokens = append(tokens, tokenForGroup(g)+offset)
  1035  	}
  1036  
  1037  	return tokens
  1038  }
  1039  
  1040  func callDeleteTenantAPI(t *testing.T, api *Ruler, userID string) {
  1041  	ctx := user.InjectOrgID(context.Background(), userID)
  1042  
  1043  	req := &http.Request{}
  1044  	resp := httptest.NewRecorder()
  1045  	api.DeleteTenantConfiguration(resp, req.WithContext(ctx))
  1046  
  1047  	require.Equal(t, http.StatusOK, resp.Code)
  1048  }
  1049  
  1050  func verifyExpectedDeletedRuleGroupsForUser(t *testing.T, r *Ruler, userID string, expectedDeleted bool) {
  1051  	list, err := r.store.ListRuleGroupsForUserAndNamespace(context.Background(), userID, "")
  1052  	require.NoError(t, err)
  1053  
  1054  	if expectedDeleted {
  1055  		require.Equal(t, 0, len(list))
  1056  	} else {
  1057  		require.NotEqual(t, 0, len(list))
  1058  	}
  1059  }
  1060  
  1061  func setupRuleGroupsStore(t *testing.T, ruleGroups []ruleGroupKey) (*testutils.MockStorage, rulestore.RuleStore) {
  1062  	obj := testutils.NewMockStorage()
  1063  	rs := objectclient.NewRuleStore(obj, 5, log.NewNopLogger())
  1064  	testutils.ResetMockStorage()
  1065  	// "upload" rule groups
  1066  	for _, key := range ruleGroups {
  1067  		desc := rulespb.ToProto(key.user, key.namespace, rulefmt.RuleGroup{Name: key.group})
  1068  		require.NoError(t, rs.SetRuleGroup(context.Background(), key.user, key.namespace, desc))
  1069  	}
  1070  
  1071  	return obj, rs
  1072  }
  1073  
  1074  type ruleGroupKey struct {
  1075  	user, namespace, group string
  1076  }
  1077  
  1078  func TestRuler_ListAllRules(t *testing.T) {
  1079  	cfg := defaultRulerConfig(t, newMockRuleStore(mockRules))
  1080  
  1081  	r := newTestRuler(t, cfg)
  1082  	defer services.StopAndAwaitTerminated(context.Background(), r) //nolint:errcheck
  1083  
  1084  	router := mux.NewRouter()
  1085  	router.Path("/ruler/rule_groups").Methods(http.MethodGet).HandlerFunc(r.ListAllRules)
  1086  
  1087  	req := requestFor(t, http.MethodGet, "https://localhost:8080/ruler/rule_groups", nil, "")
  1088  	w := httptest.NewRecorder()
  1089  	router.ServeHTTP(w, req)
  1090  
  1091  	resp := w.Result()
  1092  	body, _ := ioutil.ReadAll(resp.Body)
  1093  
  1094  	// Check status code and header
  1095  	require.Equal(t, http.StatusOK, resp.StatusCode)
  1096  	require.Equal(t, "application/yaml", resp.Header.Get("Content-Type"))
  1097  
  1098  	gs := make(map[string]map[string][]rulefmt.RuleGroup) // user:namespace:[]rulefmt.RuleGroup
  1099  	for userID := range mockRules {
  1100  		gs[userID] = mockRules[userID].Formatted()
  1101  	}
  1102  	expectedResponse, err := yaml.Marshal(gs)
  1103  	require.NoError(t, err)
  1104  	require.YAMLEq(t, string(expectedResponse), string(body))
  1105  }
  1106  
  1107  type senderFunc func(alerts ...*notifier.Alert)
  1108  
  1109  func (s senderFunc) Send(alerts ...*notifier.Alert) {
  1110  	s(alerts...)
  1111  }
  1112  
  1113  func TestSendAlerts(t *testing.T) {
  1114  	testCases := []struct {
  1115  		in  []*promRules.Alert
  1116  		exp []*notifier.Alert
  1117  	}{
  1118  		{
  1119  			in: []*promRules.Alert{
  1120  				{
  1121  					Labels:      []labels.Label{{Name: "l1", Value: "v1"}},
  1122  					Annotations: []labels.Label{{Name: "a2", Value: "v2"}},
  1123  					ActiveAt:    time.Unix(1, 0),
  1124  					FiredAt:     time.Unix(2, 0),
  1125  					ValidUntil:  time.Unix(3, 0),
  1126  				},
  1127  			},
  1128  			exp: []*notifier.Alert{
  1129  				{
  1130  					Labels:       []labels.Label{{Name: "l1", Value: "v1"}},
  1131  					Annotations:  []labels.Label{{Name: "a2", Value: "v2"}},
  1132  					StartsAt:     time.Unix(2, 0),
  1133  					EndsAt:       time.Unix(3, 0),
  1134  					GeneratorURL: "http://localhost:9090/graph?g0.expr=up&g0.tab=1",
  1135  				},
  1136  			},
  1137  		},
  1138  		{
  1139  			in: []*promRules.Alert{
  1140  				{
  1141  					Labels:      []labels.Label{{Name: "l1", Value: "v1"}},
  1142  					Annotations: []labels.Label{{Name: "a2", Value: "v2"}},
  1143  					ActiveAt:    time.Unix(1, 0),
  1144  					FiredAt:     time.Unix(2, 0),
  1145  					ResolvedAt:  time.Unix(4, 0),
  1146  				},
  1147  			},
  1148  			exp: []*notifier.Alert{
  1149  				{
  1150  					Labels:       []labels.Label{{Name: "l1", Value: "v1"}},
  1151  					Annotations:  []labels.Label{{Name: "a2", Value: "v2"}},
  1152  					StartsAt:     time.Unix(2, 0),
  1153  					EndsAt:       time.Unix(4, 0),
  1154  					GeneratorURL: "http://localhost:9090/graph?g0.expr=up&g0.tab=1",
  1155  				},
  1156  			},
  1157  		},
  1158  		{
  1159  			in: []*promRules.Alert{},
  1160  		},
  1161  	}
  1162  
  1163  	for i, tc := range testCases {
  1164  		tc := tc
  1165  		t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
  1166  			senderFunc := senderFunc(func(alerts ...*notifier.Alert) {
  1167  				if len(tc.in) == 0 {
  1168  					t.Fatalf("sender called with 0 alert")
  1169  				}
  1170  				require.Equal(t, tc.exp, alerts)
  1171  			})
  1172  			SendAlerts(senderFunc, "http://localhost:9090")(context.TODO(), "up", tc.in...)
  1173  		})
  1174  	}
  1175  }
  1176  
  1177  type fakeQuerier struct {
  1178  	fn func(sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet
  1179  }
  1180  
  1181  func (f *fakeQuerier) Select(sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet {
  1182  	return f.fn(sortSeries, hints, matchers...)
  1183  }
  1184  
  1185  func (f *fakeQuerier) LabelValues(name string, matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
  1186  	return nil, nil, nil
  1187  }
  1188  
  1189  func (f *fakeQuerier) LabelNames(matchers ...*labels.Matcher) ([]string, storage.Warnings, error) {
  1190  	return nil, nil, nil
  1191  }
  1192  func (f *fakeQuerier) Close() error { return nil }
  1193  
  1194  // Tests for whether the Ruler is able to recover ALERTS_FOR_STATE state
  1195  func TestRecoverAlertsPostOutage(t *testing.T) {
  1196  	// Test Setup
  1197  	// alert FOR 30m, already ran for 10m, outage down at 15m prior to now(), outage tolerance set to 1hr
  1198  	// EXPECTATION: for state for alert restores to 10m+(now-15m)
  1199  
  1200  	// FIRST set up 1 Alert rule with 30m FOR duration
  1201  	alertForDuration, _ := time.ParseDuration("30m")
  1202  	mockRules := map[string]rulespb.RuleGroupList{
  1203  		"user1": {
  1204  			&rulespb.RuleGroupDesc{
  1205  				Name:      "group1",
  1206  				Namespace: "namespace1",
  1207  				User:      "user1",
  1208  				Rules: []*rulespb.RuleDesc{
  1209  					{
  1210  						Alert: "UP_ALERT",
  1211  						Expr:  "1", // always fire for this test
  1212  						For:   alertForDuration,
  1213  					},
  1214  				},
  1215  				Interval: interval,
  1216  			},
  1217  		},
  1218  	}
  1219  
  1220  	// NEXT, set up ruler config with outage tolerance = 1hr
  1221  	rulerCfg := defaultRulerConfig(t, newMockRuleStore(mockRules))
  1222  	rulerCfg.OutageTolerance, _ = time.ParseDuration("1h")
  1223  
  1224  	// NEXT, set up mock distributor containing sample,
  1225  	// metric: ALERTS_FOR_STATE{alertname="UP_ALERT"}, ts: time.now()-15m, value: time.now()-25m
  1226  	currentTime := time.Now().UTC()
  1227  	downAtTime := currentTime.Add(time.Minute * -15)
  1228  	downAtTimeMs := downAtTime.UnixNano() / int64(time.Millisecond)
  1229  	downAtActiveAtTime := currentTime.Add(time.Minute * -25)
  1230  	downAtActiveSec := downAtActiveAtTime.Unix()
  1231  
  1232  	m := loki_storage.NewClientMetrics()
  1233  	defer m.Unregister()
  1234  	// create a ruler but don't start it. instead, we'll evaluate the rule groups manually.
  1235  	r := buildRuler(t, rulerCfg, &fakeQuerier{
  1236  		fn: func(sortSeries bool, hints *storage.SelectHints, matchers ...*labels.Matcher) storage.SeriesSet {
  1237  			return series.NewConcreteSeriesSet([]storage.Series{
  1238  				series.NewConcreteSeries(
  1239  					labels.Labels{
  1240  						{Name: labels.MetricName, Value: "ALERTS_FOR_STATE"},
  1241  						{Name: labels.AlertName, Value: mockRules["user1"][0].GetRules()[0].Alert},
  1242  					},
  1243  					[]model.SamplePair{{Timestamp: model.Time(downAtTimeMs), Value: model.SampleValue(downAtActiveSec)}},
  1244  				),
  1245  			})
  1246  		},
  1247  	}, m, nil)
  1248  	r.syncRules(context.Background(), rulerSyncReasonInitial)
  1249  
  1250  	// assert initial state of rule group
  1251  	ruleGroup := r.manager.GetRules("user1")[0]
  1252  	require.Equal(t, time.Time{}, ruleGroup.GetLastEvaluation())
  1253  	require.Equal(t, "group1", ruleGroup.Name())
  1254  	require.Equal(t, 1, len(ruleGroup.Rules()))
  1255  
  1256  	// assert initial state of rule within rule group
  1257  	alertRule := ruleGroup.Rules()[0]
  1258  	require.Equal(t, time.Time{}, alertRule.GetEvaluationTimestamp())
  1259  	require.Equal(t, "UP_ALERT", alertRule.Name())
  1260  	require.Equal(t, promRules.HealthUnknown, alertRule.Health())
  1261  
  1262  	// NEXT, evaluate the rule group the first time and assert
  1263  	ctx := user.InjectOrgID(context.Background(), "user1")
  1264  	ruleGroup.Eval(ctx, currentTime)
  1265  
  1266  	// since the eval is done at the current timestamp, the activeAt timestamp of alert should equal current timestamp
  1267  	require.Equal(t, "UP_ALERT", alertRule.Name())
  1268  	require.Equal(t, promRules.HealthGood, alertRule.Health())
  1269  
  1270  	activeMapRaw := reflect.ValueOf(alertRule).Elem().FieldByName("active")
  1271  	activeMapKeys := activeMapRaw.MapKeys()
  1272  	require.True(t, len(activeMapKeys) == 1)
  1273  
  1274  	activeAlertRuleRaw := activeMapRaw.MapIndex(activeMapKeys[0]).Elem()
  1275  	activeAtTimeRaw := activeAlertRuleRaw.FieldByName("ActiveAt")
  1276  
  1277  	require.Equal(t, promRules.StatePending, promRules.AlertState(activeAlertRuleRaw.FieldByName("State").Int()))
  1278  	require.Equal(t, reflect.NewAt(activeAtTimeRaw.Type(), unsafe.Pointer(activeAtTimeRaw.UnsafeAddr())).Elem().Interface().(time.Time), currentTime)
  1279  
  1280  	// NEXT, restore the FOR state and assert
  1281  	ruleGroup.RestoreForState(currentTime)
  1282  
  1283  	require.Equal(t, "UP_ALERT", alertRule.Name())
  1284  	require.Equal(t, promRules.HealthGood, alertRule.Health())
  1285  	require.Equal(t, promRules.StatePending, promRules.AlertState(activeAlertRuleRaw.FieldByName("State").Int()))
  1286  	require.Equal(t, reflect.NewAt(activeAtTimeRaw.Type(), unsafe.Pointer(activeAtTimeRaw.UnsafeAddr())).Elem().Interface().(time.Time), downAtActiveAtTime.Add(currentTime.Sub(downAtTime)))
  1287  
  1288  	// NEXT, 20 minutes is expected to be left, eval timestamp at currentTimestamp +20m
  1289  	currentTime = currentTime.Add(time.Minute * 20)
  1290  	ruleGroup.Eval(ctx, currentTime)
  1291  
  1292  	// assert alert state after alert is firing
  1293  	firedAtRaw := activeAlertRuleRaw.FieldByName("FiredAt")
  1294  	firedAtTime := reflect.NewAt(firedAtRaw.Type(), unsafe.Pointer(firedAtRaw.UnsafeAddr())).Elem().Interface().(time.Time)
  1295  	require.Equal(t, firedAtTime, currentTime)
  1296  
  1297  	require.Equal(t, promRules.StateFiring, promRules.AlertState(activeAlertRuleRaw.FieldByName("State").Int()))
  1298  }