diff --git a/api/v2/api_test.go b/api/v2/api_test.go index 5cabf2e0..438e6f44 100644 --- a/api/v2/api_test.go +++ b/api/v2/api_test.go @@ -15,6 +15,7 @@ package v2 import ( "bytes" + "encoding/json" "fmt" "io" "net/http" @@ -24,6 +25,7 @@ import ( "time" "github.com/go-openapi/runtime" + "github.com/go-openapi/runtime/middleware" "github.com/go-openapi/strfmt" "github.com/prometheus/common/model" "github.com/stretchr/testify/require" @@ -269,32 +271,108 @@ func TestPostSilencesHandler(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - silence, silenceBytes := createSilence(t, tc.sid, "silenceCreator", tc.start, tc.end) - api := API{ uptime: time.Now(), silences: silences, logger: log.NewNopLogger(), } - r, err := http.NewRequest("POST", "/api/v2/silence/${tc.sid}", bytes.NewReader(silenceBytes)) - require.NoError(t, err) - + sil := createSilence(t, tc.sid, "silenceCreator", tc.start, tc.end) w := httptest.NewRecorder() - p := runtime.TextProducer() - responder := api.postSilencesHandler(silence_ops.PostSilencesParams{ - HTTPRequest: r, - Silence: &silence, - }) - responder.WriteResponse(w, p) + postSilences(t, w, api.postSilencesHandler, sil) body, _ := io.ReadAll(w.Result().Body) - require.Equal(t, tc.expectedCode, w.Code, fmt.Sprintf("test case: %d, response: %s", i, string(body))) }) } }) } +func TestPostSilencesHandlerMissingIdCreatesSilence(t *testing.T) { + now := time.Now() + silences := newSilences(t) + api := API{ + uptime: time.Now(), + silences: silences, + logger: log.NewNopLogger(), + } + + // Create a new silence. It should be assigned a random UUID. + sil := createSilence(t, "", "silenceCreator", now.Add(time.Hour), now.Add(time.Hour*2)) + w := httptest.NewRecorder() + postSilences(t, w, api.postSilencesHandler, sil) + require.Equal(t, http.StatusOK, w.Code) + + // Get the silences from the API. + w = httptest.NewRecorder() + getSilences(t, w, api.getSilencesHandler) + require.Equal(t, http.StatusOK, w.Code) + var resp []open_api_models.GettableSilence + require.NoError(t, json.NewDecoder(w.Body).Decode(&resp)) + require.Len(t, resp, 1) + + // Change the ID. It should return 404 Not Found. + sil = open_api_models.PostableSilence{ + ID: "unknownID", + Silence: resp[0].Silence, + } + w = httptest.NewRecorder() + postSilences(t, w, api.postSilencesHandler, sil) + require.Equal(t, http.StatusNotFound, w.Code) + + // Remove the ID. It should duplicate the silence with a different UUID. + sil = open_api_models.PostableSilence{ + ID: "", + Silence: resp[0].Silence, + } + w = httptest.NewRecorder() + postSilences(t, w, api.postSilencesHandler, sil) + require.Equal(t, http.StatusOK, w.Code) + + // Get the silences from the API. There should now be 2 silences. + w = httptest.NewRecorder() + getSilences(t, w, api.getSilencesHandler) + require.Equal(t, http.StatusOK, w.Code) + require.NoError(t, json.NewDecoder(w.Body).Decode(&resp)) + require.Len(t, resp, 2) + require.NotEqual(t, resp[0].ID, resp[1].ID) +} + +func getSilences( + t *testing.T, + w *httptest.ResponseRecorder, + handlerFunc func(params silence_ops.GetSilencesParams) middleware.Responder, +) { + r, err := http.NewRequest("GET", "/api/v2/silences", nil) + require.NoError(t, err) + + p := runtime.TextProducer() + responder := handlerFunc(silence_ops.GetSilencesParams{ + HTTPRequest: r, + Filter: nil, + }) + responder.WriteResponse(w, p) +} + +func postSilences( + t *testing.T, + w *httptest.ResponseRecorder, + handlerFunc func(params silence_ops.PostSilencesParams) middleware.Responder, + sil open_api_models.PostableSilence, +) { + b, err := json.Marshal(sil) + require.NoError(t, err) + + r, err := http.NewRequest("POST", "/api/v2/silences", bytes.NewReader(b)) + require.NoError(t, err) + + p := runtime.TextProducer() + responder := handlerFunc(silence_ops.PostSilencesParams{ + HTTPRequest: r, + Silence: &sil, + }) + responder.WriteResponse(w, p) +} + func TestCheckSilenceMatchesFilterLabels(t *testing.T) { type test struct { silenceMatchers []*silencepb.Matcher diff --git a/api/v2/testing.go b/api/v2/testing.go index c813d350..7665a19f 100644 --- a/api/v2/testing.go +++ b/api/v2/testing.go @@ -14,19 +14,17 @@ package v2 import ( - "encoding/json" "testing" "time" "github.com/go-openapi/strfmt" - "github.com/stretchr/testify/require" open_api_models "github.com/prometheus/alertmanager/api/v2/models" "github.com/prometheus/alertmanager/pkg/labels" "github.com/prometheus/alertmanager/silence/silencepb" ) -func createSilence(t *testing.T, ID, creator string, start, ends time.Time) (open_api_models.PostableSilence, []byte) { +func createSilence(t *testing.T, ID, creator string, start, ends time.Time) open_api_models.PostableSilence { t.Helper() comment := "test" @@ -46,10 +44,7 @@ func createSilence(t *testing.T, ID, creator string, start, ends time.Time) (ope Comment: &comment, }, } - b, err := json.Marshal(&sil) - require.NoError(t, err) - - return sil, b + return sil } func createSilenceMatcher(t *testing.T, name, pattern string, matcherType silencepb.Matcher_Type) *silencepb.Matcher {