github.com/yankunsam/loki/v2@v2.6.3-0.20220817130409-389df5235c27/pkg/ruler/storage/instance/manager_test.go (about)

     1  // This directory was copied and adapted from https://github.com/grafana/agent/tree/main/pkg/metrics.
     2  // We cannot vendor the agent in since the agent vendors loki in, which would cause a cyclic dependency.
     3  // NOTE: many changes have been made to the original code for our use-case.
     4  package instance
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  	"os"
    10  	"testing"
    11  
    12  	"github.com/go-kit/log"
    13  	"github.com/prometheus/prometheus/scrape"
    14  	"github.com/prometheus/prometheus/storage"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestBasicManager_ApplyConfig(t *testing.T) {
    19  	logger := log.NewLogfmtLogger(log.NewSyncWriter(os.Stderr))
    20  
    21  	baseMock := mockInstance{
    22  		RunFunc: func(ctx context.Context) error {
    23  			logger.Log("msg", "starting an instance")
    24  			<-ctx.Done()
    25  			return nil
    26  		},
    27  		UpdateFunc: func(c Config) error {
    28  			return nil
    29  		},
    30  		TargetsActiveFunc: func() map[string][]*scrape.Target {
    31  			return nil
    32  		},
    33  	}
    34  
    35  	t.Run("dynamic update successful", func(t *testing.T) {
    36  		spawnedCount := 0
    37  		spawner := func(c Config) (ManagedInstance, error) {
    38  			spawnedCount++
    39  
    40  			newMock := baseMock
    41  			return &newMock, nil
    42  		}
    43  
    44  		cm := NewBasicManager(DefaultBasicManagerConfig, NewMetrics(nil), logger, spawner)
    45  
    46  		for i := 0; i < 10; i++ {
    47  			err := cm.ApplyConfig(Config{Name: "test"})
    48  			require.NoError(t, err)
    49  		}
    50  
    51  		require.Equal(t, 1, spawnedCount)
    52  	})
    53  
    54  	t.Run("dynamic update unsuccessful", func(t *testing.T) {
    55  		spawnedCount := 0
    56  		spawner := func(c Config) (ManagedInstance, error) {
    57  			spawnedCount++
    58  
    59  			newMock := baseMock
    60  			newMock.UpdateFunc = func(c Config) error {
    61  				return ErrInvalidUpdate{
    62  					Inner: fmt.Errorf("cannot dynamically update for testing reasons"),
    63  				}
    64  			}
    65  			return &newMock, nil
    66  		}
    67  
    68  		cm := NewBasicManager(DefaultBasicManagerConfig, NewMetrics(nil), logger, spawner)
    69  
    70  		for i := 0; i < 10; i++ {
    71  			err := cm.ApplyConfig(Config{Name: "test"})
    72  			require.NoError(t, err)
    73  		}
    74  
    75  		require.Equal(t, 10, spawnedCount)
    76  	})
    77  
    78  	t.Run("dynamic update errored", func(t *testing.T) {
    79  		spawnedCount := 0
    80  		spawner := func(c Config) (ManagedInstance, error) {
    81  			spawnedCount++
    82  
    83  			newMock := baseMock
    84  			newMock.UpdateFunc = func(c Config) error {
    85  				return fmt.Errorf("something really bad happened")
    86  			}
    87  			return &newMock, nil
    88  		}
    89  
    90  		cm := NewBasicManager(DefaultBasicManagerConfig, NewMetrics(nil), logger, spawner)
    91  
    92  		// Creation should succeed
    93  		err := cm.ApplyConfig(Config{Name: "test"})
    94  		require.NoError(t, err)
    95  
    96  		// ...but the update should fail
    97  		err = cm.ApplyConfig(Config{Name: "test"})
    98  		require.Error(t, err, "something really bad happened")
    99  		require.Equal(t, 1, spawnedCount)
   100  	})
   101  }
   102  
   103  type mockInstance struct {
   104  	RunFunc              func(ctx context.Context) error
   105  	UpdateFunc           func(c Config) error
   106  	TargetsActiveFunc    func() map[string][]*scrape.Target
   107  	StorageDirectoryFunc func() string
   108  	AppenderFunc         func() storage.Appender
   109  }
   110  
   111  func (m mockInstance) Ready() bool {
   112  	return true
   113  }
   114  
   115  func (m mockInstance) Stop() error {
   116  	return nil
   117  }
   118  
   119  func (m mockInstance) Tenant() string {
   120  	return ""
   121  }
   122  
   123  func (m mockInstance) Run(ctx context.Context) error {
   124  	if m.RunFunc != nil {
   125  		return m.RunFunc(ctx)
   126  	}
   127  	panic("RunFunc not provided")
   128  }
   129  
   130  func (m mockInstance) Update(c Config) error {
   131  	if m.UpdateFunc != nil {
   132  		return m.UpdateFunc(c)
   133  	}
   134  	panic("UpdateFunc not provided")
   135  }
   136  
   137  func (m mockInstance) TargetsActive() map[string][]*scrape.Target {
   138  	if m.TargetsActiveFunc != nil {
   139  		return m.TargetsActiveFunc()
   140  	}
   141  	panic("TargetsActiveFunc not provided")
   142  }
   143  
   144  func (m mockInstance) StorageDirectory() string {
   145  	if m.StorageDirectoryFunc != nil {
   146  		return m.StorageDirectoryFunc()
   147  	}
   148  	panic("StorageDirectoryFunc not provided")
   149  }
   150  
   151  func (m mockInstance) Appender(_ context.Context) storage.Appender {
   152  	if m.AppenderFunc != nil {
   153  		return m.AppenderFunc()
   154  	}
   155  	panic("AppenderFunc not provided")
   156  }