Commit d8f6e959 authored by 李科's avatar 李科

feat: 普罗米修斯规则

parent 87e9e94f
......@@ -42,10 +42,13 @@ require (
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/henrylee2cn/ameda v1.5.0 // indirect
github.com/henrylee2cn/goutil v0.0.0-20220704075712-42f2ec55fe8d // indirect
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af // indirect
......@@ -62,6 +65,7 @@ require (
github.com/nyaruka/phonenumbers v1.1.7 // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.66.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/sirupsen/logrus v1.9.2 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
......@@ -75,11 +79,16 @@ require (
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/text v0.10.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.27.2 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect
)
This diff is collapsed.
......@@ -43,6 +43,9 @@ type Config struct {
SmsAccessSecret string
SmsTemplateLogin string
SmsSignName string
AweRestURL string
KubernetesToken string
}
const (
......
......@@ -80,10 +80,12 @@ func initConfig() {
//PublicKeySSH: util.SetEnvStr("PUBLIC_KEY_SSH", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCw4WT05QHzCD19348MfJfycS1NI9Jlj62PGrZ1rU9/kWQif5TV1rqHZ6qjAX2WfK+W3u4SV51MhZBkMZZOgZgJmdGiaZJkSmj+8gj6XU/bxslUd+BYUKqbE18gFkVDgqs6n2tcqJ2at3x+WEr81Msk2qvKuGEiIOzcJPICWKxwiw== chenzilong@example.com\n"),
OrderDingTalkAccessToken: util.SetEnvStr("ORDER_DING_TALK_ACCESS_TOKEN", "203fe1644b446bba0a34e6e622c523d39ee9916fdad94b9c64224449f659e20b"),
OrderDingTalkSecret: util.SetEnvStr("ORDER_DING_TALK_SECRET", "SECa73d8372e336451c9daf29a99f750ee1bdd170c1dab910eab9cd06d729a831b7"),
SmsAccessKeyId: util.SetEnvStr("SMS_ACCESS_KEY", "LTAI4GBcVubRjzX7ABPcHnhB"), // 短信key
SmsAccessSecret: util.SetEnvStr("SMS_ACCESS_SECRET", "dYE2dtABFOqYtK1ijcrits0yedHkw7"), // 短信secret
SmsTemplateLogin: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_212925130"), // 短信验证码模板
SmsSignName: util.SetEnvStr("SMS_SIGN_NAME", "比格数据"), // 签名
SmsAccessKeyId: util.SetEnvStr("SMS_ACCESS_KEY", "LTAI4GBcVubRjzX7ABPcHnhB"), // 短信key
SmsAccessSecret: util.SetEnvStr("SMS_ACCESS_SECRET", "dYE2dtABFOqYtK1ijcrits0yedHkw7"), // 短信secret
SmsTemplateLogin: util.SetEnvStr("SMS_TEMPLATE_LOGIN", "SMS_212925130"), // 短信验证码模板
SmsSignName: util.SetEnvStr("SMS_SIGN_NAME", "比格数据"), // 签名
AweRestURL: util.SetEnvStr("AWE_REST_URL", "http://awecloud-rest/awecloud/rest"), // awecloud-rest
KubernetesToken: util.SetEnvStr("AWE_REST_K8S_TOKEN", "eyJhbGciOiJSUzI1NiIsImtpZCI6InJ1alJzNEVGamN5UC0wRU1rS1BKQ0JZVUtNNWpzR0t2bmlrSlJhY2Q3R00ifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJiZWFnbGUtc3lzdGVtIiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6InJvb3QiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC5uYW1lIjoicm9vdCIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjRlMDM0OTI3LTc0ZTMtNDQ5Yy1hN2RlLWExMGE3MjU1NGYyMCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDpiZWFnbGUtc3lzdGVtOnJvb3QifQ.YPLE_E2kIeo-YFQtKScBt5p4KhnniJF9n3iWN2i9UMYS06lIsq2-2wBrgON-YsJihWJupYyDQRiZ9h8bUWTrQzhnpsnuJ_aUclKyAw3QOT9rjvZhJp7qP--27dmdspSHncKtvIiprWE7UTUKzvF33WsMB0fSYFqYXOggNFMoT-fXmWwUXjgar3op0iOl3c3deJ_GeBzFyLSHEuGM7OVdjU8032aUmTen0Kji_P1yB4-O3Iqd0OdVs33BQy_tycjbxhQ8TDEpqrqhLnXjAwJCprLDEpFMx7ODZbjB9Wmuns8yJhaRDxTO47rTME7ZIAxjZ-zLR_QybtW97rlwnUTaNw"), // k8s token
}
}
......
......@@ -122,3 +122,13 @@ var OpTypeIntMap = map[OpType]int{
DownMove: 13,
Export: 14,
}
// RiskLevel 风险等级
type RiskLevel int
const (
RiskLevelLow RiskLevel = iota + 1 // 1:低风险
RiskLevelModerate // 1:一般风险
RiskLevelHigh // 3:较大风险
RiskLevelCritical // 4:重大风险
)
package k8s
import (
"encoding/json"
"fmt"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"github.com/pkg/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type K8sSvc struct {
Header map[string]string
}
type SendFile struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Content interface{} `json:"content"`
}
type K8sCsrfToken struct {
Token string `json:"token"`
}
type UploadFileObj struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Content Content `json:"content"`
}
type Content struct {
Kind string `json:"kind"`
ApiVersion string `json:"apiVersion"`
Metadata v1.ObjectMeta `json:"metadata"`
Spec interface{} `json:"spec"`
}
type AddBgObjectFile struct {
ApiVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Metadata struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels"`
} `json:"metadata"`
Spec interface{} `json:"spec"`
Data interface{} `json:"data"`
}
var KindBlackList = []string{"PersistentVolumeClaim", "PersistentVolume", "namespace"}
func (k *K8sSvc) SendFile(content *Content) (res string, err error) {
if err = k.checkK8sKind(content.Kind); err != nil {
return
}
csrfUrl := fmt.Sprintf("%s/kubernetes/api/v1/csrftoken/appdeploymentfromfile", conf.Options.AweRestURL)
sendUrl := fmt.Sprintf("%s/kubernetes/api/v1/appdeploymentfromfile", conf.Options.AweRestURL)
csrf, err := util.ProxySendRes("GET", csrfUrl, "", k.Header)
if err != nil {
return "", err
}
csrfToken := K8sCsrfToken{}
json.Unmarshal(csrf, &csrfToken)
if csrfToken.Token == "" {
err := errors.New("get csrfToken failed")
return "", err
}
k.Header["x-csrf-token"] = csrfToken.Token
k.Header["Content-Type"] = "application/json"
// sendFile
sendFile := SendFile{Name: content.Metadata.Name, Namespace: content.Metadata.Namespace}
c, _ := json.Marshal(content)
sendFile.Content = string(c)
sStr, _ := json.Marshal(sendFile)
k8sUserJwtRes, err := util.ProxySendRes("POST", sendUrl, string(sStr), k.Header)
if err != nil {
return "", err
}
res = string(k8sUserJwtRes)
//json.Unmarshal(k8sUserJwtRes, &res)
return
}
func (k *K8sSvc) checkK8sKind(kind string) (err error) {
for _, v := range KindBlackList {
if kind == v {
return errors.New("当前用户没有上传此类型资源的权限!")
}
}
return nil
}
package k8s
import (
"encoding/json"
"fmt"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/util"
"strings"
v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
)
var (
PrometheusRuleGroup = "monitoring.beagle.io" // kubectl api-resources | grep -i prome
PrometheusRuleVersion = "v1"
PrometheusRuleKind = "PrometheusRule"
PrometheusRuleApiVersion = PrometheusRuleGroup + "/" + PrometheusRuleVersion
PrometheusRuleName = strings.ToLower(PrometheusRuleKind) + "s." + PrometheusRuleGroup
)
type PrometheusRule struct {
Header map[string]string
}
func (p PrometheusRule) Create(pRule *v1.PrometheusRule) error {
k8sSvc := K8sSvc{Header: p.Header}
c := &Content{Kind: PrometheusRuleKind, ApiVersion: PrometheusRuleApiVersion, Metadata: pRule.ObjectMeta, Spec: pRule.Spec}
_, err := k8sSvc.SendFile(c)
return err
}
func (p PrometheusRule) Delete(namespace string, name string) error {
delUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, PrometheusRuleName, namespace, name)
_, err := util.ProxySendRes("DELETE", delUrl, "", p.Header)
return err
}
func (p PrometheusRule) Update(pRule *v1.PrometheusRule) error {
updateUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, PrometheusRuleName, pRule.Namespace, pRule.Name)
body, _ := json.Marshal(pRule)
p.Header["Content-Type"] = "application/json"
_, err := util.ProxySendRes("PUT", updateUrl, string(body), p.Header)
return err
}
func (p PrometheusRule) Get(namespace string, name string) (obj *v1.PrometheusRule, err error) {
// http://awecloud-rest/awecloud/rest/kubernetes/api/v1/_raw/prometheusrules.monitoring.coreos.com/namespace/kube-public/name/nginx
getUrl := fmt.Sprintf("%s/kubernetes/api/v1/_raw/%s/namespace/%s/name/%s", conf.Options.AweRestURL, PrometheusRuleName, namespace, name)
res, err := util.ProxySendRes("GET", getUrl, "", p.Header)
if err != nil {
return
}
err = json.Unmarshal(res, &obj)
return
}
package k8s
import (
"fmt"
v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
"github.com/spf13/cast"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/pkg/beagle/constant"
"k8s.io/apimachinery/pkg/util/intstr"
"log"
"testing"
"time"
)
var svc PrometheusRule
var obj v1.PrometheusRule
var AlertDefLabels = map[string]string{
"app": "prometheus",
"app.bd-apaas.com/cluster-component": "monitoring",
"prometheus-operator": "monitoring",
"release": "beagle-prometheus",
}
func init() {
conf.Options = &conf.Config{}
conf.Options.AweRestURL = "https://cloud.wodcloud.com/awecloud/rest"
conf.Options.KubernetesToken = "380e3557499a13c4ec4aa11d7456bb45ef2303c1"
header := make(map[string]string)
header["Authorization"] = "Bearer " + conf.Options.KubernetesToken
svc = PrometheusRule{Header: header}
obj = v1.PrometheusRule{}
obj.Name = "beagle-prometheus-operation-api-rules-101"
obj.Namespace = "beagle-monitoring"
obj.Labels = AlertDefLabels
}
func TestRule(t *testing.T) {
group := v1.RuleGroup{}
group.Name = "demo-group-1m"
rule := v1.Rule{}
rule.Alert = "kubernetes启动状态"
rule.Annotations = make(map[string]string)
rule.Annotations["value"] = "{{ $value }}"
rule.Annotations["message"] = "启动了"
rule.Expr = intstr.FromString(`up{endpoint="https", instance="192.168.1.244:6443", job="apiserver", namespace="default", service="kubernetes"} == 1`)
ruleFor := v1.Duration("1m")
rule.For = &ruleFor
rule.Labels = make(map[string]string)
rule.Labels["severity"] = "warning"
rule.Labels["severity_name"] = "一般风险"
rule.Labels["risk_level"] = cast.ToString(constant.RiskLevelLow)
rule.Labels["source"] = "so-operation-api"
rule.Labels["alert_id"] = "101"
group.Rules = append(group.Rules, rule)
obj.Spec.Groups = append(obj.Spec.Groups, group)
err := svc.Create(&obj)
if err != nil {
fmt.Println("添加失败" + err.Error())
} else {
fmt.Println("添加成功")
}
}
func TestGet(t *testing.T) {
// 获取对象
ruleObj, err := svc.Get(obj.Namespace, obj.Name)
if err != nil {
fmt.Println("获取失败" + err.Error())
} else {
fmt.Println("获取成功")
}
log.Printf("ruleObj:%+v\n", ruleObj)
}
func TestUpdate(t *testing.T) {
ruleObj, err := svc.Get(obj.Namespace, obj.Name)
if err != nil {
fmt.Println("获取失败" + err.Error())
} else {
fmt.Println("获取成功")
}
// 更新
ruleObj.Name = "galileo-101"
ruleObj.Spec.Groups[0].Rules[0].Alert = "请求次数大于10"
ruleObj.Spec.Groups[0].Name = "2分钟组"
ruleFor := v1.Duration("2m")
ruleObj.Spec.Groups[0].Rules[0].For = &ruleFor
ruleObj.Spec.Groups[0].Rules[0].Expr = intstr.FromString(`up{endpoint="https", instance="192.168.1.244:6443", job="apiserver", namespace="default", service="kubernetes"} == 0`)
err = svc.Update(ruleObj)
if err != nil {
fmt.Println("更新失败" + err.Error())
} else {
fmt.Println("更新成功")
}
}
func TestDelete(t *testing.T) {
// 删除
time.Sleep(time.Second * 10)
err := svc.Delete(obj.Namespace, obj.Name)
if err != nil {
fmt.Println("删除失败" + err.Error())
} else {
fmt.Println("删除成功")
}
}
......@@ -2,15 +2,20 @@ package util
import (
"crypto/tls"
"errors"
"github.com/valyala/fasthttp"
"gitlab.wodcloud.com/smart-operation/so-operation-api/src/common/conf"
"go.uber.org/zap"
"io"
"net"
"net/http"
"strings"
"sync"
"time"
)
var lock sync.RWMutex
const (
MediaTypeJSON = "application/json"
MediaTypeXML = "application/xml"
......@@ -121,3 +126,37 @@ func HttpSend(sendType string, url string, body string, header map[string]string
}
return response, err
}
func ProxySendRes(sendType string, url string, body string, header map[string]string) (result []byte, err error) {
client := &http.Client{}
var reqest *http.Request
if sendType == "GET" || sendType == "DELETE" {
reqest, _ = http.NewRequest(sendType, url, nil)
} else if sendType == "POST" || sendType == "PUT" {
reqest, _ = http.NewRequest(sendType, url, strings.NewReader(body))
}
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
lock.Lock()
if header == nil {
header = make(map[string]string)
}
reqest.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
reqest.Header.Set("Accept-Language", "ja,zh-CN;q=0.8,zh;q=0.6")
reqest.Header.Set("Connection", "keep-alive")
for k, v := range header {
reqest.Header.Set(k, v)
}
lock.Unlock()
response, errc := client.Do(reqest)
if errc != nil {
return nil, errc
} else {
defer response.Body.Close()
body, erra := io.ReadAll(response.Body)
if response.StatusCode >= 400 {
err = errors.New(string(body))
return
}
return body, erra
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment