mirror of
https://github.com/ccfos/nightingale.git
synced 2026-03-10 18:08:58 +00:00
Compare commits
7 Commits
op-set
...
optimize-o
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73e5e8096b | ||
|
|
c5ae1b2136 | ||
|
|
f3db007423 | ||
|
|
8b99be7a83 | ||
|
|
fe05b0b242 | ||
|
|
ab54baeb7e | ||
|
|
0ba31842a0 |
@@ -90,11 +90,12 @@
|
||||
- 推荐搜索关注夜莺公众号,第一时间获取社区动态:`夜莺监控Nightingale`
|
||||
- 日常问题交流:
|
||||
- QQ群:730841964
|
||||
- [加入微信群](https://download.flashcat.cloud/ulric/20241008153952.png),如果二维码过期了,可以联系我(我的微信:`picobyte`)拉群,备注: `夜莺互助群`
|
||||
- [加入微信群](https://download.flashcat.cloud/ulric/20240926101321.png),如果二维码过期了,可以联系我(我的微信:`picobyte`)拉群,备注: `夜莺互助群`
|
||||
|
||||
## 广受关注
|
||||
[](https://star-history.com/#ccfos/nightingale&Date)
|
||||
|
||||
|
||||
## 社区共建
|
||||
- ❇️ 请阅读浏览[夜莺开源项目和社区治理架构草案](./doc/community-governance.md),真诚欢迎每一位用户、开发者、公司以及组织,使用夜莺监控、积极反馈 Bug、提交功能需求、分享最佳实践,共建专业、活跃的夜莺开源社区。
|
||||
- ❤️ 夜莺贡献者
|
||||
|
||||
@@ -60,6 +60,10 @@ func (a *Alert) PreCheck(configDir string) {
|
||||
a.Heartbeat.Interval = 1000
|
||||
}
|
||||
|
||||
if a.Heartbeat.EngineName == "" {
|
||||
a.Heartbeat.EngineName = "default"
|
||||
}
|
||||
|
||||
if a.EngineDelay == 0 {
|
||||
a.EngineDelay = 30
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -268,7 +267,7 @@ func (arw *AlertRuleWorker) GetTdengineAnomalyPoint(rule *models.AlertRule, dsId
|
||||
if len(ruleQuery.Queries) > 0 {
|
||||
seriesStore := make(map[uint64]models.DataResp)
|
||||
// 将不同查询的 hash 索引分组存放
|
||||
seriesTagIndexes := make(map[string]map[uint64][]uint64)
|
||||
seriesTagIndexes := make([]map[uint64][]uint64, 0)
|
||||
|
||||
for _, query := range ruleQuery.Queries {
|
||||
seriesTagIndex := make(map[uint64][]uint64)
|
||||
@@ -293,13 +292,7 @@ func (arw *AlertRuleWorker) GetTdengineAnomalyPoint(rule *models.AlertRule, dsId
|
||||
// 此条日志很重要,是告警判断的现场值
|
||||
logger.Debugf("rule_eval rid:%d req:%+v resp:%+v", rule.Id, query, series)
|
||||
MakeSeriesMap(series, seriesTagIndex, seriesStore)
|
||||
ref, err := GetQueryRef(query)
|
||||
if err != nil {
|
||||
logger.Warningf("rule_eval rid:%d query ref error: %v query:%+v", rule.Id, err, query)
|
||||
arw.processor.Stats.CounterRuleEvalErrorTotal.WithLabelValues(fmt.Sprintf("%v", arw.processor.DatasourceId()), GET_RULE_CONFIG).Inc()
|
||||
continue
|
||||
}
|
||||
seriesTagIndexes[ref] = seriesTagIndex
|
||||
seriesTagIndexes = append(seriesTagIndexes, seriesTagIndex)
|
||||
}
|
||||
|
||||
points, recoverPoints = GetAnomalyPoint(rule.Id, ruleQuery, seriesTagIndexes, seriesStore)
|
||||
@@ -452,7 +445,7 @@ func (arw *AlertRuleWorker) GetHostAnomalyPoint(ruleConfig string) []common.Anom
|
||||
return lst
|
||||
}
|
||||
|
||||
func GetAnomalyPoint(ruleId int64, ruleQuery models.RuleQuery, seriesTagIndexes map[string]map[uint64][]uint64, seriesStore map[uint64]models.DataResp) ([]common.AnomalyPoint, []common.AnomalyPoint) {
|
||||
func GetAnomalyPoint(ruleId int64, ruleQuery models.RuleQuery, seriesTagIndexes []map[uint64][]uint64, seriesStore map[uint64]models.DataResp) ([]common.AnomalyPoint, []common.AnomalyPoint) {
|
||||
points := []common.AnomalyPoint{}
|
||||
recoverPoints := []common.AnomalyPoint{}
|
||||
|
||||
@@ -466,7 +459,59 @@ func GetAnomalyPoint(ruleId int64, ruleQuery models.RuleQuery, seriesTagIndexes
|
||||
|
||||
for _, trigger := range ruleQuery.Triggers {
|
||||
// seriesTagIndex 的 key 仅做分组使用,value 为每组 series 的 hash
|
||||
seriesTagIndex := ProcessJoins(ruleId, trigger, seriesTagIndexes, seriesStore)
|
||||
seriesTagIndex := make(map[uint64][]uint64)
|
||||
|
||||
if len(trigger.Joins) == 0 {
|
||||
// 没有 join 条件,走原逻辑
|
||||
last := seriesTagIndexes[0]
|
||||
for i := 1; i < len(seriesTagIndexes); i++ {
|
||||
last = originalJoin(last, seriesTagIndexes[i])
|
||||
}
|
||||
seriesTagIndex = last
|
||||
} else {
|
||||
// 有 join 条件,按条件依次合并
|
||||
if len(seriesTagIndexes) != len(trigger.Joins)+1 {
|
||||
logger.Errorf("rule_eval rid:%d queries' count: %d not match join condition's count: %d", ruleId, len(seriesTagIndexes), len(trigger.Joins))
|
||||
continue
|
||||
}
|
||||
|
||||
last := seriesTagIndexes[0]
|
||||
lastRehashed := rehashSet(last, seriesStore, trigger.Joins[0].On)
|
||||
for i := range trigger.Joins {
|
||||
cur := seriesTagIndexes[i+1]
|
||||
switch trigger.Joins[i].JoinType {
|
||||
case "original":
|
||||
last = originalJoin(last, cur)
|
||||
case "none":
|
||||
last = noneJoin(last, cur)
|
||||
case "cartesian":
|
||||
last = cartesianJoin(last, cur)
|
||||
case "inner_join":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = onJoin(lastRehashed, curRehashed, Inner)
|
||||
last = flatten(lastRehashed)
|
||||
case "left_join":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = onJoin(lastRehashed, curRehashed, Left)
|
||||
last = flatten(lastRehashed)
|
||||
case "right_join":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = onJoin(curRehashed, lastRehashed, Right)
|
||||
last = flatten(lastRehashed)
|
||||
case "left_exclude":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = exclude(lastRehashed, curRehashed)
|
||||
last = flatten(lastRehashed)
|
||||
case "right_exclude":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = exclude(curRehashed, lastRehashed)
|
||||
last = flatten(lastRehashed)
|
||||
default:
|
||||
logger.Warningf("rule_eval rid:%d join type:%s not support", ruleId, trigger.Joins[i].JoinType)
|
||||
}
|
||||
}
|
||||
seriesTagIndex = last
|
||||
}
|
||||
|
||||
for _, seriesHash := range seriesTagIndex {
|
||||
sort.Slice(seriesHash, func(i, j int) bool {
|
||||
@@ -562,7 +607,7 @@ func flatten(rehashed map[uint64][][]uint64) map[uint64][]uint64 {
|
||||
// [[A3{data_base=2, table=board},B2{data_base=2, table=alert}],[A4{data_base=2, table=alert},B2{data_base=2, table=alert}]]
|
||||
func onJoin(reHashTagIndex1 map[uint64][][]uint64, reHashTagIndex2 map[uint64][][]uint64, joinType JoinType) map[uint64][][]uint64 {
|
||||
reHashTagIndex := make(map[uint64][][]uint64)
|
||||
for rehash := range reHashTagIndex1 {
|
||||
for rehash, _ := range reHashTagIndex1 {
|
||||
if _, ok := reHashTagIndex2[rehash]; ok {
|
||||
// 若有 rehash 相同的记录,两两合并
|
||||
for i1 := range reHashTagIndex1[rehash] {
|
||||
@@ -605,7 +650,6 @@ func rehashSet(seriesTagIndex1 map[uint64][]uint64, seriesStore map[uint64]model
|
||||
if !exists {
|
||||
continue
|
||||
}
|
||||
|
||||
rehash := hash.GetTargetTagHash(series.Metric, on)
|
||||
if _, ok := reHashTagIndex[rehash]; !ok {
|
||||
reHashTagIndex[rehash] = make([][]uint64, 0)
|
||||
@@ -697,100 +741,3 @@ func mergeNewArray(arg ...[]uint64) []uint64 {
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func ProcessJoins(ruleId int64, trigger models.Trigger, seriesTagIndexes map[string]map[uint64][]uint64, seriesStore map[uint64]models.DataResp) map[uint64][]uint64 {
|
||||
last := make(map[uint64][]uint64)
|
||||
if len(seriesTagIndexes) == 0 {
|
||||
return last
|
||||
}
|
||||
|
||||
if len(trigger.Joins) == 0 {
|
||||
idx := 0
|
||||
for _, seriesTagIndex := range seriesTagIndexes {
|
||||
if idx == 0 {
|
||||
last = seriesTagIndex
|
||||
} else {
|
||||
last = originalJoin(last, seriesTagIndex)
|
||||
}
|
||||
idx++
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
// 有 join 条件,按条件依次合并
|
||||
if len(seriesTagIndexes) < len(trigger.Joins)+1 {
|
||||
logger.Errorf("rule_eval rid:%d queries' count: %d not match join condition's count: %d", ruleId, len(seriesTagIndexes), len(trigger.Joins))
|
||||
return nil
|
||||
}
|
||||
|
||||
last = seriesTagIndexes[trigger.JoinRef]
|
||||
lastRehashed := rehashSet(last, seriesStore, trigger.Joins[0].On)
|
||||
for i := range trigger.Joins {
|
||||
cur := seriesTagIndexes[trigger.Joins[i].Ref]
|
||||
switch trigger.Joins[i].JoinType {
|
||||
case "original":
|
||||
last = originalJoin(last, cur)
|
||||
case "none":
|
||||
last = noneJoin(last, cur)
|
||||
case "cartesian":
|
||||
last = cartesianJoin(last, cur)
|
||||
case "inner_join":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = onJoin(lastRehashed, curRehashed, Inner)
|
||||
last = flatten(lastRehashed)
|
||||
case "left_join":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = onJoin(lastRehashed, curRehashed, Left)
|
||||
last = flatten(lastRehashed)
|
||||
case "right_join":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = onJoin(curRehashed, lastRehashed, Right)
|
||||
last = flatten(lastRehashed)
|
||||
case "left_exclude":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = exclude(lastRehashed, curRehashed)
|
||||
last = flatten(lastRehashed)
|
||||
case "right_exclude":
|
||||
curRehashed := rehashSet(cur, seriesStore, trigger.Joins[i].On)
|
||||
lastRehashed = exclude(curRehashed, lastRehashed)
|
||||
last = flatten(lastRehashed)
|
||||
default:
|
||||
logger.Warningf("rule_eval rid:%d join type:%s not support", ruleId, trigger.Joins[i].JoinType)
|
||||
}
|
||||
}
|
||||
return last
|
||||
}
|
||||
|
||||
func GetQueryRef(query interface{}) (string, error) {
|
||||
// 首先检查是否为 map
|
||||
if m, ok := query.(map[string]interface{}); ok {
|
||||
if ref, exists := m["ref"]; exists {
|
||||
if refStr, ok := ref.(string); ok {
|
||||
return refStr, nil
|
||||
}
|
||||
return "", fmt.Errorf("ref 字段不是字符串类型")
|
||||
}
|
||||
return "", fmt.Errorf("query 中没有找到 ref 字段")
|
||||
}
|
||||
|
||||
// 如果不是 map,则按原来的方式处理结构体
|
||||
v := reflect.ValueOf(query)
|
||||
if v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
if v.Kind() != reflect.Struct {
|
||||
return "", fmt.Errorf("query not a struct or map")
|
||||
}
|
||||
|
||||
refField := v.FieldByName("Ref")
|
||||
if !refField.IsValid() {
|
||||
return "", fmt.Errorf("not find ref field")
|
||||
}
|
||||
|
||||
if refField.Kind() != reflect.String {
|
||||
return "", fmt.Errorf("ref not a string")
|
||||
}
|
||||
|
||||
return refField.String(), nil
|
||||
}
|
||||
|
||||
@@ -72,7 +72,7 @@ func Initialize(configDir string, cryptoKey string) (func(), error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go integration.Init(ctx, config.Center.BuiltinIntegrationsDir)
|
||||
integration.Init(ctx, config.Center.BuiltinIntegrationsDir)
|
||||
var redis storage.Redis
|
||||
redis, err = storage.NewRedis(config.Redis)
|
||||
if err != nil {
|
||||
@@ -115,7 +115,10 @@ func Initialize(configDir string, cryptoKey string) (func(), error) {
|
||||
redis, sso, ctx, metas, idents, targetCache, userCache, userGroupCache)
|
||||
pushgwRouter := pushgwrt.New(config.HTTP, config.Pushgw, config.Alert, targetCache, busiGroupCache, idents, metas, writers, ctx)
|
||||
|
||||
go models.MigrateBg(ctx, pushgwRouter.Pushgw.BusiGroupLabelKey)
|
||||
models.MigrateBg(ctx, pushgwRouter.Pushgw.BusiGroupLabelKey)
|
||||
if config.Center.MigrateBusiGroupLabel {
|
||||
models.DoMigrateBg(ctx, config.Pushgw.BusiGroupLabelKey)
|
||||
}
|
||||
|
||||
r := httpx.GinEngine(config.Global.RunMode, config.HTTP)
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/ccfos/nightingale/v6/conf"
|
||||
_ "github.com/ccfos/nightingale/v6/front/statik"
|
||||
"github.com/ccfos/nightingale/v6/memsto"
|
||||
"github.com/ccfos/nightingale/v6/models"
|
||||
"github.com/ccfos/nightingale/v6/pkg/aop"
|
||||
"github.com/ccfos/nightingale/v6/pkg/ctx"
|
||||
"github.com/ccfos/nightingale/v6/pkg/httpx"
|
||||
@@ -52,7 +51,6 @@ type Router struct {
|
||||
UserGroupCache *memsto.UserGroupCacheType
|
||||
Ctx *ctx.Context
|
||||
HeartbeatHook HeartbeatHookFunc
|
||||
TargetDeleteHook models.TargetDeleteHookFunc
|
||||
}
|
||||
|
||||
func New(httpConfig httpx.Config, center cconf.Center, alert aconf.Alert, ibex conf.Ibex,
|
||||
@@ -79,14 +77,9 @@ func New(httpConfig httpx.Config, center cconf.Center, alert aconf.Alert, ibex c
|
||||
UserGroupCache: ugc,
|
||||
Ctx: ctx,
|
||||
HeartbeatHook: func(ident string) map[string]interface{} { return nil },
|
||||
TargetDeleteHook: emptyDeleteHook,
|
||||
}
|
||||
}
|
||||
|
||||
func emptyDeleteHook(ctx *ctx.Context, idents []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func stat() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
start := time.Now()
|
||||
@@ -475,7 +468,6 @@ func (rt *Router) Config(r *gin.Engine) {
|
||||
pages.GET("/builtin-payload/:id", rt.auth(), rt.user(), rt.perm("/built-in-components"), rt.builtinPayloadGet)
|
||||
pages.PUT("/builtin-payloads", rt.auth(), rt.user(), rt.perm("/built-in-components/put"), rt.builtinPayloadsPut)
|
||||
pages.DELETE("/builtin-payloads", rt.auth(), rt.user(), rt.perm("/built-in-components/del"), rt.builtinPayloadsDel)
|
||||
pages.GET("/builtin-payload", rt.auth(), rt.user(), rt.builtinPayloadsGetByUUIDOrID)
|
||||
}
|
||||
|
||||
r.GET("/api/n9e/versions", func(c *gin.Context) {
|
||||
|
||||
@@ -206,9 +206,7 @@ func (rt *Router) checkCurEventBusiGroupRWPermission(c *gin.Context, ids []int64
|
||||
for i := 0; i < len(ids); i++ {
|
||||
event, err := models.AlertCurEventGetById(rt.Ctx, ids[i])
|
||||
ginx.Dangerous(err)
|
||||
if event == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if _, has := set[event.GroupId]; !has {
|
||||
rt.bgrwCheck(c, event.GroupId)
|
||||
set[event.GroupId] = struct{}{}
|
||||
|
||||
@@ -73,12 +73,10 @@ func (rt *Router) alertRuleGetsByGids(c *gin.Context) {
|
||||
if err == nil {
|
||||
cache := make(map[int64]*models.UserGroup)
|
||||
rids := make([]int64, 0, len(ars))
|
||||
names := make([]string, 0, len(ars))
|
||||
for i := 0; i < len(ars); i++ {
|
||||
ars[i].FillNotifyGroups(rt.Ctx, cache)
|
||||
ars[i].FillSeverities()
|
||||
rids = append(rids, ars[i].Id)
|
||||
names = append(names, ars[i].UpdateBy)
|
||||
}
|
||||
|
||||
stime, etime := getAlertCueEventTimeRange(c)
|
||||
@@ -88,15 +86,6 @@ func (rt *Router) alertRuleGetsByGids(c *gin.Context) {
|
||||
ars[i].CurEventCount = cnt[ars[i].Id]
|
||||
}
|
||||
}
|
||||
|
||||
users := models.UserMapGet(rt.Ctx, "username in (?)", names)
|
||||
if users != nil {
|
||||
for i := 0; i < len(ars); i++ {
|
||||
if user, exist := users[ars[i].UpdateBy]; exist {
|
||||
ars[i].UpdateByNickname = user.Nickname
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ginx.NewRender(c).Data(ars, err)
|
||||
}
|
||||
|
||||
@@ -260,15 +260,3 @@ func (rt *Router) builtinPayloadsDel(c *gin.Context) {
|
||||
|
||||
ginx.NewRender(c).Message(models.BuiltinPayloadDels(rt.Ctx, req.Ids))
|
||||
}
|
||||
|
||||
func (rt *Router) builtinPayloadsGetByUUIDOrID(c *gin.Context) {
|
||||
uuid := ginx.QueryInt64(c, "uuid", 0)
|
||||
// 优先以 uuid 为准
|
||||
if uuid != 0 {
|
||||
ginx.NewRender(c).Data(models.BuiltinPayloadGet(rt.Ctx, "uuid = ?", uuid))
|
||||
return
|
||||
}
|
||||
|
||||
id := ginx.QueryInt64(c, "id", 0)
|
||||
ginx.NewRender(c).Data(models.BuiltinPayloadGet(rt.Ctx, "id = ?", id))
|
||||
}
|
||||
|
||||
@@ -92,12 +92,10 @@ func (rt *Router) datasourceUpsert(c *gin.Context) {
|
||||
var err error
|
||||
var count int64
|
||||
|
||||
if !req.ForceSave {
|
||||
err = DatasourceCheck(req)
|
||||
if err != nil {
|
||||
Dangerous(c, err)
|
||||
return
|
||||
}
|
||||
err = DatasourceCheck(req)
|
||||
if err != nil {
|
||||
Dangerous(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
if req.Id == 0 {
|
||||
|
||||
@@ -502,7 +502,7 @@ func (rt *Router) targetDel(c *gin.Context) {
|
||||
ginx.Bomb(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
ginx.NewRender(c).Data(failedResults, models.TargetDel(rt.Ctx, f.Idents, rt.TargetDeleteHook))
|
||||
ginx.NewRender(c).Data(failedResults, models.TargetDel(rt.Ctx, f.Idents))
|
||||
}
|
||||
|
||||
func (rt *Router) targetDelByService(c *gin.Context) {
|
||||
@@ -521,7 +521,7 @@ func (rt *Router) targetDelByService(c *gin.Context) {
|
||||
ginx.Bomb(http.StatusBadRequest, err.Error())
|
||||
}
|
||||
|
||||
ginx.NewRender(c).Data(failedResults, models.TargetDel(rt.Ctx, f.Idents, rt.TargetDeleteHook))
|
||||
ginx.NewRender(c).Data(failedResults, models.TargetDel(rt.Ctx, f.Idents))
|
||||
}
|
||||
|
||||
func (rt *Router) checkTargetPerm(c *gin.Context, idents []string) {
|
||||
|
||||
@@ -1,463 +0,0 @@
|
||||
{
|
||||
"name": "IPMI for Prometheus",
|
||||
"ident": "",
|
||||
"configs": {
|
||||
"version": "2.0.0",
|
||||
"links": [],
|
||||
"var": [
|
||||
{
|
||||
"name": "node",
|
||||
"type": "query",
|
||||
"datasource": {
|
||||
"cate": "prometheus"
|
||||
},
|
||||
"definition": "label_values(ipmi_bmc_info, ident)",
|
||||
"reg": "",
|
||||
"multi": false
|
||||
}
|
||||
],
|
||||
"panels": [
|
||||
{
|
||||
"type": "gauge",
|
||||
"id": "f975fded-f57e-4a6e-80b4-50d5be6dd84c",
|
||||
"layout": {
|
||||
"h": 7,
|
||||
"w": 24,
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"i": "f975fded-f57e-4a6e-80b4-50d5be6dd84c",
|
||||
"isResizable": true
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"datasourceCate": "prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "ipmi_temperature_celsius{ident='$node'}",
|
||||
"legend": "{{name}}"
|
||||
}
|
||||
],
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"name": "Temperatures",
|
||||
"links": [],
|
||||
"custom": {
|
||||
"textMode": "valueAndName",
|
||||
"calc": "avg"
|
||||
},
|
||||
"options": {
|
||||
"valueMappings": [],
|
||||
"standardOptions": {
|
||||
"util": "none"
|
||||
},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null,
|
||||
"type": "base"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"id": "681f1191-4777-4377-8b77-404d9f036406",
|
||||
"layout": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 7,
|
||||
"i": "681f1191-4777-4377-8b77-404d9f036406",
|
||||
"isResizable": true
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"datasourceCate": "prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "ipmi_power_watts{ident='$node'}",
|
||||
"legend": "{{name}}"
|
||||
}
|
||||
],
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"name": "Power",
|
||||
"links": [],
|
||||
"options": {
|
||||
"tooltip": {
|
||||
"mode": "all",
|
||||
"sort": "none"
|
||||
},
|
||||
"legend": {
|
||||
"displayMode": "hidden"
|
||||
},
|
||||
"standardOptions": {},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "#634CD9",
|
||||
"value": null,
|
||||
"type": "base"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"drawStyle": "lines",
|
||||
"lineInterpolation": "smooth",
|
||||
"spanNulls": false,
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 0.5,
|
||||
"gradientMode": "none",
|
||||
"stack": "off",
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"id": "feede24c-8296-4127-982e-08cfc4151933",
|
||||
"layout": {
|
||||
"h": 5,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 7,
|
||||
"i": "feede24c-8296-4127-982e-08cfc4151933",
|
||||
"isResizable": true
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"datasourceCate": "prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "ipmi_power_watts{ident='$node'} * 30 * 24 ",
|
||||
"legend": "{{name}}"
|
||||
}
|
||||
],
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"name": "Power usage 30d",
|
||||
"links": [],
|
||||
"options": {
|
||||
"tooltip": {
|
||||
"mode": "all",
|
||||
"sort": "none"
|
||||
},
|
||||
"legend": {
|
||||
"displayMode": "hidden"
|
||||
},
|
||||
"standardOptions": {},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "#634CD9",
|
||||
"value": null,
|
||||
"type": "base"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"drawStyle": "lines",
|
||||
"lineInterpolation": "smooth",
|
||||
"spanNulls": false,
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 0.5,
|
||||
"gradientMode": "none",
|
||||
"stack": "off",
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"id": "9e11e7f5-ed3c-49eb-8a72-ee76c8700c24",
|
||||
"layout": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 12,
|
||||
"i": "9e11e7f5-ed3c-49eb-8a72-ee76c8700c24",
|
||||
"isResizable": true
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"datasourceCate": "prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "ipmi_temperature_celsius{ident='$node'}",
|
||||
"legend": "{{name}}"
|
||||
}
|
||||
],
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"name": "Temperatures",
|
||||
"links": [],
|
||||
"description": "",
|
||||
"options": {
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
},
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"standardOptions": {
|
||||
"util": "none"
|
||||
},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null,
|
||||
"type": "base"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"drawStyle": "lines",
|
||||
"lineInterpolation": "linear",
|
||||
"spanNulls": false,
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 0.5,
|
||||
"gradientMode": "none",
|
||||
"stack": "off",
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"id": "95c734f7-26cb-41a7-8376-49332cc220c2",
|
||||
"layout": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 12,
|
||||
"i": "95c734f7-26cb-41a7-8376-49332cc220c2",
|
||||
"isResizable": true
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"datasourceCate": "prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "ipmi_power_watts{ident='$node'}",
|
||||
"legend": "{{name}}"
|
||||
}
|
||||
],
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"name": "Power",
|
||||
"links": [],
|
||||
"description": "",
|
||||
"options": {
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
},
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"standardOptions": {
|
||||
"util": "none"
|
||||
},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null,
|
||||
"type": "base"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"drawStyle": "lines",
|
||||
"lineInterpolation": "linear",
|
||||
"spanNulls": false,
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 0.01,
|
||||
"gradientMode": "none",
|
||||
"stack": "off",
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"id": "0313f34f-afcf-41e9-8f69-9a3dbd4b2e56",
|
||||
"layout": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 19,
|
||||
"i": "0313f34f-afcf-41e9-8f69-9a3dbd4b2e56",
|
||||
"isResizable": true
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"datasourceCate": "prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "ipmi_fan_speed_rpm{ident='$node'}",
|
||||
"legend": "{{name}}"
|
||||
}
|
||||
],
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"name": "Fans",
|
||||
"links": [],
|
||||
"description": "",
|
||||
"options": {
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
},
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"standardOptions": {
|
||||
"util": "none"
|
||||
},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null,
|
||||
"type": "base"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"drawStyle": "lines",
|
||||
"lineInterpolation": "linear",
|
||||
"spanNulls": false,
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 0.5,
|
||||
"gradientMode": "none",
|
||||
"stack": "off",
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "timeseries",
|
||||
"id": "29ee004d-a95c-405d-97d1-d715fab4e1de",
|
||||
"layout": {
|
||||
"h": 7,
|
||||
"w": 12,
|
||||
"x": 12,
|
||||
"y": 19,
|
||||
"i": "29ee004d-a95c-405d-97d1-d715fab4e1de",
|
||||
"isResizable": true
|
||||
},
|
||||
"version": "2.0.0",
|
||||
"datasourceCate": "prometheus",
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"expr": "ipmi_voltage_volts{ident='$node',name!~\"Voltage 1|Voltage 2\"}",
|
||||
"legend": "{{name}}"
|
||||
}
|
||||
],
|
||||
"transformations": [
|
||||
{
|
||||
"id": "organize",
|
||||
"options": {}
|
||||
}
|
||||
],
|
||||
"name": "Voltages",
|
||||
"links": [],
|
||||
"description": "",
|
||||
"options": {
|
||||
"tooltip": {
|
||||
"mode": "multi"
|
||||
},
|
||||
"legend": {
|
||||
"displayMode": "list",
|
||||
"placement": "bottom"
|
||||
},
|
||||
"standardOptions": {
|
||||
"util": "none"
|
||||
},
|
||||
"thresholds": {
|
||||
"steps": [
|
||||
{
|
||||
"color": "green",
|
||||
"value": null,
|
||||
"type": "base"
|
||||
},
|
||||
{
|
||||
"color": "red",
|
||||
"value": 80
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"custom": {
|
||||
"drawStyle": "lines",
|
||||
"lineInterpolation": "linear",
|
||||
"spanNulls": false,
|
||||
"lineWidth": 1,
|
||||
"fillOpacity": 0.5,
|
||||
"gradientMode": "none",
|
||||
"stack": "off",
|
||||
"scaleDistribution": {
|
||||
"type": "linear"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"uuid": 1727587308068775200
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -99,7 +99,6 @@ type AlertRule struct {
|
||||
UpdateBy string `json:"update_by"`
|
||||
UUID int64 `json:"uuid" gorm:"-"` // tpl identifier
|
||||
CurEventCount int64 `json:"cur_event_count" gorm:"-"`
|
||||
UpdateByNickname string `json:"update_by_nickname" gorm:"-"` // for fe
|
||||
}
|
||||
|
||||
type Tpl struct {
|
||||
@@ -163,12 +162,10 @@ type Trigger struct {
|
||||
Duration int `json:"duration,omitempty"`
|
||||
Percent int `json:"percent,omitempty"`
|
||||
Joins []Join `json:"joins"`
|
||||
JoinRef string `json:"join_ref"`
|
||||
}
|
||||
|
||||
type Join struct {
|
||||
JoinType string `json:"join_type"`
|
||||
Ref string `json:"ref"`
|
||||
On []string `json:"on"`
|
||||
}
|
||||
|
||||
@@ -823,8 +820,7 @@ func AlertRuleGetsAll(ctx *ctx.Context) ([]*AlertRule, error) {
|
||||
return lst, nil
|
||||
}
|
||||
|
||||
func AlertRulesGetsBy(ctx *ctx.Context, prods []string, query, algorithm, cluster string,
|
||||
cates []string, disabled int) ([]*AlertRule, error) {
|
||||
func AlertRulesGetsBy(ctx *ctx.Context, prods []string, query, algorithm, cluster string, cates []string, disabled int) ([]*AlertRule, error) {
|
||||
session := DB(ctx)
|
||||
|
||||
if len(prods) > 0 {
|
||||
|
||||
@@ -35,7 +35,6 @@ type Datasource struct {
|
||||
UpdatedBy string `json:"updated_by"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
Transport *http.Transport `json:"-" gorm:"-"`
|
||||
ForceSave bool `json:"force_save" gorm:"-"`
|
||||
}
|
||||
|
||||
type Auth struct {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"log"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -16,8 +16,6 @@ import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type TargetDeleteHookFunc func(ctx *ctx.Context, idents []string) error
|
||||
|
||||
type Target struct {
|
||||
Id int64 `json:"id" gorm:"primaryKey"`
|
||||
GroupId int64 `json:"group_id"`
|
||||
@@ -119,22 +117,11 @@ func TargetStatistics(ctx *ctx.Context) (*Statistics, error) {
|
||||
return stats[0], nil
|
||||
}
|
||||
|
||||
func TargetDel(ctx *ctx.Context, idents []string, deleteHook TargetDeleteHookFunc) error {
|
||||
func TargetDel(ctx *ctx.Context, idents []string) error {
|
||||
if len(idents) == 0 {
|
||||
panic("idents empty")
|
||||
}
|
||||
|
||||
return DB(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
txErr := tx.Where("ident in ?", idents).Delete(new(Target)).Error
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
txErr = deleteHook(ctx, idents)
|
||||
if txErr != nil {
|
||||
return txErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return DB(ctx).Where("ident in ?", idents).Delete(new(Target)).Error
|
||||
}
|
||||
|
||||
type BuildTargetWhereOption func(session *gorm.DB) *gorm.DB
|
||||
@@ -561,36 +548,31 @@ func (m *Target) UpdateFieldsMap(ctx *ctx.Context, fields map[string]interface{}
|
||||
|
||||
func MigrateBg(ctx *ctx.Context, bgLabelKey string) {
|
||||
// 1. 判断是否已经完成迁移
|
||||
var maxGroupId int64
|
||||
if err := DB(ctx).Model(&Target{}).Select("MAX(group_id)").Scan(&maxGroupId).Error; err != nil {
|
||||
log.Println("failed to get max group_id from target table, err:", err)
|
||||
var cnt int64
|
||||
if err := DB(ctx).Model(&TargetBusiGroup{}).Count(&cnt).Error; err != nil {
|
||||
fmt.Println("Failed to count target_busi_group, err:", err)
|
||||
return
|
||||
}
|
||||
if cnt > 0 {
|
||||
fmt.Println("Migration has been completed.")
|
||||
return
|
||||
}
|
||||
|
||||
if maxGroupId == 0 {
|
||||
log.Println("migration bgid has been completed.")
|
||||
return
|
||||
}
|
||||
|
||||
err := DoMigrateBg(ctx, bgLabelKey)
|
||||
if err != nil {
|
||||
log.Println("failed to migrate bgid, err:", err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("migration bgid has been completed")
|
||||
DoMigrateBg(ctx, bgLabelKey)
|
||||
}
|
||||
|
||||
func DoMigrateBg(ctx *ctx.Context, bgLabelKey string) error {
|
||||
// 2. 获取全量 target
|
||||
targets, err := TargetGetsAll(ctx)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to get target, err:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
// 3. 获取全量 busi_group
|
||||
bgs, err := BusiGroupGetAll(ctx)
|
||||
if err != nil {
|
||||
fmt.Println("Failed to get bg, err:", err)
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -622,7 +604,7 @@ func DoMigrateBg(ctx *ctx.Context, bgLabelKey string) error {
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
log.Printf("failed to migrate %v bg, err: %v\n", t.Ident, err)
|
||||
fmt.Println("Failed to migrate bg, err:", err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,34 +296,6 @@ func UserGet(ctx *ctx.Context, where string, args ...interface{}) (*User, error)
|
||||
return lst[0], nil
|
||||
}
|
||||
|
||||
func UsersGet(ctx *ctx.Context, where string, args ...interface{}) ([]*User, error) {
|
||||
var lst []*User
|
||||
err := DB(ctx).Where(where, args...).Find(&lst).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, user := range lst {
|
||||
user.RolesLst = strings.Fields(user.Roles)
|
||||
user.Admin = user.IsAdmin()
|
||||
}
|
||||
|
||||
return lst, nil
|
||||
}
|
||||
|
||||
func UserMapGet(ctx *ctx.Context, where string, args ...interface{}) map[string]*User {
|
||||
lst, err := UsersGet(ctx, where, args...)
|
||||
if err != nil {
|
||||
logger.Errorf("UsersGet err: %v", err)
|
||||
return nil
|
||||
}
|
||||
um := make(map[string]*User, len(lst))
|
||||
for _, user := range lst {
|
||||
um[user.Username] = user
|
||||
}
|
||||
return um
|
||||
}
|
||||
|
||||
func UserGetByUsername(ctx *ctx.Context, username string) (*User, error) {
|
||||
return UserGet(ctx, "username=?", username)
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ type SsoClient struct {
|
||||
Host string
|
||||
Port int
|
||||
BaseDn string
|
||||
BaseDns []string
|
||||
BindUser string
|
||||
BindPass string
|
||||
SyncAdd bool
|
||||
@@ -132,8 +131,6 @@ func (s *SsoClient) Reload(cf Config) {
|
||||
if s.SyncInterval > 0 {
|
||||
s.Ticker.Reset(s.SyncInterval * time.Second)
|
||||
}
|
||||
|
||||
s.BaseDns = strings.Split(s.BaseDn, "|")
|
||||
}
|
||||
|
||||
func (s *SsoClient) Copy() *SsoClient {
|
||||
@@ -161,40 +158,27 @@ func (s *SsoClient) LoginCheck(user, pass string) (*ldap.SearchResult, error) {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
srs, err := lc.ldapReq(conn, lc.AuthFilter, user)
|
||||
sr, err := lc.ldapReq(conn, lc.AuthFilter, user)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ldap.error: ldap search fail: %v", err)
|
||||
}
|
||||
|
||||
var sr *ldap.SearchResult
|
||||
|
||||
for i := range srs {
|
||||
if srs[i] == nil || len(srs[i].Entries) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// 多个 dn 中,账号的唯一性由 LDAP 保证
|
||||
if len(srs[i].Entries) > 1 {
|
||||
return nil, fmt.Errorf("ldap.error: search user(%s), multi entries found", user)
|
||||
}
|
||||
|
||||
sr = srs[i]
|
||||
|
||||
if err := conn.Bind(srs[i].Entries[0].DN, pass); err != nil {
|
||||
return nil, fmt.Errorf("username or password invalid")
|
||||
}
|
||||
|
||||
for _, info := range srs[i].Entries[0].Attributes {
|
||||
logger.Infof("ldap.info: user(%s) info: %+v", user, info)
|
||||
}
|
||||
|
||||
break
|
||||
if len(sr.Entries) == 0 {
|
||||
return nil, fmt.Errorf("username or password invalid")
|
||||
}
|
||||
|
||||
if sr == nil {
|
||||
if len(sr.Entries) > 1 {
|
||||
return nil, fmt.Errorf("ldap.error: search user(%s), multi entries found", user)
|
||||
}
|
||||
|
||||
if err := conn.Bind(sr.Entries[0].DN, pass); err != nil {
|
||||
return nil, fmt.Errorf("username or password invalid")
|
||||
}
|
||||
|
||||
for _, info := range sr.Entries[0].Attributes {
|
||||
logger.Infof("ldap.info: user(%s) info: %+v", user, info)
|
||||
}
|
||||
|
||||
return sr, nil
|
||||
}
|
||||
|
||||
@@ -234,26 +218,21 @@ func (s *SsoClient) newLdapConn() (*ldap.Conn, error) {
|
||||
return conn, nil
|
||||
}
|
||||
|
||||
func (s *SsoClient) ldapReq(conn *ldap.Conn, filter string, values ...interface{}) ([]*ldap.SearchResult, error) {
|
||||
srs := make([]*ldap.SearchResult, 0, len(s.BaseDns))
|
||||
func (s *SsoClient) ldapReq(conn *ldap.Conn, filter string, values ...interface{}) (*ldap.SearchResult, error) {
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
s.BaseDn, // The base dn to search
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
fmt.Sprintf(filter, values...), // The filter to apply
|
||||
s.genLdapAttributeSearchList(), // A list attributes to retrieve
|
||||
nil,
|
||||
)
|
||||
|
||||
for i := range s.BaseDns {
|
||||
searchRequest := ldap.NewSearchRequest(
|
||||
strings.TrimSpace(s.BaseDns[i]), // The base dn to search
|
||||
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
|
||||
fmt.Sprintf(filter, values...), // The filter to apply
|
||||
s.genLdapAttributeSearchList(), // A list attributes to retrieve
|
||||
nil,
|
||||
)
|
||||
sr, err := conn.Search(searchRequest)
|
||||
if err != nil {
|
||||
logger.Errorf("ldap.error: ldap search fail: %v", err)
|
||||
continue
|
||||
}
|
||||
srs = append(srs, sr)
|
||||
sr, err := conn.Search(searchRequest)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ldap.error: ldap search fail: %v", err)
|
||||
}
|
||||
|
||||
return srs, nil
|
||||
return sr, nil
|
||||
}
|
||||
|
||||
// GetUserRolesAndTeams Gets the roles and teams of the user
|
||||
@@ -323,7 +302,6 @@ func LdapLogin(ctx *ctx.Context, username, pass string, defaultRoles []string, d
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// copy attributes from ldap
|
||||
ldap.RLock()
|
||||
attrs := ldap.Attributes
|
||||
|
||||
@@ -82,35 +82,29 @@ func (s *SsoClient) UserGetAll() (map[string]*models.User, error) {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
srs, err := lc.ldapReq(conn, lc.UserFilter)
|
||||
sr, err := lc.ldapReq(conn, lc.UserFilter)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("ldap.error: ldap search fail: %v", err)
|
||||
}
|
||||
|
||||
res := make(map[string]*models.User)
|
||||
res := make(map[string]*models.User, len(sr.Entries))
|
||||
for _, entry := range sr.Entries {
|
||||
attrs := lc.Attributes
|
||||
username := entry.GetAttributeValue(attrs.Username)
|
||||
nickname := entry.GetAttributeValue(attrs.Nickname)
|
||||
email := entry.GetAttributeValue(attrs.Email)
|
||||
phone := entry.GetAttributeValue(attrs.Phone)
|
||||
|
||||
for i := range srs {
|
||||
if srs[i] == nil {
|
||||
continue
|
||||
// Gets the roles and teams for this entry
|
||||
roleTeamMapping := lc.GetUserRolesAndTeams(entry)
|
||||
if len(roleTeamMapping.Roles) == 0 {
|
||||
// No role mapping is configured, the configured default role is used
|
||||
roleTeamMapping.Roles = lc.DefaultRoles
|
||||
}
|
||||
for _, entry := range srs[i].Entries {
|
||||
attrs := lc.Attributes
|
||||
username := entry.GetAttributeValue(attrs.Username)
|
||||
nickname := entry.GetAttributeValue(attrs.Nickname)
|
||||
email := entry.GetAttributeValue(attrs.Email)
|
||||
phone := entry.GetAttributeValue(attrs.Phone)
|
||||
user := new(models.User)
|
||||
user.FullSsoFieldsWithTeams("ldap", username, nickname, phone, email, roleTeamMapping.Roles, roleTeamMapping.Teams)
|
||||
|
||||
// Gets the roles and teams for this entry
|
||||
roleTeamMapping := lc.GetUserRolesAndTeams(entry)
|
||||
if len(roleTeamMapping.Roles) == 0 {
|
||||
// No role mapping is configured, the configured default role is used
|
||||
roleTeamMapping.Roles = lc.DefaultRoles
|
||||
}
|
||||
user := new(models.User)
|
||||
user.FullSsoFieldsWithTeams("ldap", username, nickname, phone, email, roleTeamMapping.Roles, roleTeamMapping.Teams)
|
||||
|
||||
res[entry.GetAttributeValue(attrs.Username)] = user
|
||||
}
|
||||
res[entry.GetAttributeValue(attrs.Username)] = user
|
||||
}
|
||||
|
||||
return res, nil
|
||||
@@ -178,20 +172,13 @@ func (s *SsoClient) UserExist(username string) (bool, error) {
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
srs, err := lc.ldapReq(conn, "(&(%s=%s))", lc.Attributes.Username, username)
|
||||
sr, err := lc.ldapReq(conn, "(&(%s=%s))", lc.Attributes.Username, username)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
for i := range srs {
|
||||
if srs[i] == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if len(srs[i].Entries) > 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
if len(sr.Entries) > 0 {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return false, nil
|
||||
|
||||
@@ -208,7 +208,7 @@ func (s *SsoClient) exchangeUser(code string) (*CallbackOutput, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to exchange token: %s", err)
|
||||
}
|
||||
userInfo, err := s.getUserInfo(s.UserInfoAddr, oauth2Token.AccessToken, s.TranTokenMethod)
|
||||
userInfo, err := s.getUserInfo(s.Config.ClientID, s.UserInfoAddr, oauth2Token.AccessToken, s.TranTokenMethod)
|
||||
if err != nil {
|
||||
logger.Errorf("failed to get user info: %s", err)
|
||||
return nil, fmt.Errorf("failed to get user info: %s", err)
|
||||
@@ -223,10 +223,10 @@ func (s *SsoClient) exchangeUser(code string) (*CallbackOutput, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *SsoClient) getUserInfo(UserInfoAddr, accessToken string, TranTokenMethod string) ([]byte, error) {
|
||||
func (s *SsoClient) getUserInfo(ClientId, UserInfoAddr, accessToken string, TranTokenMethod string) ([]byte, error) {
|
||||
var req *http.Request
|
||||
if TranTokenMethod == "formdata" {
|
||||
body := bytes.NewBuffer([]byte("access_token=" + accessToken))
|
||||
body := bytes.NewBuffer([]byte("access_token=" + accessToken + "&client_id=" + ClientId))
|
||||
r, err := http.NewRequest("POST", UserInfoAddr, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -234,7 +234,8 @@ func (s *SsoClient) getUserInfo(UserInfoAddr, accessToken string, TranTokenMetho
|
||||
r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
|
||||
req = r
|
||||
} else if TranTokenMethod == "querystring" {
|
||||
r, err := http.NewRequest("GET", UserInfoAddr+"?access_token="+accessToken, nil)
|
||||
|
||||
r, err := http.NewRequest("GET", UserInfoAddr+"?access_token="+accessToken+"&client_id="+ClientId, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -246,6 +247,7 @@ func (s *SsoClient) getUserInfo(UserInfoAddr, accessToken string, TranTokenMetho
|
||||
return nil, err
|
||||
}
|
||||
r.Header.Add("Authorization", "Bearer "+accessToken)
|
||||
r.Header.Add("client_id", ClientId)
|
||||
req = r
|
||||
}
|
||||
|
||||
@@ -262,6 +264,7 @@ func (s *SsoClient) getUserInfo(UserInfoAddr, accessToken string, TranTokenMetho
|
||||
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
resp.Body.Close()
|
||||
logger.Debugf("getUserInfo req:%+v resp: %+v", req, string(body))
|
||||
return body, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user