1// Copyright 2016 Circonus, Inc. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// RuleSetGroup API support - Fetch, Create, Update, Delete, and Search
6// See: https://login.circonus.com/resources/api/calls/rule_set_group
7
8package api
9
10import (
11	"encoding/json"
12	"fmt"
13	"net/url"
14	"regexp"
15
16	"github.com/circonus-labs/circonus-gometrics/api/config"
17)
18
19// RuleSetGroupFormula defines a formula for raising alerts
20type RuleSetGroupFormula struct {
21	Expression    interface{} `json:"expression"`     // string or uint BUG doc: string, api: string or numeric
22	RaiseSeverity uint        `json:"raise_severity"` // uint
23	Wait          uint        `json:"wait"`           // uint
24}
25
26// RuleSetGroupCondition defines conditions for raising alerts
27type RuleSetGroupCondition struct {
28	MatchingSeverities []string `json:"matching_serverities"` // [] len >= 1
29	RuleSetCID         string   `json:"rule_set"`             // string
30}
31
32// RuleSetGroup defines a ruleset group. See https://login.circonus.com/resources/api/calls/rule_set_group for more information.
33type RuleSetGroup struct {
34	CID               string                  `json:"_cid,omitempty"`      // string
35	ContactGroups     map[uint8][]string      `json:"contact_groups"`      // [] len == 5
36	Formulas          []RuleSetGroupFormula   `json:"formulas"`            // [] len >= 0
37	Name              string                  `json:"name"`                // string
38	RuleSetConditions []RuleSetGroupCondition `json:"rule_set_conditions"` // [] len >= 1
39	Tags              []string                `json:"tags"`                // [] len >= 0
40}
41
42// NewRuleSetGroup returns a new RuleSetGroup (with defaults, if applicable)
43func NewRuleSetGroup() *RuleSetGroup {
44	return &RuleSetGroup{}
45}
46
47// FetchRuleSetGroup retrieves rule set group with passed cid.
48func (a *API) FetchRuleSetGroup(cid CIDType) (*RuleSetGroup, error) {
49	if cid == nil || *cid == "" {
50		return nil, fmt.Errorf("Invalid rule set group CID [none]")
51	}
52
53	groupCID := string(*cid)
54
55	matched, err := regexp.MatchString(config.RuleSetGroupCIDRegex, groupCID)
56	if err != nil {
57		return nil, err
58	}
59	if !matched {
60		return nil, fmt.Errorf("Invalid rule set group CID [%s]", groupCID)
61	}
62
63	result, err := a.Get(groupCID)
64	if err != nil {
65		return nil, err
66	}
67
68	if a.Debug {
69		a.Log.Printf("[DEBUG] fetch rule set group, received JSON: %s", string(result))
70	}
71
72	rulesetGroup := &RuleSetGroup{}
73	if err := json.Unmarshal(result, rulesetGroup); err != nil {
74		return nil, err
75	}
76
77	return rulesetGroup, nil
78}
79
80// FetchRuleSetGroups retrieves all rule set groups available to API Token.
81func (a *API) FetchRuleSetGroups() (*[]RuleSetGroup, error) {
82	result, err := a.Get(config.RuleSetGroupPrefix)
83	if err != nil {
84		return nil, err
85	}
86
87	var rulesetGroups []RuleSetGroup
88	if err := json.Unmarshal(result, &rulesetGroups); err != nil {
89		return nil, err
90	}
91
92	return &rulesetGroups, nil
93}
94
95// UpdateRuleSetGroup updates passed rule set group.
96func (a *API) UpdateRuleSetGroup(cfg *RuleSetGroup) (*RuleSetGroup, error) {
97	if cfg == nil {
98		return nil, fmt.Errorf("Invalid rule set group config [nil]")
99	}
100
101	groupCID := string(cfg.CID)
102
103	matched, err := regexp.MatchString(config.RuleSetGroupCIDRegex, groupCID)
104	if err != nil {
105		return nil, err
106	}
107	if !matched {
108		return nil, fmt.Errorf("Invalid rule set group CID [%s]", groupCID)
109	}
110
111	jsonCfg, err := json.Marshal(cfg)
112	if err != nil {
113		return nil, err
114	}
115
116	if a.Debug {
117		a.Log.Printf("[DEBUG] update rule set group, sending JSON: %s", string(jsonCfg))
118	}
119
120	result, err := a.Put(groupCID, jsonCfg)
121	if err != nil {
122		return nil, err
123	}
124
125	groups := &RuleSetGroup{}
126	if err := json.Unmarshal(result, groups); err != nil {
127		return nil, err
128	}
129
130	return groups, nil
131}
132
133// CreateRuleSetGroup creates a new rule set group.
134func (a *API) CreateRuleSetGroup(cfg *RuleSetGroup) (*RuleSetGroup, error) {
135	if cfg == nil {
136		return nil, fmt.Errorf("Invalid rule set group config [nil]")
137	}
138
139	jsonCfg, err := json.Marshal(cfg)
140	if err != nil {
141		return nil, err
142	}
143
144	if a.Debug {
145		a.Log.Printf("[DEBUG] create rule set group, sending JSON: %s", string(jsonCfg))
146	}
147
148	result, err := a.Post(config.RuleSetGroupPrefix, jsonCfg)
149	if err != nil {
150		return nil, err
151	}
152
153	group := &RuleSetGroup{}
154	if err := json.Unmarshal(result, group); err != nil {
155		return nil, err
156	}
157
158	return group, nil
159}
160
161// DeleteRuleSetGroup deletes passed rule set group.
162func (a *API) DeleteRuleSetGroup(cfg *RuleSetGroup) (bool, error) {
163	if cfg == nil {
164		return false, fmt.Errorf("Invalid rule set group config [nil]")
165	}
166	return a.DeleteRuleSetGroupByCID(CIDType(&cfg.CID))
167}
168
169// DeleteRuleSetGroupByCID deletes rule set group with passed cid.
170func (a *API) DeleteRuleSetGroupByCID(cid CIDType) (bool, error) {
171	if cid == nil || *cid == "" {
172		return false, fmt.Errorf("Invalid rule set group CID [none]")
173	}
174
175	groupCID := string(*cid)
176
177	matched, err := regexp.MatchString(config.RuleSetGroupCIDRegex, groupCID)
178	if err != nil {
179		return false, err
180	}
181	if !matched {
182		return false, fmt.Errorf("Invalid rule set group CID [%s]", groupCID)
183	}
184
185	_, err = a.Delete(groupCID)
186	if err != nil {
187		return false, err
188	}
189
190	return true, nil
191}
192
193// SearchRuleSetGroups returns rule set groups matching the
194// specified search query and/or filter. If nil is passed for
195// both parameters all rule set groups will be returned.
196func (a *API) SearchRuleSetGroups(searchCriteria *SearchQueryType, filterCriteria *SearchFilterType) (*[]RuleSetGroup, error) {
197	q := url.Values{}
198
199	if searchCriteria != nil && *searchCriteria != "" {
200		q.Set("search", string(*searchCriteria))
201	}
202
203	if filterCriteria != nil && len(*filterCriteria) > 0 {
204		for filter, criteria := range *filterCriteria {
205			for _, val := range criteria {
206				q.Add(filter, val)
207			}
208		}
209	}
210
211	if q.Encode() == "" {
212		return a.FetchRuleSetGroups()
213	}
214
215	reqURL := url.URL{
216		Path:     config.RuleSetGroupPrefix,
217		RawQuery: q.Encode(),
218	}
219
220	result, err := a.Get(reqURL.String())
221	if err != nil {
222		return nil, fmt.Errorf("[ERROR] API call error %+v", err)
223	}
224
225	var groups []RuleSetGroup
226	if err := json.Unmarshal(result, &groups); err != nil {
227		return nil, err
228	}
229
230	return &groups, nil
231}
232