moira

Форк
0
/
subscription.go 
248 строк · 7.8 Кб
1
package controller
2

3
import (
4
	"errors"
5
	"fmt"
6
	"strings"
7
	"time"
8

9
	"github.com/go-graphite/carbonapi/date"
10
	"github.com/satori/go.uuid"
11

12
	"go.avito.ru/DO/moira"
13
	"go.avito.ru/DO/moira/api"
14
	"go.avito.ru/DO/moira/api/dto"
15
	"go.avito.ru/DO/moira/database"
16
)
17

18
func GetSubscriptionsByContactValue(database moira.Database, contactValue string) (*dto.SubscriptionFilteredList, *api.ErrorResponse) {
19
	contactValue = strings.ToLower(contactValue)
20
	if len(contactValue) < 3 {
21
		return nil, api.ErrorInvalidRequest(errors.New("\"contact\" must be at least 3 bytes long"))
22
	}
23

24
	result := &dto.SubscriptionFilteredList{
25
		List: nil,
26
	}
27

28
	// all existing contacts
29
	contacts, err := database.GetAllContacts()
30
	if err != nil {
31
		return nil, api.ErrorInternalServer(fmt.Errorf("Failed to get contacts data: %v", err))
32
	}
33

34
	// filter all contacts by value
35
	contactsAllMap := make(map[string]moira.ContactData, len(contacts))
36
	contactsMatchedSet := make(map[string]bool, len(contacts))
37
	usersSet := make(map[string]bool, len(contacts))
38
	for _, contact := range contacts {
39
		if contact == nil || contact.ID == "" {
40
			continue
41
		}
42

43
		contactsAllMap[contact.ID] = *contact
44
		if strings.Contains(strings.ToLower(contact.Value), contactValue) {
45
			contactsMatchedSet[contact.ID] = true
46
			usersSet[contact.User] = true
47
		}
48
	}
49

50
	// no contact has matched - hence no need to hit DB for subscriptions
51
	if len(contactsMatchedSet) == 0 {
52
		return result, nil
53
	}
54

55
	// search for all subscriptions of found users
56
	subscriptions := make([]*moira.SubscriptionData, 0, 100)
57
	for user := range usersSet {
58
		subscriptionIDs, err := database.GetUserSubscriptionIDs(user)
59
		if err != nil {
60
			return nil, api.ErrorInternalServer(err)
61
		}
62

63
		subscriptionsByUser, err := database.GetSubscriptions(subscriptionIDs)
64
		if err != nil {
65
			return nil, api.ErrorInternalServer(err)
66
		}
67

68
		for _, subscriptionByUser := range subscriptionsByUser {
69
			if subscriptionByUser != nil {
70
				subscriptions = append(subscriptions, subscriptionByUser)
71
			}
72
		}
73
	}
74
	result.List = make([]dto.SubscriptionFiltered, 0, len(subscriptions))
75

76
	// filter subscriptions and escalations by contact ids
77
	for _, subscription := range subscriptions {
78
		matchedEsc := make([]bool, len(subscription.Escalations)) // indicated which escalations have matched
79
		matchedSub := false                                       // indicates if subscription itself has matched
80
		matchedAny := false                                       // indicates if anything (either subscription or at least one escalation) has matched
81

82
		// define if subscription itself matches any contact
83
		for _, contactID := range subscription.Contacts {
84
			if contactID != "" && contactsMatchedSet[contactID] {
85
				matchedAny = true
86
				matchedSub = true
87
				break
88
			}
89
		}
90

91
		// for each escalation define if it matches any contact
92
		for i, escalation := range subscription.Escalations {
93
			for _, contactID := range escalation.Contacts {
94
				if contactID != "" && contactsMatchedSet[contactID] {
95
					matchedAny = true
96
					matchedEsc[i] = true
97
					break // range escalation.Contacts
98
				}
99
			}
100
		}
101

102
		// don't include unmatched subscription into result set
103
		if !matchedAny {
104
			continue
105
		}
106

107
		// make a copy of escalations
108
		escalations := make([]dto.EscalationFiltered, 0, len(subscription.Escalations))
109
		for _, escalation := range subscription.Escalations {
110
			escalations = append(escalations, dto.EscalationFiltered{
111
				ID:              escalation.ID,
112
				Contacts:        transformContactIDs(contactsAllMap, escalation.Contacts),
113
				OffsetInMinutes: escalation.OffsetInMinutes,
114
			})
115
		}
116

117
		// search result
118
		result.List = append(result.List, dto.SubscriptionFiltered{
119
			ID:          subscription.ID,
120
			Enabled:     subscription.Enabled,
121
			Tags:        subscription.Tags,
122
			User:        subscription.User,
123
			Contacts:    transformContactIDs(contactsAllMap, subscription.Contacts),
124
			Escalations: escalations,
125
			MatchedEsc:  matchedEsc,
126
			MatchedSub:  matchedSub,
127
		})
128
	}
129

130
	return result, nil
131
}
132

