1// Copyright 2021 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
14package v2
15
16import (
17	"fmt"
18	"time"
19
20	"github.com/go-openapi/strfmt"
21	open_api_models "github.com/prometheus/alertmanager/api/v2/models"
22	"github.com/prometheus/alertmanager/silence/silencepb"
23	"github.com/prometheus/alertmanager/types"
24	prometheus_model "github.com/prometheus/common/model"
25)
26
27// GettableSilenceFromProto converts *silencepb.Silence to open_api_models.GettableSilence.
28func GettableSilenceFromProto(s *silencepb.Silence) (open_api_models.GettableSilence, error) {
29	start := strfmt.DateTime(s.StartsAt)
30	end := strfmt.DateTime(s.EndsAt)
31	updated := strfmt.DateTime(s.UpdatedAt)
32	state := string(types.CalcSilenceState(s.StartsAt, s.EndsAt))
33	sil := open_api_models.GettableSilence{
34		Silence: open_api_models.Silence{
35			StartsAt:  &start,
36			EndsAt:    &end,
37			Comment:   &s.Comment,
38			CreatedBy: &s.CreatedBy,
39		},
40		ID:        &s.Id,
41		UpdatedAt: &updated,
42		Status: &open_api_models.SilenceStatus{
43			State: &state,
44		},
45	}
46
47	for _, m := range s.Matchers {
48		matcher := &open_api_models.Matcher{
49			Name:  &m.Name,
50			Value: &m.Pattern,
51		}
52		f := false
53		t := true
54		switch m.Type {
55		case silencepb.Matcher_EQUAL:
56			matcher.IsEqual = &t
57			matcher.IsRegex = &f
58		case silencepb.Matcher_NOT_EQUAL:
59			matcher.IsEqual = &f
60			matcher.IsRegex = &f
61		case silencepb.Matcher_REGEXP:
62			matcher.IsEqual = &t
63			matcher.IsRegex = &t
64		case silencepb.Matcher_NOT_REGEXP:
65			matcher.IsEqual = &f
66			matcher.IsRegex = &t
67		default:
68			return sil, fmt.Errorf(
69				"unknown matcher type for matcher '%v' in silence '%v'",
70				m.Name,
71				s.Id,
72			)
73		}
74		sil.Matchers = append(sil.Matchers, matcher)
75	}
76
77	return sil, nil
78}
79
80// PostableSilenceToProto converts *open_api_models.PostableSilenc to *silencepb.Silence.
81func PostableSilenceToProto(s *open_api_models.PostableSilence) (*silencepb.Silence, error) {
82	sil := &silencepb.Silence{
83		Id:        s.ID,
84		StartsAt:  time.Time(*s.StartsAt),
85		EndsAt:    time.Time(*s.EndsAt),
86		Comment:   *s.Comment,
87		CreatedBy: *s.CreatedBy,
88	}
89	for _, m := range s.Matchers {
90		matcher := &silencepb.Matcher{
91			Name:    *m.Name,
92			Pattern: *m.Value,
93		}
94		isEqual := true
95		if m.IsEqual != nil {
96			isEqual = *m.IsEqual
97		}
98		isRegex := false
99		if m.IsRegex != nil {
100			isRegex = *m.IsRegex
101		}
102
103		switch {
104		case isEqual && !isRegex:
105			matcher.Type = silencepb.Matcher_EQUAL
106		case !isEqual && !isRegex:
107			matcher.Type = silencepb.Matcher_NOT_EQUAL
108		case isEqual && isRegex:
109			matcher.Type = silencepb.Matcher_REGEXP
110		case !isEqual && isRegex:
111			matcher.Type = silencepb.Matcher_NOT_REGEXP
112		}
113		sil.Matchers = append(sil.Matchers, matcher)
114	}
115	return sil, nil
116}
117
118// AlertToOpenAPIAlert converts internal alerts, alert types, and receivers to *open_api_models.GettableAlert.
119func AlertToOpenAPIAlert(alert *types.Alert, status types.AlertStatus, receivers []string) *open_api_models.GettableAlert {
120	startsAt := strfmt.DateTime(alert.StartsAt)
121	updatedAt := strfmt.DateTime(alert.UpdatedAt)
122	endsAt := strfmt.DateTime(alert.EndsAt)
123
124	apiReceivers := make([]*open_api_models.Receiver, 0, len(receivers))
125	for i := range receivers {
126		apiReceivers = append(apiReceivers, &open_api_models.Receiver{Name: &receivers[i]})
127	}
128
129	fp := alert.Fingerprint().String()
130	state := string(status.State)
131	aa := &open_api_models.GettableAlert{
132		Alert: open_api_models.Alert{
133			GeneratorURL: strfmt.URI(alert.GeneratorURL),
134			Labels:       ModelLabelSetToAPILabelSet(alert.Labels),
135		},
136		Annotations: ModelLabelSetToAPILabelSet(alert.Annotations),
137		StartsAt:    &startsAt,
138		UpdatedAt:   &updatedAt,
139		EndsAt:      &endsAt,
140		Fingerprint: &fp,
141		Receivers:   apiReceivers,
142		Status: &open_api_models.AlertStatus{
143			State:       &state,
144			SilencedBy:  status.SilencedBy,
145			InhibitedBy: status.InhibitedBy,
146		},
147	}
148
149	if aa.Status.SilencedBy == nil {
150		aa.Status.SilencedBy = []string{}
151	}
152
153	if aa.Status.InhibitedBy == nil {
154		aa.Status.InhibitedBy = []string{}
155	}
156
157	return aa
158}
159
160// OpenAPIAlertsToAlerts converts open_api_models.PostableAlerts to []*types.Alert.
161func OpenAPIAlertsToAlerts(apiAlerts open_api_models.PostableAlerts) []*types.Alert {
162	alerts := []*types.Alert{}
163	for _, apiAlert := range apiAlerts {
164		alert := types.Alert{
165			Alert: prometheus_model.Alert{
166				Labels:       APILabelSetToModelLabelSet(apiAlert.Labels),
167				Annotations:  APILabelSetToModelLabelSet(apiAlert.Annotations),
168				StartsAt:     time.Time(apiAlert.StartsAt),
169				EndsAt:       time.Time(apiAlert.EndsAt),
170				GeneratorURL: string(apiAlert.GeneratorURL),
171			},
172		}
173		alerts = append(alerts, &alert)
174	}
175
176	return alerts
177}
178
179// ModelLabelSetToAPILabelSet converts prometheus_model.LabelSet to open_api_models.LabelSet.
180func ModelLabelSetToAPILabelSet(modelLabelSet prometheus_model.LabelSet) open_api_models.LabelSet {
181	apiLabelSet := open_api_models.LabelSet{}
182	for key, value := range modelLabelSet {
183		apiLabelSet[string(key)] = string(value)
184	}
185
186	return apiLabelSet
187}
188
189// APILabelSetToModelLabelSet converts open_api_models.LabelSet to prometheus_model.LabelSet.
190func APILabelSetToModelLabelSet(apiLabelSet open_api_models.LabelSet) prometheus_model.LabelSet {
191	modelLabelSet := prometheus_model.LabelSet{}
192	for key, value := range apiLabelSet {
193		modelLabelSet[prometheus_model.LabelName(key)] = prometheus_model.LabelValue(value)
194	}
195
196	return modelLabelSet
197}
198