console/service/alerting/destination.go

635 lines
15 KiB
Go

package alerting
import (
"errors"
"fmt"
"infini.sh/console/config"
"infini.sh/console/model/alerting"
httprouter "infini.sh/framework/core/api/router"
"infini.sh/framework/core/elastic"
"infini.sh/framework/core/orm"
"infini.sh/framework/core/util"
"net/http"
"strings"
"time"
)
func GetDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
conf := getDefaultConfig()
dstID := ps.ByName("destID")
reqUrl := fmt.Sprintf("%s/%s/_doc/%s", conf.Endpoint, orm.GetIndexName(alerting.Config{}), dstID)
res, err := doRequest(reqUrl, http.MethodGet, nil, nil)
if err != nil {
writeError(w, err)
return
}
var resBody = IfaceMap{}
err = decodeJSON(res.Body, &resBody)
if err != nil {
writeError(w, err)
return
}
res.Body.Close()
writeJSON(w, IfaceMap{
"ok": true,
"destination": queryValue(resBody, "_source.destination", nil),
}, http.StatusOK)
}
func GetDestinations(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
var (
from = getQueryParam(req, "from", "0")
size = getQueryParam(req, "size", "20")
search = getQueryParam(req, "search", "")
sortDirection = getQueryParam(req, "sortDirection", "desc")
sortField = getQueryParam(req, "sortField", "")
typ = getQueryParam(req, "type", "")
)
must := []IfaceMap{
{
"exists": IfaceMap{
"field": DESTINATION_FIELD,
},
},
//{
// "match": IfaceMap{
// "cluster_id": id,
// },
//},
}
if clearSearch := strings.TrimSpace(search); clearSearch != "" {
clearSearch = strings.ReplaceAll(clearSearch, " ", "* *")
must = append(must, IfaceMap{
"query_string": IfaceMap{
//"default_field": "destination.name",
"default_operator": "AND",
"query": fmt.Sprintf(`*%s*`, clearSearch),
},
})
}
var sort interface{} = IfaceMap{}
switch (sortField) {
case "name":
sort = IfaceMap{ "destination.name.keyword": sortDirection }
case "type":
sort = IfaceMap{ "destination.type": sortDirection }
default:
}
if typ != "" && typ != "ALL" {
must = append(must, IfaceMap{
"match": IfaceMap{
"destination.type": typ,
},
})
}
reqBody := IfaceMap{
"from": from,
"size": size,
"sort": sort,
"query": IfaceMap{
"bool": IfaceMap{
"must": must,
},
},
}
esConfig := getDefaultConfig()
esClient := elastic.GetClient(esConfig.ID)
res, err := esClient.SearchWithRawQueryDSL( orm.GetIndexName(alerting.Config{}), util.MustToJSONBytes(reqBody))
if err != nil {
writeError(w, err)
return
}
totalDestinations := res.GetTotal()
rawHits := res.Hits.Hits
dests := []IfaceMap{}
for _, hit := range rawHits {
newItem := IfaceMap{}
newItem["id"] = hit.ID
source := queryValue(hit.Source,DESTINATION_FIELD, nil)
if ms, ok := source.(map[string]interface{}); ok {
assignTo(newItem, ms)
}
dests = append(dests, newItem)
}
writeJSON(w, IfaceMap{
"ok": true,
"destinations": dests,
"totalDestinations":totalDestinations,
}, http.StatusOK)
}
func CreateDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
esConfig := getDefaultConfig()
destId := util.GetUUID()
var destination = &alerting.Destination{}
err := decodeJSON(req.Body, &destination)
if err != nil {
writeError(w, err)
return
}
destination.LastUpdateTime = time.Now().UnixNano()/1e6
var toSaveDest = IfaceMap{
"type": destination.Type,
"name": destination.Name,
"last_update_time": destination.LastUpdateTime,
"schema_version": destination.SchemaVersion,
"id": destId,
}
switch destination.Type {
case "email" :
toSaveDest[destination.Type] = destination.Email
case "custom_webhook":
toSaveDest[destination.Type] = destination.CustomWebhook
default:
writeError(w, errors.New("type unsupported"))
return
}
esClient := elastic.GetClient(esConfig.ID)
indexRes, err := esClient.Index(orm.GetIndexName(alerting.Config{}), "", destId, IfaceMap{
DESTINATION_FIELD: toSaveDest,
}, "wait_for")
if err != nil {
writeError(w, err)
return
}
writeJSON(w, IfaceMap{
"ok": true,
"resp": IfaceMap{
DESTINATION_FIELD: toSaveDest,
"_id": indexRes.ID,
"_version": indexRes.Version,
},
}, http.StatusOK)
}
func UpdateDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
destinationId := ps.ByName("destinationId")
config := getDefaultConfig()
var destination = &alerting.Destination{}
err := decodeJSON(req.Body, &destination)
if err != nil {
writeError(w, err)
return
}
destination.LastUpdateTime = time.Now().UnixNano()/1e6
var toSaveDest = IfaceMap{
"type": destination.Type,
"name": destination.Name,
"last_update_time": destination.LastUpdateTime,
"schema_version": destination.SchemaVersion,
"id": destinationId,
}
switch destination.Type {
case "email" :
toSaveDest[destination.Type] = destination.Email
case "custom_webhook":
toSaveDest[destination.Type] = destination.CustomWebhook
default:
writeError(w, errors.New("type unsupported"))
return
}
esClient := elastic.GetClient(config.ID)
indexRes, err := esClient.Index(orm.GetIndexName(alerting.Config{}), "", destinationId, IfaceMap{
DESTINATION_FIELD: toSaveDest,
}, "wait_for")
if err != nil {
writeError(w, err)
return
}
writeJSON(w, IfaceMap{
"ok": true,
"version": indexRes.Version,
"id": indexRes.ID,
}, http.StatusOK)
}
func DeleteDestination(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
destinationId := ps.ByName("destinationId")
config := getDefaultConfig()
esClient := elastic.GetClient(config.ID)
deleteRes, err := esClient.Delete(orm.GetIndexName(alerting.Config{}), "", destinationId)
if err != nil {
writeError(w, err)
return
}
var isOk = false
if deleteRes.Result == "deleted" {
isOk = true
}
writeJSON(w, IfaceMap{
"ok": isOk,
}, http.StatusOK)
}
func getDefaultConfig() *elastic.ElasticsearchConfig {
elasticsearch := "default"
if appConfig != nil {
elasticsearch = appConfig.Elasticsearch
}
return elastic.GetConfig(elasticsearch)
}
var appConfig *config.AppConfig
func InitAppConfig(config *config.AppConfig){
appConfig = config
}
//var (
// ks keystore.WritableKeystore
// ksOnce = &sync.Once{}
//)
//func getKeystore() keystore.WritableKeystore {
// ksOnce.Do(func() {
// tempKS, err := keystore.Factory(nil, "data/search-center/keystore")
// if err != nil {
// panic(err)
// }
// ks, err = keystore.AsWritableKeystore(tempKS)
// if err != nil {
// panic(err)
// }
// })
// return ks
//}
func CreateEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
config := getDefaultConfig()
var emailAccount = &alerting.EmailAccount{}
err := decodeJSON(req.Body, &emailAccount)
if err != nil {
writeError(w, err)
return
}
//var password = emailAccount.Password
//emailAccount.Password = ""
esClient := elastic.GetClient(config.ID)
indexRes, err := esClient.Index(orm.GetIndexName(alerting.Config{}), "", util.GetUUID(), IfaceMap{
EMAIL_ACCOUNT_FIELD: emailAccount,
},"wait_for")
if err != nil {
writeError(w, err)
return
}
//kk := fmt.Sprintf("search-center_alerting.destination.email.%s.password", emailAccount.Name)
//secStr, _ := getKeystore().Retrieve(kk)
//kst := getKeystore()
//if secStr == nil {
// kst.Store(kk, []byte(password))
// kst.Save()
//}else{
// oldPwd, _ := secStr.Get()
// if bytes.Compare(oldPwd, []byte(password)) != 0 {
// kst.Store(kk, []byte(password))
// }
// kst.Save()
//}
writeJSON(w, IfaceMap{
"ok": true,
"resp": IfaceMap{
EMAIL_ACCOUNT_FIELD: emailAccount,
"_id": indexRes.ID,
"_version": indexRes.Version,
},
}, http.StatusOK)
}
func UpdateEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
emailAccountId := ps.ByName("emailAccountId")
config := getDefaultConfig()
var emailAccount = &alerting.EmailAccount{}
err := decodeJSON(req.Body, &emailAccount)
if err != nil {
writeError(w, err)
return
}
esClient := elastic.GetClient(config.ID)
indexRes, err := esClient.Index(orm.GetIndexName(alerting.Config{}),"", emailAccountId, IfaceMap{
EMAIL_ACCOUNT_FIELD: emailAccount,
}, "wait_for")
if err != nil {
writeError(w, err)
return
}
writeJSON(w, IfaceMap{
"ok": true,
"id": indexRes.ID,
}, http.StatusOK)
}
func DeleteEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
emailAccountId := ps.ByName("emailAccountId")
config := getDefaultConfig()
esClient := elastic.GetClient(config.ID)
deleteRes, err := esClient.Delete(orm.GetIndexName(alerting.Config{}), "", emailAccountId, "wait_for")
if err != nil {
writeError(w, err)
return
}
var isOk = false
if deleteRes.Result == "deleted" {
isOk = true
}
writeJSON(w, IfaceMap{
"ok": isOk,
}, http.StatusOK)
}
func GetEmailAccounts(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
var (
from = getQueryParam(req, "from", "0")
size = getQueryParam(req, "size", "20")
search = getQueryParam(req, "search", "")
sortDirection = getQueryParam(req, "sortDirection", "desc")
sortField = getQueryParam(req, "sortField", "name")
)
must := []IfaceMap{
{
"exists": IfaceMap{
"field": EMAIL_ACCOUNT_FIELD,
},
},
}
if clearSearch := strings.TrimSpace(search); clearSearch != "" {
clearSearch = strings.ReplaceAll(clearSearch, " ", "* *")
must = append(must, IfaceMap{
"query_string": IfaceMap{
"default_field": "email_account.name",
"default_operator": "AND",
"query": fmt.Sprintf(`*%s*`, clearSearch),
},
})
}
sortQueryMap := IfaceMap{ "name": IfaceMap{ "email_account.name.keyword": sortDirection } }
var sort interface{}
if sortQuery, ok := sortQueryMap[sortField]; ok {
sort = sortQuery
}
reqBody := IfaceMap{
"from": from,
"size": size,
"sort": sort,
"query": IfaceMap{
"bool": IfaceMap{
"must": must,
},
},
}
config := getDefaultConfig()
esClient := elastic.GetClient(config.ID)
searchRes, err := esClient.SearchWithRawQueryDSL( orm.GetIndexName(alerting.Config{}), util.MustToJSONBytes(reqBody))
if err != nil {
writeError(w, err)
return
}
totalEmailAccounts := searchRes.GetTotal()
rawHits := searchRes.Hits.Hits
emailAccounts := []IfaceMap{}
for _, hit := range rawHits {
newItem := IfaceMap{}
newItem["id"] = hit.ID
source := queryValue(hit.Source, EMAIL_ACCOUNT_FIELD, nil)
if ms, ok := source.(map[string]interface{}); ok {
assignTo(newItem, ms)
}
emailAccounts = append(emailAccounts, newItem)
}
writeJSON(w, IfaceMap{
"ok": true,
"emailAccounts": emailAccounts,
"totalEmailAccounts": totalEmailAccounts,
}, http.StatusOK)
}
func GetEmailAccount(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
emailAccountId := ps.ByName("emailAccountId")
config := getDefaultConfig()
esClient := elastic.GetClient(config.ID)
getRes, err := esClient.Get(orm.GetIndexName(alerting.Config{}), "", emailAccountId)
if err != nil {
writeError(w, err)
return
}
//name := queryValue(resBody,"_source.email_account.name", "")
//kk := fmt.Sprintf("search-center_alerting.destination.email.%s.password", name)
//secStr, _ := getKeystore().Retrieve(kk)
//if secStr != nil {
// pwd, _ := secStr.Get()
// fmt.Println(string(pwd))
//}
writeJSON(w, IfaceMap{
"ok": true,
"resp": queryValue(getRes.Source, "email_account", nil),
}, http.StatusOK)
}
// --- email group
func CreateEmailGroup(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
config := getDefaultConfig()
var emailGroup = &alerting.EmailGroup{}
err := decodeJSON(req.Body, &emailGroup)
if err != nil {
writeError(w, err)
return
}
esClient := elastic.GetClient(config.ID)
indexRes, err := esClient.Index(orm.GetIndexName(alerting.Config{}), "", util.GetUUID(), IfaceMap{
EMAIL_GROUP_FIELD: emailGroup,
},"wait_for")
if err != nil {
writeError(w, err)
return
}
writeJSON(w, IfaceMap{
"ok": true,
"resp": IfaceMap{
EMAIL_GROUP_FIELD: IfaceMap{
"emails": emailGroup.Emails,
"name": emailGroup.Name,
"schema_version": emailGroup.SchemaVersion,
},
"_id": indexRes.ID,
"_version": indexRes.Version,
},
}, http.StatusOK)
}
func UpdateEmailGroup(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
emailGroupId := ps.ByName("emailGroupId")
config := getDefaultConfig()
var emailGroup = &alerting.EmailGroup{}
err := decodeJSON(req.Body, &emailGroup)
if err != nil {
writeError(w, err)
return
}
esClient := elastic.GetClient(config.ID)
indexRes, err := esClient.Index( orm.GetIndexName(alerting.Config{}), "", emailGroupId, IfaceMap{
EMAIL_GROUP_FIELD: emailGroup,
}, "wait_for")
if err != nil {
writeError(w, err)
return
}
writeJSON(w, IfaceMap{
"ok": true,
"id": indexRes.ID,
}, http.StatusOK)
}
func DeleteEmailGroup(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
emailGroupId := ps.ByName("emailGroupId")
config := getDefaultConfig()
esClient := elastic.GetClient(config.ID)
res, err := esClient.Delete(orm.GetIndexName(alerting.Config{}), "", emailGroupId)
if err != nil {
writeError(w, err)
return
}
var isOk = false
if res.Result == "deleted" {
isOk = true
}
writeJSON(w, IfaceMap{
"ok": isOk,
}, http.StatusOK)
}
func GetEmailGroups(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
var (
from = getQueryParam(req, "from", "0")
size = getQueryParam(req, "size", "20")
search = getQueryParam(req, "search", "")
sortDirection = getQueryParam(req, "sortDirection", "desc")
sortField = getQueryParam(req, "sortField", "name")
)
must := []IfaceMap{
{
"exists": IfaceMap{
"field": EMAIL_GROUP_FIELD,
},
},
}
if clearSearch := strings.TrimSpace(search); clearSearch != "" {
clearSearch = strings.ReplaceAll(clearSearch, " ", "* *")
must = append(must, IfaceMap{
"query_string": IfaceMap{
"default_field": "email_group.name",
"default_operator": "AND",
"query": fmt.Sprintf(`*%s*`, clearSearch),
},
})
}
sortQueryMap := IfaceMap{ "name": IfaceMap{ "email_group.name.keyword": sortDirection } }
var sort interface{}
if sortQuery, ok := sortQueryMap[sortField]; ok {
sort = sortQuery
}
reqBody := IfaceMap{
"from": from,
"size": size,
"sort": sort,
"query": IfaceMap{
"bool": IfaceMap{
"must": must,
},
},
}
config := getDefaultConfig()
esClient := elastic.GetClient(config.ID)
res, err := esClient.SearchWithRawQueryDSL(orm.GetIndexName(alerting.Config{}), util.MustToJSONBytes(reqBody))
if err != nil {
writeError(w, err)
return
}
totalEmailGroups := res.GetTotal()
rawHits := res.Hits.Hits
emailGroups := []IfaceMap{}
for _, hit := range rawHits {
newItem := IfaceMap{}
newItem["id"] = hit.ID
source := queryValue(hit.Source, EMAIL_GROUP_FIELD, nil)
if ms, ok := source.(map[string]interface{}); ok {
assignTo(newItem, ms)
}
emailGroups = append(emailGroups, newItem)
}
writeJSON(w, IfaceMap{
"ok": true,
"emailGroups": emailGroups,
"totalEmailGroups": totalEmailGroups,
}, http.StatusOK)
}
func GetEmailGroup(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
emailGroupId := ps.ByName("emailGroupId")
config := getDefaultConfig()
esClient := elastic.GetClient(config.ID)
getRes, err := esClient.Get(orm.GetIndexName(alerting.Config{}), "", emailGroupId)
if err != nil {
writeError(w, err)
return
}
emailGroup := queryValue(getRes.Source, EMAIL_GROUP_FIELD, nil)
if emailGroup == nil {
writeJSON(w, IfaceMap{
"ok": false,
}, http.StatusOK)
return
}
writeJSON(w, IfaceMap{
"ok": true,
"resp": emailGroup,
}, http.StatusOK)
}