133
// GetSubscriptionById is a proxy for the same database method
134
func GetSubscriptionById(database moira.Database, id string) (*moira.SubscriptionData, *api.ErrorResponse) {
135
	subscriptionData, err := database.GetSubscription(id)
136
	if err != nil {
137
		return nil, api.ErrorInternalServer(err)
138
	} else {
139
		return &subscriptionData, nil
140
	}
141
}
142

143
// GetUserSubscriptions get all user subscriptions
144
func GetUserSubscriptions(database moira.Database, userLogin string) (*dto.SubscriptionList, *api.ErrorResponse) {
145
	subscriptionIDs, err := database.GetUserSubscriptionIDs(userLogin)
146
	if err != nil {
147
		return nil, api.ErrorInternalServer(err)
148
	}
149
	subscriptions, err := database.GetSubscriptions(subscriptionIDs)
150
	if err != nil {
151
		return nil, api.ErrorInternalServer(err)
152
	}
153
	subscriptionsList := &dto.SubscriptionList{
154
		List: make([]moira.SubscriptionData, 0),
155
	}
156
	for _, subscription := range subscriptions {
157
		if subscription != nil {
158
			subscriptionsList.List = append(subscriptionsList.List, *subscription)
159
		}
160
	}
161
	return subscriptionsList, nil
162
}
163

164
// CreateSubscription create or update subscription
165
func CreateSubscription(dataBase moira.Database, userLogin string, subscription *dto.Subscription) *api.ErrorResponse {
166
	if subscription.ID == "" {
167
		subscription.ID = uuid.NewV4().String()
168
	} else {
169
		exists, err := isSubscriptionExists(dataBase, subscription.ID)
170
		if err != nil {
171
			return api.ErrorInternalServer(err)
172
		}
173
		if exists {
174
			return api.ErrorInvalidRequest(fmt.Errorf("Subscription with this ID already exists"))
175
		}
176
	}
177

178
	subscription.User = userLogin
179
	data := moira.SubscriptionData(*subscription)
180
	if err := dataBase.SaveSubscription(&data); err != nil {
181
		return api.ErrorInternalServer(err)
182
	}
183
	return nil
184
}
185

186
// UpdateSubscription updates existing subscription
187
func UpdateSubscription(dataBase moira.Database, subscriptionID string, userLogin string, subscription *dto.Subscription) *api.ErrorResponse {
188
	subscription.ID = subscriptionID
189
	subscription.User = userLogin
190
	data := moira.SubscriptionData(*subscription)
191
	if err := dataBase.SaveSubscription(&data); err != nil {
192
		return api.ErrorInternalServer(err)
193
	}
194
	return nil
195
}
196

197
// RemoveSubscription deletes subscription
198
func RemoveSubscription(database moira.Database, subscriptionID string) *api.ErrorResponse {
199
	if err := database.RemoveSubscription(subscriptionID); err != nil {
200
		return api.ErrorInternalServer(err)
201
	}
202
	return nil
203
}
204

205
// SendTestNotification push test notification to verify the correct notification settings
206
func SendTestNotification(database moira.Database, subscriptionID string) *api.ErrorResponse {
207
	var value float64 = 1
208
	eventData := &moira.NotificationEvent{
209
		SubscriptionID: &subscriptionID,
210
		Metric:         "Test.metric.value",
211
		Value:          &value,
212
		OldState:       moira.TEST,
213
		State:          moira.TEST,
214
		Timestamp:      int64(date.DateParamToEpoch("now", "", time.Now().Add(-24*time.Hour).Unix(), time.UTC)),
215
	}
216

217
	if err := database.PushNotificationEvent(eventData); err != nil {
218
		return api.ErrorInternalServer(err)
219
	}
220

221
	return nil
222
}
223

224
// CheckUserPermissionsForSubscription checks subscription for existence and permissions for given user
225
func CheckUserPermissionsForSubscription(dataBase moira.Database, subscriptionID string, userLogin string) (moira.SubscriptionData, *api.ErrorResponse) {
226
	subscription, err := dataBase.GetSubscription(subscriptionID)
227
	if err != nil {
228
		if err == database.ErrNil {
229
			return subscription, api.ErrorNotFound(fmt.Sprintf("Subscription with ID '%s' does not exists", subscriptionID))
230
		}
231
		return subscription, api.ErrorInternalServer(err)
232
	}
233
	if subscription.User != userLogin {
234
		return subscription, api.ErrorForbidden("You have not permissions")
235
	}
236
	return subscription, nil
237
}
238

239
func isSubscriptionExists(dataBase moira.Database, subscriptionID string) (bool, error) {
240
	_, err := dataBase.GetSubscription(subscriptionID)
241
	if err == database.ErrNil {
242
		return false, nil
243
	}
244
	if err != nil {
245
		return false, err
246
	}
247
	return true, nil
248
}
249

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.