...

Source file src/github.com/prometheus/alertmanager/notify/victorops/victorops_test.go

Documentation: github.com/prometheus/alertmanager/notify/victorops

     1  // Copyright 2019 Prometheus Team
     2  // Licensed under the Apache License, Version 2.0 (the "License");
     3  // you may not use this file except in compliance with the License.
     4  // You may obtain a copy of the License at
     5  //
     6  // http://www.apache.org/licenses/LICENSE-2.0
     7  //
     8  // Unless required by applicable law or agreed to in writing, software
     9  // distributed under the License is distributed on an "AS IS" BASIS,
    10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    11  // See the License for the specific language governing permissions and
    12  // limitations under the License.
    13  
    14  package victorops
    15  
    16  import (
    17  	"context"
    18  	"encoding/json"
    19  	"fmt"
    20  	"net/http"
    21  	"net/http/httptest"
    22  	"net/url"
    23  	"os"
    24  	"testing"
    25  	"time"
    26  
    27  	"github.com/go-kit/log"
    28  	commoncfg "github.com/prometheus/common/config"
    29  	"github.com/prometheus/common/model"
    30  	"github.com/stretchr/testify/require"
    31  
    32  	"github.com/prometheus/alertmanager/config"
    33  	"github.com/prometheus/alertmanager/notify"
    34  	"github.com/prometheus/alertmanager/notify/test"
    35  	"github.com/prometheus/alertmanager/types"
    36  )
    37  
    38  func TestVictorOpsCustomFields(t *testing.T) {
    39  	logger := log.NewNopLogger()
    40  	tmpl := test.CreateTmpl(t)
    41  
    42  	url, err := url.Parse("http://nowhere.com")
    43  
    44  	require.NoError(t, err, "unexpected error parsing mock url")
    45  
    46  	conf := &config.VictorOpsConfig{
    47  		APIKey:            `12345`,
    48  		APIURL:            &config.URL{URL: url},
    49  		EntityDisplayName: `{{ .CommonLabels.Message }}`,
    50  		StateMessage:      `{{ .CommonLabels.Message }}`,
    51  		RoutingKey:        `test`,
    52  		MessageType:       ``,
    53  		MonitoringTool:    `AM`,
    54  		CustomFields: map[string]string{
    55  			"Field_A": "{{ .CommonLabels.Message }}",
    56  		},
    57  		HTTPConfig: &commoncfg.HTTPClientConfig{},
    58  	}
    59  
    60  	notifier, err := New(conf, tmpl, logger)
    61  	require.NoError(t, err)
    62  
    63  	ctx := context.Background()
    64  	ctx = notify.WithGroupKey(ctx, "1")
    65  
    66  	alert := &types.Alert{
    67  		Alert: model.Alert{
    68  			Labels: model.LabelSet{
    69  				"Message": "message",
    70  			},
    71  			StartsAt: time.Now(),
    72  			EndsAt:   time.Now().Add(time.Hour),
    73  		},
    74  	}
    75  
    76  	msg, err := notifier.createVictorOpsPayload(ctx, alert)
    77  	require.NoError(t, err)
    78  
    79  	var m map[string]string
    80  	err = json.Unmarshal(msg.Bytes(), &m)
    81  
    82  	require.NoError(t, err)
    83  
    84  	// Verify that a custom field was added to the payload and templatized.
    85  	require.Equal(t, "message", m["Field_A"])
    86  }
    87  
    88  func TestVictorOpsRetry(t *testing.T) {
    89  	notifier, err := New(
    90  		&config.VictorOpsConfig{
    91  			APIKey:     config.Secret("secret"),
    92  			HTTPConfig: &commoncfg.HTTPClientConfig{},
    93  		},
    94  		test.CreateTmpl(t),
    95  		log.NewNopLogger(),
    96  	)
    97  	require.NoError(t, err)
    98  	for statusCode, expected := range test.RetryTests(test.DefaultRetryCodes()) {
    99  		actual, _ := notifier.retrier.Check(statusCode, nil)
   100  		require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
   101  	}
   102  }
   103  
   104  func TestVictorOpsRedactedURL(t *testing.T) {
   105  	ctx, u, fn := test.GetContextWithCancelingURL()
   106  	defer fn()
   107  
   108  	secret := "secret"
   109  	notifier, err := New(
   110  		&config.VictorOpsConfig{
   111  			APIURL:     &config.URL{URL: u},
   112  			APIKey:     config.Secret(secret),
   113  			HTTPConfig: &commoncfg.HTTPClientConfig{},
   114  		},
   115  		test.CreateTmpl(t),
   116  		log.NewNopLogger(),
   117  	)
   118  	require.NoError(t, err)
   119  
   120  	test.AssertNotifyLeaksNoSecret(ctx, t, notifier, secret)
   121  }
   122  
   123  func TestVictorOpsReadingApiKeyFromFile(t *testing.T) {
   124  	key := "key"
   125  	f, err := os.CreateTemp("", "victorops_test")
   126  	require.NoError(t, err, "creating temp file failed")
   127  	_, err = f.WriteString(key)
   128  	require.NoError(t, err, "writing to temp file failed")
   129  
   130  	ctx, u, fn := test.GetContextWithCancelingURL()
   131  	defer fn()
   132  
   133  	notifier, err := New(
   134  		&config.VictorOpsConfig{
   135  			APIURL:     &config.URL{URL: u},
   136  			APIKeyFile: f.Name(),
   137  			HTTPConfig: &commoncfg.HTTPClientConfig{},
   138  		},
   139  		test.CreateTmpl(t),
   140  		log.NewNopLogger(),
   141  	)
   142  	require.NoError(t, err)
   143  
   144  	test.AssertNotifyLeaksNoSecret(ctx, t, notifier, key)
   145  }
   146  
   147  func TestVictorOpsTemplating(t *testing.T) {
   148  	srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
   149  		dec := json.NewDecoder(r.Body)
   150  		out := make(map[string]interface{})
   151  		err := dec.Decode(&out)
   152  		if err != nil {
   153  			panic(err)
   154  		}
   155  	}))
   156  	defer srv.Close()
   157  	u, _ := url.Parse(srv.URL)
   158  
   159  	tests := []struct {
   160  		name   string
   161  		cfg    *config.VictorOpsConfig
   162  		errMsg string
   163  	}{
   164  		{
   165  			name: "default valid templates",
   166  			cfg:  &config.VictorOpsConfig{},
   167  		},
   168  		{
   169  			name: "invalid message_type",
   170  			cfg: &config.VictorOpsConfig{
   171  				MessageType: "{{ .CommonLabels.alertname }",
   172  			},
   173  			errMsg: "templating error",
   174  		},
   175  		{
   176  			name: "invalid entity_display_name",
   177  			cfg: &config.VictorOpsConfig{
   178  				EntityDisplayName: "{{ .CommonLabels.alertname }",
   179  			},
   180  			errMsg: "templating error",
   181  		},
   182  		{
   183  			name: "invalid state_message",
   184  			cfg: &config.VictorOpsConfig{
   185  				StateMessage: "{{ .CommonLabels.alertname }",
   186  			},
   187  			errMsg: "templating error",
   188  		},
   189  		{
   190  			name: "invalid monitoring tool",
   191  			cfg: &config.VictorOpsConfig{
   192  				MonitoringTool: "{{ .CommonLabels.alertname }",
   193  			},
   194  			errMsg: "templating error",
   195  		},
   196  		{
   197  			name: "invalid routing_key",
   198  			cfg: &config.VictorOpsConfig{
   199  				RoutingKey: "{{ .CommonLabels.alertname }",
   200  			},
   201  			errMsg: "templating error",
   202  		},
   203  	}
   204  
   205  	for _, tc := range tests {
   206  		t.Run(tc.name, func(t *testing.T) {
   207  			tc.cfg.HTTPConfig = &commoncfg.HTTPClientConfig{}
   208  			tc.cfg.APIURL = &config.URL{URL: u}
   209  			tc.cfg.APIKey = "test"
   210  			vo, err := New(tc.cfg, test.CreateTmpl(t), log.NewNopLogger())
   211  			require.NoError(t, err)
   212  			ctx := context.Background()
   213  			ctx = notify.WithGroupKey(ctx, "1")
   214  
   215  			_, err = vo.Notify(ctx, []*types.Alert{
   216  				{
   217  					Alert: model.Alert{
   218  						Labels: model.LabelSet{
   219  							"lbl1": "val1",
   220  						},
   221  						StartsAt: time.Now(),
   222  						EndsAt:   time.Now().Add(time.Hour),
   223  					},
   224  				},
   225  			}...)
   226  			if tc.errMsg == "" {
   227  				require.NoError(t, err)
   228  			} else {
   229  				require.Contains(t, err.Error(), tc.errMsg)
   230  			}
   231  		})
   232  	}
   233  }
   234  

View as plain text