Skip to content

Commit e5b8476

Browse files
Add a custom JSON marshaller for Alertmanager configurations
1 parent 863b097 commit e5b8476

File tree

4 files changed

+439
-0
lines changed

4 files changed

+439
-0
lines changed

definition/json.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package definition
2+
3+
import (
4+
"unsafe"
5+
6+
jsoniter "github.com/json-iterator/go"
7+
"github.com/modern-go/reflect2"
8+
amcfg "github.com/prometheus/alertmanager/config"
9+
commoncfg "github.com/prometheus/common/config"
10+
)
11+
12+
// secretEncoder encodes Secret to plain text JSON,
13+
// avoding the default masking behavior of the structure.
14+
type secretEncoder struct{}
15+
16+
func (encoder *secretEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
17+
stream.WriteString(getStr(ptr))
18+
}
19+
20+
func (encoder *secretEncoder) IsEmpty(ptr unsafe.Pointer) bool {
21+
return len(getStr(ptr)) == 0
22+
}
23+
24+
func getStr(ptr unsafe.Pointer) string {
25+
return *(*string)(ptr)
26+
}
27+
28+
// secretEncoder encodes SecretURL to plain text JSON,
29+
// avoding the default masking behavior of the structure.
30+
type secretURLEncoder struct{}
31+
32+
func (encoder *secretURLEncoder) Encode(ptr unsafe.Pointer, stream *jsoniter.Stream) {
33+
url := getURL(ptr)
34+
if url.URL != nil {
35+
stream.WriteString(url.String())
36+
} else {
37+
stream.WriteNil()
38+
}
39+
}
40+
41+
func (encoder *secretURLEncoder) IsEmpty(ptr unsafe.Pointer) bool {
42+
url := getURL(ptr)
43+
return url.URL == nil
44+
}
45+
46+
func getURL(ptr unsafe.Pointer) *amcfg.URL {
47+
v := (*amcfg.SecretURL)(ptr)
48+
url := amcfg.URL(*v)
49+
return &url
50+
}
51+
52+
func newPlainAPI() jsoniter.API {
53+
api := jsoniter.ConfigCompatibleWithStandardLibrary
54+
55+
secretEnc := &secretEncoder{}
56+
secretURLEnc := &secretURLEncoder{}
57+
58+
extension := jsoniter.EncoderExtension{
59+
// Value types
60+
reflect2.TypeOfPtr((*amcfg.Secret)(nil)).Elem(): secretEnc,
61+
reflect2.TypeOfPtr((*commoncfg.Secret)(nil)).Elem(): secretEnc,
62+
reflect2.TypeOfPtr((*amcfg.SecretURL)(nil)).Elem(): secretURLEnc,
63+
// Pointer types
64+
reflect2.TypeOfPtr((*amcfg.Secret)(nil)): &jsoniter.OptionalEncoder{ValueEncoder: secretEnc},
65+
reflect2.TypeOfPtr((*commoncfg.Secret)(nil)): &jsoniter.OptionalEncoder{ValueEncoder: secretEnc},
66+
reflect2.TypeOfPtr((*amcfg.SecretURL)(nil)): &jsoniter.OptionalEncoder{ValueEncoder: secretURLEnc},
67+
}
68+
69+
api.RegisterExtension(extension)
70+
71+
return api
72+
}
73+
74+
var (
75+
plainJSON = newPlainAPI()
76+
)
77+
78+
// MarshalJSONWithSecrets marshals the given value to JSON with secrets in plain text.
79+
//
80+
// alertmanager's and prometeus' Secret and SecretURL types mask their values
81+
// when marshaled with the standard JSON or YAML marshallers. This function
82+
// preserves the values of these types by using a custom JSON encoder.
83+
func MarshalJSONWithSecrets(v any) ([]byte, error) {
84+
return plainJSON.Marshal(v)
85+
}

0 commit comments

Comments
 (0)