blob: 8f91a9702e0ca1b26bd4b22ec741373a07a771d9 [file] [log] [blame]
khenaidooab1f7bd2019-11-14 14:00:27 -05001// Copyright 2015 The Prometheus Authors
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
14package model
15
16import (
17 "encoding/json"
Abhay Kumara2ae5992025-11-10 14:02:24 +000018 "errors"
khenaidooab1f7bd2019-11-14 14:00:27 -050019 "fmt"
20 "regexp"
21 "time"
22)
23
24// Matcher describes a matches the value of a given label.
25type Matcher struct {
26 Name LabelName `json:"name"`
27 Value string `json:"value"`
28 IsRegex bool `json:"isRegex"`
29}
30
31func (m *Matcher) UnmarshalJSON(b []byte) error {
32 type plain Matcher
33 if err := json.Unmarshal(b, (*plain)(m)); err != nil {
34 return err
35 }
36
37 if len(m.Name) == 0 {
Abhay Kumara2ae5992025-11-10 14:02:24 +000038 return errors.New("label name in matcher must not be empty")
khenaidooab1f7bd2019-11-14 14:00:27 -050039 }
40 if m.IsRegex {
41 if _, err := regexp.Compile(m.Value); err != nil {
42 return err
43 }
44 }
45 return nil
46}
47
48// Validate returns true iff all fields of the matcher have valid values.
49func (m *Matcher) Validate() error {
50 if !m.Name.IsValid() {
51 return fmt.Errorf("invalid name %q", m.Name)
52 }
53 if m.IsRegex {
54 if _, err := regexp.Compile(m.Value); err != nil {
55 return fmt.Errorf("invalid regular expression %q", m.Value)
56 }
57 } else if !LabelValue(m.Value).IsValid() || len(m.Value) == 0 {
58 return fmt.Errorf("invalid value %q", m.Value)
59 }
60 return nil
61}
62
63// Silence defines the representation of a silence definition in the Prometheus
64// eco-system.
65type Silence struct {
66 ID uint64 `json:"id,omitempty"`
67
68 Matchers []*Matcher `json:"matchers"`
69
70 StartsAt time.Time `json:"startsAt"`
71 EndsAt time.Time `json:"endsAt"`
72
73 CreatedAt time.Time `json:"createdAt,omitempty"`
74 CreatedBy string `json:"createdBy"`
75 Comment string `json:"comment,omitempty"`
76}
77
78// Validate returns true iff all fields of the silence have valid values.
79func (s *Silence) Validate() error {
80 if len(s.Matchers) == 0 {
Abhay Kumara2ae5992025-11-10 14:02:24 +000081 return errors.New("at least one matcher required")
khenaidooab1f7bd2019-11-14 14:00:27 -050082 }
83 for _, m := range s.Matchers {
84 if err := m.Validate(); err != nil {
Abhay Kumara2ae5992025-11-10 14:02:24 +000085 return fmt.Errorf("invalid matcher: %w", err)
khenaidooab1f7bd2019-11-14 14:00:27 -050086 }
87 }
88 if s.StartsAt.IsZero() {
Abhay Kumara2ae5992025-11-10 14:02:24 +000089 return errors.New("start time missing")
khenaidooab1f7bd2019-11-14 14:00:27 -050090 }
91 if s.EndsAt.IsZero() {
Abhay Kumara2ae5992025-11-10 14:02:24 +000092 return errors.New("end time missing")
khenaidooab1f7bd2019-11-14 14:00:27 -050093 }
94 if s.EndsAt.Before(s.StartsAt) {
Abhay Kumara2ae5992025-11-10 14:02:24 +000095 return errors.New("start time must be before end time")
khenaidooab1f7bd2019-11-14 14:00:27 -050096 }
97 if s.CreatedBy == "" {
Abhay Kumara2ae5992025-11-10 14:02:24 +000098 return errors.New("creator information missing")
khenaidooab1f7bd2019-11-14 14:00:27 -050099 }
100 if s.Comment == "" {
Abhay Kumara2ae5992025-11-10 14:02:24 +0000101 return errors.New("comment missing")
khenaidooab1f7bd2019-11-14 14:00:27 -0500102 }
103 if s.CreatedAt.IsZero() {
Abhay Kumara2ae5992025-11-10 14:02:24 +0000104 return errors.New("creation timestamp missing")
khenaidooab1f7bd2019-11-14 14:00:27 -0500105 }
106 return nil
107}