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// Maintenance window API support - Fetch, Create, Update, Delete, and Search 6// See: https://login.circonus.com/resources/api/calls/maintenance 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// Maintenance defines a maintenance window. See https://login.circonus.com/resources/api/calls/maintenance for more information. 20type Maintenance struct { 21 CID string `json:"_cid,omitempty"` // string 22 Item string `json:"item,omitempty"` // string 23 Notes string `json:"notes,omitempty"` // string 24 Severities interface{} `json:"severities,omitempty"` // []string NOTE can be set with CSV string or []string 25 Start uint `json:"start,omitempty"` // uint 26 Stop uint `json:"stop,omitempty"` // uint 27 Tags []string `json:"tags,omitempty"` // [] len >= 0 28 Type string `json:"type,omitempty"` // string 29} 30 31// NewMaintenanceWindow returns a new Maintenance window (with defaults, if applicable) 32func NewMaintenanceWindow() *Maintenance { 33 return &Maintenance{} 34} 35 36// FetchMaintenanceWindow retrieves maintenance [window] with passed cid. 37func (a *API) FetchMaintenanceWindow(cid CIDType) (*Maintenance, error) { 38 if cid == nil || *cid == "" { 39 return nil, fmt.Errorf("Invalid maintenance window CID [none]") 40 } 41 42 maintenanceCID := string(*cid) 43 44 matched, err := regexp.MatchString(config.MaintenanceCIDRegex, maintenanceCID) 45 if err != nil { 46 return nil, err 47 } 48 if !matched { 49 return nil, fmt.Errorf("Invalid maintenance window CID [%s]", maintenanceCID) 50 } 51 52 result, err := a.Get(maintenanceCID) 53 if err != nil { 54 return nil, err 55 } 56 57 if a.Debug { 58 a.Log.Printf("[DEBUG] fetch maintenance window, received JSON: %s", string(result)) 59 } 60 61 window := &Maintenance{} 62 if err := json.Unmarshal(result, window); err != nil { 63 return nil, err 64 } 65 66 return window, nil 67} 68 69// FetchMaintenanceWindows retrieves all maintenance [windows] available to API Token. 70func (a *API) FetchMaintenanceWindows() (*[]Maintenance, error) { 71 result, err := a.Get(config.MaintenancePrefix) 72 if err != nil { 73 return nil, err 74 } 75 76 var windows []Maintenance 77 if err := json.Unmarshal(result, &windows); err != nil { 78 return nil, err 79 } 80 81 return &windows, nil 82} 83 84// UpdateMaintenanceWindow updates passed maintenance [window]. 85func (a *API) UpdateMaintenanceWindow(cfg *Maintenance) (*Maintenance, error) { 86 if cfg == nil { 87 return nil, fmt.Errorf("Invalid maintenance window config [nil]") 88 } 89 90 maintenanceCID := string(cfg.CID) 91 92 matched, err := regexp.MatchString(config.MaintenanceCIDRegex, maintenanceCID) 93 if err != nil { 94 return nil, err 95 } 96 if !matched { 97 return nil, fmt.Errorf("Invalid maintenance window CID [%s]", maintenanceCID) 98 } 99 100 jsonCfg, err := json.Marshal(cfg) 101 if err != nil { 102 return nil, err 103 } 104 105 if a.Debug { 106 a.Log.Printf("[DEBUG] update maintenance window, sending JSON: %s", string(jsonCfg)) 107 } 108 109 result, err := a.Put(maintenanceCID, jsonCfg) 110 if err != nil { 111 return nil, err 112 } 113 114 window := &Maintenance{} 115 if err := json.Unmarshal(result, window); err != nil { 116 return nil, err 117 } 118 119 return window, nil 120} 121 122// CreateMaintenanceWindow creates a new maintenance [window]. 123func (a *API) CreateMaintenanceWindow(cfg *Maintenance) (*Maintenance, error) { 124 if cfg == nil { 125 return nil, fmt.Errorf("Invalid maintenance window config [nil]") 126 } 127 128 jsonCfg, err := json.Marshal(cfg) 129 if err != nil { 130 return nil, err 131 } 132 133 if a.Debug { 134 a.Log.Printf("[DEBUG] create maintenance window, sending JSON: %s", string(jsonCfg)) 135 } 136 137 result, err := a.Post(config.MaintenancePrefix, jsonCfg) 138 if err != nil { 139 return nil, err 140 } 141 142 window := &Maintenance{} 143 if err := json.Unmarshal(result, window); err != nil { 144 return nil, err 145 } 146 147 return window, nil 148} 149 150// DeleteMaintenanceWindow deletes passed maintenance [window]. 151func (a *API) DeleteMaintenanceWindow(cfg *Maintenance) (bool, error) { 152 if cfg == nil { 153 return false, fmt.Errorf("Invalid maintenance window config [nil]") 154 } 155 return a.DeleteMaintenanceWindowByCID(CIDType(&cfg.CID)) 156} 157 158// DeleteMaintenanceWindowByCID deletes maintenance [window] with passed cid. 159func (a *API) DeleteMaintenanceWindowByCID(cid CIDType) (bool, error) { 160 if cid == nil || *cid == "" { 161 return false, fmt.Errorf("Invalid maintenance window CID [none]") 162 } 163 164 maintenanceCID := string(*cid) 165 166 matched, err := regexp.MatchString(config.MaintenanceCIDRegex, maintenanceCID) 167 if err != nil { 168 return false, err 169 } 170 if !matched { 171 return false, fmt.Errorf("Invalid maintenance window CID [%s]", maintenanceCID) 172 } 173 174 _, err = a.Delete(maintenanceCID) 175 if err != nil { 176 return false, err 177 } 178 179 return true, nil 180} 181 182// SearchMaintenanceWindows returns maintenance [windows] matching 183// the specified search query and/or filter. If nil is passed for 184// both parameters all maintenance [windows] will be returned. 185func (a *API) SearchMaintenanceWindows(searchCriteria *SearchQueryType, filterCriteria *SearchFilterType) (*[]Maintenance, error) { 186 q := url.Values{} 187 188 if searchCriteria != nil && *searchCriteria != "" { 189 q.Set("search", string(*searchCriteria)) 190 } 191 192 if filterCriteria != nil && len(*filterCriteria) > 0 { 193 for filter, criteria := range *filterCriteria { 194 for _, val := range criteria { 195 q.Add(filter, val) 196 } 197 } 198 } 199 200 if q.Encode() == "" { 201 return a.FetchMaintenanceWindows() 202 } 203 204 reqURL := url.URL{ 205 Path: config.MaintenancePrefix, 206 RawQuery: q.Encode(), 207 } 208 209 result, err := a.Get(reqURL.String()) 210 if err != nil { 211 return nil, fmt.Errorf("[ERROR] API call error %+v", err) 212 } 213 214 var windows []Maintenance 215 if err := json.Unmarshal(result, &windows); err != nil { 216 return nil, err 217 } 218 219 return &windows, nil 220} 221