Skip to content

Commit

Permalink
Merge release 0.20 (#2140)
Browse files Browse the repository at this point in the history
* Revert "slack: retry 429 errors (#2112)" (#2128)

This reverts commit 26cc96a.

Signed-off-by: Simon Pasquier <[email protected]>

* Revert "config: remove support for JSON marshaling (#2086)" (#2133)

This reverts commit 918f08b.

Signed-off-by: Simon Pasquier <[email protected]>

* config: fix JSON unmarshaling for HostPort (#2134)

Signed-off-by: Simon Pasquier <[email protected]>

* Cut 0.20.0 (#2137)

Signed-off-by: Simon Pasquier <[email protected]>
  • Loading branch information
simonpasquier authored Dec 12, 2019
1 parent 3640bb8 commit b49ebfc
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 15 deletions.
3 changes: 1 addition & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## 0.20.0-rc.0 / 2019-11-27
## 0.20.0 / 2019-12-11

* [CHANGE] Check that at least one silence matcher matches a non-empty string. #2081
* [ENHANCEMENT] [pagerduty] Check that PagerDuty keys aren't empty. #2085
Expand All @@ -11,7 +11,6 @@
* [BUGFIX] Don't garbage-collect alerts from the store. #2040
* [BUGFIX] [ui] Disable the grammarly plugin on all textareas. #2061
* [BUGFIX] [config] Forbid nil regexp matchers. #2083
* [BUGFIX] [slack] Retry 429 errors. #2112
* [BUGFIX] [ui] Fix Silences UI when several filters are applied. #2075

Contributors:
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.20.0-rc.0
0.20.0
13 changes: 11 additions & 2 deletions client/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,18 @@ func TestAPI(t *testing.T) {
client := &fakeAPIClient{T: t, ch: make(chan fakeAPIResponse, 1)}
now := time.Now()

u, err := url.Parse("http://example.com")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
statusData := &ServerStatus{
ConfigYAML: "{}",
ConfigJSON: &config.Config{},
ConfigYAML: "{}",
ConfigJSON: &config.Config{
Global: &config.GlobalConfig{
PagerdutyURL: &config.URL{URL: u},
SMTPSmarthost: config.HostPort{Host: "localhost", Port: "25"},
},
},
VersionInfo: map[string]string{"version": "v1"},
Uptime: now,
ClusterStatus: &ClusterStatus{Peers: []PeerStatus{}},
Expand Down
71 changes: 71 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ func (u URL) MarshalJSON() ([]byte, error) {
return nil, nil
}

// UnmarshalJSON implements the json.Marshaler interface for URL.
func (u *URL) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
urlp, err := parseURL(s)
if err != nil {
return err
}
u.URL = urlp.URL
return nil
}

// SecretURL is a URL that must not be revealed on marshaling.
type SecretURL URL

Expand Down Expand Up @@ -137,6 +151,18 @@ func (s SecretURL) MarshalJSON() ([]byte, error) {
return json.Marshal(secretToken)
}

// UnmarshalJSON implements the json.Marshaler interface for SecretURL.
func (s *SecretURL) UnmarshalJSON(data []byte) error {
// In order to deserialize a previously serialized configuration (eg from
// the Alertmanager API with amtool), `<secret>` needs to be treated
// specially, as it isn't a valid URL.
if string(data) == secretToken || string(data) == secretTokenJSON {
s.URL = &url.URL{}
return nil
}
return json.Unmarshal(data, (*URL)(s))
}

// Load parses the YAML input s into a Config.
func Load(s string) (*Config, error) {
cfg := &Config{}
Expand Down Expand Up @@ -490,6 +516,28 @@ func (hp *HostPort) UnmarshalYAML(unmarshal func(interface{}) error) error {
return nil
}

// UnmarshalJSON implements the json.Unmarshaler interface for HostPort.
func (hp *HostPort) UnmarshalJSON(data []byte) error {
var (
s string
err error
)
if err = json.Unmarshal(data, &s); err != nil {
return err
}
if s == "" {
return nil
}
hp.Host, hp.Port, err = net.SplitHostPort(s)
if err != nil {
return err
}
if hp.Port == "" {
return errors.Errorf("address %q: port cannot be empty", s)
}
return nil
}

// MarshalYAML implements the yaml.Marshaler interface for HostPort.
func (hp HostPort) MarshalYAML() (interface{}, error) {
return hp.String(), nil
Expand Down Expand Up @@ -729,3 +777,26 @@ func (re Regexp) MarshalYAML() (interface{}, error) {
}
return nil, nil
}

// UnmarshalJSON implements the json.Marshaler interface for Regexp
func (re *Regexp) UnmarshalJSON(data []byte) error {
var s string
if err := json.Unmarshal(data, &s); err != nil {
return err
}
regex, err := regexp.Compile("^(?:" + s + ")$")
if err != nil {
return err
}
re.Regexp = regex
re.original = s
return nil
}

// MarshalJSON implements the json.Marshaler interface for Regexp.
func (re Regexp) MarshalJSON() ([]byte, error) {
if re.original != "" {
return json.Marshal(re.original)
}
return nil, nil
}
60 changes: 54 additions & 6 deletions config/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,13 +367,27 @@ func TestMarshalSecretURL(t *testing.T) {
}
u := &SecretURL{urlp}

c, err := yaml.Marshal(u)
c, err := json.Marshal(u)
if err != nil {
t.Fatal(err)
}
require.Equal(t, "<secret>\n", string(c), "SecretURL not properly elided in YAML.")
// u003c -> "<"
// u003e -> ">"
require.Equal(t, "\"\\u003csecret\\u003e\"", string(c), "SecretURL not properly elided in JSON.")
// Check that the marshaled data can be unmarshaled again.
out := &SecretURL{}
err = json.Unmarshal(c, out)
if err != nil {
t.Fatal(err)
}

c, err = yaml.Marshal(u)
if err != nil {
t.Fatal(err)
}
require.Equal(t, "<secret>\n", string(c), "SecretURL not properly elided in YAML.")
// Check that the marshaled data can be unmarshaled again.
out = &SecretURL{}
err = yaml.Unmarshal(c, &out)
if err != nil {
t.Fatal(err)
Expand All @@ -384,7 +398,13 @@ func TestUnmarshalSecretURL(t *testing.T) {
b := []byte(`"http://example.com/se cret"`)
var u SecretURL

err := yaml.Unmarshal(b, &u)
err := json.Unmarshal(b, &u)
if err != nil {
t.Fatal(err)
}
require.Equal(t, "http://example.com/se%20cret", u.String(), "SecretURL not properly unmarshalled in JSON.")

err = yaml.Unmarshal(b, &u)
if err != nil {
t.Fatal(err)
}
Expand Down Expand Up @@ -416,7 +436,13 @@ func TestUnmarshalURL(t *testing.T) {
b := []byte(`"http://example.com/a b"`)
var u URL

err := yaml.Unmarshal(b, &u)
err := json.Unmarshal(b, &u)
if err != nil {
t.Fatal(err)
}
require.Equal(t, "http://example.com/a%20b", u.String(), "URL not properly unmarshalled in JSON.")

err = yaml.Unmarshal(b, &u)
if err != nil {
t.Fatal(err)
}
Expand All @@ -431,7 +457,12 @@ func TestUnmarshalInvalidURL(t *testing.T) {
} {
var u URL

err := yaml.Unmarshal(b, &u)
err := json.Unmarshal(b, &u)
if err == nil {
t.Errorf("Expected an error unmarshalling %q from JSON", string(b))
}

err = yaml.Unmarshal(b, &u)
if err == nil {
t.Errorf("Expected an error unmarshalling %q from YAML", string(b))
}
Expand All @@ -443,10 +474,27 @@ func TestUnmarshalRelativeURL(t *testing.T) {
b := []byte(`"/home"`)
var u URL

err := yaml.Unmarshal(b, &u)
err := json.Unmarshal(b, &u)
if err == nil {
t.Errorf("Expected an error parsing URL")
}

err = yaml.Unmarshal(b, &u)
if err == nil {
t.Errorf("Expected an error parsing URL")
}
}

func TestJSONUnmarshal(t *testing.T) {
c, err := LoadFile("testdata/conf.good.yml")
if err != nil {
t.Errorf("Error parsing %s: %s", "testdata/conf.good.yml", err)
}

_, err = json.Marshal(c)
if err != nil {
t.Fatal("JSON Marshaling failed:", err)
}
}

func TestMarshalIdempotency(t *testing.T) {
Expand Down
24 changes: 24 additions & 0 deletions dispatch/route.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package dispatch

import (
"encoding/json"
"fmt"
"sort"
"strings"
Expand Down Expand Up @@ -181,3 +182,26 @@ func (ro *RouteOpts) String() string {
return fmt.Sprintf("<RouteOpts send_to:%q group_by:%q group_by_all:%t timers:%q|%q>",
ro.Receiver, labels, ro.GroupByAll, ro.GroupWait, ro.GroupInterval)
}

// MarshalJSON returns a JSON representation of the routing options.
func (ro *RouteOpts) MarshalJSON() ([]byte, error) {
v := struct {
Receiver string `json:"receiver"`
GroupBy model.LabelNames `json:"groupBy"`
GroupByAll bool `json:"groupByAll"`
GroupWait time.Duration `json:"groupWait"`
GroupInterval time.Duration `json:"groupInterval"`
RepeatInterval time.Duration `json:"repeatInterval"`
}{
Receiver: ro.Receiver,
GroupByAll: ro.GroupByAll,
GroupWait: ro.GroupWait,
GroupInterval: ro.GroupInterval,
RepeatInterval: ro.RepeatInterval,
}
for ln := range ro.GroupBy {
v.GroupBy = append(v.GroupBy, ln)
}

return json.Marshal(&v)
}
2 changes: 1 addition & 1 deletion notify/slack/slack.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func New(c *config.SlackConfig, t *template.Template, l log.Logger) (*Notifier,
tmpl: t,
logger: l,
client: client,
retrier: &notify.Retrier{RetryCodes: []int{http.StatusTooManyRequests}},
retrier: &notify.Retrier{},
}, nil
}

Expand Down
4 changes: 1 addition & 3 deletions notify/slack/slack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package slack

import (
"fmt"
"net/http"
"testing"

"github.com/go-kit/kit/log"
Expand All @@ -36,8 +35,7 @@ func TestSlackRetry(t *testing.T) {
)
require.NoError(t, err)

retryCodes := append(test.DefaultRetryCodes(), http.StatusTooManyRequests)
for statusCode, expected := range test.RetryTests(retryCodes) {
for statusCode, expected := range test.RetryTests(test.DefaultRetryCodes()) {
actual, _ := notifier.retrier.Check(statusCode, nil)
require.Equal(t, expected, actual, fmt.Sprintf("error on status %d", statusCode))
}
Expand Down

0 comments on commit b49ebfc

Please sign in to comment.