From 1ccfdb1abb350007193a6afbc238cc9b47c0d762 Mon Sep 17 00:00:00 2001 From: medcl Date: Sat, 22 Oct 2022 18:40:52 +0800 Subject: [PATCH 01/10] add setup module to console --- Jenkinsfile | 2 +- env_check.go => bootstrap_check.go | 35 +- config/initialization.tpl | 333 ++++++++++++++++++ config/system_config.tpl | 76 ++++ config/system_config.yml | 9 + console.yml | 80 +---- main.go | 118 +++++-- plugin/api/alerting/alert.go | 3 +- plugin/api/alerting/api.go | 2 - plugin/api/alerting/message.go | 3 +- plugin/api/alerting/rule.go | 6 +- plugin/api/index_management/common_command.go | 9 +- plugin/api/index_management/elasticsearch.go | 9 +- plugin/api/index_management/index.go | 4 +- plugin/api/index_management/rebuild.go | 7 +- plugin/api/init.go | 1 - plugin/setup/setup.go | 326 +++++++++++++++++ 17 files changed, 871 insertions(+), 152 deletions(-) rename env_check.go => bootstrap_check.go (74%) create mode 100644 config/initialization.tpl create mode 100644 config/system_config.tpl create mode 100644 config/system_config.yml create mode 100644 plugin/setup/setup.go diff --git a/Jenkinsfile b/Jenkinsfile index 37618649..9e96317e 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -32,7 +32,7 @@ pipeline { sh label: 'copy-license', script: 'cd /home/jenkins/go/src/infini.sh/console && cp ../framework/LICENSE bin && cat ../framework/NOTICE NOTICE > bin/NOTICE' - sh label: 'copy-configs', script: 'cd /home/jenkins/go/src/infini.sh/console && mkdir -p bin/config && cp config/*.json bin/config' + sh label: 'copy-configs', script: 'cd /home/jenkins/go/src/infini.sh/console && mkdir -p bin/config && cp config/*.json bin/config && cp config/*.yml bin/config && cp config/*.tpl bin/config' sh label: 'package-linux-amd64', script: 'cd /home/jenkins/go/src/infini.sh/console/bin && tar cfz ${WORKSPACE}/console-$VERSION-$BUILD_NUMBER-linux-amd64.tar.gz console-linux-amd64 console.yml LICENSE NOTICE config' sh label: 'package-linux-386', script: 'cd /home/jenkins/go/src/infini.sh/console/bin && tar cfz ${WORKSPACE}/console-$VERSION-$BUILD_NUMBER-linux-386.tar.gz console-linux-386 console.yml LICENSE NOTICE config' diff --git a/env_check.go b/bootstrap_check.go similarity index 74% rename from env_check.go rename to bootstrap_check.go index 395c7df1..c934f070 100644 --- a/env_check.go +++ b/bootstrap_check.go @@ -8,14 +8,14 @@ import ( "fmt" "github.com/buger/jsonparser" log "github.com/cihub/seelog" - "infini.sh/console/config" "infini.sh/framework/core/elastic" "infini.sh/framework/core/env" + "infini.sh/framework/core/global" "infini.sh/framework/core/util" ) func bootstrapRequirementCheck() error{ - err := checkElasticsearchRequire() + err := checkElasticsearchRequirements() if err != nil { return err } @@ -23,7 +23,7 @@ func bootstrapRequirementCheck() error{ } -func checkElasticsearchRequire() error{ +func checkElasticsearchRequirements() error{ log.Trace("start to check elasticsearch requirement") var esConfigs = []elastic.ElasticsearchConfig{} ok, err := env.ParseConfig("elasticsearch", &esConfigs) @@ -33,27 +33,24 @@ func checkElasticsearchRequire() error{ if !ok { return fmt.Errorf("elasticsearch config section not found") } - appConfig = &config.AppConfig{ - Elasticsearch: "default", - } - ok, err = env.ParseConfig("web", appConfig) - if err != nil { - return fmt.Errorf("parse web config section error: %v", err) - } - if !ok { - return fmt.Errorf("web config section not found") - } - if appConfig.Elasticsearch == "" { - return fmt.Errorf("elasticsearch config of web section can not be empty") + + elasticsearchID:=global.Lookup(elastic.GlobalSystemElasticsearchID) + + if elasticsearchID == nil||elasticsearchID=="" { + return fmt.Errorf("elasticsearch config in web section can not be empty") } + + esID:=elasticsearchID.(string) + var targetEsConfig *elastic.ElasticsearchConfig for _, esConfig := range esConfigs { - if esConfig.Name == appConfig.Elasticsearch { + if esConfig.ID == esID||(esConfig.ID==""&&esConfig.Name==esID) { targetEsConfig = &esConfig } } + if targetEsConfig == nil { - return fmt.Errorf("elasticsearch config named %s not found", appConfig.Elasticsearch) + return fmt.Errorf("elasticsearch config %s was not found", esID) } var req = util.NewGetRequest(targetEsConfig.Endpoint, nil) if targetEsConfig.BasicAuth != nil { @@ -65,6 +62,10 @@ func checkElasticsearchRequire() error{ return fmt.Errorf("check elasticsearch requirement error: %v", err) } + if result==nil||result.Body==nil||len(result.Body)==0{ + return fmt.Errorf("failed to retrive elasticsearch version info") + } + versionNumber, err := jsonparser.GetString(result.Body, "version", "number") if err != nil { return fmt.Errorf("check elasticsearch requirement error: %v, got response: %s", err, string(result.Body)) diff --git a/config/initialization.tpl b/config/initialization.tpl new file mode 100644 index 00000000..0f5b22bd --- /dev/null +++ b/config/initialization.tpl @@ -0,0 +1,333 @@ +PUT _template/.infini +{ + "order": 0, + "index_patterns": [ + ".infini_*" + ], + "settings": { + "index": { + "max_result_window": "10000000", + "mapping": { + "total_fields": { + "limit": "20000" + } + }, + "analysis": { + "analyzer": { + "suggest_text_search": { + "filter": [ + "word_delimiter" + ], + "tokenizer": "classic" + } + } + }, + "number_of_shards": "1" + } + }, + "mappings": { + "dynamic_templates": [ + { + "strings": { + "mapping": { + "ignore_above": 256, + "type": "keyword" + }, + "match_mapping_type": "string" + } + } + ] + }, + "aliases": {} +} + +PUT _ilm/policy/infini_metrics-30days-retention +{ + "policy": { + "phases": { + "hot": { + "min_age": "0ms", + "actions": { + "rollover": { + "max_age": "30d", + "max_size": "50gb" + }, + "set_priority": { + "priority": 100 + } + } + }, + "delete": { + "min_age": "30d", + "actions": { + "delete": { + "delete_searchable_snapshot": true + } + } + } + } + } +} + +PUT _template/.infini_metrics-rollover +{ + "order" : 100000, + "index_patterns" : [ + ".infini_metrics*" + ], + "settings" : { + "index" : { + "format" : "7", + "lifecycle" : { + "name" : "infini_metrics-30days-retention", + "rollover_alias" : ".infini_metrics" + }, + "codec" : "best_compression", + "number_of_shards" : "1", + "translog.durability":"async" + } + }, + "mappings" : { + "dynamic_templates" : [ + { + "strings" : { + "mapping" : { + "ignore_above" : 256, + "type" : "keyword" + }, + "match_mapping_type" : "string" + } + } + ] + }, + "aliases" : { } + } + + +# DELETE .infini_metrics +# DELETE .infini_metrics-00001 +PUT .infini_metrics-00001 +{ + "settings": { + "index.lifecycle.rollover_alias":".infini_metrics" + , "refresh_interval": "5s" + }, + "aliases":{ + ".infini_metrics":{ + "is_write_index":true + } + } +} + + + +PUT _template/.infini_alert-history-rollover +{ + "order" : 100000, + "index_patterns" : [ + ".infini_alert-history*" + ], + "settings" : { + "index" : { + "format" : "7", + "lifecycle" : { + "name" : "infini_metrics-30days-retention", + "rollover_alias" : ".infini_alert-history" + }, + "codec" : "best_compression", + "number_of_shards" : "1", + "translog.durability":"async" + } + }, + "mappings" : { + "dynamic_templates" : [ + { + "strings" : { + "mapping" : { + "ignore_above" : 256, + "type" : "keyword" + }, + "match_mapping_type" : "string" + } + } + ] + }, + "aliases" : { } + } + +# DELETE .infini_alert-history +# DELETE .infini_alert-history-00001 +PUT .infini_alert-history-00001 +{ + "settings": { + "index.lifecycle.rollover_alias":".infini_alert-history" + , "refresh_interval": "5s" + }, + "aliases":{ + ".infini_alert-history":{ + "is_write_index":true + } + }, + "mappings": { + "properties" : { + "condition" : { + "properties" : { + "items" : { + "properties" : { + "expression" : { + "type" : "keyword", + "ignore_above" : 256 + }, + "minimum_period_match" : { + "type" : "long" + }, + "operator" : { + "type" : "keyword", + "ignore_above" : 256 + }, + "severity" : { + "type" : "keyword", + "ignore_above" : 256 + }, + "values" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "operator" : { + "type" : "keyword", + "ignore_above" : 256 + } + } + }, + "condition_result" : { + "type" : "object", + "enabled" : false + }, + "context" : { + "type" : "keyword", + "copy_to" : [ + "search_text" + ] + }, + "created" : { + "type" : "date" + }, + "expression" : { + "type" : "keyword", + "copy_to" : [ + "search_text" + ] + }, + "id" : { + "type" : "keyword" + }, + "is_escalated" : { + "type" : "boolean" + }, + "is_notified" : { + "type" : "boolean" + }, + "message" : { + "type" : "keyword", + "ignore_above" : 256 + }, + "objects" : { + "type" : "keyword", + "copy_to" : [ + "search_text" + ] + }, + "resource_id" : { + "type" : "keyword" + }, + "resource_name" : { + "type" : "keyword" + }, + "rule_id" : { + "type" : "keyword" + }, + "rule_name" : { + "type" : "keyword" + }, + "search_text" : { + "type" : "text", + "analyzer" : "suggest_text_search", + "index_prefixes" : { + "min_chars" : 2, + "max_chars" : 5 + }, + "index_phrases" : true + }, + "severity" : { + "type" : "keyword" + }, + "state" : { + "type" : "keyword", + "ignore_above" : 256 + }, + "title" : { + "type" : "keyword" + }, + "updated" : { + "type" : "date" + } + } + } +} + + + + +PUT _template/.infini_activities-rollover +{ + "order" : 100000, + "index_patterns" : [ + ".infini_activities*" + ], + "settings" : { + "index" : { + "format" : "7", + "lifecycle" : { + "name" : "infini_metrics-30days-retention", + "rollover_alias" : ".infini_activities" + }, + "codec" : "best_compression", + "number_of_shards" : "1", + "translog.durability":"async" + } + }, + "mappings" : { + "dynamic_templates" : [ + { + "strings" : { + "mapping" : { + "ignore_above" : 256, + "type" : "keyword" + }, + "match_mapping_type" : "string" + } + } + ] + }, + "aliases" : { } + } + +#DELETE .infini_activities +#DELETE .infini_activities-00001 + +PUT .infini_activities-00001 +{ +"settings": { + "index.lifecycle.rollover_alias":".infini_activities" + , "refresh_interval": "5s" +}, +"aliases":{ + ".infini_activities":{ + "is_write_index":true + } +} +} + + diff --git a/config/system_config.tpl b/config/system_config.tpl new file mode 100644 index 00000000..c1f9aaa4 --- /dev/null +++ b/config/system_config.tpl @@ -0,0 +1,76 @@ + +elasticsearch: + - id: $[[CLUSTER_ID]] + name: $[[CLUSTER_ID]] + enabled: true + monitored: false + reserved: true + endpoint: $[[CLUSTER_ENDPINT]] + basic_auth: + username: $[[CLUSTER_USER]] + password: $[[CLUSTER_PASS]] + +elastic.elasticsearch: $[[CLUSTER_ID]] + +pipeline: + - name: indexing_merge + auto_start: true + keep_running: true + processor: + - indexing_merge: + input_queue: "metrics" + elasticsearch: "$[[CLUSTER_ID]]" + index_name: "$[[INDEX_PREFIX]]metrics" + output_queue: + name: "metrics_requests" + label: + tag: "metrics" + worker_size: 1 + bulk_size_in_mb: 5 + - name: consume-metrics_requests + auto_start: true + keep_running: true + processor: + - bulk_indexing: + bulk: + compress: true + batch_size_in_mb: 5 + batch_size_in_docs: 5000 + consumer: + fetch_max_messages: 100 + queues: + type: indexing_merge + when: + cluster_available: ["$[[CLUSTER_ID]]"] + - name: metadata_ingest + auto_start: true + keep_running: true + processor: + - metadata: + bulk_size_in_mb: 5 + bulk_max_docs_count: 5000 + fetch_max_messages: 100 + elasticsearch: "$[[CLUSTER_ID]]" + queues: + type: metadata + category: elasticsearch + consumer: + group: metadata + when: + cluster_available: ["$[[CLUSTER_ID]]"] + - name: activity_ingest + auto_start: true + keep_running: true + processor: + - activity: + bulk_size_in_mb: 5 + bulk_max_docs_count: 5000 + fetch_max_messages: 100 + elasticsearch: "$[[CLUSTER_ID]]" + queues: + category: elasticsearch + activity: true + consumer: + group: activity + when: + cluster_available: ["$[[CLUSTER_ID]]"] diff --git a/config/system_config.yml b/config/system_config.yml new file mode 100644 index 00000000..87531125 --- /dev/null +++ b/config/system_config.yml @@ -0,0 +1,9 @@ +configs.template: + - name: "system" + path: ./config/system_config.tpl + variable: + CLUSTER_ID: _setup_clustercd9s5brq50k75kji57tg + CLUSTER_ENDPINT: "http://192.168.3.188:9206" + CLUSTER_USER: "admin" + CLUSTER_PASS: "pass" + INDEX_PREFIX: ".infini_" \ No newline at end of file diff --git a/console.yml b/console.yml index 7f24d827..23116695 100644 --- a/console.yml +++ b/console.yml @@ -1,20 +1,10 @@ -# for the system cluster, please use Elasticsearch v7.3+ -elasticsearch: - - name: default - enabled: true - monitored: false - endpoint: http://localhost:9200 - basic_auth: - username: elastic - password: infinilabs - discovery: - enabled: true +path.configs: "config" web: enabled: true embedding_api: true auth: - enabled: false + enabled: true ui: enabled: true path: .public @@ -27,7 +17,6 @@ web: enabled: true elastic: - elasticsearch: default enabled: true remote_configs: true health_check: @@ -58,67 +47,4 @@ metrics: enabled: true cluster_stats: true node_stats: true - index_stats: true - -pipeline: - - name: indexing_merge - auto_start: true - keep_running: true - processor: - - indexing_merge: - input_queue: "metrics" - elasticsearch: "default" - index_name: ".infini_metrics" - output_queue: - name: "metrics_requests" - label: - tag: "metrics" - worker_size: 1 - bulk_size_in_mb: 10 - - name: consume-metrics_requests - auto_start: true - keep_running: true - processor: - - bulk_indexing: - bulk: - compress: true - batch_size_in_mb: 10 - batch_size_in_docs: 5000 - consumer: - fetch_max_messages: 100 - queues: - type: indexing_merge - when: - cluster_available: ["default"] - - name: metadata_ingest - auto_start: true - keep_running: true - processor: - - metadata: - bulk_size_in_mb: 10 - bulk_max_docs_count: 5000 - fetch_max_messages: 1000 - elasticsearch: "default" - queues: - type: metadata - category: elasticsearch - consumer: - group: metadata - when: - cluster_available: ["default"] - - name: activity_ingest - auto_start: true - keep_running: true - processor: - - activity: - bulk_size_in_mb: 10 - bulk_max_docs_count: 5000 - fetch_max_messages: 1000 - elasticsearch: "default" - queues: - category: elasticsearch - activity: true - consumer: - group: activity - when: - cluster_available: ["default"] + index_stats: true \ No newline at end of file diff --git a/main.go b/main.go index f481e8e4..4a9c3119 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "context" "errors" _ "expvar" log "github.com/cihub/seelog" @@ -12,10 +13,12 @@ import ( "infini.sh/framework" "infini.sh/framework/core/elastic" "infini.sh/framework/core/env" + "infini.sh/framework/core/global" "infini.sh/framework/core/insight" _ "infini.sh/framework/core/log" "infini.sh/framework/core/module" "infini.sh/framework/core/orm" + task1 "infini.sh/framework/core/task" "infini.sh/framework/modules/agent" _ "infini.sh/framework/modules/api" elastic2 "infini.sh/framework/modules/elastic" @@ -23,10 +26,13 @@ import ( "infini.sh/framework/modules/pipeline" queue2 "infini.sh/framework/modules/queue/disk_queue" "infini.sh/framework/modules/redis" + "infini.sh/framework/modules/security" "infini.sh/framework/modules/stats" "infini.sh/framework/modules/task" "infini.sh/framework/modules/ui" _ "infini.sh/framework/plugins" + setup1 "infini.sh/console/plugin/setup" + _ "infini.sh/console/plugin" api2 "infini.sh/gateway/api" _ "infini.sh/gateway/proxy" _ "time/tzdata" @@ -36,12 +42,7 @@ var appConfig *config.AppConfig var appUI *UI func main() { - terminalHeader := ("\n\n") - terminalHeader += (" ___ __ ___ ___ \n") - terminalHeader += (" / __\\/ / /___\\/\\ /\\ / \\ \n") - terminalHeader += (" / / / / // // / \\ \\/ /\\ / \n") - terminalHeader += ("/ /__/ /__/ \\_//\\ \\_/ / /_// \n") - terminalHeader += ("\\____|____|___/ \\___/___,' \n") + terminalHeader := ("\n") terminalHeader += (" ___ ___ __ __ ___ __ __ \n") terminalHeader += (" / __\\/___\\/\\ \\ \\/ _\\ /___\\/ / /__\\\n") terminalHeader += (" / / // // \\/ /\\ \\ // // / /_\\ \n") @@ -51,7 +52,7 @@ func main() { terminalFooter := "" - app := framework.NewApp("console", "INFINI Cloud Console, The easiest way to operate your own elasticsearch platform.", + app := framework.NewApp("console", "The easiest way to operate your own search platform.", config.Version, config.BuildNumber, config.LastCommitLog, config.BuildDate, config.EOLDate, terminalHeader, terminalFooter) app.Init(nil) @@ -59,28 +60,44 @@ func main() { api := api2.GatewayAPI{} + modules:=[]module.Module{} + modules=append(modules,&stats.SimpleStatsModule{}) + modules=append(modules,&elastic2.ElasticModule{}) + modules=append(modules,&queue2.DiskQueue{}) + modules=append(modules,&redis.RedisModule{}) + modules=append(modules,&pipeline.PipeModule{}) + modules=append(modules,&task.TaskModule{}) + modules=append(modules,&agent.AgentModule{}) + modules=append(modules,&metrics.MetricsModule{}) + + if app.Setup(func() { - err := bootstrapRequirementCheck() - if err != nil { - panic(err) - } //load core modules first - module.RegisterSystemModule(&elastic2.ElasticModule{}) - module.RegisterSystemModule(&stats.SimpleStatsModule{}) - module.RegisterSystemModule(&queue2.DiskQueue{}) - module.RegisterSystemModule(&redis.RedisModule{}) + module.RegisterSystemModule(&setup1.Module{}) module.RegisterSystemModule(&ui.UIModule{}) - module.RegisterSystemModule(&pipeline.PipeModule{}) - module.RegisterSystemModule(&task.TaskModule{}) - module.RegisterSystemModule(&agent.AgentModule{}) - module.RegisterUserPlugin(&metrics.MetricsModule{}) + var initFunc= func() { + module.RegisterSystemModule(&stats.SimpleStatsModule{}) + module.RegisterSystemModule(&elastic2.ElasticModule{}) + module.RegisterSystemModule(&queue2.DiskQueue{}) + module.RegisterSystemModule(&redis.RedisModule{}) + module.RegisterSystemModule(&pipeline.PipeModule{}) + module.RegisterSystemModule(&task.TaskModule{}) + module.RegisterSystemModule(&agent.AgentModule{}) + module.RegisterUserPlugin(&metrics.MetricsModule{}) + module.RegisterUserPlugin(&security.Module{}) + } + + if !global.Env().SetupRequired(){ + initFunc() + }else{ + setup1.RegisterSetupCallback(initFunc) + } api.RegisterAPI("") appConfig = &config.AppConfig{ - Elasticsearch: "default", UI: config.UIConfig{ LocalPath: ".public", VFSEnabled: true, @@ -104,26 +121,51 @@ func main() { module.Start() - //orm.RegisterSchemaWithIndexName(model.Dict{}, "dict") - //orm.RegisterSchemaWithIndexName(model.Reindex{}, "reindex") - orm.RegisterSchemaWithIndexName(elastic.View{}, "view") - orm.RegisterSchemaWithIndexName(elastic.CommonCommand{}, "commands") - //orm.RegisterSchemaWithIndexName(elastic.TraceTemplate{}, "trace-template") - orm.RegisterSchemaWithIndexName(gateway.Instance{}, "gateway-instance") - orm.RegisterSchemaWithIndexName(alerting.Rule{}, "alert-rule") - orm.RegisterSchemaWithIndexName(alerting.Alert{}, "alert-history") - orm.RegisterSchemaWithIndexName(alerting.AlertMessage{}, "alert-message") - orm.RegisterSchemaWithIndexName(alerting.Channel{}, "channel") - orm.RegisterSchemaWithIndexName(insight.Visualization{}, "visualization") - orm.RegisterSchemaWithIndexName(insight.Dashboard{}, "dashboard") - api.RegisterSchema() + var initFunc= func() { + if global.Env().SetupRequired() { - go func() { - err := alerting2.InitTasks() - if err != nil { - log.Errorf("init alerting task error: %v", err) + for _, v := range modules { + v.Setup() + v.Start() + } } - }() + + elastic2.InitTemplate(false) + + //orm.RegisterSchemaWithIndexName(model.Dict{}, "dict") + orm.RegisterSchemaWithIndexName(elastic.View{}, "view") + orm.RegisterSchemaWithIndexName(elastic.CommonCommand{}, "commands") + //orm.RegisterSchemaWithIndexName(elastic.TraceTemplate{}, "trace-template") + orm.RegisterSchemaWithIndexName(gateway.Instance{}, "gateway-instance") + orm.RegisterSchemaWithIndexName(alerting.Rule{}, "alert-rule") + orm.RegisterSchemaWithIndexName(alerting.Alert{}, "alert-history") + orm.RegisterSchemaWithIndexName(alerting.AlertMessage{}, "alert-message") + orm.RegisterSchemaWithIndexName(alerting.Channel{}, "channel") + orm.RegisterSchemaWithIndexName(insight.Visualization{}, "visualization") + orm.RegisterSchemaWithIndexName(insight.Dashboard{}, "dashboard") + api.RegisterSchema() + + task1.RunWithinGroup("initialize_alerting",func(ctx context.Context) error { + err := alerting2.InitTasks() + if err != nil { + log.Errorf("init alerting task error: %v", err) + } + return err + }) + } + + if !global.Env().SetupRequired(){ + initFunc() + }else{ + setup1.RegisterSetupCallback(initFunc) + } + + if !global.Env().SetupRequired(){ + err := bootstrapRequirementCheck() + if err != nil { + panic(err) + } + } }, nil) { app.Run() diff --git a/plugin/api/alerting/alert.go b/plugin/api/alerting/alert.go index e62579f9..3336a2e4 100644 --- a/plugin/api/alerting/alert.go +++ b/plugin/api/alerting/alert.go @@ -10,6 +10,7 @@ import ( "infini.sh/console/model/alerting" httprouter "infini.sh/framework/core/api/router" "infini.sh/framework/core/elastic" + "infini.sh/framework/core/global" "infini.sh/framework/core/orm" "infini.sh/framework/core/util" "net/http" @@ -109,7 +110,7 @@ func (h *AlertAPI) searchAlert(w http.ResponseWriter, req *http.Request, ps http } func (h *AlertAPI) getAlertStats(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { - esClient := elastic.GetClient(h.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDsl := util.MapStr{ "size": 0, "query": util.MapStr{ diff --git a/plugin/api/alerting/api.go b/plugin/api/alerting/api.go index 0e0627b2..6ce66dea 100644 --- a/plugin/api/alerting/api.go +++ b/plugin/api/alerting/api.go @@ -5,7 +5,6 @@ package alerting import ( - "infini.sh/console/config" "infini.sh/framework/core/api" "infini.sh/framework/core/api/rbac/enum" ) @@ -13,7 +12,6 @@ import ( type AlertAPI struct { api.Handler - Config *config.AppConfig } func (alert *AlertAPI) Init() { diff --git a/plugin/api/alerting/message.go b/plugin/api/alerting/message.go index ae98e2cb..d52d349d 100644 --- a/plugin/api/alerting/message.go +++ b/plugin/api/alerting/message.go @@ -11,6 +11,7 @@ import ( alerting2 "infini.sh/console/service/alerting" httprouter "infini.sh/framework/core/api/router" "infini.sh/framework/core/elastic" + "infini.sh/framework/core/global" "infini.sh/framework/core/kv" "infini.sh/framework/core/orm" "infini.sh/framework/core/util" @@ -82,7 +83,7 @@ func (h *AlertAPI) ignoreAlertMessage(w http.ResponseWriter, req *http.Request, } func (h *AlertAPI) getAlertMessageStats(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { - esClient := elastic.GetClient(h.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) must := []util.MapStr{ { "terms": util.MapStr{ diff --git a/plugin/api/alerting/rule.go b/plugin/api/alerting/rule.go index ee89bc70..e28b07e4 100644 --- a/plugin/api/alerting/rule.go +++ b/plugin/api/alerting/rule.go @@ -14,6 +14,7 @@ import ( httprouter "infini.sh/framework/core/api/router" "infini.sh/framework/core/elastic" "infini.sh/framework/core/event" + "infini.sh/framework/core/global" "infini.sh/framework/core/kv" "infini.sh/framework/core/orm" "infini.sh/framework/core/queue" @@ -462,7 +463,8 @@ func (alertAPI *AlertAPI) searchRule(w http.ResponseWriter, req *http.Request, p } func (alertAPI *AlertAPI) getRuleAlertMessageNumbers(ruleIDs []string) ( map[string]interface{},error) { - esClient := elastic.GetClient(alertAPI.Config.Elasticsearch) + + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDsl := util.MapStr{ "size": 0, "query": util.MapStr{ @@ -513,7 +515,7 @@ func (alertAPI *AlertAPI) fetchAlertInfos(w http.ResponseWriter, req *http.Reque alertAPI.WriteJSON(w, util.MapStr{}, http.StatusOK) return } - esClient := elastic.GetClient(alertAPI.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDsl := util.MapStr{ "_source": []string{"state", "rule_id"}, "sort": []util.MapStr{ diff --git a/plugin/api/index_management/common_command.go b/plugin/api/index_management/common_command.go index c5dd19c9..08e5bcf2 100644 --- a/plugin/api/index_management/common_command.go +++ b/plugin/api/index_management/common_command.go @@ -5,6 +5,7 @@ import ( log "github.com/cihub/seelog" httprouter "infini.sh/framework/core/api/router" "infini.sh/framework/core/elastic" + "infini.sh/framework/core/global" "infini.sh/framework/core/orm" "infini.sh/framework/core/util" "net/http" @@ -28,7 +29,7 @@ func (h *APIHandler) HandleAddCommonCommandAction(w http.ResponseWriter, req *ht reqParams.Created = time.Now() reqParams.ID = util.GetUUID() - esClient := elastic.GetClient(h.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDSL :=[]byte(fmt.Sprintf(`{"size":1, "query":{"bool":{"must":{"match":{"title.keyword":"%s"}}}}}`, reqParams.Title)) var indexName = orm.GetIndexName(reqParams) @@ -73,7 +74,7 @@ func (h *APIHandler) HandleSaveCommonCommandAction(w http.ResponseWriter, req *h return } reqParams.ID = ps.ByName("cid") - esClient := elastic.GetClient(h.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDSL :=[]byte(fmt.Sprintf(`{"size":1, "query":{"bool":{"must":{"match":{"title.keyword":"%s"}}}}}`, reqParams.Title)) var indexName = orm.GetIndexName(reqParams) @@ -133,7 +134,7 @@ func (h *APIHandler) HandleQueryCommonCommandAction(w http.ResponseWriter, req * } queryDSL = fmt.Sprintf(queryDSL, filterBuilder.String(), size, from) - esClient := elastic.GetClient(h.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) searchRes, err := esClient.SearchWithRawQueryDSL(orm.GetIndexName(elastic.CommonCommand{}), []byte(queryDSL)) if err != nil { @@ -149,7 +150,7 @@ func (h *APIHandler) HandleQueryCommonCommandAction(w http.ResponseWriter, req * func (h *APIHandler) HandleDeleteCommonCommandAction(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { resBody := map[string]interface{}{} id := ps.ByName("cid") - esClient := elastic.GetClient(h.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) delRes, err := esClient.Delete(orm.GetIndexName(elastic.CommonCommand{}), "", id, "wait_for") if err != nil { log.Error(err) diff --git a/plugin/api/index_management/elasticsearch.go b/plugin/api/index_management/elasticsearch.go index 50a2719c..ba815d6c 100644 --- a/plugin/api/index_management/elasticsearch.go +++ b/plugin/api/index_management/elasticsearch.go @@ -6,6 +6,7 @@ import ( httprouter "infini.sh/framework/core/api/router" "infini.sh/framework/core/elastic" "infini.sh/framework/core/event" + "infini.sh/framework/core/global" "infini.sh/framework/core/host" "infini.sh/framework/core/orm" "infini.sh/framework/core/util" @@ -25,7 +26,7 @@ func (handler APIHandler) ElasticsearchOverviewAction(w http.ResponseWriter, req // clusterIDs = append(clusterIDs, key) // return true //}) - esClient := elastic.GetClient(handler.Config.Elasticsearch) + esClient := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDsl := util.MapStr{ "size": 100, } @@ -110,7 +111,7 @@ func (handler APIHandler) ElasticsearchOverviewAction(w http.ResponseWriter, req } func (handler APIHandler) getLatestClusterMonitorData(clusterIDs []interface{}) (*elastic.SearchResponse, error){ - client := elastic.GetClient(handler.Config.Elasticsearch) + client := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDSLTpl := `{ "size": %d, "query": { @@ -155,7 +156,7 @@ func (handler APIHandler) getLatestClusterMonitorData(clusterIDs []interface{}) } func (handler APIHandler) getMetricCount(indexName, field string, clusterIDs []interface{}) (interface{}, error){ - client := elastic.GetClient(handler.Config.Elasticsearch) + client := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDSL := util.MapStr{ "size": 0, "aggs": util.MapStr{ @@ -182,7 +183,7 @@ func (handler APIHandler) getMetricCount(indexName, field string, clusterIDs []i } func (handler APIHandler) getLastActiveHostCount() (int, error){ - client := elastic.GetClient(handler.Config.Elasticsearch) + client := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) queryDSL := `{ "size": 0, "query": { diff --git a/plugin/api/index_management/index.go b/plugin/api/index_management/index.go index 99ee9422..9f6d637c 100644 --- a/plugin/api/index_management/index.go +++ b/plugin/api/index_management/index.go @@ -1,6 +1,8 @@ package index_management import ( + "infini.sh/framework/core/elastic" + "infini.sh/framework/core/global" "net/http" "strconv" "strings" @@ -33,7 +35,7 @@ func (handler APIHandler) GetDictListAction(w http.ResponseWriter, req *http.Req if len(tags) > 3 { tags = tags[0:3] } - rel, err := model2.GetDictList(from, size, name, tags, handler.Config.Elasticsearch) + rel, err := model2.GetDictList(from, size, name, tags, global.MustLookupString(elastic.GlobalSystemElasticsearchID)) if err != nil { resp["error"] = err resp["status"] = false diff --git a/plugin/api/index_management/rebuild.go b/plugin/api/index_management/rebuild.go index 25799bb6..2853cd35 100644 --- a/plugin/api/index_management/rebuild.go +++ b/plugin/api/index_management/rebuild.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" log "github.com/cihub/seelog" + "infini.sh/framework/core/global" "infini.sh/framework/core/orm" "net/http" "strings" @@ -33,7 +34,7 @@ func (handler APIHandler) HandleReindexAction(w http.ResponseWriter, req *http.R //fmt.Println(reindexItem) typ := handler.GetParameter(req, "_type") - ID, err := reindex(handler.Config.Elasticsearch, reindexItem, typ) + ID, err := reindex(global.MustLookupString(elastic.GlobalSystemElasticsearchID), reindexItem, typ) if err != nil { log.Error(err) resResult["error"] = err @@ -94,7 +95,7 @@ func (handler APIHandler) HandleDeleteRebuildAction(w http.ResponseWriter, req * id := ps.ByName("id") var ids = []string{id} resBody := newResponseBody() - err := deleteTasksByIds(handler.Config.Elasticsearch, ids) + err := deleteTasksByIds(global.MustLookupString(elastic.GlobalSystemElasticsearchID), ids) if err != nil { log.Error(err) resBody["error"] = err @@ -111,7 +112,7 @@ func (handler APIHandler) HandleGetRebuildListAction(w http.ResponseWriter, req size = handler.GetIntOrDefault(req, "size", 10) name = handler.GetParameter(req, "name") resBody = newResponseBody() - esName = handler.Config.Elasticsearch + esName = global.MustLookupString(elastic.GlobalSystemElasticsearchID) ) esResp, err := model.GetRebuildList(esName, from, size, name) if err != nil { diff --git a/plugin/api/init.go b/plugin/api/init.go index 4e43870e..72818baf 100644 --- a/plugin/api/init.go +++ b/plugin/api/init.go @@ -58,7 +58,6 @@ func Init(cfg *config.AppConfig) { //}) alertAPI := alerting.AlertAPI{ - Config: cfg, } alertAPI.Init() diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go new file mode 100644 index 00000000..6f24bc01 --- /dev/null +++ b/plugin/setup/setup.go @@ -0,0 +1,326 @@ +package task + +import ( + "bytes" + "fmt" + "infini.sh/framework/core/api" + httprouter "infini.sh/framework/core/api/router" + "infini.sh/framework/core/elastic" + "infini.sh/framework/core/env" + "infini.sh/framework/core/errors" + "infini.sh/framework/core/global" + "infini.sh/framework/core/module" + "infini.sh/framework/core/orm" + "infini.sh/framework/core/util" + elastic1 "infini.sh/framework/modules/elastic/common" + elastic2 "infini.sh/framework/modules/elastic" + "net/http" + "path" + "runtime" + "time" +) + +type Module struct { + api.Handler +} + +func (module *Module) Name() string { + return "setup" +} + +func init() { + module.RegisterSystemModule(&Module{}) +} + +func (module *Module) Setup() { + + if !global.Env().SetupRequired(){ + return + } + + api.HandleAPIMethod(api.POST, "/setup/_validate", module.validate) + api.HandleAPIMethod(api.POST, "/setup/_initialize", module.initialize) +} + +var setupFinishedCallback= []func() {} +func RegisterSetupCallback(f func()) { + setupFinishedCallback=append(setupFinishedCallback,f) +} + +func InvokeSetupCallback() { + for _,v:=range setupFinishedCallback{ + v() + } +} + +func (module *Module) Start() error { + return nil +} +func (module *Module) Stop() error { + return nil +} + +type SetupRequest struct { + Cluster struct { + Endpoint string `json:"endpoint"` + Username string `json:"username"` + Password string `json:"password"` + } `json:"cluster"` + + BootstrapUsername string `json:"bootstrap_username"` + BootstrapPassword string `json:"bootstrap_password"` +} + +var tempID="_setup_cluster"+util.GetUUID() + +const VersionTooOld ="elasticsearch_version_too_old" +const IndicesExists ="elasticsearch_indices_exists" +const TemplateExists ="elasticsearch_template_exists" + +var cfg1 elastic1.ORMConfig + +func (module *Module) validate(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + + if !global.Env().SetupRequired(){ + module.WriteError(w, "setup not permitted", 500) + return + } + + success:=false + var err error + var errType string + var fixTips string + var code int + code=200 + defer func() { + result := util.MapStr{} + result["success"]=success + + if r := recover(); r != nil { + var v string + switch r.(type) { + case error: + v = r.(error).Error() + case runtime.Error: + v = r.(runtime.Error).Error() + case string: + v = r.(string) + } + if v!=""{ + success=false + result["error"]=util.MapStr{ + "reason":v, + } + if errType!=""{ + result["type"]=errType + } + if fixTips!=""{ + result["fix_tips"]=fixTips + } + code=500 + } + } + module.WriteJSON(w, result, code) + }() + + err, client := module.initTempClient(r) + if err!=nil{ + panic(err) + } + + //validate version + version := client.GetVersion() + if version != "" { + ver := &util.Version{} + ver, err = util.ParseSemantic(version) + if err != nil { + panic(err) + } + if ver.Major() >= 7 { + if ver.Major() == 7 && ver.Minor() < 3 { + errType = VersionTooOld + panic(errors.Errorf("elasticsearch version(%v) should greater than v7.3", version)) + } + } else { + errType = VersionTooOld + panic(errors.Errorf("elasticsearch version(%v) should greater than v7.3", version)) + } + } + cfg1 = elastic1.ORMConfig{} + exist, err := env.ParseConfig("elastic.orm", &cfg1) + if exist && err != nil { + panic(err) + } + + if cfg1.IndexPrefix==""{ + cfg1.IndexPrefix=".infini_" + } + if cfg1.TemplateName==""{ + cfg1.TemplateName=".infini" + } + + //validate indices + indices, err := client.GetIndices(util.TrimSpaces(cfg1.IndexPrefix) + "*") + if err != nil { + panic(err) + } + + if indices != nil && len(*indices) > 0 { + buff := bytes.Buffer{} + for k, _ := range *indices { + buff.WriteString(k) + buff.WriteString("\n") + } + errType = IndicesExists + fixTips="DELETE "+util.TrimSpaces(cfg1.IndexPrefix) + "*" + panic(errors.Errorf("there are following indices exists in target elasticsearch: \n%v", buff.String())) + } + + ok, err := client.TemplateExists(cfg1.TemplateName) + if err != nil { + panic(err) + } + if ok { + errType = TemplateExists + fixTips="DELETE /_template/"+util.TrimSpaces(cfg1.TemplateName) + panic(errors.Errorf("there are following template already exists in target elasticsearch: \n%v", cfg1.TemplateName)) + } + + success = true +} +var cfg elastic.ElasticsearchConfig +func (module *Module) initTempClient(r *http.Request) (error, elastic.API) { + request := SetupRequest{} + err := module.DecodeJSON(r, &request) + if err != nil { + return err,nil + } + + cfg = elastic.ElasticsearchConfig{ + Enabled: true, + Reserved: true, + Endpoint: request.Cluster.Endpoint, + BasicAuth: &elastic.BasicAuth{ + Username: request.Cluster.Username, + Password: request.Cluster.Password, + }, + } + + cfg.ID = tempID + cfg.Name = "INFINI_SYSTEM ("+util.PickRandomName()+")" + elastic.InitMetadata(&cfg, true) + client, err := elastic1.InitClientWithConfig(cfg) + if err != nil { + return err,nil + } + + elastic.UpdateConfig(cfg) + elastic.UpdateClient(cfg, client) + + global.Register(elastic.GlobalSystemElasticsearchID,tempID) + + return err, client +} + +func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { + if !global.Env().SetupRequired(){ + module.WriteError(w, "setup not permitted", 500) + return + } + + success:=false + var err error + var errType string + var fixTips string + var code int + code=200 + defer func() { + result := util.MapStr{} + result["success"]=success + + if r := recover(); r != nil { + var v string + switch r.(type) { + case error: + v = r.(error).Error() + case runtime.Error: + v = r.(runtime.Error).Error() + case string: + v = r.(string) + } + if v!=""{ + success=false + result["error"]=util.MapStr{ + "reason":v, + } + if errType!=""{ + result["type"]=errType + } + if fixTips!=""{ + result["fix_tips"]=fixTips + } + code=500 + } + } + module.WriteJSON(w, result, code) + }() + + err, client := module.initTempClient(r) + if err!=nil{ + panic(err) + } + + if cfg1.IndexPrefix==""{ + cfg1.IndexPrefix=".infini_" + } + if cfg1.TemplateName==""{ + cfg1.TemplateName=".infini" + } + + if !cfg1.Enabled{ + cfg1.Enabled=true + } + + if !cfg1.InitTemplate{ + cfg1.InitTemplate=true + } + + cfg.Reserved=true + + //处理ORM + handler := elastic2.ElasticORM{Client: client, Config:cfg1 } + orm.Register("elastic_setup", handler) + + //处理模版 + elastic2.InitTemplate(true) + elastic2.InitSchema() + + //保存默认集群 + err=orm.Save(&cfg) + if err!=nil{ + panic(err) + } + + //save to local file + file:=path.Join(global.Env().GetConfigDir(),"system_config.yml") + util.FilePutContent(file,fmt.Sprintf("configs.template:\n - name: \"system\"\n path: ./config/system_config.tpl\n variable:\n " + + "CLUSTER_ID: %v\n CLUSTER_ENDPINT: \"%v\"\n " + + "CLUSTER_USER: \"%v\"\n CLUSTER_PASS: \"%v\"\n INDEX_PREFIX: \"%v\"", + tempID,cfg.Endpoint,cfg.BasicAuth.Username,cfg.BasicAuth.Password,cfg1.IndexPrefix )) + + //处理 ILM + //处理默认用户信息 + + //callback + InvokeSetupCallback() + + //place setup lock file + setupLock:=path.Join(global.Env().GetDataDir(),".setup_lock") + _,err=util.FilePutContent(setupLock,time.Now().String()) + if err!=nil{ + panic(err) + } + + success=true + +} From af5a25269418778a763598ad3b6422a6b0873b06 Mon Sep 17 00:00:00 2001 From: medcl Date: Sat, 22 Oct 2022 19:49:38 +0800 Subject: [PATCH 02/10] setup bootstrap user --- plugin/setup/setup.go | 61 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 8 deletions(-) diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index 6f24bc01..aeb7413b 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -4,6 +4,7 @@ import ( "bytes" "fmt" "infini.sh/framework/core/api" + "infini.sh/framework/core/api/rbac" httprouter "infini.sh/framework/core/api/router" "infini.sh/framework/core/elastic" "infini.sh/framework/core/env" @@ -14,9 +15,11 @@ import ( "infini.sh/framework/core/util" elastic1 "infini.sh/framework/modules/elastic/common" elastic2 "infini.sh/framework/modules/elastic" + "infini.sh/framework/modules/security" "net/http" "path" "runtime" + "golang.org/x/crypto/bcrypt" "time" ) @@ -71,7 +74,7 @@ type SetupRequest struct { BootstrapPassword string `json:"bootstrap_password"` } -var tempID="_setup_cluster"+util.GetUUID() +var tempID="infini_system_cluster_"+util.GetUUID() const VersionTooOld ="elasticsearch_version_too_old" const IndicesExists ="elasticsearch_indices_exists" @@ -123,7 +126,8 @@ func (module *Module) validate(w http.ResponseWriter, r *http.Request, ps httpro module.WriteJSON(w, result, code) }() - err, client := module.initTempClient(r) + + err, client,request := module.initTempClient(r) if err!=nil{ panic(err) } @@ -189,11 +193,15 @@ func (module *Module) validate(w http.ResponseWriter, r *http.Request, ps httpro success = true } var cfg elastic.ElasticsearchConfig -func (module *Module) initTempClient(r *http.Request) (error, elastic.API) { +func (module *Module) initTempClient(r *http.Request) (error, elastic.API,SetupRequest) { request := SetupRequest{} err := module.DecodeJSON(r, &request) if err != nil { - return err,nil + return err,nil,request + } + + if request.Cluster.Endpoint==""{ + panic("invalid configuration") } cfg = elastic.ElasticsearchConfig{ @@ -211,7 +219,7 @@ func (module *Module) initTempClient(r *http.Request) (error, elastic.API) { elastic.InitMetadata(&cfg, true) client, err := elastic1.InitClientWithConfig(cfg) if err != nil { - return err,nil + return err,nil,request } elastic.UpdateConfig(cfg) @@ -219,7 +227,7 @@ func (module *Module) initTempClient(r *http.Request) (error, elastic.API) { global.Register(elastic.GlobalSystemElasticsearchID,tempID) - return err, client + return err, client,request } func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps httprouter.Params) { @@ -265,7 +273,7 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http module.WriteJSON(w, result, code) }() - err, client := module.initTempClient(r) + err, client,request := module.initTempClient(r) if err!=nil{ panic(err) } @@ -293,7 +301,15 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http //处理模版 elastic2.InitTemplate(true) + + //处理生命周期 + //TEMPLATE_NAME + //INDEX_PREFIX + + //处理索引 elastic2.InitSchema() + //init security + security.InitSecurity() //保存默认集群 err=orm.Save(&cfg) @@ -301,12 +317,41 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http panic(err) } + if request.BootstrapUsername!=""&&request.BootstrapPassword!=""{ + //Save bootstrap user + user:=rbac.User{} + user.ID="default_user_"+util.GetUUID() + user.Name=request.BootstrapUsername + user.NickName=request.BootstrapUsername + var hash []byte + hash, err = bcrypt.GenerateFromPassword([]byte(request.BootstrapPassword), bcrypt.DefaultCost) + if err!=nil{ + panic(err) + } + + user.Password=string(hash) + role:=[]rbac.UserRole{} + role=append(role,rbac.UserRole{ + ID: rbac.RoleAdminName, + Name: rbac.RoleAdminName, + }) + user.Roles=role + err=orm.Save(&user) + if err!=nil{ + panic(err) + } + } + + //save to local file file:=path.Join(global.Env().GetConfigDir(),"system_config.yml") - util.FilePutContent(file,fmt.Sprintf("configs.template:\n - name: \"system\"\n path: ./config/system_config.tpl\n variable:\n " + + _,err=util.FilePutContent(file,fmt.Sprintf("configs.template:\n - name: \"system\"\n path: ./config/system_config.tpl\n variable:\n " + "CLUSTER_ID: %v\n CLUSTER_ENDPINT: \"%v\"\n " + "CLUSTER_USER: \"%v\"\n CLUSTER_PASS: \"%v\"\n INDEX_PREFIX: \"%v\"", tempID,cfg.Endpoint,cfg.BasicAuth.Username,cfg.BasicAuth.Password,cfg1.IndexPrefix )) + if err!=nil{ + panic(err) + } //处理 ILM //处理默认用户信息 From 5892a5ea9bb8165d9312a4809aacc0708a110215 Mon Sep 17 00:00:00 2001 From: medcl Date: Sat, 22 Oct 2022 20:01:26 +0800 Subject: [PATCH 03/10] fix setup module --- plugin/setup/setup.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index aeb7413b..7aa873e9 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -3,6 +3,7 @@ package task import ( "bytes" "fmt" + "golang.org/x/crypto/bcrypt" "infini.sh/framework/core/api" "infini.sh/framework/core/api/rbac" httprouter "infini.sh/framework/core/api/router" @@ -13,13 +14,12 @@ import ( "infini.sh/framework/core/module" "infini.sh/framework/core/orm" "infini.sh/framework/core/util" - elastic1 "infini.sh/framework/modules/elastic/common" elastic2 "infini.sh/framework/modules/elastic" + elastic1 "infini.sh/framework/modules/elastic/common" "infini.sh/framework/modules/security" "net/http" "path" "runtime" - "golang.org/x/crypto/bcrypt" "time" ) @@ -127,7 +127,7 @@ func (module *Module) validate(w http.ResponseWriter, r *http.Request, ps httpro }() - err, client,request := module.initTempClient(r) + err, client,_ := module.initTempClient(r) if err!=nil{ panic(err) } @@ -199,7 +199,7 @@ func (module *Module) initTempClient(r *http.Request) (error, elastic.API,SetupR if err != nil { return err,nil,request } - + if request.Cluster.Endpoint==""{ panic("invalid configuration") } From f90601ef1a8665e6b3b709f27e820171d44e258c Mon Sep 17 00:00:00 2001 From: medcl Date: Sat, 22 Oct 2022 23:22:16 +0800 Subject: [PATCH 04/10] improve setup, fix auth issue --- config/config.go | 1 - config/initialization.tpl | 57 ++++++++++++++----------------- config/system_config.tpl | 2 +- config/system_config.yml | 9 ----- main.go | 13 ++++--- plugin/setup/setup.go | 72 +++++++++++++++++++++++++++++++++++++-- 6 files changed, 103 insertions(+), 51 deletions(-) delete mode 100644 config/system_config.yml diff --git a/config/config.go b/config/config.go index 94d1e6d8..a3cfb9a2 100644 --- a/config/config.go +++ b/config/config.go @@ -3,7 +3,6 @@ package config import "infini.sh/framework/core/config" type AppConfig struct { - Elasticsearch string `config:"elasticsearch"` UI UIConfig `config:"ui"` Network config.NetworkConfig `config:"network"` TLSConfig config.TLSConfig `config:"tls"` diff --git a/config/initialization.tpl b/config/initialization.tpl index 0f5b22bd..6e284740 100644 --- a/config/initialization.tpl +++ b/config/initialization.tpl @@ -1,8 +1,8 @@ -PUT _template/.infini +PUT _template/$[[TEMPLATE_NAME]] { "order": 0, "index_patterns": [ - ".infini_*" + "$[[INDEX_PREFIX]]*" ], "settings": { "index": { @@ -41,7 +41,7 @@ PUT _template/.infini "aliases": {} } -PUT _ilm/policy/infini_metrics-30days-retention +PUT _ilm/policy/ilm_$[[INDEX_PREFIX]]metrics-30days-retention { "policy": { "phases": { @@ -69,18 +69,18 @@ PUT _ilm/policy/infini_metrics-30days-retention } } -PUT _template/.infini_metrics-rollover +PUT _template/$[[INDEX_PREFIX]]metrics-rollover { "order" : 100000, "index_patterns" : [ - ".infini_metrics*" + "$[[INDEX_PREFIX]]metrics*" ], "settings" : { "index" : { "format" : "7", "lifecycle" : { - "name" : "infini_metrics-30days-retention", - "rollover_alias" : ".infini_metrics" + "name" : "ilm_$[[INDEX_PREFIX]]metrics-30days-retention", + "rollover_alias" : "$[[INDEX_PREFIX]]metrics" }, "codec" : "best_compression", "number_of_shards" : "1", @@ -104,16 +104,14 @@ PUT _template/.infini_metrics-rollover } -# DELETE .infini_metrics -# DELETE .infini_metrics-00001 -PUT .infini_metrics-00001 +PUT $[[INDEX_PREFIX]]metrics-00001 { "settings": { - "index.lifecycle.rollover_alias":".infini_metrics" + "index.lifecycle.rollover_alias":"$[[INDEX_PREFIX]]metrics" , "refresh_interval": "5s" }, "aliases":{ - ".infini_metrics":{ + "$[[INDEX_PREFIX]]metrics":{ "is_write_index":true } } @@ -121,18 +119,18 @@ PUT .infini_metrics-00001 -PUT _template/.infini_alert-history-rollover +PUT _template/$[[INDEX_PREFIX]]alert-history-rollover { "order" : 100000, "index_patterns" : [ - ".infini_alert-history*" + "$[[INDEX_PREFIX]]alert-history*" ], "settings" : { "index" : { "format" : "7", "lifecycle" : { - "name" : "infini_metrics-30days-retention", - "rollover_alias" : ".infini_alert-history" + "name" : "ilm_$[[INDEX_PREFIX]]metrics-30days-retention", + "rollover_alias" : "$[[INDEX_PREFIX]]alert-history" }, "codec" : "best_compression", "number_of_shards" : "1", @@ -155,16 +153,15 @@ PUT _template/.infini_alert-history-rollover "aliases" : { } } -# DELETE .infini_alert-history -# DELETE .infini_alert-history-00001 -PUT .infini_alert-history-00001 + +PUT $[[INDEX_PREFIX]]alert-history-00001 { "settings": { - "index.lifecycle.rollover_alias":".infini_alert-history" + "index.lifecycle.rollover_alias":"$[[INDEX_PREFIX]]alert-history" , "refresh_interval": "5s" }, "aliases":{ - ".infini_alert-history":{ + "$[[INDEX_PREFIX]]alert-history":{ "is_write_index":true } }, @@ -278,20 +275,18 @@ PUT .infini_alert-history-00001 } - - -PUT _template/.infini_activities-rollover +PUT _template/$[[INDEX_PREFIX]]activities-rollover { "order" : 100000, "index_patterns" : [ - ".infini_activities*" + "$[[INDEX_PREFIX]]activities*" ], "settings" : { "index" : { "format" : "7", "lifecycle" : { - "name" : "infini_metrics-30days-retention", - "rollover_alias" : ".infini_activities" + "name" : "ilm_$[[INDEX_PREFIX]]metrics-30days-retention", + "rollover_alias" : "$[[INDEX_PREFIX]]activities" }, "codec" : "best_compression", "number_of_shards" : "1", @@ -314,17 +309,15 @@ PUT _template/.infini_activities-rollover "aliases" : { } } -#DELETE .infini_activities -#DELETE .infini_activities-00001 -PUT .infini_activities-00001 +PUT $[[INDEX_PREFIX]]activities-00001 { "settings": { - "index.lifecycle.rollover_alias":".infini_activities" + "index.lifecycle.rollover_alias":"$[[INDEX_PREFIX]]activities" , "refresh_interval": "5s" }, "aliases":{ - ".infini_activities":{ + "$[[INDEX_PREFIX]]activities":{ "is_write_index":true } } diff --git a/config/system_config.tpl b/config/system_config.tpl index c1f9aaa4..2e1d7811 100644 --- a/config/system_config.tpl +++ b/config/system_config.tpl @@ -3,7 +3,7 @@ elasticsearch: - id: $[[CLUSTER_ID]] name: $[[CLUSTER_ID]] enabled: true - monitored: false + monitored: true reserved: true endpoint: $[[CLUSTER_ENDPINT]] basic_auth: diff --git a/config/system_config.yml b/config/system_config.yml deleted file mode 100644 index 87531125..00000000 --- a/config/system_config.yml +++ /dev/null @@ -1,9 +0,0 @@ -configs.template: - - name: "system" - path: ./config/system_config.tpl - variable: - CLUSTER_ID: _setup_clustercd9s5brq50k75kji57tg - CLUSTER_ENDPINT: "http://192.168.3.188:9206" - CLUSTER_USER: "admin" - CLUSTER_PASS: "pass" - INDEX_PREFIX: ".infini_" \ No newline at end of file diff --git a/main.go b/main.go index 4a9c3119..f9b6a73e 100644 --- a/main.go +++ b/main.go @@ -69,13 +69,15 @@ func main() { modules=append(modules,&task.TaskModule{}) modules=append(modules,&agent.AgentModule{}) modules=append(modules,&metrics.MetricsModule{}) + modules=append(modules,&security.Module{}) + uiModule:=&ui.UIModule{} if app.Setup(func() { //load core modules first module.RegisterSystemModule(&setup1.Module{}) - module.RegisterSystemModule(&ui.UIModule{}) + module.RegisterSystemModule(uiModule) var initFunc= func() { module.RegisterSystemModule(&stats.SimpleStatsModule{}) @@ -85,13 +87,16 @@ func main() { module.RegisterSystemModule(&pipeline.PipeModule{}) module.RegisterSystemModule(&task.TaskModule{}) module.RegisterSystemModule(&agent.AgentModule{}) - module.RegisterUserPlugin(&metrics.MetricsModule{}) - module.RegisterUserPlugin(&security.Module{}) + module.RegisterSystemModule(&metrics.MetricsModule{}) + module.RegisterSystemModule(&security.Module{}) } if !global.Env().SetupRequired(){ initFunc() }else{ + for _, v := range modules { + v.Setup() + } setup1.RegisterSetupCallback(initFunc) } @@ -123,9 +128,7 @@ func main() { var initFunc= func() { if global.Env().SetupRequired() { - for _, v := range modules { - v.Setup() v.Start() } } diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index 7aa873e9..961f2926 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -16,10 +16,14 @@ import ( "infini.sh/framework/core/util" elastic2 "infini.sh/framework/modules/elastic" elastic1 "infini.sh/framework/modules/elastic/common" + elastic3 "infini.sh/framework/modules/elastic/api" "infini.sh/framework/modules/security" + "io" "net/http" + uri2 "net/url" "path" "runtime" + "github.com/valyala/fasttemplate" "time" ) @@ -43,6 +47,7 @@ func (module *Module) Setup() { api.HandleAPIMethod(api.POST, "/setup/_validate", module.validate) api.HandleAPIMethod(api.POST, "/setup/_initialize", module.initialize) + elastic3.InitTestAPI() } var setupFinishedCallback= []func() {} @@ -65,6 +70,8 @@ func (module *Module) Stop() error { type SetupRequest struct { Cluster struct { + Host string `json:"host"` + Schema string `json:"schema"` Endpoint string `json:"endpoint"` Username string `json:"username"` Password string `json:"password"` @@ -96,6 +103,9 @@ func (module *Module) validate(w http.ResponseWriter, r *http.Request, ps httpro var code int code=200 defer func() { + + global.Env().CheckSetup() + result := util.MapStr{} result["success"]=success @@ -171,12 +181,17 @@ func (module *Module) validate(w http.ResponseWriter, r *http.Request, ps httpro if indices != nil && len(*indices) > 0 { buff := bytes.Buffer{} + tipBuff := bytes.Buffer{} for k, _ := range *indices { buff.WriteString(k) buff.WriteString("\n") + + tipBuff.WriteString("DELETE ") + tipBuff.WriteString(k) + tipBuff.WriteString("\n") } errType = IndicesExists - fixTips="DELETE "+util.TrimSpaces(cfg1.IndexPrefix) + "*" + fixTips=tipBuff.String() panic(errors.Errorf("there are following indices exists in target elasticsearch: \n%v", buff.String())) } @@ -200,10 +215,16 @@ func (module *Module) initTempClient(r *http.Request) (error, elastic.API,SetupR return err,nil,request } - if request.Cluster.Endpoint==""{ + if request.Cluster.Endpoint==""&&request.Cluster.Host==""{ panic("invalid configuration") } + if request.Cluster.Endpoint==""{ + if request.Cluster.Host!=""&&request.Cluster.Schema!=""{ + request.Cluster.Endpoint=fmt.Sprintf("%v://%v",request.Cluster.Schema,request.Cluster.Host) + } + } + cfg = elastic.ElasticsearchConfig{ Enabled: true, Reserved: true, @@ -214,6 +235,15 @@ func (module *Module) initTempClient(r *http.Request) (error, elastic.API,SetupR }, } + if cfg.Endpoint!=""&&cfg.Host==""{ + uri,err:=uri2.Parse(cfg.Endpoint) + if err!=nil{ + panic(err) + } + cfg.Host=uri.Host + cfg.Schema=uri.Scheme + } + cfg.ID = tempID cfg.Name = "INFINI_SYSTEM ("+util.PickRandomName()+")" elastic.InitMetadata(&cfg, true) @@ -243,6 +273,9 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http var code int code=200 defer func() { + + global.Env().CheckSetup() + result := util.MapStr{} result["success"]=success @@ -297,7 +330,7 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http //处理ORM handler := elastic2.ElasticORM{Client: client, Config:cfg1 } - orm.Register("elastic_setup", handler) + orm.Register("elastic_setup_"+util.GetUUID(), handler) //处理模版 elastic2.InitTemplate(true) @@ -306,6 +339,39 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http //TEMPLATE_NAME //INDEX_PREFIX + dslTplFile:=path.Join(global.Env().GetConfigDir(),"initialization.tpl") + dslFile:=path.Join(global.Env().GetConfigDir(),"initialization.dsl") + + var dsl []byte + dsl,err=util.FileGetContent(dslTplFile) + if err!=nil{ + panic(err) + } + + if len(dsl)>0{ + var tpl *fasttemplate.Template + tpl,err=fasttemplate.NewTemplate(string(dsl), "$[[", "]]") + if err!=nil{ + panic(err) + } + if tpl!=nil{ + output:=tpl.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { + switch tag { + case "TEMPLATE_NAME": + return w.Write([]byte(cfg1.TemplateName)) + case "INDEX_PREFIX": + return w.Write([]byte(cfg1.IndexPrefix)) + } + panic(errors.Errorf("unknown tag: %v",tag)) + }) + _,err=util.FilePutContent(dslFile,output) + if err!=nil{ + panic(err) + } + } + } + + //处理索引 elastic2.InitSchema() //init security From 48c436828275efa16a476448a2fcc6cc8d3c338a Mon Sep 17 00:00:00 2001 From: medcl Date: Sat, 22 Oct 2022 23:46:51 +0800 Subject: [PATCH 05/10] enable system monitoring by default --- plugin/setup/setup.go | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index 961f2926..c39c1da0 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -327,6 +327,7 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http } cfg.Reserved=true + cfg.Monitored=true //处理ORM handler := elastic2.ElasticORM{Client: client, Config:cfg1 } From 17136af69dd8a5c457c454a83b6313b9baa00623 Mon Sep 17 00:00:00 2001 From: medcl Date: Sun, 23 Oct 2022 11:51:27 +0800 Subject: [PATCH 06/10] fix api not for setup module --- config/initialization.tpl | 1 - plugin/api/gateway/api.go | 2 +- plugin/api/init.go | 4 ++++ plugin/api/insight/api.go | 2 +- plugin/setup/setup.go | 3 +-- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/config/initialization.tpl b/config/initialization.tpl index 6e284740..a87f8cd0 100644 --- a/config/initialization.tpl +++ b/config/initialization.tpl @@ -61,7 +61,6 @@ PUT _ilm/policy/ilm_$[[INDEX_PREFIX]]metrics-30days-retention "min_age": "30d", "actions": { "delete": { - "delete_searchable_snapshot": true } } } diff --git a/plugin/api/gateway/api.go b/plugin/api/gateway/api.go index d41a9524..e37d444a 100644 --- a/plugin/api/gateway/api.go +++ b/plugin/api/gateway/api.go @@ -13,7 +13,7 @@ type GatewayAPI struct { api.Handler } -func init() { +func InitAPI() { gateway:=GatewayAPI{} api.HandleAPIMethod(api.POST, "/gateway/instance/try_connect", gateway.RequireLogin(gateway.tryConnect)) api.HandleAPIMethod(api.GET, "/gateway/instance/:instance_id", gateway.RequirePermission(gateway.getInstance, enum.PermissionGatewayInstanceRead)) diff --git a/plugin/api/init.go b/plugin/api/init.go index 72818baf..aff72102 100644 --- a/plugin/api/init.go +++ b/plugin/api/init.go @@ -3,7 +3,9 @@ package api import ( "infini.sh/console/config" "infini.sh/console/plugin/api/alerting" + "infini.sh/console/plugin/api/gateway" "infini.sh/console/plugin/api/index_management" + "infini.sh/console/plugin/api/insight" "infini.sh/framework/core/api" "infini.sh/framework/core/api/rbac/enum" "path" @@ -62,4 +64,6 @@ func Init(cfg *config.AppConfig) { alertAPI.Init() + gateway.InitAPI() + insight.InitAPI() } diff --git a/plugin/api/insight/api.go b/plugin/api/insight/api.go index cba24a23..f050a45e 100644 --- a/plugin/api/insight/api.go +++ b/plugin/api/insight/api.go @@ -10,7 +10,7 @@ type InsightAPI struct { api.Handler } -func init() { +func InitAPI() { insight := InsightAPI{} api.HandleAPIMethod(api.POST, "/elasticsearch/:id/visualization/metadata", insight.HandleGetMetadata) api.HandleAPIMethod(api.POST, "/elasticsearch/:id/visualization/data", insight.HandleGetMetricData) diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index c39c1da0..abed8e99 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -387,7 +387,7 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http if request.BootstrapUsername!=""&&request.BootstrapPassword!=""{ //Save bootstrap user user:=rbac.User{} - user.ID="default_user_"+util.GetUUID() + user.ID="default_user_"+request.BootstrapUsername user.Name=request.BootstrapUsername user.NickName=request.BootstrapUsername var hash []byte @@ -421,7 +421,6 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http } //处理 ILM - //处理默认用户信息 //callback InvokeSetupCallback() From 2002a38c92c1a46afc1b28a082ec0e8460b8ab96 Mon Sep 17 00:00:00 2001 From: medcl Date: Sun, 23 Oct 2022 22:45:41 +0800 Subject: [PATCH 07/10] disable builtin user by default --- plugin/setup/setup.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index abed8e99..31c229e9 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -254,7 +254,7 @@ func (module *Module) initTempClient(r *http.Request) (error, elastic.API,SetupR elastic.UpdateConfig(cfg) elastic.UpdateClient(cfg, client) - + cfg.Version=client.GetVersion() global.Register(elastic.GlobalSystemElasticsearchID,tempID) return err, client,request @@ -425,6 +425,12 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http //callback InvokeSetupCallback() + //disable builtin auth + err=api.DisableBuiltinUserAdmin() + if err!=nil{ + panic(err) + } + //place setup lock file setupLock:=path.Join(global.Env().GetDataDir(),".setup_lock") _,err=util.FilePutContent(setupLock,time.Now().String()) From b08c12dfbe6d5669d70e448feb09a6133bf8f9aa Mon Sep 17 00:00:00 2001 From: medcl Date: Mon, 24 Oct 2022 17:56:25 +0800 Subject: [PATCH 08/10] fix ilm template --- config/initialization.tpl | 159 +++++++++++++++++++++++++++++++++++--- 1 file changed, 150 insertions(+), 9 deletions(-) diff --git a/config/initialization.tpl b/config/initialization.tpl index a87f8cd0..d5a08cb6 100644 --- a/config/initialization.tpl +++ b/config/initialization.tpl @@ -113,7 +113,77 @@ PUT $[[INDEX_PREFIX]]metrics-00001 "$[[INDEX_PREFIX]]metrics":{ "is_write_index":true } - } + }, + "mappings": { + "dynamic_templates": [ + { + "strings": { + "match_mapping_type": "string", + "mapping": { + "ignore_above": 256, + "type": "keyword" + } + } + } + ], + "properties": { + "metadata": { + "properties": { + "category": { + "type": "keyword", + "ignore_above": 256 + }, + "datatype": { + "type": "keyword", + "ignore_above": 256 + }, + "labels": { + "properties": { + "cluster_id": { + "type": "keyword", + "ignore_above": 256 + }, + "index_id": { + "type": "keyword", + "ignore_above": 256 + }, + "index_name": { + "type": "keyword", + "ignore_above": 256 + }, + "index_uuid": { + "type": "keyword", + "ignore_above": 256 + }, + "ip": { + "type": "keyword", + "ignore_above": 256 + }, + "node_id": { + "type": "keyword", + "ignore_above": 256 + }, + "node_name": { + "type": "keyword", + "ignore_above": 256 + }, + "transport_address": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "name": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "timestamp": { + "type": "date" + } + } + } } @@ -311,15 +381,86 @@ PUT _template/$[[INDEX_PREFIX]]activities-rollover PUT $[[INDEX_PREFIX]]activities-00001 { -"settings": { - "index.lifecycle.rollover_alias":"$[[INDEX_PREFIX]]activities" - , "refresh_interval": "5s" -}, -"aliases":{ - "$[[INDEX_PREFIX]]activities":{ - "is_write_index":true + "mappings": { + "dynamic_templates": [ + { + "strings": { + "match_mapping_type": "string", + "mapping": { + "ignore_above": 256, + "type": "keyword" + } + } + } + ], + "properties": { + "changelog": { + "type": "flattened" + }, + "id": { + "type": "keyword" + }, + "metadata": { + "properties": { + "category": { + "type": "keyword", + "ignore_above": 256 + }, + "group": { + "type": "keyword", + "ignore_above": 256 + }, + "labels": { + "type": "flattened" + }, + "name": { + "type": "keyword", + "ignore_above": 256 + }, + "type": { + "type": "keyword", + "ignore_above": 256 + } + } + }, + "payload": { + "type": "object", + "enabled": false + }, + "timestamp": { + "type": "date" + } + } + }, + "settings": { + "index": { + "lifecycle.rollover_alias": "$[[INDEX_PREFIX]]activities", + "refresh_interval": "5s", + "mapping": { + "total_fields": { + "limit": "20000" + } + }, + "max_result_window": "10000000", + "analysis": { + "analyzer": { + "suggest_text_search": { + "filter": [ + "word_delimiter" + ], + "tokenizer": "classic" + } + } + } + } + }, + "aliases": { + "$[[INDEX_PREFIX]]activities": { + "is_write_index": true + } } } -} + +GET / From 02aa8c58f8ffbc388324e5a30df9759103cbb2af Mon Sep 17 00:00:00 2001 From: medcl Date: Mon, 24 Oct 2022 17:56:40 +0800 Subject: [PATCH 09/10] add replay flow --- plugin/setup/setup.go | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index 31c229e9..7abdd519 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -13,17 +13,20 @@ import ( "infini.sh/framework/core/global" "infini.sh/framework/core/module" "infini.sh/framework/core/orm" + "infini.sh/framework/core/pipeline" "infini.sh/framework/core/util" elastic2 "infini.sh/framework/modules/elastic" elastic1 "infini.sh/framework/modules/elastic/common" elastic3 "infini.sh/framework/modules/elastic/api" "infini.sh/framework/modules/security" + "infini.sh/framework/plugins/replay" "io" "net/http" uri2 "net/url" "path" "runtime" "github.com/valyala/fasttemplate" + log "github.com/cihub/seelog" "time" ) @@ -339,7 +342,6 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http //处理生命周期 //TEMPLATE_NAME //INDEX_PREFIX - dslTplFile:=path.Join(global.Env().GetConfigDir(),"initialization.tpl") dslFile:=path.Join(global.Env().GetConfigDir(),"initialization.dsl") @@ -349,6 +351,7 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http panic(err) } + var dslWriteSuccess=false if len(dsl)>0{ var tpl *fasttemplate.Template tpl,err=fasttemplate.NewTemplate(string(dsl), "$[[", "]]") @@ -369,6 +372,15 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http if err!=nil{ panic(err) } + dslWriteSuccess=true + } + } + + if dslWriteSuccess{ + lines := util.FileGetLines(dslFile) + _,err,_:=replay.ReplayLines(pipeline.AcquireContext(),lines,cfg.Schema,cfg.Host) + if err!=nil{ + log.Error(err) } } From e607254cc455617e3f3cbff828e11a63b4c47933 Mon Sep 17 00:00:00 2001 From: medcl Date: Mon, 24 Oct 2022 19:01:49 +0800 Subject: [PATCH 10/10] add default alerting rules to setup process --- config/initialization.tpl | 1009 +++++++++++++++++++++++++++++++++++++ plugin/setup/setup.go | 6 +- 2 files changed, 1014 insertions(+), 1 deletion(-) diff --git a/config/initialization.tpl b/config/initialization.tpl index d5a08cb6..29332649 100644 --- a/config/initialization.tpl +++ b/config/initialization.tpl @@ -461,6 +461,1015 @@ PUT $[[INDEX_PREFIX]]activities-00001 } } + +#alerting +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-calakp97h710dpnp1fa2 +{ + "id": "builtin-calakp97h710dpnp1fa2", + "created": "2022-06-16T03:58:29.437447113Z", + "updated": "2022-07-21T23:12:51.111569117Z", + "name": "CPU utilization is Too High", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]metrics*" + ], + "filter": {}, + "raw_filter": { + "bool": { + "must": [ + { + "term": { + "metadata.name": { + "value": "node_stats" + } + } + }, + { + "term": { + "metadata.category": { + "value": "elasticsearch" + } + } + } + ] + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.labels.cluster_id", + "limit": 5 + }, + { + "field": "metadata.labels.node_id", + "limit": 300 + } + ], + "formula": "a", + "items": [ + { + "name": "a", + "field": "payload.elasticsearch.node_stats.process.cpu.percent", + "statistic": "avg" + } + ], + "format_type": "ratio", + "expression": "avg(payload.elasticsearch.node_stats.process.cpu.percent)", + "title": "CPU Usage of Node[s] ({{.first_group_value}} ..., {{len .results}} nodes in total) >= {{.first_threshold}}%", + "message": "Timestamp:{{.timestamp | datetime}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}};NodeID:{{index .group_values 1}}; CPU:{{.result_value | to_fixed 2}}%;\n{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "80" + ], + "priority": "low" + }, + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "90" + ], + "priority": "medium" + }, + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "95" + ], + "priority": "high" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-06-16T04:11:10.242061032Z", + "name": "Slack", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"error\"}} \"#EB4C21\" {{else}} \"#FFB449\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*NodeID:* {{index .group_values 1}}\"\n }\n ,\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Usage:* {{.result_value | to_fixed 2}}%\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}/#/cluster/overview/{{ index .group_values 0}}/nodes/{{ index .group_values 1}}|View Node Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + } + ], + "throttle_period": "6h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-cal8n7p7h710dpnoaps0 +{ + "id": "builtin-cal8n7p7h710dpnoaps0", + "created": "2022-06-16T01:47:11.326727124Z", + "updated": "2022-07-13T04:00:06.181994982Z", + "name": "Cluster Health Change to Red", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]metrics*" + ], + "filter": {}, + "raw_filter": { + "bool": { + "must": [ + { + "match": { + "payload.elasticsearch.cluster_health.status": "red" + } + }, + { + "term": { + "metadata.name": { + "value": "cluster_health" + } + } + } + ] + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.labels.cluster_id", + "limit": 5 + } + ], + "formula": "a", + "items": [ + { + "name": "a", + "field": "payload.elasticsearch.cluster_health.status", + "statistic": "count" + } + ], + "format_type": "num", + "expression": "count(payload.elasticsearch.cluster_health.status)", + "title": "Health of Cluster[s] ({{.first_group_value}} ..., {{len .results}} clusters in total) Changed to Red", + "message": "Priority:{{.priority}}\nTimestamp:{{.timestamp | datetime}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}} is red now;\n{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "1" + ], + "priority": "critical" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-06-16T01:47:11.326727124Z", + "updated": "2022-06-16T01:47:11.326727124Z", + "name": "Slack webhook", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"high\"}} \"#EB4C21\" {{else if eq .priority \"medium\"}} \"#FFB449\" {{else if eq .priority \"low\"}} \"#87d068\" {{else}} \"#2db7f5\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}/#/cluster/monitor/elasticsearch/{{ index .group_values 0}}|View Cluster Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + }, + { + "created": "2022-06-16T01:47:11.326727124Z", + "updated": "2022-06-16T01:47:11.326727124Z", + "name": "DingTalk", + "type": "webhook", + "webhook": { + "header_params": { + "Content-type": "application/json" + }, + "method": "POST", + "url": "${DINGTALK_WEBHOOK_ENDPOINT}", + "body": "{\"msgtype\": \"text\",\"text\": {\"content\":\"Alerting: \\n{{.title}}\\n\\n{{.message}}\\nLink:${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}\"}}" + } + } + ], + "throttle_period": "1h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-cal8n7p7h710dpnogps1 +{ + "id": "builtin-cal8n7p7h710dpnogps1", + "created": "2022-06-16T03:11:01.445958361Z", + "updated": "2022-07-22T00:06:26.498903821Z", + "name": "Disk utilization is Too High", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]metrics*" + ], + "filter": {}, + "raw_filter": { + "bool": { + "must": [ + { + "term": { + "metadata.name": { + "value": "node_stats" + } + } + }, + { + "term": { + "metadata.category": { + "value": "elasticsearch" + } + } + } + ] + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.labels.cluster_id", + "limit": 5 + }, + { + "field": "metadata.labels.node_id", + "limit": 200 + } + ], + "formula": "((a-b)/a)*100", + "items": [ + { + "name": "a", + "field": "payload.elasticsearch.node_stats.fs.data.total_in_bytes", + "statistic": "max" + }, + { + "name": "b", + "field": "payload.elasticsearch.node_stats.fs.data.free_in_bytes", + "statistic": "max" + } + ], + "format_type": "ratio", + "expression": "((max(payload.elasticsearch.node_stats.fs.data.total_in_bytes)-max(payload.elasticsearch.node_stats.fs.data.free_in_bytes))/max(payload.elasticsearch.node_stats.fs.data.total_in_bytes))*100", + "title": "Disk Utilization is Too High", + "message": "Priority:{{.priority}}\nTimestamp:{{.timestamp | datetime}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}} ;\nNodeID:{{index .group_values 1}} ;\nDisk Usage:{{.result_value | to_fixed 2}}%;Free Storage:{{.relation_values.b | format_bytes 2}};\n{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 5, + "operator": "gte", + "values": [ + "85" + ], + "priority": "low" + }, + { + "minimum_period_match": 5, + "operator": "gte", + "values": [ + "90" + ], + "priority": "medium" + }, + { + "minimum_period_match": 5, + "operator": "gte", + "values": [ + "95" + ], + "priority": "high" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "0001-01-01T00:00:00Z", + "updated": "0001-01-01T00:00:00Z", + "name": "Slack", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"error\"}} \"#EB4C21\" {{else}} \"#FFB449\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*NodeID:* {{index .group_values 1}}\"\n }\n ,\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Usage:* {{.result_value | to_fixed 2}}%\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Free:* {{.relation_values.b | format_bytes 2}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}#/cluster/overview/{{ index .group_values 0}}/nodes/{{ index .group_values 1}}|View Node Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + } + ], + "throttle_period": "3h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-cbp20n2anisjmu4gehc5 +{ + "id": "builtin-cbp20n2anisjmu4gehc5", + "created": "2022-08-09T08:52:44.63345561Z", + "updated": "2022-08-09T08:52:44.633455664Z", + "name": "Elasticsearch node left cluster", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]node" + ], + "filter": {}, + "raw_filter": { + "match_phrase": { + "metadata.labels.status": "unavailable" + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.cluster_id", + "limit": 5 + }, + { + "field": "metadata.node_id", + "limit": 50 + } + ], + "formula": "a", + "items": [ + { + "name": "a", + "field": "metadata.labels.status", + "statistic": "count" + } + ], + "format_type": "num", + "expression": "count(metadata.labels.status)", + "title": "Elasticsearch node left cluster", + "message": "Priority:{{.priority}}\nTimestamp:{{.timestamp | datetime_in_zone \"Asia/Shanghai\"}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}}; \nNodeID:{{index .group_values 1}}; \n{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "1" + ], + "priority": "critical" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-08-09T08:52:44.63345561Z", + "updated": "2022-08-09T08:52:44.63345561Z", + "name": "Wechat", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${WECHAT_WEBHOOK_ENDPOINT}", + "body": "{\n \"msgtype\": \"markdown\",\n \"markdown\": {\n \"content\": \"Incident [#{{.event_id}}](${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}) is ongoing\\n{{.title}}\\n\n {{range .results}}\n >ClusterID:{{index .group_values 0}}\n >NodeID:{{index .group_values 1}}\n >Priority:{{.priority}}\n >Link:[View Cluster Monitoring](${INFINI_CONSOLE_ENDPOINT}/#/cluster/overview/{{ index .group_values 0}}/nodes/{{ index .group_values 1}}) \n {{end}}\"\n }\n}\n" + } + } + ], + "throttle_period": "1h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-calavvp7h710dpnp32r3 +{ + "id": "builtin-calavvp7h710dpnp32r3", + "created": "2022-06-16T04:22:23.001354546Z", + "updated": "2022-07-21T23:10:36.70696738Z", + "name": "Index Health Change to Red", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]index" + ], + "filter": {}, + "raw_filter": { + "match_phrase": { + "metadata.labels.health_status": "red" + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.cluster_id", + "limit": 5 + }, + { + "field": "metadata.index_name", + "limit": 5 + } + ], + "formula": "a", + "items": [ + { + "name": "a", + "field": "metadata.index_name", + "statistic": "count" + } + ], + "format_type": "num", + "expression": "count(metadata.index_name)", + "title": "Health of Indices ({{.first_group_value}} ..., {{len .results}} indices in total) Changed to Red", + "message": "Timestamp:{{.timestamp | datetime}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}}; Index name:{{index .group_values 1}}; {{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "1" + ], + "priority": "high" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-06-16T04:11:10.242061032Z", + "name": "Slack", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"error\"}} \"#EB4C21\" {{else}} \"#FFB449\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Index:* {{index .group_values 1}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}/#/cluster/monitor/elasticsearch/{{ index .group_values 0}}?_g=%7B%22tab%22%3A%22indices%22%7D|View Index Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + } + ], + "throttle_period": "1h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-calaqnh7h710dpnp2bm8 +{ + "id": "builtin-calaqnh7h710dpnp2bm8", + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-07-21T23:12:07.142532243Z", + "name": "JVM utilization is Too High", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]metrics*" + ], + "filter": {}, + "raw_filter": { + "bool": { + "must": [ + { + "term": { + "metadata.name": { + "value": "node_stats" + } + } + }, + { + "term": { + "metadata.category": { + "value": "elasticsearch" + } + } + } + ] + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.labels.cluster_id", + "limit": 5 + }, + { + "field": "metadata.labels.node_id", + "limit": 300 + } + ], + "formula": "a", + "items": [ + { + "name": "a", + "field": "payload.elasticsearch.node_stats.jvm.mem.heap_used_percent", + "statistic": "p90" + } + ], + "format_type": "ratio", + "expression": "p90(payload.elasticsearch.node_stats.jvm.mem.heap_used_percent)", + "title": "JVM Usage of Node[s] ({{.first_group_value}} ..., {{len .results}} nodes in total) >= {{.first_threshold}}%", + "message": "Timestamp:{{.timestamp | datetime}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}}; Node name:{{index .group_values 1}}; memory used percent:{{.result_value | to_fixed 2}}%;{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "80" + ], + "priority": "low" + }, + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "90" + ], + "priority": "medium" + }, + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "95" + ], + "priority": "high" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-06-16T04:11:10.242061032Z", + "name": "Slack", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"error\"}} \"#EB4C21\" {{else}} \"#FFB449\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*NodeID:* {{index .group_values 1}}\"\n }\n ,\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Usage:* {{.result_value | to_fixed 2}}%\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}/#/cluster/overview/{{ index .group_values 0}}/nodes/{{ index .group_values 1}}|View Node Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + } + ], + "throttle_period": "3h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-cbp2e4ianisjmu4giqs7 +{ + "id": "builtin-cbp2e4ianisjmu4giqs7", + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-08-09T09:39:29.604751601Z", + "name": "Search latency is great than 500ms", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]metrics*" + ], + "filter": {}, + "raw_filter": { + "bool": { + "must": [ + { + "term": { + "metadata.name": { + "value": "index_stats" + } + } + }, + { + "term": { + "metadata.category": { + "value": "elasticsearch" + } + } + } + ], + "must_not": [ + { + "term": { + "metadata.labels.index_name": { + "value": "_all" + } + } + } + ] + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.labels.cluster_id", + "limit": 5 + }, + { + "field": "metadata.labels.index_name", + "limit": 500 + } + ], + "formula": "a/b", + "items": [ + { + "name": "a", + "field": "payload.elasticsearch.index_stats.total.search.query_time_in_millis", + "statistic": "rate" + }, + { + "name": "b", + "field": "payload.elasticsearch.index_stats.primaries.search.query_total", + "statistic": "rate" + } + ], + "format_type": "num", + "expression": "rate(payload.elasticsearch.index_stats.total.search.query_time_in_millis)/rate(payload.elasticsearch.index_stats.primaries.search.query_total)", + "title": "Search latency is great than 500ms", + "message": "Priority:{{.priority}}\nTimestamp:{{.timestamp | datetime_in_zone \"Asia/Shanghai\"}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}}; \nIndex name:{{index .group_values 1}}; \nCurrent value:{{.result_value | to_fixed 2}}ms;\n{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "500" + ], + "priority": "medium" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-06-16T04:11:10.242061032Z", + "name": "Slack", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"error\"}} \"#EB4C21\" {{else}} \"#FFB449\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Index:* {{index .group_values 1}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Latency:* {{.result_value | to_fixed 2}}ms\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}/#/cluster/overview/{{ index .group_values 0}}/indices/{{ index .group_values 1}}|View Index Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + } + ], + "throttle_period": "1h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/builtin-calgapp7h710dpnpbeb6 +{ + "id": "builtin-calgapp7h710dpnpbeb6", + "created": "2022-06-16T10:26:47.360988761Z", + "updated": "2022-07-22T00:03:34.044562893Z", + "name": "Shard Storage >= 55G", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]metrics*" + ], + "filter": {}, + "raw_filter": { + "range": { + "payload.elasticsearch.index_stats.shard_info.store_in_bytes": { + "gte": 59055800320 + } + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.labels.cluster_id", + "limit": 5 + }, + { + "field": "metadata.labels.index_name", + "limit": 500 + } + ], + "formula": "a", + "items": [ + { + "name": "a", + "field": "payload.elasticsearch.index_stats.shard_info.store_in_bytes", + "statistic": "max" + } + ], + "format_type": "bytes", + "expression": "max(payload.elasticsearch.index_stats.shard_info.store_in_bytes)", + "title": "Shard Storage >55GB in ({{.first_group_value}} ..., {{len .results}} indices in total)", + "message": "Timestamp:{{.timestamp | datetime}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}}; Index:{{index .group_values 1}}; Max Shard Storage:{{.result_value | format_bytes 2}};{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "53687091200" + ], + "priority": "high" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-06-16T04:11:10.242061032Z", + "name": "Slack", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"error\"}} \"#EB4C21\" {{else}} \"#FFB449\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Index:* {{index .group_values 1}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Max Shard Storage:* {{.result_value | format_bytes 2}}\"\n },\n \n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}/#/cluster/overview/{{ index .group_values 0}}/indices/{{ index .group_values 1}}?_g={%22cluster_name%22:%22{{ index .group_values 0}}%22}|View Index Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + } + ], + "throttle_period": "24h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + +#The `id` value is consistent with the `_id` value +POST $[[INDEX_PREFIX]]alert-rule/_doc/cb34sfl6psfiqtovhpt4 +{ + "id": "cb34sfl6psfiqtovhpt4", + "created": "2022-07-07T03:08:46.297166036Z", + "updated": "2022-08-09T08:40:05.323148338Z", + "name": "Too Many Deleted Documents", + "enabled": false, + "resource": { + "resource_id": "$[[RESOURCE_ID]]", + "resource_name": "$[[RESOURCE_NAME]]", + "type": "elasticsearch", + "objects": [ + "$[[INDEX_PREFIX]]metrics*" + ], + "filter": {}, + "raw_filter": { + "range": { + "payload.elasticsearch.cluster_stats.indices.store.size_in_bytes": { + "gte": 32212254720 + } + } + }, + "time_field": "timestamp", + "context": { + "fields": null + } + }, + "metrics": { + "bucket_size": "1m", + "groups": [ + { + "field": "metadata.labels.cluster_id", + "limit": 5 + }, + { + "field": "metadata.labels.index_name", + "limit": 300 + } + ], + "formula": "(a/(a+b))*100", + "items": [ + { + "name": "a", + "field": "payload.elasticsearch.index_stats.primaries.docs.deleted", + "statistic": "max" + }, + { + "name": "b", + "field": "payload.elasticsearch.index_stats.primaries.docs.count", + "statistic": "max" + } + ], + "format_type": "ratio", + "expression": "(max(payload.elasticsearch.index_stats.primaries.docs.deleted)/(max(payload.elasticsearch.index_stats.primaries.docs.deleted)+max(payload.elasticsearch.index_stats.primaries.docs.count)))*100", + "title": "Too Many Deleted Documents (>30%)", + "message": "Priority:{{.priority}}\nTimestamp:{{.timestamp | datetime_in_zone \"Asia/Shanghai\"}}\nRuleID:{{.rule_id}}\nEventID:{{.event_id}}\n{{range .results}}\nClusterID:{{index .group_values 0}}; \nIndex:{{index .group_values 0}}; \nRatio of Deleted Documents:{{.result_value}};\n{{end}}" + }, + "conditions": { + "operator": "any", + "items": [ + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "30" + ], + "priority": "medium" + }, + { + "minimum_period_match": 1, + "operator": "gte", + "values": [ + "40" + ], + "priority": "high" + } + ] + }, + "channels": { + "enabled": true, + "normal": [ + { + "created": "2022-06-16T04:11:10.242061032Z", + "updated": "2022-06-16T04:11:10.242061032Z", + "name": "Slack", + "type": "webhook", + "webhook": { + "header_params": { + "Content-Type": "application/json" + }, + "method": "POST", + "url": "${SLACK_WEBHOOK_ENDPOINT}", + "body": "{\n \"blocks\": [\n {\n \"type\": \"section\",\n \"text\": {\n \"type\": \"mrkdwn\",\n \"text\": \"Incident <${INFINI_CONSOLE_ENDPOINT}/#/alerting/alert/{{.event_id}}|#{{.event_id}}> is ongoing\\n{{.title}}\"\n }\n }\n ],\n \"attachments\": [\n {{range .results}}\n {\n \"color\": {{if eq .priority \"critical\"}} \"#C91010\" {{else if eq .priority \"error\"}} \"#EB4C21\" {{else}} \"#FFB449\" {{end}},\n \"blocks\": [\n {\n \"type\": \"section\",\n \"fields\": [\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Priority:* {{.priority}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*ClusterID:* {{index .group_values 0}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Index:* {{index .group_values 1}}\"\n },\n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Deleted:* {{.result_value | to_fixed 2}}%\"\n },\n \n {\n \"type\": \"mrkdwn\",\n \"text\": \"*Link:* <${INFINI_CONSOLE_ENDPOINT}/#/cluster/overview/{{ index .group_values 0}}/indices/{{ index .group_values 1}}?_g={%22cluster_name%22:%22{{ index .group_values 0}}%22}|View Index Monitoring>\"\n }\n ]\n }\n ]\n },\n {{end}}\n ]\n}" + } + } + ], + "throttle_period": "24h", + "accept_time_range": { + "start": "00:00", + "end": "23:59" + } + }, + "schedule": { + "interval": "1m" + } +} + + GET / diff --git a/plugin/setup/setup.go b/plugin/setup/setup.go index 7abdd519..b4d7984c 100644 --- a/plugin/setup/setup.go +++ b/plugin/setup/setup.go @@ -84,7 +84,7 @@ type SetupRequest struct { BootstrapPassword string `json:"bootstrap_password"` } -var tempID="infini_system_cluster_"+util.GetUUID() +var tempID="infini_default_system_cluster" const VersionTooOld ="elasticsearch_version_too_old" const IndicesExists ="elasticsearch_indices_exists" @@ -365,6 +365,10 @@ func (module *Module) initialize(w http.ResponseWriter, r *http.Request, ps http return w.Write([]byte(cfg1.TemplateName)) case "INDEX_PREFIX": return w.Write([]byte(cfg1.IndexPrefix)) + case "RESOURCE_ID": + return w.Write([]byte(cfg.ID)) + case "RESOURCE_NAME": + return w.Write([]byte(cfg.Name)) } panic(errors.Errorf("unknown tag: %v",tag)) })