Path: blob/main/pkg/integrations/redis_exporter/redis_exporter_test.go
5395 views
package redis_exporter //nolint:golint12import (3"bytes"4"fmt"5"io"6"net/http"7"net/http/httptest"8"testing"910"github.com/grafana/agent/pkg/config"1112"github.com/go-kit/log"13"github.com/gorilla/mux"14"github.com/prometheus/prometheus/model/textparse"15"github.com/stretchr/testify/require"16)1718const addr string = "localhost:6379"19const redisExporterFile string = "./redis_exporter.go"20const redisPasswordMapFile string = "./testdata/password_map_file.json"2122func TestRedisCases(t *testing.T) {23tt := []struct {24name string25cfg Config26expectedMetrics []string27expectConstructorError bool28}{29// Test that default config results in some metrics that can be parsed by30// prometheus.31{32name: "Default config",33cfg: (func() Config {34c := DefaultConfig35c.RedisAddr = addr36return c37})(),38expectedMetrics: []string{},39},40// Test that exporter metrics are included when configured to do so.41{42name: "Include exporter metrics",43cfg: (func() Config {44c := DefaultConfig45c.RedisAddr = addr46c.IncludeExporterMetrics = true47return c48})(),49expectedMetrics: []string{50"promhttp_metric_handler_requests_total",51"promhttp_metric_handler_requests_in_flight",52},53},54// Test that some valid pre-constructor config logic doesn't cause errors.55{56name: "Lua script read OK",57cfg: (func() Config {58c := DefaultConfig59c.RedisAddr = addr60c.ScriptPath = redisExporterFile // file content is irrelevant61return c62})(),63},64// Test that multiple lua scripts in a csv doesn't cause errors.65{66name: "Multiple Lua scripts read OK",67cfg: (func() Config {68c := DefaultConfig69c.RedisAddr = addr70c.ScriptPath = fmt.Sprintf("%s,%s", redisExporterFile, redisPasswordMapFile) // file contents are irrelevant71return c72})(),73},74// Test that some invalid pre-constructor config logic causes an error.75{76name: "Lua script read fail",77cfg: (func() Config {78c := DefaultConfig79c.RedisAddr = addr80c.ScriptPath = "/does/not/exist"81return c82})(),83expectConstructorError: true,84},85// Test exporter complains when no address given via env or config.86{87name: "no address given",88cfg: Config{}, // no address in here89expectConstructorError: true,90},91// Test exporter constructs ok when password file is defined and exists92{93name: "valid password file",94cfg: (func() Config {95c := DefaultConfig96c.RedisAddr = addr97c.RedisPasswordFile = redisExporterFile // contents not important98return c99})(),100},101// Test exporter construction fails when password file is defined and doesn't102// exist103{104name: "invalid password file",105cfg: (func() Config {106c := DefaultConfig107c.RedisAddr = addr108c.RedisPasswordFile = "/does/not/exist"109return c110})(),111expectConstructorError: true,112},113// Test exporter constructs ok when password map file is defined, exists, and is valid114{115name: "valid password map file",116cfg: (func() Config {117c := DefaultConfig118c.RedisAddr = addr119c.RedisPasswordMapFile = redisPasswordMapFile120return c121})(),122},123// Test exporter fails to construct when the password map file is not valid json124{125name: "invalid password map file",126cfg: (func() Config {127c := DefaultConfig128c.RedisAddr = addr129c.RedisPasswordMapFile = redisExporterFile130return c131})(),132expectConstructorError: true,133},134// Test exporter construction fails when both redis_password_file and redis_password_map_file135// are specified136{137name: "too many password files",138cfg: (func() Config {139c := DefaultConfig140c.RedisAddr = addr141c.RedisPasswordFile = redisExporterFile // contents not important142c.RedisPasswordMapFile = redisExporterFile // contents not important143return c144})(),145expectConstructorError: true,146},147}148149logger := log.NewNopLogger()150151for _, test := range tt {152t.Run(test.name, func(t *testing.T) {153integration, err := New(logger, &test.cfg)154155if test.expectConstructorError {156require.Error(t, err, "expected failure when setting up redis_exporter")157return158}159require.NoError(t, err, "failed to setup redis_exporter")160161r := mux.NewRouter()162handler, err := integration.MetricsHandler()163require.NoError(t, err)164r.Handle("/metrics", handler)165require.NoError(t, err)166167srv := httptest.NewServer(r)168defer srv.Close()169170res, err := http.Get(srv.URL + "/metrics")171require.NoError(t, err)172173body, err := io.ReadAll(res.Body)174require.NoError(t, err)175176foundMetricNames := map[string]bool{}177for _, name := range test.expectedMetrics {178foundMetricNames[name] = false179}180181p := textparse.NewPromParser(body)182for {183entry, err := p.Next()184if err == io.EOF {185break186}187require.NoError(t, err)188189if entry == textparse.EntryHelp {190matchMetricNames(foundMetricNames, p)191}192}193194for metric, exists := range foundMetricNames {195require.True(t, exists, "could not find metric %s", metric)196}197})198}199}200201func TestConfig_SecretRedisPassword(t *testing.T) {202stringCfg := `203prometheus:204wal_directory: /tmp/agent205integrations:206redis_exporter:207enabled: true208redis_password: secret_password209`210config.CheckSecret(t, stringCfg, "secret_password")211}212213func matchMetricNames(names map[string]bool, p textparse.Parser) {214for name := range names {215metricName, _ := p.Help()216if bytes.Equal([]byte(name), metricName) {217names[name] = true218}219}220}221222223