github.com/muhammadn/cortex@v1.9.1-0.20220510110439-46bb7000d03d/pkg/alertmanager/merger/v2_silences_test.go (about)

     1  package merger
     2  
     3  import (
     4  	"testing"
     5  
     6  	v2_models "github.com/prometheus/alertmanager/api/v2/models"
     7  	"github.com/stretchr/testify/require"
     8  )
     9  
    10  func TestV2Silences(t *testing.T) {
    11  
    12  	// This test is to check the parsing round-trip is working as expected, the merging logic is
    13  	// tested in TestMergeV2Silences. The test data is based on captures from an actual Alertmanager.
    14  
    15  	in := [][]byte{
    16  		[]byte(`[` +
    17  			`{"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5","status":{"state":"expired"},` +
    18  			`"updatedAt":"2021-04-28T17:31:02.215Z","comment":"Silence Comment #1",` +
    19  			`"createdBy":"","endsAt":"2021-04-28T17:31:02.215Z","matchers":` +
    20  			`[{"isEqual":true,"isRegex":false,"name":"instance","value":"prometheus-one"}],` +
    21  			`"startsAt":"2021-04-28T17:31:01.725Z"},` +
    22  			`{"id":"261248d1-4ff7-4cf1-9957-850c65f4e48b","status":{"state":"expired"},` +
    23  			`"updatedAt":"2021-04-28T17:31:02.082Z","comment":"Silence Comment #3",` +
    24  			`"createdBy":"","endsAt":"2021-04-28T17:31:02.082Z","matchers":` +
    25  			`[{"isEqual":true,"isRegex":false,"name":"instance","value":"prometheus-one"}],` +
    26  			`"startsAt":"2021-04-28T17:31:01.735Z"}` +
    27  			`]`),
    28  		[]byte(`[` +
    29  			`{"id":"17526003-c745-4464-a355-4f06de26a236","status":{"state":"expired"},` +
    30  			`"updatedAt":"2021-04-28T17:31:01.953Z","comment":"Silence Comment #2",` +
    31  			`"createdBy":"","endsAt":"2021-04-28T17:31:01.953Z","matchers":` +
    32  			`[{"isEqual":true,"isRegex":false,"name":"instance","value":"prometheus-one"}],` +
    33  			`"startsAt":"2021-04-28T17:31:01.731Z"}` +
    34  			`]`),
    35  		[]byte(`[]`),
    36  	}
    37  
    38  	expected := []byte(`[` +
    39  		`{"id":"77b580dd-1d9c-4b7e-9bba-13ac173cb4e5","status":{"state":"expired"},` +
    40  		`"updatedAt":"2021-04-28T17:31:02.215Z","comment":"Silence Comment #1",` +
    41  		`"createdBy":"","endsAt":"2021-04-28T17:31:02.215Z","matchers":` +
    42  		`[{"isEqual":true,"isRegex":false,"name":"instance","value":"prometheus-one"}],` +
    43  		`"startsAt":"2021-04-28T17:31:01.725Z"},` +
    44  		`{"id":"261248d1-4ff7-4cf1-9957-850c65f4e48b","status":{"state":"expired"},` +
    45  		`"updatedAt":"2021-04-28T17:31:02.082Z","comment":"Silence Comment #3",` +
    46  		`"createdBy":"","endsAt":"2021-04-28T17:31:02.082Z","matchers":` +
    47  		`[{"isEqual":true,"isRegex":false,"name":"instance","value":"prometheus-one"}],` +
    48  		`"startsAt":"2021-04-28T17:31:01.735Z"},` +
    49  		`{"id":"17526003-c745-4464-a355-4f06de26a236","status":{"state":"expired"},` +
    50  		`"updatedAt":"2021-04-28T17:31:01.953Z","comment":"Silence Comment #2",` +
    51  		`"createdBy":"","endsAt":"2021-04-28T17:31:01.953Z","matchers":` +
    52  		`[{"isEqual":true,"isRegex":false,"name":"instance","value":"prometheus-one"}],` +
    53  		`"startsAt":"2021-04-28T17:31:01.731Z"}` +
    54  		`]`)
    55  
    56  	out, err := V2Silences{}.MergeResponses(in)
    57  	require.NoError(t, err)
    58  	require.Equal(t, string(expected), string(out))
    59  }
    60  
    61  // v2silence is a convenience function to create silence structures with certain important fields set
    62  // and with sensible defaults for the remaining fields to test they are passed through.
    63  func v2silence(id, endsAt, updatedAt string) *v2_models.GettableSilence {
    64  	var (
    65  		active    = v2_models.SilenceStatusStateActive
    66  		comment   = "test"
    67  		createdBy = "someone"
    68  		isEqual   = true
    69  		isRegex   = false
    70  		name      = "foo"
    71  		value     = "bar"
    72  	)
    73  	return &v2_models.GettableSilence{
    74  		ID: &id,
    75  		Status: &v2_models.SilenceStatus{
    76  			State: &active,
    77  		},
    78  		UpdatedAt: v2ParseTime(updatedAt),
    79  		Silence: v2_models.Silence{
    80  			Comment:   &comment,
    81  			CreatedBy: &createdBy,
    82  			EndsAt:    v2ParseTime(endsAt),
    83  			Matchers: v2_models.Matchers{
    84  				&v2_models.Matcher{
    85  					IsEqual: &isEqual,
    86  					IsRegex: &isRegex,
    87  					Name:    &name,
    88  					Value:   &value,
    89  				},
    90  			},
    91  			StartsAt: v2ParseTime("2020-01-01T12:00:00.000Z"),
    92  		},
    93  	}
    94  }
    95  
    96  func v2silences(silences ...*v2_models.GettableSilence) v2_models.GettableSilences {
    97  	return silences
    98  }
    99  
   100  func TestMergeV2Silences(t *testing.T) {
   101  	var (
   102  		silence1      = v2silence("id1", "2020-01-01T12:11:11.000Z", "2020-01-01T12:00:00.000Z")
   103  		newerSilence1 = v2silence("id1", "2020-01-01T12:11:11.000Z", "2020-01-01T12:00:00.001Z")
   104  		silence2      = v2silence("id2", "2020-01-01T12:22:22.000Z", "2020-01-01T12:00:00.000Z")
   105  		silence3      = v2silence("id3", "2020-01-01T12:33:33.000Z", "2020-01-01T12:00:00.000Z")
   106  	)
   107  	cases := []struct {
   108  		name string
   109  		in   v2_models.GettableSilences
   110  		err  error
   111  		out  v2_models.GettableSilences
   112  	}{
   113  		{
   114  			name: "no silences, should return an empty list",
   115  			in:   v2silences(),
   116  			out:  v2_models.GettableSilences{},
   117  		},
   118  		{
   119  			name: "one silence, should return the silence",
   120  			in:   v2silences(silence1),
   121  			out:  v2silences(silence1),
   122  		},
   123  		{
   124  			name: "two silences, should return two silences",
   125  			in:   v2silences(silence1, silence2),
   126  			out:  v2silences(silence1, silence2),
   127  		},
   128  		{
   129  			name: "three silences, should return three silences",
   130  			in:   v2silences(silence1, silence2, silence3),
   131  			out:  v2silences(silence1, silence2, silence3),
   132  		},
   133  		{
   134  			name: "three active silences out of order, should return three silences in expiry order",
   135  			in:   v2silences(silence3, silence2, silence1),
   136  			out:  v2silences(silence1, silence2, silence3),
   137  		},
   138  		{
   139  			name: "two identical silences, should return one silence",
   140  			in:   v2silences(silence1, silence1),
   141  			out:  v2silences(silence1),
   142  		},
   143  		{
   144  			name: "two identical silences plus another, should return two silences",
   145  			in:   v2silences(silence1, silence1, silence2),
   146  			out:  v2silences(silence1, silence2),
   147  		},
   148  		{
   149  			name: "two duplicates out of sync silences, should return newer silence",
   150  			in:   v2silences(silence1, newerSilence1),
   151  			out:  v2silences(newerSilence1),
   152  		},
   153  		{
   154  			name: "two duplicates out of sync silences (newer first), should return newer silence",
   155  			in:   v2silences(newerSilence1, silence1),
   156  			out:  v2silences(newerSilence1),
   157  		},
   158  		{
   159  			name: "two duplicates plus others, should return newer silence and others",
   160  			in:   v2silences(newerSilence1, silence3, silence1, silence2),
   161  			out:  v2silences(newerSilence1, silence2, silence3),
   162  		},
   163  	}
   164  
   165  	for _, c := range cases {
   166  		t.Run(c.name, func(t *testing.T) {
   167  			out, err := mergeV2Silences(c.in)
   168  			require.Equal(t, c.err, err)
   169  			require.Equal(t, c.out, out)
   170  		})
   171  	}
   172  }