Rdb (#479)
* use collector interface * mysql can work fine * add basecollector * add prober & monapi.plugins * enable mysql plugins work * rename collector -> manager * add white list access check for rdb * add cache module for authConfig & session * rollback n9e_rdb_3.3.0.sql * add sql ddl document * add white_list, pwd, login access control * add email code for login & reset password * use sessionUsername instead of cookieUsername * remove cookie name and data from session * rename userName to username * add remote_addr with session connection * add get user by sid with cache * enable cookie life time could be zero * go mod tidy * Rdb with session & monapi with telegraf (#456) * use collector interface * mysql can work fine * add basecollector * add prober & monapi.plugins * enable mysql plugins work * rename collector -> manager * add white list access check for rdb * add cache module for authConfig & session * rollback n9e_rdb_3.3.0.sql * add sql ddl document * add white_list, pwd, login access control * add email code for login & reset password * use sessionUsername instead of cookieUsername * remove cookie name and data from session * rename userName to username * add remote_addr with session connection * add get user by sid with cache * enable cookie life time could be zero * go mod tidy * add plugins config for prober * add prober plugin expression parse * update transfer default config for m3 * Rdb (#458) * bugfix: session gc * use flag for pwdMustInclude * change user login function * delete invite token after use * bugfix: login response * add sessionStart middle ware * add auth module * add i18n for rdb * add i18n.zh for rdb.auth * add mon plugins(redis, mongodb) * update config * add sub struct into definitions * clean up sid cache after session destory * bugfix: get user return nil when not found * update i18n * bugfix: ignore cache nologin user * add user for callback output * add password change api * update default configfile & sql patch * merge mon http middleware from rdb * remove sso logout, sso already supporte one time auth
This commit is contained in:
parent
bad43090ff
commit
d45ea02562
|
@ -31,6 +31,7 @@ _test
|
||||||
/build
|
/build
|
||||||
/dist
|
/dist
|
||||||
/etc/*.local.yml
|
/etc/*.local.yml
|
||||||
|
/etc/plugins/*.local.yml
|
||||||
/etc/log/log.test.json
|
/etc/log/log.test.json
|
||||||
/data*
|
/data*
|
||||||
/tarball
|
/tarball
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
## 登陆相关
|
||||||
|
|
||||||
|
#### 来源地址限制
|
||||||
|
|
||||||
|
IP地址的获取顺序
|
||||||
|
|
||||||
|
- http header "X-Forwarded-For"
|
||||||
|
- http header "X-Real-Ip"
|
||||||
|
- http request RemoteAddr
|
||||||
|
|
||||||
|
nginx 代理配置客户端地址
|
||||||
|
|
||||||
|
```
|
||||||
|
# https://www.nginx.com/resources/wiki/start/topics/examples/forwarded/
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
```
|
|
@ -42,5 +42,11 @@ judge:
|
||||||
addresses:
|
addresses:
|
||||||
- 127.0.0.1
|
- 127.0.0.1
|
||||||
|
|
||||||
|
prober:
|
||||||
|
http: 0.0.0.0:8023
|
||||||
|
rpc: 0.0.0.0:8024
|
||||||
|
addresses:
|
||||||
|
- 127.0.0.1
|
||||||
|
|
||||||
agent:
|
agent:
|
||||||
http: 0.0.0.0:2080
|
http: 0.0.0.0:2080
|
||||||
|
|
|
@ -6,7 +6,7 @@ logger:
|
||||||
http:
|
http:
|
||||||
mode: release
|
mode: release
|
||||||
cookieDomain: ""
|
cookieDomain: ""
|
||||||
cookieName: ecmc-user
|
cookieName: ecmc-sid
|
||||||
|
|
||||||
tokens:
|
tokens:
|
||||||
- ams-builtin-token
|
- ams-builtin-token
|
||||||
|
|
|
@ -57,6 +57,101 @@
|
||||||
"node is managed by other system": "租户正在被系统系统使用",
|
"node is managed by other system": "租户正在被系统系统使用",
|
||||||
"resources not found by %s": "通过 %s 没有找到资源",
|
"resources not found by %s": "通过 %s 没有找到资源",
|
||||||
"cannot delete root user": "root用户不能删除",
|
"cannot delete root user": "root用户不能删除",
|
||||||
"user not found": "用户未找到"
|
"user not found": "用户未找到",
|
||||||
|
|
||||||
|
"Databases": "数据库",
|
||||||
|
"if the list is empty, then metrics are gathered from all database tables": "如果列表为空,则收集所有数据库表",
|
||||||
|
"Process List": "进程列表",
|
||||||
|
"gather thread state counts from INFORMATION_SCHEMA.PROCESSLIST": "从 INFORMATION_SCHEMA.PROCESSLIST 收集线程状态信息",
|
||||||
|
"User Statistics": "User Statistics",
|
||||||
|
"gather user statistics from INFORMATION_SCHEMA.USER_STATISTICS": "从 INFORMATION_SCHEMA.USER_STATISTICS 收集用户状态信息",
|
||||||
|
"Auto Increment": "Auto Increment",
|
||||||
|
"gather auto_increment columns and max values from information schema": "采集 auto_increment 和 max values 信息",
|
||||||
|
"Innodb Metrics": "Innodb Metrics",
|
||||||
|
"gather metrics from INFORMATION_SCHEMA.INNODB_METRICS": "采集 INFORMATION_SCHEMA.INNODB_METRICS 信息",
|
||||||
|
"Slave Status": "Slave Status",
|
||||||
|
"gather metrics from SHOW SLAVE STATUS command output": "采集 metrics from SHOW SLAVE STATUS command output",
|
||||||
|
"Binary Logs": "Binary Logs",
|
||||||
|
"gather metrics from SHOW BINARY LOGS command output": "采集 metrics from SHOW BINARY LOGS command output",
|
||||||
|
"Table IO Waits": "Table IO Waits",
|
||||||
|
"gather metrics from PERFORMANCE_SCHEMA.TABLE_IO_WAITS_SUMMARY_BY_TABLE": "采集 from PERFORMANCE_SCHEMA.TABLE_IO_WAITS_SUMMARY_BY_TABLE",
|
||||||
|
"Table Lock Waits": "Table Lock Waits",
|
||||||
|
"gather metrics from PERFORMANCE_SCHEMA.TABLE_LOCK_WAITS": "采集 from PERFORMANCE_SCHEMA.TABLE_LOCK_WAITS",
|
||||||
|
"Index IO Waits": "Index IO Waits",
|
||||||
|
"gather metrics from PERFORMANCE_SCHEMA.TABLE_IO_WAITS_SUMMARY_BY_INDEX_USAGE": "采集 from PERFORMANCE_SCHEMA.TABLE_IO_WAITS_SUMMARY_BY_INDEX_USAGE",
|
||||||
|
"Event Waits": "Event Waits",
|
||||||
|
"gather metrics from PERFORMANCE_SCHEMA.EVENT_WAITS": "采集 from PERFORMANCE_SCHEMA.EVENT_WAITS",
|
||||||
|
"Tables": "Tables",
|
||||||
|
"gather metrics from INFORMATION_SCHEMA.TABLES for databases provided above list": "采集 from INFORMATION_SCHEMA.TABLES for databases provided above list",
|
||||||
|
"File Events Stats": "File Events Stats",
|
||||||
|
"gather metrics from PERFORMANCE_SCHEMA.FILE_SUMMARY_BY_EVENT_NAME": "采集 from PERFORMANCE_SCHEMA.FILE_SUMMARY_BY_EVENT_NAME",
|
||||||
|
"Perf Events Statements": "Perf Events Statements",
|
||||||
|
"gather metrics from PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_SUMMARY_BY_DIGEST": "采集 from PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_SUMMARY_BY_DIGEST",
|
||||||
|
"Interval Slow": "Interval Slow",
|
||||||
|
|
||||||
|
"Repositories": "Repositories",
|
||||||
|
"List of repositories to monitor": "List of repositories to monitor",
|
||||||
|
"Access token": "Access token",
|
||||||
|
"Github API access token. Unauthenticated requests are limited to 60 per hour": "Github API access token. Unauthenticated requests are limited to 60 per hour",
|
||||||
|
"Enterprise base url": "Enterprise base url",
|
||||||
|
"Github API enterprise url. Github Enterprise accounts must specify their base url": "Github API enterprise url. Github Enterprise accounts must specify their base url",
|
||||||
|
"HTTP timeout": "HTTP timeout",
|
||||||
|
"Timeout for HTTP requests": "Timeout for HTTP requests",
|
||||||
|
|
||||||
|
"Unable to get captcha": "无法获得验证码",
|
||||||
|
"Invalid captcha answer": "错误的验证码",
|
||||||
|
"Username %s is invalid": "用户名 %s 不符合规范",
|
||||||
|
"Username %s too long > 64": "用户名 %s 太长(64)",
|
||||||
|
"Unable to get login arguments": "无法获得登陆参数",
|
||||||
|
"Deny Access from %s with whitelist control": "来自 %s 的访问被白名单规则拒绝",
|
||||||
|
"Invalid login type %s": "不支持的登陆类型 %s",
|
||||||
|
"Unable to get type, sms-code | email-code": "无法获得验证码类型",
|
||||||
|
"Unable to get code arg": "无法获得验证码类型",
|
||||||
|
"sms/email sender is disabled": "无法发送 短信/邮件 验证码",
|
||||||
|
"Invalid code type %s": "不支持的验证码类型 %s",
|
||||||
|
"Cannot find the user by %s": "无法用 %s 找到相关用户",
|
||||||
|
"Unable to get password": "无法获取密码",
|
||||||
|
"Invalid code": "不符合规范的验证码",
|
||||||
|
"The code is incorrect": "无效的验证码",
|
||||||
|
"The code has expired": "失效的验证码",
|
||||||
|
"Invalid arguments %s": "不合法的参数 %s",
|
||||||
|
"Login fail, check your username and password": "登陆失败,请检查用户名/密码",
|
||||||
|
"User dose not exist": "用户不存在",
|
||||||
|
"Username %s already exists": "用户名 %s 已存在",
|
||||||
|
|
||||||
|
"Upper char": "大写字母",
|
||||||
|
"Lower char": "小写字母",
|
||||||
|
"Number": "数字",
|
||||||
|
"Special char": "特殊字符",
|
||||||
|
"Must include %s": "必须包含 %s",
|
||||||
|
"Invalid Password, %s": "密码不符合规范, %s",
|
||||||
|
"character: %s not supported": "不支持的字符 %s",
|
||||||
|
"Incorrect login/password %s times, you still have %s chances": "登陆失败%d次,你还有%d次机会",
|
||||||
|
"The limited sessions %d": "会话数量限制,最多%d个会话",
|
||||||
|
"Password has been expired": "密码已过期,请重置密码",
|
||||||
|
"User is inactive": "用户已禁用",
|
||||||
|
"User is locked": "用户已锁定",
|
||||||
|
"User is frozen": "用户已休眠",
|
||||||
|
"User is writen off": "用户已注销",
|
||||||
|
"Minimum password length %d": "密码最小长度 %d",
|
||||||
|
"Password too short (min:%d) %s": "密码太短 (最小 %d) %s",
|
||||||
|
"%s format error":"%s 所填内容不符合规范",
|
||||||
|
"%s %s format error":"%s %s 所填内容不符合规范",
|
||||||
|
"username too long (max:%d)": "用户名太长 (最长:%d)",
|
||||||
|
"dispname too long (max:%d)": "昵称太长 (最长:%d)",
|
||||||
|
"email %s or phone %s is exists": "邮箱 %s 或者 手机号 %s 已存在",
|
||||||
|
"Password is not set": "密码未设置",
|
||||||
|
"Incorrect old password": "密码错误",
|
||||||
|
"The password is the same as the old password": "密码与历史密码重复",
|
||||||
|
"phone": "手机号",
|
||||||
|
"email": "邮箱",
|
||||||
|
"username": "用户名",
|
||||||
|
"dispname": "昵称",
|
||||||
|
"Temporary user has expired": "临时账户,已过有效期",
|
||||||
|
"Invalid user status %d": "异常的用户状态 %d",
|
||||||
|
"Password expired, please change the password in time": "密码过期,请及时修改密码",
|
||||||
|
"First Login, please change the password in time": "初始登陆,请及时修改密码",
|
||||||
|
|
||||||
|
"EOF": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ ip:
|
||||||
specify: ""
|
specify: ""
|
||||||
shell: ifconfig `route|grep '^default'|awk '{print $NF}'`|grep inet|awk '{print $2}'|head -n 1|awk -F':' '{print $NF}'
|
shell: ifconfig `route|grep '^default'|awk '{print $NF}'`|grep inet|awk '{print $2}'|head -n 1|awk -F':' '{print $NF}'
|
||||||
|
|
||||||
# MON、JOB的客户端拿来做本机标识
|
# MON、JOB, judge, prober 的客户端拿来做本机标识
|
||||||
ident:
|
ident:
|
||||||
specify: ""
|
specify: ""
|
||||||
shell: ifconfig `route|grep '^default'|awk '{print $NF}'`|grep inet|awk '{print $2}'|head -n 1|awk -F':' '{print $NF}'
|
shell: ifconfig `route|grep '^default'|awk '{print $NF}'`|grep inet|awk '{print $2}'|head -n 1|awk -F':' '{print $NF}'
|
||||||
|
|
|
@ -6,7 +6,7 @@ logger:
|
||||||
http:
|
http:
|
||||||
mode: release
|
mode: release
|
||||||
cookieDomain: ""
|
cookieDomain: ""
|
||||||
cookieName: ecmc-user
|
cookieName: ecmc-sid
|
||||||
|
|
||||||
output:
|
output:
|
||||||
# database | remote
|
# database | remote
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
您好,您的登录验证码为 {{.Code}} 。
|
您好,您的验证码为 {{.Code}} 。
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
您好,您的登录验证码为 {{.Code}} 。
|
您好,您的验证码为 {{.Code}} 。
|
||||||
|
|
|
@ -25,6 +25,8 @@ redis:
|
||||||
# conn: 500
|
# conn: 500
|
||||||
# read: 3000
|
# read: 3000
|
||||||
# write: 3000
|
# write: 3000
|
||||||
|
i18n:
|
||||||
|
lang: zh
|
||||||
|
|
||||||
notify:
|
notify:
|
||||||
p1: ["voice", "sms", "mail", "im"]
|
p1: ["voice", "sms", "mail", "im"]
|
||||||
|
@ -36,3 +38,8 @@ link:
|
||||||
stra: http://n9e.com/mon/strategy/%v
|
stra: http://n9e.com/mon/strategy/%v
|
||||||
event: http://n9e.com/mon/history/his/%v
|
event: http://n9e.com/mon/history/his/%v
|
||||||
claim: http://n9e.com/mon/history/cur/%v
|
claim: http://n9e.com/mon/history/cur/%v
|
||||||
|
|
||||||
|
http:
|
||||||
|
mode: release
|
||||||
|
cookieDomain: ""
|
||||||
|
cookieName: ecmc-sid
|
||||||
|
|
|
@ -0,0 +1,856 @@
|
||||||
|
metrics:
|
||||||
|
- name: mysql_queries
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_transactions
|
||||||
|
type: COUNTER
|
||||||
|
expr: mysql_com_commit + mysql_com_rollback
|
||||||
|
- name: mysql_threads_running
|
||||||
|
type: GAUGE
|
||||||
|
comment: "并发数"
|
||||||
|
- name: mysql_threads_connected
|
||||||
|
type: GAUGE
|
||||||
|
comment: "当前连接数"
|
||||||
|
- name: mysql_variables_max_connections
|
||||||
|
type: GAUGE
|
||||||
|
comment: "最大连接数"
|
||||||
|
- name: mysql_connections_threshold
|
||||||
|
type: GAUGE
|
||||||
|
expr: mysql_threads_connected / mysql_variables_max_connections
|
||||||
|
comment: "连接数阈值 < 0.8"
|
||||||
|
- name: mysql_innodb_buffer_pool_read_requests
|
||||||
|
type: COUNTER
|
||||||
|
comment: "innodb缓冲池查询总数"
|
||||||
|
- name: mysql_innodb_buffer_pool_reads
|
||||||
|
type: COUNTER
|
||||||
|
comment: "innodb从磁盘查询数"
|
||||||
|
- name: mysql_innodb_buffer_read_threshold
|
||||||
|
type: COUNTER
|
||||||
|
expr: (mysql_innodb_buffer_pool_read_requests - mysql_innodb_buffer_pool_reads) / mysql_innodb_buffer_pool_read_requests
|
||||||
|
comment: "磁盘查询报警阈值 < 0.95"
|
||||||
|
- name: mysql_binary_files_count
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_binary_size_bytes
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_binlog_bytes_written
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_binlog_cache_disk_use
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_binlog_cache_use
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_binlog_commits
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_begin
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_binlog
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_commit
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_create_table
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_delete
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_delete_multi
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_drop_table
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_empty_query
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_execute_sql
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_flush
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_insert
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_lock_tables
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_rollback
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_stmt_close
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_stmt_execute
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_stmt_prepare
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_stmt_reprepare
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_stmt_reset
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_stmt_fetch
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_update
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_com_update_multi
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_compression
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_connections
|
||||||
|
type: GAUGE
|
||||||
|
- name: mysql_max_used_connections
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_open_files
|
||||||
|
type: GAUGE
|
||||||
|
- name: mysql_open_streams
|
||||||
|
type: GAUGE
|
||||||
|
- name: mysql_open_tables
|
||||||
|
type: GAUGE
|
||||||
|
- name: mysql_opened_files
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_opened_table_definitions
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_opened_tables
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_opened_views
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_rows_read
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_rows_sent
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_sort_rows
|
||||||
|
type: COUNTER
|
||||||
|
|
||||||
|
trash:
|
||||||
|
- name: mysql_aborted_clients
|
||||||
|
type: COUNTER
|
||||||
|
comment: "mysql aborted clients number"
|
||||||
|
- name: mysql_aborted_connects
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_access_denied_errors
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_pagecache_blocks_not_flushed
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_pagecache_blocks_unused
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_pagecache_blocks_used
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_pagecache_read_requests
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_pagecache_reads
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_pagecache_write_requests
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_pagecache_writes
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_aria_transaction_log_syncs
|
||||||
|
type: COUNTER
|
||||||
|
- name: mysql_binlog_group_commits
|
||||||
|
- name: mysql_binlog_snapshot_position
|
||||||
|
- name: mysql_binlog_stmt_cache_disk_use
|
||||||
|
- name: mysql_binlog_stmt_cache_use
|
||||||
|
- name: mysql_busy_time
|
||||||
|
- name: mysql_bytes_received
|
||||||
|
- name: mysql_bytes_sent
|
||||||
|
- name: mysql_com_admin_commands
|
||||||
|
- name: mysql_com_alter_db
|
||||||
|
- name: mysql_com_alter_db_upgrade
|
||||||
|
- name: mysql_com_alter_event
|
||||||
|
- name: mysql_com_alter_function
|
||||||
|
- name: mysql_com_alter_procedure
|
||||||
|
- name: mysql_com_alter_server
|
||||||
|
- name: mysql_com_alter_table
|
||||||
|
- name: mysql_com_alter_tablespace
|
||||||
|
- name: mysql_com_analyze
|
||||||
|
- name: mysql_com_assign_to_keycache
|
||||||
|
- name: mysql_com_call_procedure
|
||||||
|
- name: mysql_com_change_db
|
||||||
|
- name: mysql_com_change_master
|
||||||
|
- name: mysql_com_check
|
||||||
|
- name: mysql_com_checksum
|
||||||
|
- name: mysql_com_create_db
|
||||||
|
- name: mysql_com_create_event
|
||||||
|
- name: mysql_com_create_function
|
||||||
|
- name: mysql_com_create_index
|
||||||
|
- name: mysql_com_create_procedure
|
||||||
|
- name: mysql_com_create_server
|
||||||
|
- name: mysql_com_create_trigger
|
||||||
|
- name: mysql_com_create_udf
|
||||||
|
- name: mysql_com_create_user
|
||||||
|
- name: mysql_com_create_view
|
||||||
|
- name: mysql_com_dealloc_sql
|
||||||
|
- name: mysql_com_do
|
||||||
|
- name: mysql_com_drop_db
|
||||||
|
- name: mysql_com_drop_event
|
||||||
|
- name: mysql_com_drop_function
|
||||||
|
- name: mysql_com_drop_index
|
||||||
|
- name: mysql_com_drop_procedure
|
||||||
|
- name: mysql_com_drop_server
|
||||||
|
- name: mysql_com_drop_trigger
|
||||||
|
- name: mysql_com_drop_user
|
||||||
|
- name: mysql_com_drop_view
|
||||||
|
- name: mysql_com_grant
|
||||||
|
- name: mysql_com_ha_close
|
||||||
|
- name: mysql_com_ha_open
|
||||||
|
- name: mysql_com_ha_read
|
||||||
|
- name: mysql_com_help
|
||||||
|
- name: mysql_com_insert_select
|
||||||
|
- name: mysql_com_install_plugin
|
||||||
|
- name: mysql_com_kill
|
||||||
|
- name: mysql_com_load
|
||||||
|
- name: mysql_com_optimize
|
||||||
|
- name: mysql_com_preload_keys
|
||||||
|
- name: mysql_com_prepare_sql
|
||||||
|
- name: mysql_com_purge
|
||||||
|
- name: mysql_com_purge_before_date
|
||||||
|
- name: mysql_com_release_savepoint
|
||||||
|
- name: mysql_com_rename_table
|
||||||
|
- name: mysql_com_rename_user
|
||||||
|
- name: mysql_com_repair
|
||||||
|
- name: mysql_com_replace
|
||||||
|
- name: mysql_com_replace_select
|
||||||
|
- name: mysql_com_reset
|
||||||
|
- name: mysql_com_resignal
|
||||||
|
- name: mysql_com_revoke
|
||||||
|
- name: mysql_com_revoke_all
|
||||||
|
- name: mysql_com_rollback_to_savepoint
|
||||||
|
- name: mysql_com_savepoint
|
||||||
|
- name: mysql_com_select
|
||||||
|
- name: mysql_com_set_option
|
||||||
|
- name: mysql_com_show_authors
|
||||||
|
- name: mysql_com_show_binlog_events
|
||||||
|
- name: mysql_com_show_binlogs
|
||||||
|
- name: mysql_com_show_charsets
|
||||||
|
- name: mysql_com_show_client_statistics
|
||||||
|
- name: mysql_com_show_collations
|
||||||
|
- name: mysql_com_show_contributors
|
||||||
|
- name: mysql_com_show_create_db
|
||||||
|
- name: mysql_com_show_create_event
|
||||||
|
- name: mysql_com_show_create_func
|
||||||
|
- name: mysql_com_show_create_proc
|
||||||
|
- name: mysql_com_show_create_table
|
||||||
|
- name: mysql_com_show_create_trigger
|
||||||
|
- name: mysql_com_show_databases
|
||||||
|
- name: mysql_com_show_engine_logs
|
||||||
|
- name: mysql_com_show_engine_mutex
|
||||||
|
- name: mysql_com_show_engine_status
|
||||||
|
- name: mysql_com_show_errors
|
||||||
|
- name: mysql_com_show_events
|
||||||
|
- name: mysql_com_show_fields
|
||||||
|
- name: mysql_com_show_function_status
|
||||||
|
- name: mysql_com_show_grants
|
||||||
|
- name: mysql_com_show_index_statistics
|
||||||
|
- name: mysql_com_show_keys
|
||||||
|
- name: mysql_com_show_master_status
|
||||||
|
- name: mysql_com_show_open_tables
|
||||||
|
- name: mysql_com_show_plugins
|
||||||
|
- name: mysql_com_show_privileges
|
||||||
|
- name: mysql_com_show_procedure_status
|
||||||
|
- name: mysql_com_show_processlist
|
||||||
|
- name: mysql_com_show_profile
|
||||||
|
- name: mysql_com_show_profiles
|
||||||
|
- name: mysql_com_show_relaylog_events
|
||||||
|
- name: mysql_com_show_slave_hosts
|
||||||
|
- name: mysql_com_show_slave_status
|
||||||
|
- name: mysql_com_show_status
|
||||||
|
- name: mysql_com_show_storage_engines
|
||||||
|
- name: mysql_com_show_table_statistics
|
||||||
|
- name: mysql_com_show_table_status
|
||||||
|
- name: mysql_com_show_tables
|
||||||
|
- name: mysql_com_show_triggers
|
||||||
|
- name: mysql_com_show_user_statistics
|
||||||
|
- name: mysql_com_show_variables
|
||||||
|
- name: mysql_com_show_warnings
|
||||||
|
- name: mysql_com_signal
|
||||||
|
- name: mysql_com_slave_start
|
||||||
|
- name: mysql_com_slave_stop
|
||||||
|
- name: mysql_com_stmt_send_long_data
|
||||||
|
- name: mysql_com_truncate
|
||||||
|
- name: mysql_com_uninstall_plugin
|
||||||
|
- name: mysql_com_unlock_tables
|
||||||
|
- name: mysql_com_xa_commit
|
||||||
|
- name: mysql_com_xa_end
|
||||||
|
- name: mysql_com_xa_prepare
|
||||||
|
- name: mysql_com_xa_recover
|
||||||
|
- name: mysql_com_xa_rollback
|
||||||
|
- name: mysql_com_xa_start
|
||||||
|
- name: mysql_cpu_time
|
||||||
|
- name: mysql_created_tmp_disk_tables
|
||||||
|
- name: mysql_created_tmp_files
|
||||||
|
- name: mysql_created_tmp_tables
|
||||||
|
- name: mysql_delayed_errors
|
||||||
|
- name: mysql_delayed_insert_threads
|
||||||
|
- name: mysql_delayed_writes
|
||||||
|
- name: mysql_empty_queries
|
||||||
|
- name: mysql_executed_events
|
||||||
|
- name: mysql_executed_triggers
|
||||||
|
- name: mysql_feature_dynamic_columns
|
||||||
|
- name: mysql_feature_fulltext
|
||||||
|
- name: mysql_feature_gis
|
||||||
|
- name: mysql_feature_locale
|
||||||
|
- name: mysql_feature_subquery
|
||||||
|
- name: mysql_feature_timezone
|
||||||
|
- name: mysql_feature_trigger
|
||||||
|
- name: mysql_feature_xml
|
||||||
|
- name: mysql_flush_commands
|
||||||
|
- name: mysql_handler_commit
|
||||||
|
- name: mysql_handler_delete
|
||||||
|
- name: mysql_handler_discover
|
||||||
|
- name: mysql_handler_icp_attempts
|
||||||
|
- name: mysql_handler_icp_match
|
||||||
|
- name: mysql_handler_mrr_init
|
||||||
|
- name: mysql_handler_mrr_key_refills
|
||||||
|
- name: mysql_handler_mrr_rowid_refills
|
||||||
|
- name: mysql_handler_prepare
|
||||||
|
- name: mysql_handler_read_first
|
||||||
|
- name: mysql_handler_read_key
|
||||||
|
- name: mysql_handler_read_last
|
||||||
|
- name: mysql_handler_read_next
|
||||||
|
- name: mysql_handler_read_prev
|
||||||
|
- name: mysql_handler_read_rnd
|
||||||
|
- name: mysql_handler_read_rnd_deleted
|
||||||
|
- name: mysql_handler_read_rnd_next
|
||||||
|
- name: mysql_handler_rollback
|
||||||
|
- name: mysql_handler_savepoint
|
||||||
|
- name: mysql_handler_savepoint_rollback
|
||||||
|
- name: mysql_handler_tmp_update
|
||||||
|
- name: mysql_handler_tmp_write
|
||||||
|
- name: mysql_handler_update
|
||||||
|
- name: mysql_handler_write
|
||||||
|
- name: mysql_innodb_adaptive_hash_cells
|
||||||
|
- name: mysql_innodb_adaptive_hash_hash_searches
|
||||||
|
- name: mysql_innodb_adaptive_hash_heap_buffers
|
||||||
|
- name: mysql_innodb_adaptive_hash_non_hash_searches
|
||||||
|
- name: mysql_innodb_background_log_sync
|
||||||
|
- name: mysql_innodb_buffer_pool_bytes_data
|
||||||
|
- name: mysql_innodb_buffer_pool_bytes_dirty
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_data
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_dirty
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_flushed
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_free
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_lru_flushed
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_made_not_young
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_made_young
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_misc
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_old
|
||||||
|
- name: mysql_innodb_buffer_pool_pages_total
|
||||||
|
- name: mysql_innodb_buffer_pool_read_ahead
|
||||||
|
- name: mysql_innodb_buffer_pool_read_ahead_evicted
|
||||||
|
- name: mysql_innodb_buffer_pool_read_ahead_rnd
|
||||||
|
- name: mysql_innodb_buffer_pool_wait_free
|
||||||
|
- name: mysql_innodb_buffer_pool_write_requests
|
||||||
|
- name: mysql_innodb_checkpoint_age
|
||||||
|
- name: mysql_innodb_checkpoint_max_age
|
||||||
|
- name: mysql_innodb_checkpoint_target_age
|
||||||
|
- name: mysql_innodb_current_row_locks
|
||||||
|
- name: mysql_innodb_data_fsyncs
|
||||||
|
- name: mysql_innodb_data_pending_fsyncs
|
||||||
|
- name: mysql_innodb_data_pending_reads
|
||||||
|
- name: mysql_innodb_data_pending_writes
|
||||||
|
- name: mysql_innodb_data_read
|
||||||
|
- name: mysql_innodb_data_reads
|
||||||
|
- name: mysql_innodb_data_writes
|
||||||
|
- name: mysql_innodb_data_written
|
||||||
|
- name: mysql_innodb_dblwr_pages_written
|
||||||
|
- name: mysql_innodb_dblwr_writes
|
||||||
|
- name: mysql_innodb_deadlocks
|
||||||
|
- name: mysql_innodb_descriptors_memory
|
||||||
|
- name: mysql_innodb_dict_tables
|
||||||
|
- name: mysql_innodb_have_atomic_builtins
|
||||||
|
- name: mysql_innodb_history_list_length
|
||||||
|
- name: mysql_innodb_ibuf_discarded_delete_marks
|
||||||
|
- name: mysql_innodb_ibuf_discarded_deletes
|
||||||
|
- name: mysql_innodb_ibuf_discarded_inserts
|
||||||
|
- name: mysql_innodb_ibuf_free_list
|
||||||
|
- name: mysql_innodb_ibuf_merged_delete_marks
|
||||||
|
- name: mysql_innodb_ibuf_merged_deletes
|
||||||
|
- name: mysql_innodb_ibuf_merged_inserts
|
||||||
|
- name: mysql_innodb_ibuf_merges
|
||||||
|
- name: mysql_innodb_ibuf_segment_size
|
||||||
|
- name: mysql_innodb_ibuf_size
|
||||||
|
- name: mysql_innodb_log_waits
|
||||||
|
- name: mysql_innodb_log_write_requests
|
||||||
|
- name: mysql_innodb_log_writes
|
||||||
|
- name: mysql_innodb_lsn_current
|
||||||
|
- name: mysql_innodb_lsn_flushed
|
||||||
|
- name: mysql_innodb_lsn_last_checkpoint
|
||||||
|
- name: mysql_innodb_master_thread_10_second_loops
|
||||||
|
- name: mysql_innodb_master_thread_1_second_loops
|
||||||
|
- name: mysql_innodb_master_thread_background_loops
|
||||||
|
- name: mysql_innodb_master_thread_main_flush_loops
|
||||||
|
- name: mysql_innodb_master_thread_sleeps
|
||||||
|
- name: mysql_innodb_max_trx_id
|
||||||
|
- name: mysql_innodb_mem_adaptive_hash
|
||||||
|
- name: mysql_innodb_mem_dictionary
|
||||||
|
- name: mysql_innodb_mem_total
|
||||||
|
- name: mysql_innodb_mutex_os_waits
|
||||||
|
- name: mysql_innodb_mutex_spin_rounds
|
||||||
|
- name: mysql_innodb_mutex_spin_waits
|
||||||
|
- name: mysql_innodb_oldest_view_low_limit_trx_id
|
||||||
|
- name: mysql_innodb_os_log_fsyncs
|
||||||
|
- name: mysql_innodb_os_log_pending_fsyncs
|
||||||
|
- name: mysql_innodb_os_log_pending_writes
|
||||||
|
- name: mysql_innodb_os_log_written
|
||||||
|
- name: mysql_innodb_page_size
|
||||||
|
- name: mysql_innodb_pages_created
|
||||||
|
- name: mysql_innodb_pages_read
|
||||||
|
- name: mysql_innodb_pages_written
|
||||||
|
- name: mysql_innodb_purge_trx_id
|
||||||
|
- name: mysql_innodb_purge_undo_no
|
||||||
|
- name: mysql_innodb_read_views_memory
|
||||||
|
- name: mysql_innodb_row_lock_current_waits
|
||||||
|
- name: mysql_innodb_row_lock_time
|
||||||
|
- name: mysql_innodb_row_lock_time_avg
|
||||||
|
- name: mysql_innodb_row_lock_time_max
|
||||||
|
- name: mysql_innodb_row_lock_waits
|
||||||
|
- name: mysql_innodb_rows_deleted
|
||||||
|
- name: mysql_innodb_rows_inserted
|
||||||
|
- name: mysql_innodb_rows_read
|
||||||
|
- name: mysql_innodb_rows_updated
|
||||||
|
- name: mysql_innodb_s_lock_os_waits
|
||||||
|
- name: mysql_innodb_s_lock_spin_rounds
|
||||||
|
- name: mysql_innodb_s_lock_spin_waits
|
||||||
|
- name: mysql_innodb_truncated_status_writes
|
||||||
|
- name: mysql_innodb_x_lock_os_waits
|
||||||
|
- name: mysql_innodb_x_lock_spin_rounds
|
||||||
|
- name: mysql_innodb_x_lock_spin_waits
|
||||||
|
- name: mysql_key_blocks_not_flushed
|
||||||
|
- name: mysql_key_blocks_unused
|
||||||
|
- name: mysql_key_blocks_used
|
||||||
|
- name: mysql_key_blocks_warm
|
||||||
|
- name: mysql_key_read_requests
|
||||||
|
- name: mysql_key_reads
|
||||||
|
- name: mysql_key_write_requests
|
||||||
|
- name: mysql_key_writes
|
||||||
|
- name: mysql_last_query_cost
|
||||||
|
- name: mysql_not_flushed_delayed_rows
|
||||||
|
- name: mysql_open_table_definitions
|
||||||
|
- name: mysql_performance_schema_cond_classes_lost
|
||||||
|
- name: mysql_performance_schema_cond_instances_lost
|
||||||
|
- name: mysql_performance_schema_file_classes_lost
|
||||||
|
- name: mysql_performance_schema_file_handles_lost
|
||||||
|
- name: mysql_performance_schema_file_instances_lost
|
||||||
|
- name: mysql_performance_schema_locker_lost
|
||||||
|
- name: mysql_performance_schema_mutex_classes_lost
|
||||||
|
- name: mysql_performance_schema_mutex_instances_lost
|
||||||
|
- name: mysql_performance_schema_rwlock_classes_lost
|
||||||
|
- name: mysql_performance_schema_rwlock_instances_lost
|
||||||
|
- name: mysql_performance_schema_table_handles_lost
|
||||||
|
- name: mysql_performance_schema_table_instances_lost
|
||||||
|
- name: mysql_performance_schema_thread_classes_lost
|
||||||
|
- name: mysql_performance_schema_thread_instances_lost
|
||||||
|
- name: mysql_prepared_stmt_count
|
||||||
|
- name: mysql_process_list_threads_after_create
|
||||||
|
- name: mysql_process_list_threads_altering_table
|
||||||
|
- name: mysql_process_list_threads_analyzing
|
||||||
|
- name: mysql_process_list_threads_checking_permissions
|
||||||
|
- name: mysql_process_list_threads_checking_table
|
||||||
|
- name: mysql_process_list_threads_cleaning_up
|
||||||
|
- name: mysql_process_list_threads_closing_tables
|
||||||
|
- name: mysql_process_list_threads_converting_heap_to_myisam
|
||||||
|
- name: mysql_process_list_threads_copying_to_tmp_table
|
||||||
|
- name: mysql_process_list_threads_creating_sort_index
|
||||||
|
- name: mysql_process_list_threads_creating_table
|
||||||
|
- name: mysql_process_list_threads_creating_tmp_table
|
||||||
|
- name: mysql_process_list_threads_deleting
|
||||||
|
- name: mysql_process_list_threads_end
|
||||||
|
- name: mysql_process_list_threads_executing
|
||||||
|
- name: mysql_process_list_threads_execution_of_init_command
|
||||||
|
- name: mysql_process_list_threads_flushing_tables
|
||||||
|
- name: mysql_process_list_threads_freeing_items
|
||||||
|
- name: mysql_process_list_threads_fulltext_initialization
|
||||||
|
- name: mysql_process_list_threads_idle
|
||||||
|
- name: mysql_process_list_threads_init
|
||||||
|
- name: mysql_process_list_threads_killed
|
||||||
|
- name: mysql_process_list_threads_logging_slow_query
|
||||||
|
- name: mysql_process_list_threads_login
|
||||||
|
- name: mysql_process_list_threads_manage_keys
|
||||||
|
- name: mysql_process_list_threads_opening_tables
|
||||||
|
- name: mysql_process_list_threads_optimizing
|
||||||
|
- name: mysql_process_list_threads_other
|
||||||
|
- name: mysql_process_list_threads_preparing
|
||||||
|
- name: mysql_process_list_threads_reading_from_net
|
||||||
|
- name: mysql_process_list_threads_removing_duplicates
|
||||||
|
- name: mysql_process_list_threads_removing_tmp_table
|
||||||
|
- name: mysql_process_list_threads_reopen_tables
|
||||||
|
- name: mysql_process_list_threads_repair_by_sorting
|
||||||
|
- name: mysql_process_list_threads_repair_done
|
||||||
|
- name: mysql_process_list_threads_repair_with_keycache
|
||||||
|
- name: mysql_process_list_threads_replication_master
|
||||||
|
- name: mysql_process_list_threads_rolling_back
|
||||||
|
- name: mysql_process_list_threads_searching_rows_for_update
|
||||||
|
- name: mysql_process_list_threads_sending_data
|
||||||
|
- name: mysql_process_list_threads_sorting_for_group
|
||||||
|
- name: mysql_process_list_threads_sorting_for_order
|
||||||
|
- name: mysql_process_list_threads_sorting_index
|
||||||
|
- name: mysql_process_list_threads_sorting_result
|
||||||
|
- name: mysql_process_list_threads_statistics
|
||||||
|
- name: mysql_process_list_threads_updating
|
||||||
|
- name: mysql_process_list_threads_waiting_for_lock
|
||||||
|
- name: mysql_process_list_threads_waiting_for_table_flush
|
||||||
|
- name: mysql_process_list_threads_waiting_for_tables
|
||||||
|
- name: mysql_process_list_threads_waiting_on_cond
|
||||||
|
- name: mysql_process_list_threads_writing_to_net
|
||||||
|
- name: mysql_qcache_free_blocks
|
||||||
|
- name: mysql_qcache_free_memory
|
||||||
|
- name: mysql_qcache_hits
|
||||||
|
- name: mysql_qcache_inserts
|
||||||
|
- name: mysql_qcache_lowmem_prunes
|
||||||
|
- name: mysql_qcache_not_cached
|
||||||
|
- name: mysql_qcache_queries_in_cache
|
||||||
|
- name: mysql_qcache_total_blocks
|
||||||
|
- name: mysql_questions
|
||||||
|
- name: mysql_rows_tmp_read
|
||||||
|
- name: mysql_select_full_join
|
||||||
|
- name: mysql_select_full_range_join
|
||||||
|
- name: mysql_select_range
|
||||||
|
- name: mysql_select_range_check
|
||||||
|
- name: mysql_select_scan
|
||||||
|
- name: mysql_slave_heartbeat_period
|
||||||
|
- name: mysql_slave_open_temp_tables
|
||||||
|
- name: mysql_slave_received_heartbeats
|
||||||
|
- name: mysql_slave_retried_transactions
|
||||||
|
- name: mysql_slave_running
|
||||||
|
- name: mysql_slow_launch_threads
|
||||||
|
- name: mysql_slow_queries
|
||||||
|
- name: mysql_sort_merge_passes
|
||||||
|
- name: mysql_sort_range
|
||||||
|
- name: mysql_sort_scan
|
||||||
|
- name: mysql_ssl_accept_renegotiates
|
||||||
|
- name: mysql_ssl_accepts
|
||||||
|
- name: mysql_ssl_callback_cache_hits
|
||||||
|
- name: mysql_ssl_client_connects
|
||||||
|
- name: mysql_ssl_connect_renegotiates
|
||||||
|
- name: mysql_ssl_ctx_verify_depth
|
||||||
|
- name: mysql_ssl_ctx_verify_mode
|
||||||
|
- name: mysql_ssl_default_timeout
|
||||||
|
- name: mysql_ssl_finished_accepts
|
||||||
|
- name: mysql_ssl_finished_connects
|
||||||
|
- name: mysql_ssl_session_cache_hits
|
||||||
|
- name: mysql_ssl_session_cache_misses
|
||||||
|
- name: mysql_ssl_session_cache_overflows
|
||||||
|
- name: mysql_ssl_session_cache_size
|
||||||
|
- name: mysql_ssl_session_cache_timeouts
|
||||||
|
- name: mysql_ssl_sessions_reused
|
||||||
|
- name: mysql_ssl_used_session_cache_entries
|
||||||
|
- name: mysql_ssl_verify_depth
|
||||||
|
- name: mysql_ssl_verify_mode
|
||||||
|
- name: mysql_subquery_cache_hit
|
||||||
|
- name: mysql_subquery_cache_miss
|
||||||
|
- name: mysql_syncs
|
||||||
|
- name: mysql_table_locks_immediate
|
||||||
|
- name: mysql_table_locks_waited
|
||||||
|
- name: mysql_tc_log_max_pages_used
|
||||||
|
- name: mysql_tc_log_page_size
|
||||||
|
- name: mysql_tc_log_page_waits
|
||||||
|
- name: mysql_threadpool_idle_threads
|
||||||
|
- name: mysql_threadpool_threads
|
||||||
|
- name: mysql_threads_cached
|
||||||
|
- name: mysql_threads_created
|
||||||
|
- name: mysql_uptime
|
||||||
|
- name: mysql_uptime_since_flush_status
|
||||||
|
- name: mysql_users_connections
|
||||||
|
- name: mysql_variables_aria_block_size
|
||||||
|
- name: mysql_variables_aria_checkpoint_interval
|
||||||
|
- name: mysql_variables_aria_checkpoint_log_activity
|
||||||
|
- name: mysql_variables_aria_force_start_after_recovery_failures
|
||||||
|
- name: mysql_variables_aria_group_commit_interval
|
||||||
|
- name: mysql_variables_aria_log_file_size
|
||||||
|
- name: mysql_variables_aria_max_sort_file_size
|
||||||
|
- name: mysql_variables_aria_page_checksum
|
||||||
|
- name: mysql_variables_aria_pagecache_age_threshold
|
||||||
|
- name: mysql_variables_aria_pagecache_buffer_size
|
||||||
|
- name: mysql_variables_aria_pagecache_division_limit
|
||||||
|
- name: mysql_variables_aria_repair_threads
|
||||||
|
- name: mysql_variables_aria_sort_buffer_size
|
||||||
|
- name: mysql_variables_aria_used_for_temp_tables
|
||||||
|
- name: mysql_variables_auto_increment_increment
|
||||||
|
- name: mysql_variables_auto_increment_offset
|
||||||
|
- name: mysql_variables_autocommit
|
||||||
|
- name: mysql_variables_automatic_sp_privileges
|
||||||
|
- name: mysql_variables_back_log
|
||||||
|
- name: mysql_variables_big_tables
|
||||||
|
- name: mysql_variables_binlog_annotate_row_events
|
||||||
|
- name: mysql_variables_binlog_cache_size
|
||||||
|
- name: mysql_variables_binlog_direct_non_transactional_updates
|
||||||
|
- name: mysql_variables_binlog_optimize_thread_scheduling
|
||||||
|
- name: mysql_variables_binlog_stmt_cache_size
|
||||||
|
- name: mysql_variables_bulk_insert_buffer_size
|
||||||
|
- name: mysql_variables_connect_timeout
|
||||||
|
- name: mysql_variables_deadlock_search_depth_long
|
||||||
|
- name: mysql_variables_deadlock_search_depth_short
|
||||||
|
- name: mysql_variables_deadlock_timeout_long
|
||||||
|
- name: mysql_variables_deadlock_timeout_short
|
||||||
|
- name: mysql_variables_debug_no_thread_alarm
|
||||||
|
- name: mysql_variables_default_week_format
|
||||||
|
- name: mysql_variables_delay_key_write
|
||||||
|
- name: mysql_variables_delayed_insert_limit
|
||||||
|
- name: mysql_variables_delayed_insert_timeout
|
||||||
|
- name: mysql_variables_delayed_queue_size
|
||||||
|
- name: mysql_variables_div_precision_increment
|
||||||
|
- name: mysql_variables_engine_condition_pushdown
|
||||||
|
- name: mysql_variables_event_scheduler
|
||||||
|
- name: mysql_variables_expensive_subquery_limit
|
||||||
|
- name: mysql_variables_expire_logs_days
|
||||||
|
- name: mysql_variables_extra_max_connections
|
||||||
|
- name: mysql_variables_extra_port
|
||||||
|
- name: mysql_variables_flush
|
||||||
|
- name: mysql_variables_flush_time
|
||||||
|
- name: mysql_variables_foreign_key_checks
|
||||||
|
- name: mysql_variables_ft_max_word_len
|
||||||
|
- name: mysql_variables_ft_min_word_len
|
||||||
|
- name: mysql_variables_ft_query_expansion_limit
|
||||||
|
- name: mysql_variables_general_log
|
||||||
|
- name: mysql_variables_group_concat_max_len
|
||||||
|
- name: mysql_variables_have_compress
|
||||||
|
- name: mysql_variables_have_crypt
|
||||||
|
- name: mysql_variables_have_csv
|
||||||
|
- name: mysql_variables_have_dynamic_loading
|
||||||
|
- name: mysql_variables_have_geometry
|
||||||
|
- name: mysql_variables_have_innodb
|
||||||
|
- name: mysql_variables_have_ndbcluster
|
||||||
|
- name: mysql_variables_have_partitioning
|
||||||
|
- name: mysql_variables_have_profiling
|
||||||
|
- name: mysql_variables_have_query_cache
|
||||||
|
- name: mysql_variables_have_rtree_keys
|
||||||
|
- name: mysql_variables_ignore_builtin_innodb
|
||||||
|
- name: mysql_variables_innodb_adaptive_flushing
|
||||||
|
- name: mysql_variables_innodb_adaptive_hash_index
|
||||||
|
- name: mysql_variables_innodb_adaptive_hash_index_partitions
|
||||||
|
- name: mysql_variables_innodb_additional_mem_pool_size
|
||||||
|
- name: mysql_variables_innodb_autoextend_increment
|
||||||
|
- name: mysql_variables_innodb_autoinc_lock_mode
|
||||||
|
- name: mysql_variables_innodb_blocking_buffer_pool_restore
|
||||||
|
- name: mysql_variables_innodb_buffer_pool_instances
|
||||||
|
- name: mysql_variables_innodb_buffer_pool_populate
|
||||||
|
- name: mysql_variables_innodb_buffer_pool_restore_at_startup
|
||||||
|
- name: mysql_variables_innodb_buffer_pool_shm_checksum
|
||||||
|
- name: mysql_variables_innodb_buffer_pool_shm_key
|
||||||
|
- name: mysql_variables_innodb_buffer_pool_size
|
||||||
|
- name: mysql_variables_innodb_checkpoint_age_target
|
||||||
|
- name: mysql_variables_innodb_checksums
|
||||||
|
- name: mysql_variables_innodb_commit_concurrency
|
||||||
|
- name: mysql_variables_innodb_concurrency_tickets
|
||||||
|
- name: mysql_variables_innodb_dict_size_limit
|
||||||
|
- name: mysql_variables_innodb_doublewrite
|
||||||
|
- name: mysql_variables_innodb_fake_changes
|
||||||
|
- name: mysql_variables_innodb_fast_checksum
|
||||||
|
- name: mysql_variables_innodb_fast_shutdown
|
||||||
|
- name: mysql_variables_innodb_file_format_check
|
||||||
|
- name: mysql_variables_innodb_file_per_table
|
||||||
|
- name: mysql_variables_innodb_flush_log_at_trx_commit
|
||||||
|
- name: mysql_variables_innodb_force_load_corrupted
|
||||||
|
- name: mysql_variables_innodb_force_recovery
|
||||||
|
- name: mysql_variables_innodb_ibuf_accel_rate
|
||||||
|
- name: mysql_variables_innodb_ibuf_active_contract
|
||||||
|
- name: mysql_variables_innodb_ibuf_max_size
|
||||||
|
- name: mysql_variables_innodb_import_table_from_xtrabackup
|
||||||
|
- name: mysql_variables_innodb_io_capacity
|
||||||
|
- name: mysql_variables_innodb_kill_idle_transaction
|
||||||
|
- name: mysql_variables_innodb_large_prefix
|
||||||
|
- name: mysql_variables_innodb_lazy_drop_table
|
||||||
|
- name: mysql_variables_innodb_lock_wait_timeout
|
||||||
|
- name: mysql_variables_innodb_locking_fake_changes
|
||||||
|
- name: mysql_variables_innodb_locks_unsafe_for_binlog
|
||||||
|
- name: mysql_variables_innodb_log_block_size
|
||||||
|
- name: mysql_variables_innodb_log_buffer_size
|
||||||
|
- name: mysql_variables_innodb_log_file_size
|
||||||
|
- name: mysql_variables_innodb_log_files_in_group
|
||||||
|
- name: mysql_variables_innodb_max_bitmap_file_size
|
||||||
|
- name: mysql_variables_innodb_max_changed_pages
|
||||||
|
- name: mysql_variables_innodb_max_dirty_pages_pct
|
||||||
|
- name: mysql_variables_innodb_max_purge_lag
|
||||||
|
- name: mysql_variables_innodb_merge_sort_block_size
|
||||||
|
- name: mysql_variables_innodb_mirrored_log_groups
|
||||||
|
- name: mysql_variables_innodb_old_blocks_pct
|
||||||
|
- name: mysql_variables_innodb_old_blocks_time
|
||||||
|
- name: mysql_variables_innodb_open_files
|
||||||
|
- name: mysql_variables_innodb_page_size
|
||||||
|
- name: mysql_variables_innodb_print_all_deadlocks
|
||||||
|
- name: mysql_variables_innodb_purge_batch_size
|
||||||
|
- name: mysql_variables_innodb_purge_threads
|
||||||
|
- name: mysql_variables_innodb_random_read_ahead
|
||||||
|
- name: mysql_variables_innodb_read_ahead_threshold
|
||||||
|
- name: mysql_variables_innodb_read_io_threads
|
||||||
|
- name: mysql_variables_innodb_recovery_stats
|
||||||
|
- name: mysql_variables_innodb_recovery_update_relay_log
|
||||||
|
- name: mysql_variables_innodb_replication_delay
|
||||||
|
- name: mysql_variables_innodb_rollback_on_timeout
|
||||||
|
- name: mysql_variables_innodb_rollback_segments
|
||||||
|
- name: mysql_variables_innodb_show_locks_held
|
||||||
|
- name: mysql_variables_innodb_show_verbose_locks
|
||||||
|
- name: mysql_variables_innodb_simulate_comp_failures
|
||||||
|
- name: mysql_variables_innodb_spin_wait_delay
|
||||||
|
- name: mysql_variables_innodb_stats_auto_update
|
||||||
|
- name: mysql_variables_innodb_stats_modified_counter
|
||||||
|
- name: mysql_variables_innodb_stats_on_metadata
|
||||||
|
- name: mysql_variables_innodb_stats_sample_pages
|
||||||
|
- name: mysql_variables_innodb_stats_traditional
|
||||||
|
- name: mysql_variables_innodb_stats_update_need_lock
|
||||||
|
- name: mysql_variables_innodb_strict_mode
|
||||||
|
- name: mysql_variables_innodb_support_xa
|
||||||
|
- name: mysql_variables_innodb_sync_spin_loops
|
||||||
|
- name: mysql_variables_innodb_table_locks
|
||||||
|
- name: mysql_variables_innodb_thread_concurrency
|
||||||
|
- name: mysql_variables_innodb_thread_concurrency_timer_based
|
||||||
|
- name: mysql_variables_innodb_thread_sleep_delay
|
||||||
|
- name: mysql_variables_innodb_track_changed_pages
|
||||||
|
- name: mysql_variables_innodb_use_atomic_writes
|
||||||
|
- name: mysql_variables_innodb_use_fallocate
|
||||||
|
- name: mysql_variables_innodb_use_global_flush_log_at_trx_commit
|
||||||
|
- name: mysql_variables_innodb_use_native_aio
|
||||||
|
- name: mysql_variables_innodb_use_stacktrace
|
||||||
|
- name: mysql_variables_innodb_use_sys_malloc
|
||||||
|
- name: mysql_variables_innodb_use_sys_stats_table
|
||||||
|
- name: mysql_variables_innodb_write_io_threads
|
||||||
|
- name: mysql_variables_interactive_timeout
|
||||||
|
- name: mysql_variables_join_buffer_size
|
||||||
|
- name: mysql_variables_join_buffer_space_limit
|
||||||
|
- name: mysql_variables_join_cache_level
|
||||||
|
- name: mysql_variables_keep_files_on_create
|
||||||
|
- name: mysql_variables_key_buffer_size
|
||||||
|
- name: mysql_variables_key_cache_age_threshold
|
||||||
|
- name: mysql_variables_key_cache_block_size
|
||||||
|
- name: mysql_variables_key_cache_division_limit
|
||||||
|
- name: mysql_variables_key_cache_segments
|
||||||
|
- name: mysql_variables_large_files_support
|
||||||
|
- name: mysql_variables_large_page_size
|
||||||
|
- name: mysql_variables_large_pages
|
||||||
|
- name: mysql_variables_local_infile
|
||||||
|
- name: mysql_variables_lock_wait_timeout
|
||||||
|
- name: mysql_variables_locked_in_memory
|
||||||
|
- name: mysql_variables_log
|
||||||
|
- name: mysql_variables_log_bin
|
||||||
|
- name: mysql_variables_log_bin_trust_function_creators
|
||||||
|
- name: mysql_variables_log_queries_not_using_indexes
|
||||||
|
- name: mysql_variables_log_slave_updates
|
||||||
|
- name: mysql_variables_log_slow_queries
|
||||||
|
- name: mysql_variables_log_slow_rate_limit
|
||||||
|
- name: mysql_variables_log_warnings
|
||||||
|
- name: mysql_variables_long_query_time
|
||||||
|
- name: mysql_variables_low_priority_updates
|
||||||
|
- name: mysql_variables_lower_case_file_system
|
||||||
|
- name: mysql_variables_lower_case_table_names
|
||||||
|
- name: mysql_variables_master_verify_checksum
|
||||||
|
- name: mysql_variables_max_allowed_packet
|
||||||
|
- name: mysql_variables_max_binlog_cache_size
|
||||||
|
- name: mysql_variables_max_binlog_size
|
||||||
|
- name: mysql_variables_max_binlog_stmt_cache_size
|
||||||
|
- name: mysql_variables_max_connect_errors
|
||||||
|
- name: mysql_variables_max_delayed_threads
|
||||||
|
- name: mysql_variables_max_error_count
|
||||||
|
- name: mysql_variables_max_heap_table_size
|
||||||
|
- name: mysql_variables_max_insert_delayed_threads
|
||||||
|
- name: mysql_variables_max_join_size
|
||||||
|
- name: mysql_variables_max_length_for_sort_data
|
||||||
|
- name: mysql_variables_max_long_data_size
|
||||||
|
- name: mysql_variables_max_prepared_stmt_count
|
||||||
|
- name: mysql_variables_max_relay_log_size
|
||||||
|
- name: mysql_variables_max_seeks_for_key
|
||||||
|
- name: mysql_variables_max_sort_length
|
||||||
|
- name: mysql_variables_max_sp_recursion_depth
|
||||||
|
- name: mysql_variables_max_tmp_tables
|
||||||
|
- name: mysql_variables_max_user_connections
|
||||||
|
- name: mysql_variables_max_write_lock_count
|
||||||
|
- name: mysql_variables_metadata_locks_cache_size
|
||||||
|
- name: mysql_variables_min_examined_row_limit
|
||||||
|
- name: mysql_variables_mrr_buffer_size
|
||||||
|
- name: mysql_variables_multi_range_count
|
||||||
|
- name: mysql_variables_myisam_block_size
|
||||||
|
- name: mysql_variables_myisam_data_pointer_size
|
||||||
|
- name: mysql_variables_myisam_max_sort_file_size
|
||||||
|
- name: mysql_variables_myisam_mmap_size
|
||||||
|
- name: mysql_variables_myisam_repair_threads
|
||||||
|
- name: mysql_variables_myisam_sort_buffer_size
|
||||||
|
- name: mysql_variables_myisam_use_mmap
|
||||||
|
- name: mysql_variables_net_buffer_length
|
||||||
|
- name: mysql_variables_net_read_timeout
|
||||||
|
- name: mysql_variables_net_retry_count
|
||||||
|
- name: mysql_variables_net_write_timeout
|
||||||
|
- name: mysql_variables_old
|
||||||
|
- name: mysql_variables_old_alter_table
|
||||||
|
- name: mysql_variables_old_passwords
|
||||||
|
- name: mysql_variables_open_files_limit
|
||||||
|
- name: mysql_variables_optimizer_prune_level
|
||||||
|
- name: mysql_variables_optimizer_search_depth
|
||||||
|
- name: mysql_variables_performance_schema
|
||||||
|
- name: mysql_variables_performance_schema_events_waits_history_long_size
|
||||||
|
- name: mysql_variables_performance_schema_events_waits_history_size
|
||||||
|
- name: mysql_variables_performance_schema_max_cond_classes
|
||||||
|
- name: mysql_variables_performance_schema_max_cond_instances
|
||||||
|
- name: mysql_variables_performance_schema_max_file_classes
|
||||||
|
- name: mysql_variables_performance_schema_max_file_handles
|
||||||
|
- name: mysql_variables_performance_schema_max_file_instances
|
||||||
|
- name: mysql_variables_performance_schema_max_mutex_classes
|
||||||
|
- name: mysql_variables_performance_schema_max_mutex_instances
|
||||||
|
- name: mysql_variables_performance_schema_max_rwlock_classes
|
||||||
|
- name: mysql_variables_performance_schema_max_rwlock_instances
|
||||||
|
- name: mysql_variables_performance_schema_max_table_handles
|
||||||
|
- name: mysql_variables_performance_schema_max_table_instances
|
||||||
|
- name: mysql_variables_performance_schema_max_thread_classes
|
||||||
|
- name: mysql_variables_performance_schema_max_thread_instances
|
||||||
|
- name: mysql_variables_port
|
||||||
|
- name: mysql_variables_preload_buffer_size
|
||||||
|
- name: mysql_variables_profiling
|
||||||
|
- name: mysql_variables_profiling_history_size
|
||||||
|
- name: mysql_variables_progress_report_time
|
||||||
|
- name: mysql_variables_protocol_version
|
||||||
|
- name: mysql_variables_query_alloc_block_size
|
||||||
|
- name: mysql_variables_query_cache_limit
|
||||||
|
- name: mysql_variables_query_cache_min_res_unit
|
||||||
|
- name: mysql_variables_query_cache_size
|
||||||
|
- name: mysql_variables_query_cache_strip_comments
|
||||||
|
- name: mysql_variables_query_cache_type
|
||||||
|
- name: mysql_variables_query_cache_wlock_invalidate
|
||||||
|
- name: mysql_variables_query_prealloc_size
|
||||||
|
- name: mysql_variables_range_alloc_block_size
|
||||||
|
- name: mysql_variables_read_buffer_size
|
||||||
|
- name: mysql_variables_read_only
|
||||||
|
- name: mysql_variables_read_rnd_buffer_size
|
||||||
|
- name: mysql_variables_relay_log_purge
|
||||||
|
- name: mysql_variables_relay_log_recovery
|
||||||
|
- name: mysql_variables_relay_log_space_limit
|
||||||
|
- name: mysql_variables_replicate_annotate_row_events
|
||||||
|
- name: mysql_variables_report_port
|
||||||
|
- name: mysql_variables_rowid_merge_buff_size
|
||||||
|
- name: mysql_variables_rpl_recovery_rank
|
||||||
|
- name: mysql_variables_secure_auth
|
||||||
|
- name: mysql_variables_server_id
|
||||||
|
- name: mysql_variables_skip_external_locking
|
||||||
|
- name: mysql_variables_skip_name_resolve
|
||||||
|
- name: mysql_variables_skip_networking
|
||||||
|
- name: mysql_variables_skip_show_database
|
||||||
|
- name: mysql_variables_slave_compressed_protocol
|
||||||
|
- name: mysql_variables_slave_max_allowed_packet
|
||||||
|
- name: mysql_variables_slave_net_timeout
|
||||||
|
- name: mysql_variables_slave_skip_errors
|
||||||
|
- name: mysql_variables_slave_sql_verify_checksum
|
||||||
|
- name: mysql_variables_slave_transaction_retries
|
||||||
|
- name: mysql_variables_slow_launch_time
|
||||||
|
- name: mysql_variables_slow_query_log
|
||||||
|
- name: mysql_variables_sort_buffer_size
|
||||||
|
- name: mysql_variables_sql_auto_is_null
|
||||||
|
- name: mysql_variables_sql_big_selects
|
||||||
|
- name: mysql_variables_sql_big_tables
|
||||||
|
- name: mysql_variables_sql_buffer_result
|
||||||
|
- name: mysql_variables_sql_log_bin
|
||||||
|
- name: mysql_variables_sql_log_off
|
||||||
|
- name: mysql_variables_sql_low_priority_updates
|
||||||
|
- name: mysql_variables_sql_max_join_size
|
||||||
|
- name: mysql_variables_sql_notes
|
||||||
|
- name: mysql_variables_sql_quote_show_create
|
||||||
|
- name: mysql_variables_sql_safe_updates
|
||||||
|
- name: mysql_variables_sql_select_limit
|
||||||
|
- name: mysql_variables_sql_slave_skip_counter
|
||||||
|
- name: mysql_variables_sql_warnings
|
||||||
|
- name: mysql_variables_stored_program_cache
|
||||||
|
- name: mysql_variables_sync_binlog
|
||||||
|
- name: mysql_variables_sync_frm
|
||||||
|
- name: mysql_variables_sync_master_info
|
||||||
|
- name: mysql_variables_sync_relay_log
|
||||||
|
- name: mysql_variables_sync_relay_log_info
|
||||||
|
- name: mysql_variables_table_definition_cache
|
||||||
|
- name: mysql_variables_table_open_cache
|
||||||
|
- name: mysql_variables_thread_cache_size
|
||||||
|
- name: mysql_variables_thread_concurrency
|
||||||
|
- name: mysql_variables_thread_pool_idle_timeout
|
||||||
|
- name: mysql_variables_thread_pool_max_threads
|
||||||
|
- name: mysql_variables_thread_pool_oversubscribe
|
||||||
|
- name: mysql_variables_thread_pool_size
|
||||||
|
- name: mysql_variables_thread_pool_stall_limit
|
||||||
|
- name: mysql_variables_thread_stack
|
||||||
|
- name: mysql_variables_timed_mutexes
|
||||||
|
- name: mysql_variables_tmp_table_size
|
||||||
|
- name: mysql_variables_transaction_alloc_block_size
|
||||||
|
- name: mysql_variables_transaction_prealloc_size
|
||||||
|
- name: mysql_variables_unique_checks
|
||||||
|
- name: mysql_variables_updatable_views_with_limit
|
||||||
|
- name: mysql_variables_userstat
|
||||||
|
- name: mysql_variables_wait_timeout
|
|
@ -0,0 +1,8 @@
|
||||||
|
region: default
|
||||||
|
workerProcesses: 5
|
||||||
|
logger:
|
||||||
|
dir: logs/prober
|
||||||
|
level: DEBUG
|
||||||
|
keepHours: 24
|
||||||
|
pluginsConfig: etc/plugins
|
||||||
|
ignoreConfig: false
|
19
etc/rdb.yml
19
etc/rdb.yml
|
@ -5,8 +5,15 @@ logger:
|
||||||
|
|
||||||
http:
|
http:
|
||||||
mode: release
|
mode: release
|
||||||
cookieDomain: ""
|
session:
|
||||||
cookieName: ecmc-user
|
cookieName: ecmc-sid
|
||||||
|
domain: ""
|
||||||
|
httpOnly: true
|
||||||
|
gcInterval: 60
|
||||||
|
cookieLifetime: 86400 # 单位秒,0: 与浏览器相同
|
||||||
|
|
||||||
|
i18n:
|
||||||
|
lang: zh
|
||||||
|
|
||||||
sso:
|
sso:
|
||||||
enable: false
|
enable: false
|
||||||
|
@ -23,7 +30,13 @@ sso:
|
||||||
coverAttributes: false
|
coverAttributes: false
|
||||||
stateExpiresIn: 300
|
stateExpiresIn: 300
|
||||||
|
|
||||||
captcha: false
|
auth:
|
||||||
|
captcha: false
|
||||||
|
extraMode:
|
||||||
|
enable: false # enable whiteList, login retry lock, userControl, ...
|
||||||
|
whiteList: false
|
||||||
|
frozenDays: 90 # frozen time (day)
|
||||||
|
writenOffDays: 365 # writenOff time (day)
|
||||||
|
|
||||||
tokens:
|
tokens:
|
||||||
- rdb-builtin-token
|
- rdb-builtin-token
|
||||||
|
|
8
go.mod
8
go.mod
|
@ -3,28 +3,28 @@ module github.com/didi/nightingale
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Shopify/sarama v1.19.0
|
github.com/Shopify/sarama v1.27.1
|
||||||
github.com/cespare/xxhash v1.1.0
|
github.com/cespare/xxhash v1.1.0
|
||||||
github.com/codegangsta/negroni v1.0.0
|
github.com/codegangsta/negroni v1.0.0
|
||||||
github.com/coreos/go-oidc v2.2.1+incompatible
|
github.com/coreos/go-oidc v2.2.1+incompatible
|
||||||
github.com/dgryski/go-tsz v0.0.0-20180227144327-03b7d791f4fe
|
github.com/dgryski/go-tsz v0.0.0-20180227144327-03b7d791f4fe
|
||||||
github.com/eapache/go-resiliency v1.2.0 // indirect
|
|
||||||
github.com/garyburd/redigo v1.6.2
|
github.com/garyburd/redigo v1.6.2
|
||||||
github.com/gin-contrib/pprof v1.3.0
|
github.com/gin-contrib/pprof v1.3.0
|
||||||
github.com/gin-gonic/gin v1.6.3
|
github.com/gin-gonic/gin v1.6.3
|
||||||
github.com/go-sql-driver/mysql v1.5.0
|
github.com/go-sql-driver/mysql v1.5.0
|
||||||
|
github.com/google/go-github/v32 v32.1.0
|
||||||
github.com/google/uuid v1.1.2-0.20190416172445-c2e93f3ae59f
|
github.com/google/uuid v1.1.2-0.20190416172445-c2e93f3ae59f
|
||||||
github.com/gorilla/mux v1.7.3
|
github.com/gorilla/mux v1.7.3
|
||||||
github.com/hashicorp/golang-lru v0.5.4
|
github.com/hashicorp/golang-lru v0.5.4
|
||||||
github.com/hpcloud/tail v1.0.0
|
github.com/hpcloud/tail v1.0.0
|
||||||
github.com/influxdata/influxdb v1.8.0
|
github.com/influxdata/influxdb v1.8.0
|
||||||
|
github.com/influxdata/telegraf v1.16.2
|
||||||
github.com/m3db/m3 v0.15.17
|
github.com/m3db/m3 v0.15.17
|
||||||
github.com/mattn/go-isatty v0.0.12
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/mattn/go-sqlite3 v1.14.0 // indirect
|
github.com/mattn/go-sqlite3 v1.14.0 // indirect
|
||||||
github.com/mojocn/base64Captcha v1.3.1
|
github.com/mojocn/base64Captcha v1.3.1
|
||||||
github.com/open-falcon/rrdlite v0.0.0-20200214140804-bf5829f786ad
|
github.com/open-falcon/rrdlite v0.0.0-20200214140804-bf5829f786ad
|
||||||
github.com/pquerna/cachecontrol v0.0.0-20200819021114-67c6ae64274f // indirect
|
github.com/pquerna/cachecontrol v0.0.0-20200819021114-67c6ae64274f // indirect
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 // indirect
|
|
||||||
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 // indirect
|
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 // indirect
|
||||||
github.com/shirou/gopsutil v3.20.11+incompatible
|
github.com/shirou/gopsutil v3.20.11+incompatible
|
||||||
github.com/spaolacci/murmur3 v1.1.0
|
github.com/spaolacci/murmur3 v1.1.0
|
||||||
|
@ -35,10 +35,8 @@ require (
|
||||||
github.com/ugorji/go/codec v1.1.7
|
github.com/ugorji/go/codec v1.1.7
|
||||||
github.com/unrolled/render v1.0.3
|
github.com/unrolled/render v1.0.3
|
||||||
go.uber.org/automaxprocs v1.3.0 // indirect
|
go.uber.org/automaxprocs v1.3.0 // indirect
|
||||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de // indirect
|
|
||||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
|
||||||
golang.org/x/text v0.3.3
|
golang.org/x/text v0.3.3
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.1 // indirect
|
|
||||||
google.golang.org/protobuf v1.25.0 // indirect
|
google.golang.org/protobuf v1.25.0 // indirect
|
||||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
|
||||||
|
|
272
go.sum
272
go.sum
|
@ -9,25 +9,44 @@ cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxK
|
||||||
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
|
||||||
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
|
||||||
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
|
||||||
cloud.google.com/go v0.51.0 h1:PvKAVQWCtlGUSlZkGW3QLelKaWq7KYv/MW1EboG8bfM=
|
|
||||||
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
|
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
|
||||||
|
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
|
||||||
|
cloud.google.com/go v0.53.0 h1:MZQCQQaRwOrAcuKjiHWHrgKykt4fZyuwF2dtiG3fGW8=
|
||||||
|
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
|
||||||
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
|
||||||
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
|
||||||
|
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
|
||||||
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
|
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
|
||||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
|
||||||
|
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
|
||||||
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
|
||||||
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
|
||||||
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
|
||||||
|
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
|
||||||
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
|
||||||
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
|
||||||
|
code.cloudfoundry.org/clock v1.0.0/go.mod h1:QD9Lzhd/ux6eNQVUDVRJX/RKTigpewimNYBi7ivZKY8=
|
||||||
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
|
||||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||||
|
github.com/Azure/azure-amqp-common-go/v3 v3.0.0/go.mod h1:SY08giD/XbhTz07tJdpw1SoxQXHPN30+DI3Z04SYqyg=
|
||||||
|
github.com/Azure/azure-event-hubs-go/v3 v3.2.0/go.mod h1:BPIIJNH/l/fVHYq3Rm6eg4clbrULrQ3q7+icmqHyyLc=
|
||||||
|
github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||||
|
github.com/Azure/azure-pipeline-go v0.1.9/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg=
|
||||||
|
github.com/Azure/azure-sdk-for-go v37.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||||
github.com/Azure/azure-sdk-for-go v40.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
github.com/Azure/azure-sdk-for-go v40.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc=
|
||||||
|
github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y=
|
||||||
|
github.com/Azure/azure-storage-queue-go v0.0.0-20181215014128-6ed74e755687/go.mod h1:K6am8mT+5iFXgingS9LUc7TmbsW6XBw3nxaRyaMyWc8=
|
||||||
|
github.com/Azure/go-amqp v0.12.6/go.mod h1:qApuH6OFTSKZFmCOxccvAv5rLizBQf4v8pRmG138DPo=
|
||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
|
||||||
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
|
||||||
|
github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0=
|
||||||
github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
|
github.com/Azure/go-autorest/autorest v0.10.0/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc=
|
||||||
|
github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||||
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM=
|
||||||
|
github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw=
|
||||||
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
|
||||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
|
@ -49,12 +68,14 @@ github.com/DataDog/datadog-go v3.7.1+incompatible h1:HmA9qHVrHIAqpSvoCYJ+c6qst0l
|
||||||
github.com/DataDog/datadog-go v3.7.1+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
github.com/DataDog/datadog-go v3.7.1+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
|
||||||
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||||
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
|
||||||
|
github.com/Mellanox/rdmamap v0.0.0-20191106181932-7c3c4763a6ee/go.mod h1:jDA6v0TUYrFEIAE5uGJ29LQOeONIgMdP4Rkqb8HUnPM=
|
||||||
github.com/MichaelTJones/pcg v0.0.0-20180122055547-df440c6ed7ed h1:hQC4FSwvsLH6rOLJTndsHnANARF9RwW4PbrDTjks/0A=
|
github.com/MichaelTJones/pcg v0.0.0-20180122055547-df440c6ed7ed h1:hQC4FSwvsLH6rOLJTndsHnANARF9RwW4PbrDTjks/0A=
|
||||||
github.com/MichaelTJones/pcg v0.0.0-20180122055547-df440c6ed7ed/go.mod h1:NQ4UMHqyfXyYVmZopcfwPRWJa0rw2aH16eDIltReVUo=
|
github.com/MichaelTJones/pcg v0.0.0-20180122055547-df440c6ed7ed/go.mod h1:NQ4UMHqyfXyYVmZopcfwPRWJa0rw2aH16eDIltReVUo=
|
||||||
|
github.com/Microsoft/ApplicationInsights-Go v0.4.2/go.mod h1:CukZ/G66zxXtI+h/VcVn3eVVDGDHfXM2zVILF7bMmsg=
|
||||||
|
github.com/Microsoft/go-winio v0.4.9/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
|
||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
|
||||||
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
|
||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
|
||||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
|
||||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||||
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
|
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
|
||||||
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
|
||||||
|
@ -66,36 +87,46 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
|
||||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
|
||||||
github.com/RoaringBitmap/roaring v0.4.21 h1:WJ/zIlNX4wQZ9x8Ey33O1UaD9TCTakYsdLFSBcTwH+8=
|
github.com/RoaringBitmap/roaring v0.4.21 h1:WJ/zIlNX4wQZ9x8Ey33O1UaD9TCTakYsdLFSBcTwH+8=
|
||||||
github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
github.com/RoaringBitmap/roaring v0.4.21/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||||
github.com/Shopify/sarama v1.19.0 h1:9oksLxC6uxVPHPVYUmq6xhr1BOF/hHobWH2UzO67z1s=
|
|
||||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||||
|
github.com/Shopify/sarama v1.27.1 h1:iUlzHymqWsITyttu6KxazcAz8WEj5FqcwFK/oEi7rE8=
|
||||||
|
github.com/Shopify/sarama v1.27.1/go.mod h1:g5s5osgELxgM+Md9Qni9rzo7Rbt+vvFQI4bt/Mc93II=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible h1:TKdv8HiTLgE5wdJuEML90aBgNWsokNbMijUGhmcoBJc=
|
||||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||||
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 h1:fLjPD/aNc3UIOA6tDi6QXUemppXK3P9BI7mr2hd6gx8=
|
||||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
|
||||||
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||||
|
github.com/aerospike/aerospike-client-go v1.27.0/go.mod h1:zj8LBEnWBDOVEIJt8LvaRvDG5ARAoa5dBeHaB472NRc=
|
||||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||||
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
|
||||||
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs=
|
||||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
|
||||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||||
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 h1:P5U+E4x5OkVEKQDklVPmzs71WM56RTTRqV4OrDC//Y4=
|
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5 h1:P5U+E4x5OkVEKQDklVPmzs71WM56RTTRqV4OrDC//Y4=
|
||||||
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
|
github.com/alexbrainman/sspi v0.0.0-20180613141037-e580b900e9f5/go.mod h1:976q2ETgjT2snVCf2ZaBnyBbVoPERGjUz+0sofzEfro=
|
||||||
|
github.com/amir/raidman v0.0.0-20170415203553-1ccc43bfb9c9/go.mod h1:eliMa/PW+RDr2QLWRmLH1R1ZA4RInpmvOzDDXtaIZkc=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||||
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
github.com/antihax/optional v0.0.0-20180407024304-ca021399b1a6/go.mod h1:V8iCPQYkqmusNa815XgQio277wI47sdRh1dUOLdyC6Q=
|
||||||
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
|
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
|
||||||
|
github.com/apex/log v1.3.0 h1:1fyfbPvUwD10nMoh3hY6MXzvZShJQn9/ck7ATgAt5pA=
|
||||||
github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs=
|
github.com/apex/log v1.3.0/go.mod h1:jd8Vpsr46WAe3EZSQ/IUMs2qQD/GOycT5rPWCO1yGcs=
|
||||||
github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
|
github.com/apex/logs v0.0.4/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo=
|
||||||
github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
|
github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE=
|
||||||
github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys=
|
github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys=
|
||||||
|
github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
|
||||||
|
github.com/aristanetworks/goarista v0.0.0-20190325233358-a123909ec740/go.mod h1:D/tb0zPVXnP7fmsLZjtdUhSsumbK/ij54UXjjVgMGxQ=
|
||||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||||
|
github.com/armon/go-metrics v0.3.0/go.mod h1:zXjbSimjXTd7vOpY8B0/2LpvNvDoXBuplAD+gJD3GYs=
|
||||||
github.com/armon/go-metrics v0.3.4 h1:Xqf+7f2Vhl9tsqDYmXhnXInUdcrtgpRNpIA15/uldSc=
|
github.com/armon/go-metrics v0.3.4 h1:Xqf+7f2Vhl9tsqDYmXhnXInUdcrtgpRNpIA15/uldSc=
|
||||||
github.com/armon/go-metrics v0.3.4/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
github.com/armon/go-metrics v0.3.4/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
|
||||||
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
|
||||||
|
@ -107,16 +138,20 @@ github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQ
|
||||||
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||||
github.com/aws/aws-sdk-go v1.29.18/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
|
github.com/aws/aws-sdk-go v1.29.18/go.mod h1:1KvfttTE3SPKMpo8g2c6jL3ZKfXtFvKscTgahTma5Xg=
|
||||||
|
github.com/aws/aws-sdk-go v1.34.34/go.mod h1:H7NKnBqNVzoTJpGfLrQkkD+ytBA93eiDYi/+8rV9s48=
|
||||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||||
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I=
|
||||||
|
github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM=
|
||||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||||
|
github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw=
|
||||||
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
|
||||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||||
github.com/bmatcuk/doublestar v1.3.1/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
github.com/bmatcuk/doublestar v1.3.1/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
|
||||||
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
|
||||||
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
|
||||||
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE=
|
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b h1:AP/Y7sqYicnjGDfD5VcY4CIfh1hRXBUavxrvELjTiOE=
|
||||||
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
|
github.com/bmizerany/perks v0.0.0-20141205001514-d9a9656a3a4b/go.mod h1:ac9efd0D1fsDb3EJvhqgXRbFx7bs2wqZ10HQPeU8U/Q=
|
||||||
|
@ -124,8 +159,10 @@ github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx2
|
||||||
github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
|
github.com/briandowns/spinner v1.11.1/go.mod h1:QOuQk7x+EaDASo80FEXwlwiA+j/PPIcX3FScO+3/ZPQ=
|
||||||
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
|
||||||
github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
github.com/c2h5oh/datasize v0.0.0-20171227191756-4eba002a5eae/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
|
||||||
|
github.com/caio/go-tdigest v2.3.0+incompatible/go.mod h1:sHQM/ubZStBUmF1WbB8FAm8q9GjDajLC5T7ydxE3JHI=
|
||||||
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||||
github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v0.0.0-20181003080854-62661b46c409/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
|
github.com/cenkalti/backoff v2.0.0+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||||
|
@ -139,15 +176,18 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P
|
||||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
|
||||||
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
|
||||||
|
github.com/cisco-ie/nx-telemetry-proto v0.0.0-20190531143454-82441e232cf6/go.mod h1:ugEfq4B8T8ciw/h5mCkgdiDRFS4CkqqhH2dymDB4knc=
|
||||||
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||||
|
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y=
|
||||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
|
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd h1:qMd81Ts1T2OTKmB4acZcyKaMtRnY5Y44NuXGX2GFJ1w=
|
||||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||||
github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=
|
github.com/codegangsta/negroni v1.0.0 h1:+aYywywx4bnKXWvoWtRfJ91vC59NbEhEY03sZjQhbVY=
|
||||||
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
|
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
|
||||||
|
github.com/containerd/containerd v1.4.1/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
|
||||||
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY=
|
github.com/containerd/continuity v0.0.0-20200413184840-d3ef23f19fbb/go.mod h1:Dq467ZllaHgAtVp4p1xUQWBrFXR9s/wyoTpG8zOJGkY=
|
||||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||||
|
@ -164,9 +204,13 @@ github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7
|
||||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f h1:lBNOc5arjvs8E5mO2tbpBpLoyyu8B6e44T7hJy6potg=
|
||||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||||
|
github.com/couchbase/go-couchbase v0.0.0-20180501122049-16db1f1fe037/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U=
|
||||||
|
github.com/couchbase/gomemcached v0.0.0-20180502221210-0da75df14530/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
|
||||||
|
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
|
||||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||||
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
||||||
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
|
@ -174,20 +218,26 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 h1:YcpmyvADGYw5LqMnHqSkyIELsHCGF6PkrmM31V8rF7o=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4 h1:YcpmyvADGYw5LqMnHqSkyIELsHCGF6PkrmM31V8rF7o=
|
||||||
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
github.com/denisenkom/go-mssqldb v0.0.0-20190707035753-2be1aa521ff4/go.mod h1:zAg7JM8CkOJ43xKXIj7eRO9kmWm/TW578qo+oDO6tuM=
|
||||||
|
github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||||
|
github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/wT555ZqwoCS+pk3p6ry4=
|
||||||
github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ=
|
github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||||
github.com/dgryski/go-tsz v0.0.0-20180227144327-03b7d791f4fe h1:VOrqop9SqFzqwZpROEOZpIufuLEUoJ3reNhdOdC9Zzw=
|
github.com/dgryski/go-tsz v0.0.0-20180227144327-03b7d791f4fe h1:VOrqop9SqFzqwZpROEOZpIufuLEUoJ3reNhdOdC9Zzw=
|
||||||
github.com/dgryski/go-tsz v0.0.0-20180227144327-03b7d791f4fe/go.mod h1:ft6P746mYUFQBCsH3OkFBG8FtjLx1XclLMo+9Jh1Yts=
|
github.com/dgryski/go-tsz v0.0.0-20180227144327-03b7d791f4fe/go.mod h1:ft6P746mYUFQBCsH3OkFBG8FtjLx1XclLMo+9Jh1Yts=
|
||||||
|
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||||
|
github.com/docker/distribution v2.6.0-rc.1.0.20170726174610-edc3ab29cdff+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||||
|
github.com/docker/docker v17.12.0-ce-rc1.0.20200916142827-bd33bbf0497b+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||||
|
github.com/docker/go-connections v0.3.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||||
|
github.com/docker/libnetwork v0.8.0-dev.2.0.20181012153825-d7b61745d166/go.mod h1:93m0aTqz6z+g32wla4l4WxTrdtvBRmVzYRkYvasA5Z8=
|
||||||
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
|
||||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4 h1:qk/FSDDxo05wdJH28W+p5yivv7LuLYLRXPPD8KQCtZs=
|
||||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||||
github.com/eapache/go-resiliency v1.1.0 h1:1NtRmCAqadE2FN4ZcN6g90TP3uk8cg9rn9eNK2197aU=
|
|
||||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
|
github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
|
||||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||||
|
@ -208,16 +258,21 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||||
|
github.com/ericchiang/k8s v1.2.0 h1:vxrMwEzY43oxu8aZyD/7b1s8tsBM+xoUoxjWECWFbPI=
|
||||||
|
github.com/ericchiang/k8s v1.2.0/go.mod h1:/OmBgSq2cd9IANnsGHGlEz27nwMZV2YxlpXuQtU3Bz4=
|
||||||
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
|
||||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||||
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
|
||||||
github.com/fortytw2/leaktest v1.2.1-0.20180901000122-b433bbd6d743 h1:QDM8xNoGxemDHdExynv+HzqkTPsFFZ8EyZdMwGElpGg=
|
|
||||||
github.com/fortytw2/leaktest v1.2.1-0.20180901000122-b433bbd6d743/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
github.com/fortytw2/leaktest v1.2.1-0.20180901000122-b433bbd6d743/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
|
||||||
|
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||||
github.com/fossas/fossa-cli v1.0.30/go.mod h1:5K4/qTj0P2qaT1G3SccFidhmazoJ9dm/OexAAYT8lOI=
|
github.com/fossas/fossa-cli v1.0.30/go.mod h1:5K4/qTj0P2qaT1G3SccFidhmazoJ9dm/OexAAYT8lOI=
|
||||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||||
|
github.com/frankban/quicktest v1.10.2 h1:19ARM85nVi4xH7xPXuc5eM/udya5ieh7b/Sv+d844Tk=
|
||||||
|
github.com/frankban/quicktest v1.10.2/go.mod h1:K+q6oSqb0W0Ininfk863uOk1lMy69l/P6txr3mVT54s=
|
||||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||||
github.com/garethr/kubeval v0.0.0-20180821130434-c44f5193dc94/go.mod h1:L8VwozDBY4bGI25r29I6FURZus8xlVo/B7lNOSfre2g=
|
github.com/garethr/kubeval v0.0.0-20180821130434-c44f5193dc94/go.mod h1:L8VwozDBY4bGI25r29I6FURZus8xlVo/B7lNOSfre2g=
|
||||||
|
@ -225,6 +280,8 @@ github.com/garyburd/redigo v1.6.2 h1:yE/pwKCrbLpLpQICzYTeZ7JsTA/C53wFTJHaEtRqniM
|
||||||
github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
github.com/garyburd/redigo v1.6.2/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
|
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew=
|
||||||
|
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
|
||||||
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
github.com/gin-contrib/pprof v1.3.0 h1:G9eK6HnbkSqDZBYbzG4wrjCsA4e+cvYAHUZw6W+W9K0=
|
||||||
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
github.com/gin-contrib/pprof v1.3.0/go.mod h1:waMjT1H9b179t3CxuG1cV3DHpga6ybizwfBaM5OXaB0=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
|
@ -233,6 +290,7 @@ github.com/gin-gonic/gin v1.6.2/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwv
|
||||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
|
||||||
|
github.com/glinton/ping v0.1.4-0.20200311211934-5ac87da8cd96/go.mod h1:uY+1eqFUyotrQxF1wYFNtMeHp/swbYRsoGzfcPZ8x3o=
|
||||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
|
||||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||||
|
@ -243,6 +301,7 @@ github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1T
|
||||||
github.com/gnewton/jargo v0.0.0-20150417131352-41f5f186a805/go.mod h1:x+HLDnZexLq1FmhrdgFf4c3EWGbqhU3ITvISBFyzvRo=
|
github.com/gnewton/jargo v0.0.0-20150417131352-41f5f186a805/go.mod h1:x+HLDnZexLq1FmhrdgFf4c3EWGbqhU3ITvISBFyzvRo=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||||
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||||
|
@ -250,6 +309,7 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||||
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
|
||||||
|
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||||
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
|
||||||
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
|
||||||
|
@ -299,6 +359,8 @@ github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD87
|
||||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||||
|
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||||
|
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
|
||||||
|
@ -306,6 +368,10 @@ github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LB
|
||||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
|
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
|
||||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
|
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:56xuuqnHyryaerycW3BfssRdxQstACi0Epw/yC5E2xM=
|
||||||
|
github.com/goburrow/modbus v0.1.0/go.mod h1:Kx552D5rLIS8E7TyUwQ/UdHEqvX5T8tyiGBTlzMcZBg=
|
||||||
|
github.com/goburrow/serial v0.1.0/go.mod h1:sAiqG0nRVswsm1C97xsttiYCzSLBmUZ/VSlVLZJ8haA=
|
||||||
|
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||||
|
github.com/gofrs/uuid v2.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||||
|
@ -321,19 +387,22 @@ github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfU
|
||||||
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7 h1:5ZkaAPbicIKTF2I64qf5Fh8Aa83Q/dnOafMYV0OMwjA=
|
|
||||||
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
|
||||||
|
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
|
||||||
|
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
|
||||||
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc=
|
||||||
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
|
||||||
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
|
|
||||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||||
|
github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||||
|
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||||
|
@ -356,8 +425,13 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
github.com/google/go-cmp v0.5.1 h1:JFrFEBb2xKufg6XkJsJr+WbKb4FQlURi5RUcBveYu9k=
|
||||||
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
|
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
|
||||||
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8=
|
github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8=
|
||||||
|
github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II=
|
||||||
|
github.com/google/go-github/v32 v32.1.0/go.mod h1:rIEpZD9CTDQwDK9GDrtMTycQNA4JU3qBsCizh3q2WCI=
|
||||||
github.com/google/go-jsonnet v0.16.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw=
|
github.com/google/go-jsonnet v0.16.0/go.mod h1:sOcuej3UW1vpPTZOr8L7RQimqai1a57bt5j22LzGZCw=
|
||||||
|
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
|
@ -365,6 +439,7 @@ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXi
|
||||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||||
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
|
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
|
||||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
@ -374,18 +449,16 @@ github.com/google/uuid v1.1.2-0.20190416172445-c2e93f3ae59f/go.mod h1:TIyPZe4Mgq
|
||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
||||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||||
|
github.com/gopcua/opcua v0.1.12/go.mod h1:a6QH4F9XeODklCmWuvaOdL8v9H0d73CEKUHWVZLQyE8=
|
||||||
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
|
||||||
github.com/gophercloud/gophercloud v0.8.0/go.mod h1:Kc/QKr9thLKruO/dG0szY8kRIYS+iENz0ziI0hJf76A=
|
github.com/gophercloud/gophercloud v0.8.0/go.mod h1:Kc/QKr9thLKruO/dG0szY8kRIYS+iENz0ziI0hJf76A=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
|
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99 h1:twflg0XRTjwKpxb/jFExr4HGq6on2dEOmnL6FV+fgPw=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20190910122728-9d188e94fb99/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
|
|
||||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||||
github.com/gorilla/handlers v1.3.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/gorilla/handlers v1.3.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
|
||||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||||
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
|
|
||||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
|
||||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
@ -407,6 +480,9 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.14.1 h1:YuM9SXYy583fxvSOkzCDyBPCtY+/IMSHEG1dKFMLZsA=
|
github.com/grpc-ecosystem/grpc-gateway v1.14.1 h1:YuM9SXYy583fxvSOkzCDyBPCtY+/IMSHEG1dKFMLZsA=
|
||||||
github.com/grpc-ecosystem/grpc-gateway v1.14.1/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0=
|
github.com/grpc-ecosystem/grpc-gateway v1.14.1/go.mod h1:6CwZWGDSPRJidgKAtJVvND6soZe6fT7iteq8wDPdhb0=
|
||||||
|
github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4=
|
||||||
|
github.com/harlow/kinesis-consumer v0.3.1-0.20181230152818-2f58b136fee0/go.mod h1:dk23l2BruuUzRP8wbybQbPn3J7sZga2QHICCeaEy5rQ=
|
||||||
|
github.com/hashicorp/consul v1.2.1/go.mod h1:mFrjN1mfidgJfYP1xrJCF+AfRhr6Eaqhb2+sfyn/OOI=
|
||||||
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
|
||||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||||
github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU=
|
github.com/hashicorp/consul/api v1.4.0/go.mod h1:xc8u05kyMa3Wjr9eEAsIAo3dg8+LywT5E/Cl7cNS5nU=
|
||||||
|
@ -428,6 +504,7 @@ github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHh
|
||||||
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
|
||||||
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
|
||||||
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
|
||||||
|
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg=
|
||||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||||
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||||
|
@ -441,7 +518,6 @@ github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b
|
||||||
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
|
|
||||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
|
||||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||||
|
@ -453,8 +529,10 @@ github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO
|
||||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
github.com/hashicorp/memberlist v0.1.4/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
|
github.com/hashicorp/memberlist v0.1.5/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||||
github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g=
|
github.com/hashicorp/memberlist v0.2.2 h1:5+RffWKwqJ71YPu9mWsF7ZOscZmwfasdA8kbdC7AO2g=
|
||||||
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
|
||||||
|
github.com/hashicorp/serf v0.8.1/go.mod h1:h/Ru6tmZazX7WO/GDmwdpS975F019L4t5ng5IgwbNrE=
|
||||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
|
||||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||||
|
@ -466,6 +544,7 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
|
||||||
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
|
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
|
||||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||||
github.com/influxdata/flux v0.65.0/go.mod h1:BwN2XG2lMszOoquQaFdPET8FRQfrXiZsWmcMO9rkaVY=
|
github.com/influxdata/flux v0.65.0/go.mod h1:BwN2XG2lMszOoquQaFdPET8FRQfrXiZsWmcMO9rkaVY=
|
||||||
|
github.com/influxdata/go-syslog/v2 v2.0.1/go.mod h1:hjvie1UTaD5E1fTnDmxaCw8RRDrT4Ve+XHr5O2dKSCo=
|
||||||
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
|
github.com/influxdata/influxdb v1.7.7/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
|
||||||
github.com/influxdata/influxdb v1.8.0 h1:/X+G+i3udzHVxpBMuXdPZcUbkIE0ouT+6U+CzQTsOys=
|
github.com/influxdata/influxdb v1.8.0 h1:/X+G+i3udzHVxpBMuXdPZcUbkIE0ouT+6U+CzQTsOys=
|
||||||
github.com/influxdata/influxdb v1.8.0/go.mod h1:SIzcnsjaHRFpmlxpJ4S3NT64qtEKYweNTUMb/vh0OMQ=
|
github.com/influxdata/influxdb v1.8.0/go.mod h1:SIzcnsjaHRFpmlxpJ4S3NT64qtEKYweNTUMb/vh0OMQ=
|
||||||
|
@ -474,8 +553,15 @@ github.com/influxdata/influxql v1.1.0/go.mod h1:KpVI7okXjK6PRi3Z5B+mtKZli+R1DnZg
|
||||||
github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE=
|
github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE=
|
||||||
github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8=
|
github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8=
|
||||||
github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE=
|
github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE=
|
||||||
|
github.com/influxdata/tail v1.0.1-0.20200707181643-03a791b270e4/go.mod h1:VeiWgI3qaGdJWust2fP27a6J+koITo/1c/UhxeOxgaM=
|
||||||
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
|
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
|
||||||
|
github.com/influxdata/telegraf v1.16.2 h1:G988b0+CL2IVDft9V2ZUteKgnbp+eI7vtQ0liPhQKxw=
|
||||||
|
github.com/influxdata/telegraf v1.16.2/go.mod h1:LZ/6hlf60cwqGr8phfbRKf8x1HoAoqxoMpTp/iqcNXk=
|
||||||
|
github.com/influxdata/toml v0.0.0-20190415235208-270119a8ce65/go.mod h1:zApaNFpP/bTpQItGZNNUMISDMDAnTXu9UqJ4yT3ocz8=
|
||||||
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
|
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
|
||||||
|
github.com/influxdata/wlog v0.0.0-20160411224016-7c63b0a71ef8/go.mod h1:/2NMgWB1DHM1ti/gqhOlg+LJeBVk6FqR5aVGYY0hlwI=
|
||||||
|
github.com/jackc/fake v0.0.0-20150926172116-812a484cc733/go.mod h1:WrMFNQdiFJ80sQsxDoMokWK1W5TQtxBFNpzWTD84ibQ=
|
||||||
|
github.com/jackc/pgx v3.6.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGkVEFm4TeybAXq+I=
|
||||||
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
|
||||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||||
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
|
||||||
|
@ -493,10 +579,15 @@ github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJS
|
||||||
github.com/jhump/protoreflect v1.6.1 h1:4/2yi5LyDPP7nN+Hiird1SAJ6YoxUm13/oxHGRnbPd8=
|
github.com/jhump/protoreflect v1.6.1 h1:4/2yi5LyDPP7nN+Hiird1SAJ6YoxUm13/oxHGRnbPd8=
|
||||||
github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4=
|
github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4=
|
||||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
|
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
|
||||||
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
|
||||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||||
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0=
|
||||||
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
|
||||||
|
github.com/jsimonetti/rtnetlink v0.0.0-20190606172950-9527aa82566a/go.mod h1:Oz+70psSo5OFh8DBl0Zv2ACw7Esh6pPUphlvZG9x7uw=
|
||||||
|
github.com/jsimonetti/rtnetlink v0.0.0-20200117123717-f846d4f6c1f4/go.mod h1:WGuG/smIU4J/54PblvSbh+xvCZmpJnFgr3ds6Z55XMQ=
|
||||||
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||||
|
@ -511,33 +602,43 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||||
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||||
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
|
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
|
||||||
|
github.com/kardianos/service v1.0.0/go.mod h1:8CzDhVuCuugtsHyZoTvsOBuvonN/UDBvl0kH+BUxvbo=
|
||||||
|
github.com/karrick/godirwalk v1.12.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||||
|
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||||
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
|
||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
|
github.com/klauspost/compress v1.11.0 h1:wJbzvpYMVGG9iTI9VxpnNZfd4DzMPoCWze3GgSqz8yg=
|
||||||
|
github.com/klauspost/compress v1.11.0/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
|
||||||
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
|
||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
|
||||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
|
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
|
||||||
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
|
||||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
|
||||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
|
github.com/kubernetes/apimachinery v0.0.0-20190119020841-d41becfba9ee/go.mod h1:Pe/YBTPc3vqoMkbuIWPH8CF9ehINdvNyS0dP3J6HC0s=
|
||||||
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
github.com/kylelemons/godebug v0.0.0-20160406211939-eadb3ce320cb/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
|
||||||
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/leanovate/gopter v0.2.8 h1:eFPtJ3aa5zLfbxGROSNY75T9Dume60CWBAqoWQ3h/ig=
|
github.com/leanovate/gopter v0.2.8 h1:eFPtJ3aa5zLfbxGROSNY75T9Dume60CWBAqoWQ3h/ig=
|
||||||
github.com/leanovate/gopter v0.2.8/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=
|
github.com/leanovate/gopter v0.2.8/go.mod h1:gNcbPWNEWRe4lm+bycKqxUYoH5uoVje5SkOJ3uoLer8=
|
||||||
|
github.com/leesper/go_rng v0.0.0-20190531154944-a612b043e353/go.mod h1:N0SVk0uhy+E1PZ3C9ctsPRlvOPAFPkCNlcPBDkt0N3U=
|
||||||
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
|
github.com/leodido/ragel-machinery v0.0.0-20181214104525-299bdde78165/go.mod h1:WZxr2/6a/Ar9bMDc2rN/LJrE/hF6bXE4LPyDSIxwAfg=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
github.com/lib/pq v1.6.0 h1:I5DPxhYJChW9KYc66se+oKFFQX6VuQrKiprsX6ivRZc=
|
github.com/lib/pq v1.6.0 h1:I5DPxhYJChW9KYc66se+oKFFQX6VuQrKiprsX6ivRZc=
|
||||||
github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g=
|
github.com/lib/pq v1.6.0/go.mod h1:4vXEAYvW1fRQ2/FhZ78H73A60MHw1geSm145z2mdY1g=
|
||||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo=
|
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743 h1:143Bb8f8DuGWck/xpNUOckBVYfFbBTnLevfRZ1aVVqo=
|
||||||
|
@ -579,6 +680,7 @@ github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
|
||||||
github.com/magiconair/properties v1.8.2 h1:znVR8Q4g7/WlcvsxLBRWvo+vtFJUAbDn3w+Yak2xVMI=
|
github.com/magiconair/properties v1.8.2 h1:znVR8Q4g7/WlcvsxLBRWvo+vtFJUAbDn3w+Yak2xVMI=
|
||||||
github.com/magiconair/properties v1.8.2/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
github.com/magiconair/properties v1.8.2/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
|
||||||
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
github.com/mailru/easyjson v0.0.0-20180717111219-efc7eb8984d6/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
|
@ -604,11 +706,17 @@ github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4f
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/mauricelam/genny v0.0.0-20180903214747-eb2c5232c885/go.mod h1:wRyVMWiOZeVj+MieWS5tIBBtJ3RtqqMbPsA5Z+t5b5U=
|
github.com/mauricelam/genny v0.0.0-20180903214747-eb2c5232c885/go.mod h1:wRyVMWiOZeVj+MieWS5tIBBtJ3RtqqMbPsA5Z+t5b5U=
|
||||||
|
github.com/mdlayher/apcupsd v0.0.0-20190314144147-eb3dd99a75fe/go.mod h1:y3mw3VG+t0m20OMqpG8RQqw8cDXvShVb+L8Z8FEnebw=
|
||||||
|
github.com/mdlayher/genetlink v1.0.0/go.mod h1:0rJ0h4itni50A86M2kHcgS85ttZazNt7a8H2a2cw0Gc=
|
||||||
|
github.com/mdlayher/netlink v0.0.0-20190409211403-11939a169225/go.mod h1:eQB3mZE4aiYnlUsyGGCOpPETfdQq4Jhsgf1fk3cwQaA=
|
||||||
|
github.com/mdlayher/netlink v1.0.0/go.mod h1:KxeJAFOFLG6AjpyDkQ/iIhxygIUKD+vcwqcnu43w/+M=
|
||||||
|
github.com/mdlayher/netlink v1.1.0/go.mod h1:H4WCitaheIsdF9yOYu8CFmCgQthAPIWZmcKp9uZHgmY=
|
||||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||||
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
|
github.com/miekg/dns v1.1.27 h1:aEH/kqUzUxGJ/UHcEKdJY+ugH6WEzsEBBSPa8zuy1aM=
|
||||||
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
github.com/miekg/dns v1.1.27/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||||
|
github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCLZ2MDGd4Gr0geeCH5HybhRJbonOgQpvSxc=
|
||||||
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
|
||||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
|
@ -631,19 +739,27 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/mojocn/base64Captcha v1.3.1 h1:2Wbkt8Oc8qjmNJ5GyOfSo4tgVQPsbKMftqASnq8GlT0=
|
github.com/mojocn/base64Captcha v1.3.1 h1:2Wbkt8Oc8qjmNJ5GyOfSo4tgVQPsbKMftqASnq8GlT0=
|
||||||
github.com/mojocn/base64Captcha v1.3.1/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
|
github.com/mojocn/base64Captcha v1.3.1/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY=
|
||||||
|
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
|
||||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
|
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
|
||||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
|
||||||
|
github.com/multiplay/go-ts3 v1.0.0/go.mod h1:14S6cS3fLNT3xOytrA/DkRyAFNuQLMLEqOYAsf87IbQ=
|
||||||
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||||
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
|
||||||
|
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
|
||||||
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
|
||||||
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
|
||||||
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
|
||||||
|
github.com/nats-io/nats-server/v2 v2.1.4/go.mod h1:Jw1Z28soD/QasIA2uWjXyM9El1jly3YwyFOuR8tH1rg=
|
||||||
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
|
||||||
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
|
||||||
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
|
||||||
|
github.com/newrelic/newrelic-telemetry-sdk-go v0.2.0/go.mod h1:G9MqE/cHGv3Hx3qpYhfuyFUsGx2DpVcGi1iJIqTg+JQ=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
|
github.com/nsqio/go-nsq v1.0.7/go.mod h1:XP5zaUs3pqf+Q71EqUJs3HYfBIqfK6G83WQMdNN+Ito=
|
||||||
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
|
||||||
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
|
||||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||||
|
@ -663,6 +779,7 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa
|
||||||
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
|
||||||
github.com/open-falcon/rrdlite v0.0.0-20200214140804-bf5829f786ad h1:GXUy5t8CYdaaEj1lRnE22CbHVY1M5h6Rv4kk0PJQc54=
|
github.com/open-falcon/rrdlite v0.0.0-20200214140804-bf5829f786ad h1:GXUy5t8CYdaaEj1lRnE22CbHVY1M5h6Rv4kk0PJQc54=
|
||||||
github.com/open-falcon/rrdlite v0.0.0-20200214140804-bf5829f786ad/go.mod h1:pXROoG0iWVnqq4u2Ii97S0Vt9iCTVypshsl9HXsV6cs=
|
github.com/open-falcon/rrdlite v0.0.0-20200214140804-bf5829f786ad/go.mod h1:pXROoG0iWVnqq4u2Ii97S0Vt9iCTVypshsl9HXsV6cs=
|
||||||
|
github.com/openconfig/gnmi v0.0.0-20180912164834-33a1865c3029/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
|
||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
|
||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
|
||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
|
||||||
|
@ -678,6 +795,7 @@ github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxS
|
||||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||||
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
|
||||||
|
github.com/openzipkin/zipkin-go-opentracing v0.3.4/go.mod h1:js2AbwmHW0YD9DwIw2JhQWmbfFi/UnWyYwdVhqbCDOE=
|
||||||
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
|
github.com/ory/dockertest v3.3.5+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
|
||||||
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
|
||||||
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
|
||||||
|
@ -698,8 +816,9 @@ github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHu
|
||||||
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
|
||||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||||
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible h1:2xWsjqPFWcplujydGg4WmhC/6fZqK42wMM8aXeqhl0I=
|
|
||||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
|
github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI=
|
||||||
|
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
|
@ -721,6 +840,7 @@ github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a h1:AA9vgIBDjM
|
||||||
github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a/go.mod h1:lzZQ3Noex5pfAy7mkAeCjcBDteYU85uWWnJ/y6gKU8k=
|
github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a/go.mod h1:lzZQ3Noex5pfAy7mkAeCjcBDteYU85uWWnJ/y6gKU8k=
|
||||||
github.com/prometheus/alertmanager v0.20.0/go.mod h1:9g2i48FAyZW6BtbsnvHtMHQXl2aVtrORKwKVCQ+nbrg=
|
github.com/prometheus/alertmanager v0.20.0/go.mod h1:9g2i48FAyZW6BtbsnvHtMHQXl2aVtrORKwKVCQ+nbrg=
|
||||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||||
|
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||||
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
|
||||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
|
||||||
|
@ -739,6 +859,7 @@ github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6T
|
||||||
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
|
github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U=
|
||||||
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
|
||||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
|
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||||
|
@ -748,11 +869,11 @@ github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+Gx
|
||||||
github.com/prometheus/prometheus v1.8.2-0.20200420081721-18254838fbe2/go.mod h1:ZnfuiMn3LNsry2q7ECmRe4WcscxmJSd2dIFpOi4w3lM=
|
github.com/prometheus/prometheus v1.8.2-0.20200420081721-18254838fbe2/go.mod h1:ZnfuiMn3LNsry2q7ECmRe4WcscxmJSd2dIFpOi4w3lM=
|
||||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
|
github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
|
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 h1:MkV+77GLUNo5oJ0jf870itWm3D0Sjh7+Za9gazKc5LQ=
|
||||||
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||||
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
github.com/remeh/sizedwaitgroup v1.0.0/go.mod h1:3j2R4OIe/SeS6YDhICBy22RWjJC5eNCJ1V+9+NVNYlo=
|
||||||
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
||||||
github.com/rhysd/go-github-selfupdate v1.2.2/go.mod h1:khesvSyKcXDUxeySCedFh621iawCks0dS/QnHPcpCws=
|
github.com/rhysd/go-github-selfupdate v1.2.2/go.mod h1:khesvSyKcXDUxeySCedFh621iawCks0dS/QnHPcpCws=
|
||||||
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 h1:pyecQtsPmlkCsMkYhT5iZ+sUXuwee+OvfuJjinEA3ko=
|
github.com/robfig/go-cache v0.0.0-20130306151617-9fc39e0dbf62 h1:pyecQtsPmlkCsMkYhT5iZ+sUXuwee+OvfuJjinEA3ko=
|
||||||
|
@ -768,6 +889,8 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
|
||||||
github.com/rveen/ogdl v0.0.0-20200522080342-eeeda1a978e7/go.mod h1:9fqUB54wJS9u5TSXJZhRfTdh1lXVxTytDjed7t2cNdw=
|
github.com/rveen/ogdl v0.0.0-20200522080342-eeeda1a978e7/go.mod h1:9fqUB54wJS9u5TSXJZhRfTdh1lXVxTytDjed7t2cNdw=
|
||||||
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
|
||||||
|
github.com/safchain/ethtool v0.0.0-20200218184317-f459e2d13664/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
|
||||||
|
github.com/samuel/go-zookeeper v0.0.0-20180130194729-c4fab1ac1bec/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
|
||||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
|
@ -780,19 +903,19 @@ github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||||
github.com/shirou/gopsutil v2.17.13-0.20180801053943-8048a2e9c577+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v2.17.13-0.20180801053943-8048a2e9c577+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/gopsutil v2.20.7+incompatible h1:Ymv4OD12d6zm+2yONe39VSmp2XooJe8za7ngOLW/o/w=
|
github.com/shirou/gopsutil v2.20.9+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/gopsutil v2.20.7+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
|
||||||
github.com/shirou/gopsutil v3.20.11+incompatible h1:LJr4ZQK4mPpIV5gOa4jCOKOGb4ty4DZO54I4FGqIpto=
|
github.com/shirou/gopsutil v3.20.11+incompatible h1:LJr4ZQK4mPpIV5gOa4jCOKOGb4ty4DZO54I4FGqIpto=
|
||||||
github.com/shirou/gopsutil v3.20.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
github.com/shirou/gopsutil v3.20.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||||
|
github.com/shopspring/decimal v0.0.0-20200105231215-408a2507e114/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
|
||||||
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
|
||||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||||
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
|
||||||
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||||
|
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||||
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
|
||||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
|
||||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||||
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
|
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
|
||||||
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
|
||||||
|
@ -802,8 +925,8 @@ github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9
|
||||||
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
|
github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs=
|
||||||
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E=
|
||||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
|
||||||
|
github.com/soniah/gosnmp v1.25.0/go.mod h1:8YvfZxH388NIIw2A+X5z2Oh97VcNhtmxDLt5QeUzVuQ=
|
||||||
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=
|
|
||||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||||
|
@ -825,7 +948,6 @@ github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0
|
||||||
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.1-0.20171106142849-4c012f6dcd95/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
|
||||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||||
|
@ -833,6 +955,7 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
|
||||||
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
github.com/spf13/viper v1.7.1 h1:pM5oEahlgWv/WnHXpgbKz7iLIxRf65tye2Ci+XFK5sk=
|
||||||
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
|
||||||
|
github.com/streadway/amqp v0.0.0-20180528204448-e5adc2ada8b8/go.mod h1:1WNBiOZtZQLpVAyu0iTduoJL9hEsMloAK5XWrtW0xdY=
|
||||||
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||||
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
|
||||||
github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
|
github.com/streadway/amqp v1.0.0 h1:kuuDrUJFZL1QYL9hUNuCxNObNzB0bV/ZG5jV3RWAQgo=
|
||||||
|
@ -840,6 +963,8 @@ github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1Sd
|
||||||
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
|
||||||
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A=
|
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25 h1:7z3LSn867ex6VSaahyKadf4WtSsJIgne6A1WLOAGM8A=
|
||||||
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU=
|
github.com/streadway/quantile v0.0.0-20150917103942-b0c588724d25/go.mod h1:lbP8tGiBjZ5YWIc2fzuRpTaz0b/53vT6PEs3QuAWzuU=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/objx v0.1.1 h1:2vfRuCMp5sSVIDSqO8oNnWJq7mPa6KVP3iPIwFBuy8A=
|
||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||||
|
@ -849,7 +974,11 @@ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s
|
||||||
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
|
||||||
github.com/subosito/gotenv v1.2.1-0.20190917103637-de67a6614a4d h1:YN4gX82mT31qsizy2jRheOCrGLCs15VF9SV5XPuBvkQ=
|
github.com/subosito/gotenv v1.2.1-0.20190917103637-de67a6614a4d h1:YN4gX82mT31qsizy2jRheOCrGLCs15VF9SV5XPuBvkQ=
|
||||||
github.com/subosito/gotenv v1.2.1-0.20190917103637-de67a6614a4d/go.mod h1:GVSeM7r0P1RI1gOKYyN9IuNkhMmQwKGsjVf3ulDrdzo=
|
github.com/subosito/gotenv v1.2.1-0.20190917103637-de67a6614a4d/go.mod h1:GVSeM7r0P1RI1gOKYyN9IuNkhMmQwKGsjVf3ulDrdzo=
|
||||||
|
github.com/tbrandon/mbserver v0.0.0-20170611213546-993e1772cc62/go.mod h1:qUzPVlSj2UgxJkVbH0ZwuuiR46U8RBMDT5KLY78Ifpw=
|
||||||
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
|
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
|
||||||
|
github.com/tedsuo/ifrit v0.0.0-20191009134036-9a97d0632f00/go.mod h1:eyZnKCc955uh98WQvzOm0dgAeLnf2O0Rz0LPoC5ze+0=
|
||||||
|
github.com/tidwall/gjson v1.6.0/go.mod h1:P256ACg0Mn+j1RXIDXoss50DeIABTYK1PULOJHhxOls=
|
||||||
|
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||||
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
|
github.com/tinylib/msgp v1.1.0 h1:9fQd+ICuRIu/ue4vxJZu6/LzxN0HwMds2nq/0cFvxHU=
|
||||||
|
@ -887,12 +1016,20 @@ github.com/unrolled/render v1.0.3/go.mod h1:gN9T0NhL4Bfbwu8ann7Ry/TGHYfosul+J0ob
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||||
github.com/vmihailenco/msgpack v2.8.3+incompatible h1:76LCLwxS08gKHRpGA10PBxfWk72JfUH6mgzp2+URwYM=
|
github.com/vishvananda/netlink v0.0.0-20171020171820-b2de5d10e38e/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
|
||||||
|
github.com/vishvananda/netns v0.0.0-20180720170159-13995c7128cc/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI=
|
||||||
|
github.com/vjeantet/grok v1.0.0/go.mod h1:/FWYEVYekkm+2VjcFmO9PufDU5FgXHUz9oy2EGqmQBo=
|
||||||
github.com/vmihailenco/msgpack v2.8.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
github.com/vmihailenco/msgpack v2.8.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
|
||||||
|
github.com/vmware/govmomi v0.19.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
|
||||||
|
github.com/wavefronthq/wavefront-sdk-go v0.9.2/go.mod h1:hQI6y8M9OtTCtc0xdwh+dCER4osxXdEAeCpacjpDZEU=
|
||||||
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
|
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
|
||||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
|
github.com/wvanbergen/kafka v0.0.0-20171203153745-e2edea948ddf/go.mod h1:nxx7XRXbR9ykhnC8lXqQyJS0rfvJGxKyKw/sT1YOttg=
|
||||||
|
github.com/wvanbergen/kazoo-go v0.0.0-20180202103751-f72d8611297a/go.mod h1:vQQATAGxVK20DC1rRubTJbZDDhhpA4QfU02pMdPxGO4=
|
||||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
|
||||||
|
github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
|
||||||
|
github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
|
||||||
|
@ -900,7 +1037,9 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 h1:eY9dn8+vbi4tKz5
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
|
github.com/yuin/gopher-lua v0.0.0-20180630135845-46796da1b0b4/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU=
|
||||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||||
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
||||||
|
@ -914,6 +1053,8 @@ go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
|
||||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||||
|
go.starlark.net v0.0.0-20200901195727-6e684ef5eeee/go.mod h1:f0znQkUKRrkk36XxWbGjMqQM8wGv/xHBVE2qc3B5oFU=
|
||||||
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
|
||||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||||
|
@ -934,6 +1075,7 @@ go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||||
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
go.uber.org/zap v1.13.0 h1:nR6NoDBgAf67s68NhaXbsojM+2gxp3S1hWkHDl27pVU=
|
||||||
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
|
||||||
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||||
|
@ -949,14 +1091,16 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U
|
||||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||||
|
golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191202143827-86a70503ff7e/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
|
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de h1:ikNHVSjEfnvz6sxdSPCaPt572qowuyMDMJLLm3Db3ig=
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a h1:vclmkQCjlDX5OydZ9wv8rBCcS0QyQY66Mpf/7BZbInM=
|
||||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
|
@ -967,6 +1111,9 @@ golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm0
|
||||||
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
|
||||||
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
|
||||||
|
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||||
|
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||||
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
|
||||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||||
|
@ -979,13 +1126,16 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f h1:J5lckAjkw6qYlOZNj90mLYNTEKDvWeuc1yieZ8qUzUE=
|
|
||||||
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
|
||||||
|
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k=
|
||||||
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||||
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
|
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
|
@ -1009,11 +1159,15 @@ golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191002035440-2ec189313ef0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191003171128-d98b1b443823/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
golang.org/x/net v0.0.0-20191007182048-72f939374954/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191126235420-ef20fe5d7933/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
|
@ -1021,8 +1175,9 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL
|
||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
|
|
||||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73 h1:MXfv8rhZWmFeqX3GNZRsd6vOLoaCHjYEX3qkRo3YBUA=
|
||||||
|
golang.org/x/net v0.0.0-20200904194848-62affa334b73/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -1036,14 +1191,15 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ
|
||||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
|
||||||
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8=
|
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6 h1:DvY3Zkh7KabQE/kfzMvYvKirSiguP9Q/veMtkYyf0o8=
|
||||||
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
|
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
@ -1087,22 +1243,34 @@ golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtn
|
||||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
|
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191203134012-c197fd4bf371/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
|
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||||
golang.org/x/tools v0.0.0-20200305205014-bc073721adb6/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
golang.org/x/tools v0.0.0-20200305205014-bc073721adb6/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
|
||||||
|
golang.org/x/tools v0.0.0-20200317043434-63da46f3035e/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
|
||||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b h1:zSzQJAznWxAh9fZxiPy2FZo+ZZEYoYFYYDYdOrU7AaM=
|
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b h1:zSzQJAznWxAh9fZxiPy2FZo+ZZEYoYFYYDYdOrU7AaM=
|
||||||
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
golang.org/x/tools v0.0.0-20200426102838-f3a5411a4c3b/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||||
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
golang.zx2c4.com/wireguard v0.0.20200121/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
|
||||||
|
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20200205215550-e35592f146e4/go.mod h1:UdS9frhv65KTfwxME1xE8+rHYoFpbm36gOud1GhBe9c=
|
||||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||||
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||||
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
||||||
|
gonum.org/v1/gonum v0.6.2/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
||||||
gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||||
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
|
||||||
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
|
||||||
|
@ -1114,6 +1282,7 @@ google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEn
|
||||||
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
|
||||||
|
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
|
||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||||
|
@ -1142,8 +1311,14 @@ google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvx
|
||||||
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
google.golang.org/genproto v0.0.0-20200108215221-bd8f9a0ef82f/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171 h1:xes2Q2k+d/+YNXVw0FpZkIDJiaux4OVrRKXRAzH6A0U=
|
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
|
||||||
|
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
|
||||||
|
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24 h1:IGPykv426z7LZSVPlaPufOyphngM4at5uZ7x5alaFvE=
|
||||||
|
google.golang.org/genproto v0.0.0-20200317114155-1f3552e48f24/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||||
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
|
||||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||||
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||||
|
@ -1160,18 +1335,15 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
||||||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||||
|
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
|
||||||
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
google.golang.org/grpc v1.29.1 h1:EC2SB8S04d2r73uptxphDSUG+kTKVgjRPF+N3xpxRB4=
|
||||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||||
google.golang.org/grpc v1.33.2 h1:EQyQC3sa8M+p6Ulc8yy9SWSS2GVwyRc83gAbG8lrl4o=
|
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.1 h1:M8spwkmx0pHrPq+uMdl22w5CvJ/Y+oAJTIs9oGoCpOE=
|
|
||||||
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.1/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
|
|
||||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
|
||||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||||
|
@ -1182,12 +1354,15 @@ gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
|
||||||
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
|
gopkg.in/fatih/pool.v2 v2.0.0/go.mod h1:8xVGeu1/2jr2wm5V9SPuMht2H5AEmf5aFMGSQixtjTY=
|
||||||
|
gopkg.in/fsnotify.v1 v1.2.1/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
|
gopkg.in/fsnotify/fsnotify.v1 v1.4.7/go.mod h1:Fyux9zXlo4rWoMSIzpn9fDAYjalPqJ/K1qJ27s+7ltE=
|
||||||
|
@ -1198,18 +1373,26 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
|
||||||
gopkg.in/go-playground/validator.v9 v9.7.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
gopkg.in/go-playground/validator.v9 v9.7.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
|
||||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
|
||||||
|
gopkg.in/gorethink/gorethink.v3 v3.0.5/go.mod h1:+3yIIHJUGMBK+wyPH+iN5TP+88ikFDfZdqTlK3Y9q8I=
|
||||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||||
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno=
|
||||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho=
|
gopkg.in/ini.v1 v1.51.1 h1:GyboHr4UqMiLUybYjd22ZjQIKEJEpgtLXtuGbR21Oho=
|
||||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||||
|
gopkg.in/jcmturner/aescts.v1 v1.0.1 h1:cVVZBK2b1zY26haWB4vbBiZrfFQnfbTVrE3xZq6hrEw=
|
||||||
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
|
||||||
|
gopkg.in/jcmturner/dnsutils.v1 v1.0.1 h1:cIuC1OLRGZrld+16ZJvvZxVJeKPsvd5eUIvxfoN5hSM=
|
||||||
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
|
||||||
|
gopkg.in/jcmturner/goidentity.v3 v3.0.0 h1:1duIyWiTaYvVx3YX2CYtpJbUFd7/UuPYCfgXtQ3VTbI=
|
||||||
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
|
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
|
||||||
|
gopkg.in/jcmturner/gokrb5.v7 v7.5.0 h1:a9tsXlIDD9SKxotJMK3niV7rPZAJeX2aD/0yg3qlIrg=
|
||||||
gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
|
gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
|
||||||
|
gopkg.in/jcmturner/rpc.v1 v1.1.0 h1:QHIUxTX1ISuAv9dD2wJ9HWQVuWDX/Zc0PfeC2tjc4rU=
|
||||||
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
|
gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
|
||||||
gopkg.in/ldap.v3 v3.1.0 h1:DIDWEjI7vQWREh0S8X5/NFPCZ3MCVd55LmXKPW4XLGE=
|
gopkg.in/ldap.v3 v3.1.0 h1:DIDWEjI7vQWREh0S8X5/NFPCZ3MCVd55LmXKPW4XLGE=
|
||||||
gopkg.in/ldap.v3 v3.1.0/go.mod h1:dQjCc0R0kfyFjIlWNMH1DORwUASZyDxo2Ry1B51dXaQ=
|
gopkg.in/ldap.v3 v3.1.0/go.mod h1:dQjCc0R0kfyFjIlWNMH1DORwUASZyDxo2Ry1B51dXaQ=
|
||||||
|
gopkg.in/mgo.v2 v2.0.0-20180705113604-9856a29383ce/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
|
||||||
|
gopkg.in/olivere/elastic.v5 v5.0.70/go.mod h1:FylZT6jQWtfHsicejzOm3jIMVPOAksa80i3o+6qtQRk=
|
||||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||||
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
|
gopkg.in/russross/blackfriday.v2 v2.0.0/go.mod h1:6sSBNz/GtOm/pJTuh5UmBK2ZHfmnxGbl2NZg1UliSOI=
|
||||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||||
|
@ -1217,6 +1400,7 @@ gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76
|
||||||
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98=
|
||||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g=
|
||||||
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8=
|
||||||
|
gopkg.in/tomb.v1 v1.0.0-20140529071818-c131134a1947/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||||
gopkg.in/validator.v2 v2.0.0-20160201165114-3e4f037f12a1 h1:1IZMbdoz1SZAQ4HMRwAP0FPSyXt7ywsiJ4q7OPTEu4A=
|
gopkg.in/validator.v2 v2.0.0-20160201165114-3e4f037f12a1 h1:1IZMbdoz1SZAQ4HMRwAP0FPSyXt7ywsiJ4q7OPTEu4A=
|
||||||
|
@ -1233,16 +1417,20 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200121175148-a6ecf24a6d71/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
|
honnef.co/go/netdb v0.0.0-20150201073656-a416d700ae39/go.mod h1:rbNo0ST5hSazCG4rGfpHrwnwvzP1QX62WbhzD+ghGzs=
|
||||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3 h1:3JgtbtFHMiCmsznwGVTUWbgGov+pVqnlf1dEJTNAXeM=
|
|
||||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U=
|
||||||
|
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
|
||||||
k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0=
|
k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0=
|
||||||
k8s.io/apimachinery v0.17.3 h1:f+uZV6rm4/tHE7xXgLyToprg6xWairaClGVkm2t8omg=
|
k8s.io/apimachinery v0.17.1/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
|
||||||
k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g=
|
k8s.io/apimachinery v0.17.3/go.mod h1:gxLnyZcGNdZTCLnq3fgzyg2A5BVCHTNDFrw8AmuJ+0g=
|
||||||
k8s.io/client-go v0.17.3/go.mod h1:cLXlTMtWHkuK4tD360KpWz2gG2KtdWEr/OT02i3emRQ=
|
k8s.io/client-go v0.17.3/go.mod h1:cLXlTMtWHkuK4tD360KpWz2gG2KtdWEr/OT02i3emRQ=
|
||||||
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
|
||||||
|
@ -1252,8 +1440,16 @@ k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
|
||||||
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
|
||||||
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
|
||||||
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
|
||||||
|
modernc.org/httpfs v1.0.0/go.mod h1:BSkfoMUcahSijQD5J/Vu4UMOxzmEf5SNRwyXC4PJBEw=
|
||||||
|
modernc.org/libc v1.3.1/go.mod h1:f8sp9GAfEyGYh3lsRIKtBh/XwACdFvGznxm6GJmQvXk=
|
||||||
|
modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
|
modernc.org/memory v1.0.1/go.mod h1:NSjvC08+g3MLOpcAxQbdctcThAEX4YlJ20WWHYEhvRg=
|
||||||
|
modernc.org/sqlite v1.7.4/go.mod h1:xse4RHCm8Fzw0COf5SJqAyiDrVeDwAQthAS1V/woNIA=
|
||||||
|
modernc.org/tcl v1.4.1/go.mod h1:8YCvzidU9SIwkz7RZwlCWK61mhV8X9UwfkRDRp7y5e0=
|
||||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
|
||||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
|
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
|
||||||
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
|
||||||
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
## sql 的维护
|
||||||
|
|
||||||
|
- n9e_{module}.sql 完整的sql
|
||||||
|
- n9e_{module}-path.sql 增量的sql
|
||||||
|
|
||||||
|
## sql 的版本发布
|
||||||
|
在使用 git tag 之前,将特定版本的增量文件固化下来
|
||||||
|
|
||||||
|
```
|
||||||
|
module=rdb
|
||||||
|
version=v3.3.3
|
||||||
|
cat n9e_${module}-patch.sql > upgrade/n9e_${module}-${version}.sql
|
||||||
|
echo > n9e_{module}-patch.sql
|
||||||
|
|
||||||
|
# 然后提交更改后,再打上版本的tag
|
||||||
|
git add .
|
||||||
|
git commit -a -m "${version} release"
|
||||||
|
git tag ${version}
|
||||||
|
git push
|
||||||
|
```
|
|
@ -10,7 +10,8 @@ create table `instance` (
|
||||||
`identity` varchar(255) not null,
|
`identity` varchar(255) not null,
|
||||||
`rpc_port` varchar(16) not null,
|
`rpc_port` varchar(16) not null,
|
||||||
`http_port` varchar(16) not null,
|
`http_port` varchar(16) not null,
|
||||||
`remark` text,
|
`region` varchar(32) not null,
|
||||||
|
`remark` text,
|
||||||
`ts` int unsigned not null,
|
`ts` int unsigned not null,
|
||||||
primary key (`id`),
|
primary key (`id`),
|
||||||
key(`module`,`identity`,`rpc_port`,`http_port`)
|
key(`module`,`identity`,`rpc_port`,`http_port`)
|
||||||
|
@ -26,4 +27,4 @@ create table `detector` (
|
||||||
`ts` int unsigned not null,
|
`ts` int unsigned not null,
|
||||||
primary key (`id`),
|
primary key (`id`),
|
||||||
key(`ip`,`port`)
|
key(`ip`,`port`)
|
||||||
) engine=innodb default charset=utf8;
|
) engine=innodb default charset=utf8;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
set names utf8;
|
||||||
|
use n9e_mon;
|
||||||
|
|
||||||
|
CREATE TABLE `collect_rule` (
|
||||||
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
|
`nid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'nid',
|
||||||
|
`step` int(11) NOT NULL DEFAULT '0' COMMENT 'step',
|
||||||
|
`timeout` int(11) NOT NULL DEFAULT '0' COMMENT 'total timeout',
|
||||||
|
`collect_type` varchar(64) NOT NULL DEFAULT '' COMMENT 'collector name',
|
||||||
|
`name` varchar(255) NOT NULL DEFAULT '' COMMENT 'name',
|
||||||
|
`region` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'region',
|
||||||
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
|
`data` blob NULL COMMENT 'data',
|
||||||
|
`tags` varchar(512) NOT NULL DEFAULT '' COMMENT 'tags',
|
||||||
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_nid` (`nid`),
|
||||||
|
KEY `idx_collect_type` (`collect_type`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'api collect';
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ create table `maskconf` (
|
||||||
`metric` varchar(255) not null,
|
`metric` varchar(255) not null,
|
||||||
`tags` varchar(255) not null default '',
|
`tags` varchar(255) not null default '',
|
||||||
`cause` varchar(255) not null default '',
|
`cause` varchar(255) not null default '',
|
||||||
`user` varchar(32) not null default 'operate user',
|
`user` varchar(64) not null default 'operate user',
|
||||||
`btime` bigint not null default 0 comment 'begin time',
|
`btime` bigint not null default 0 comment 'begin time',
|
||||||
`etime` bigint not null default 0 comment 'end time',
|
`etime` bigint not null default 0 comment 'end time',
|
||||||
primary key (`id`),
|
primary key (`id`),
|
||||||
|
@ -176,7 +176,7 @@ CREATE TABLE `stra_log` (
|
||||||
`sid` bigint(20) NOT NULL DEFAULT '0' COMMENT 'collect id',
|
`sid` bigint(20) NOT NULL DEFAULT '0' COMMENT 'collect id',
|
||||||
`action` varchar(255) NOT NULL DEFAULT '' COMMENT '动作 update, delete',
|
`action` varchar(255) NOT NULL DEFAULT '' COMMENT '动作 update, delete',
|
||||||
`body` text COMMENT '修改之前采集的内容',
|
`body` text COMMENT '修改之前采集的内容',
|
||||||
`creator` varchar(255) NOT NULL DEFAULT '' COMMENT 'creator',
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
`created` timestamp NOT NULL DEFAULT '1971-01-01 00:00:00' COMMENT 'created',
|
`created` timestamp NOT NULL DEFAULT '1971-01-01 00:00:00' COMMENT 'created',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_sid` (`sid`)
|
KEY `idx_sid` (`sid`)
|
||||||
|
@ -192,9 +192,9 @@ CREATE TABLE `port_collect` (
|
||||||
`step` int(11) NOT NULL DEFAULT '0' COMMENT '采集周期',
|
`step` int(11) NOT NULL DEFAULT '0' COMMENT '采集周期',
|
||||||
`timeout` int(11) NOT NULL DEFAULT '0' COMMENT 'connect time',
|
`timeout` int(11) NOT NULL DEFAULT '0' COMMENT 'connect time',
|
||||||
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
`creator` varchar(255) NOT NULL DEFAULT '' COMMENT 'creator',
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
`created` datetime NOT NULL COMMENT 'created',
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
`last_updator` varchar(128) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'last_updated',
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'last_updated',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_nid` (`nid`),
|
KEY `idx_nid` (`nid`),
|
||||||
|
@ -211,9 +211,9 @@ CREATE TABLE `proc_collect` (
|
||||||
`target` varchar(255) NOT NULL DEFAULT '' COMMENT '采集对象',
|
`target` varchar(255) NOT NULL DEFAULT '' COMMENT '采集对象',
|
||||||
`step` int(11) NOT NULL DEFAULT '0' COMMENT '采集周期',
|
`step` int(11) NOT NULL DEFAULT '0' COMMENT '采集周期',
|
||||||
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
`creator` varchar(255) NOT NULL DEFAULT '' COMMENT 'creator',
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
`created` datetime NOT NULL COMMENT 'created',
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
`last_updator` varchar(128) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_nid` (`nid`),
|
KEY `idx_nid` (`nid`),
|
||||||
|
@ -237,9 +237,9 @@ CREATE TABLE `log_collect` (
|
||||||
`unit` varchar(64) NOT NULL DEFAULT '' COMMENT 'unit',
|
`unit` varchar(64) NOT NULL DEFAULT '' COMMENT 'unit',
|
||||||
`zero_fill` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'zero fill',
|
`zero_fill` tinyint(4) NOT NULL DEFAULT '0' COMMENT 'zero fill',
|
||||||
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
`creator` varchar(255) NOT NULL DEFAULT '' COMMENT 'creator',
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
`created` datetime NOT NULL COMMENT 'created',
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
`last_updator` varchar(128) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_nid` (`nid`),
|
KEY `idx_nid` (`nid`),
|
||||||
|
@ -257,9 +257,9 @@ CREATE TABLE `plugin_collect` (
|
||||||
`stdin` text NOT NULL COMMENT 'stdin',
|
`stdin` text NOT NULL COMMENT 'stdin',
|
||||||
`env` text NOT NULL COMMENT 'env',
|
`env` text NOT NULL COMMENT 'env',
|
||||||
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
`creator` varchar(255) NOT NULL DEFAULT '' COMMENT 'creator',
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
`created` datetime NOT NULL COMMENT 'created',
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
`last_updator` varchar(128) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_nid` (`nid`),
|
KEY `idx_nid` (`nid`),
|
||||||
|
@ -286,9 +286,9 @@ CREATE TABLE `api_collect` (
|
||||||
`unexpected_string` varchar(255) NOT NULL DEFAULT '' COMMENT 'unexpected_string',
|
`unexpected_string` varchar(255) NOT NULL DEFAULT '' COMMENT 'unexpected_string',
|
||||||
`region` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'region',
|
`region` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'region',
|
||||||
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
`creator` varchar(255) NOT NULL DEFAULT '' COMMENT 'creator',
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
`created` datetime NOT NULL COMMENT 'created',
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
`last_updator` varchar(128) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_nid` (`nid`),
|
KEY `idx_nid` (`nid`),
|
||||||
|
@ -309,9 +309,9 @@ CREATE TABLE `snmp_collect` (
|
||||||
`step` int(11) NOT NULL DEFAULT '0' COMMENT 'step',
|
`step` int(11) NOT NULL DEFAULT '0' COMMENT 'step',
|
||||||
`timeout` int(11) NOT NULL DEFAULT '0' COMMENT 'total timeout',
|
`timeout` int(11) NOT NULL DEFAULT '0' COMMENT 'total timeout',
|
||||||
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
`creator` varchar(255) NOT NULL DEFAULT '' COMMENT 'creator',
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
`created` datetime NOT NULL COMMENT 'created',
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
`last_updator` varchar(128) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_nid` (`nid`),
|
KEY `idx_nid` (`nid`),
|
||||||
|
@ -319,6 +319,26 @@ CREATE TABLE `snmp_collect` (
|
||||||
KEY `idx_collect_type` (`collect_type`)
|
KEY `idx_collect_type` (`collect_type`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'api collect';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'api collect';
|
||||||
|
|
||||||
|
CREATE TABLE `collect_rule` (
|
||||||
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
|
`nid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'nid',
|
||||||
|
`step` int(11) NOT NULL DEFAULT '0' COMMENT 'step',
|
||||||
|
`timeout` int(11) NOT NULL DEFAULT '0' COMMENT 'total timeout',
|
||||||
|
`collect_type` varchar(64) NOT NULL DEFAULT '' COMMENT 'collector name',
|
||||||
|
`name` varchar(255) NOT NULL DEFAULT '' COMMENT 'name',
|
||||||
|
`region` varchar(32) NOT NULL DEFAULT 'default' COMMENT 'region',
|
||||||
|
`comment` varchar(512) NOT NULL DEFAULT '' COMMENT 'comment',
|
||||||
|
`data` blob NULL COMMENT 'data',
|
||||||
|
`tags` varchar(512) NOT NULL DEFAULT '' COMMENT 'tags',
|
||||||
|
`creator` varchar(64) NOT NULL DEFAULT '' COMMENT 'creator',
|
||||||
|
`last_updator` varchar(64) NOT NULL DEFAULT '' COMMENT 'last_updator',
|
||||||
|
`created` datetime NOT NULL COMMENT 'created',
|
||||||
|
`last_updated` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY `idx_nid` (`nid`),
|
||||||
|
KEY `idx_collect_type` (`collect_type`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'api collect';
|
||||||
|
|
||||||
CREATE TABLE `aggr_calc` (
|
CREATE TABLE `aggr_calc` (
|
||||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
`nid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'nid',
|
`nid` bigint(20) unsigned NOT NULL DEFAULT '0' COMMENT 'nid',
|
||||||
|
@ -389,12 +409,3 @@ CREATE TABLE `collect_hist` (
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY `idx_cid` (`cid`)
|
KEY `idx_cid` (`cid`)
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'hist';
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT 'hist';
|
||||||
|
|
||||||
|
|
||||||
CREATE TABLE `api_collect_sid` (
|
|
||||||
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'id',
|
|
||||||
`sid` bigint(20) NOT NULL DEFAULT '0' COMMENT 'stra id',
|
|
||||||
`cid` bigint(20) NOT NULL DEFAULT '0' COMMENT 'collect id',
|
|
||||||
PRIMARY KEY (`id`),
|
|
||||||
KEY (`sid`)
|
|
||||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
set names utf8;
|
||||||
|
use n9e_rdb;
|
||||||
|
|
||||||
|
CREATE TABLE `white_list` (
|
||||||
|
`id` bigint unsigned not null AUTO_INCREMENT,
|
||||||
|
`start_ip` varchar(32) DEFAULT '0' NOT NULL,
|
||||||
|
`end_ip` varchar(32) DEFAULT '0' NOT NULL,
|
||||||
|
`start_ip_int` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`end_ip_int` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`start_time` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`end_time` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`created_at` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`updated_at` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`creator` varchar(64) DEFAULT '' NOT NULL,
|
||||||
|
`updater` varchar(64) DEFAULT '' NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY (`start_ip_int`, `end_ip_int`),
|
||||||
|
KEY (`start_time`, `end_time`),
|
||||||
|
KEY (`created_at`)
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `session` (
|
||||||
|
`sid` char(128) NOT NULL,
|
||||||
|
`username` varchar(64) DEFAULT '',
|
||||||
|
`remote_addr` varchar(32) DEFAULT '',
|
||||||
|
`created_at` integer unsigned DEFAULT '0',
|
||||||
|
`updated_at` integer unsigned DEFAULT '0' NOT NULL,
|
||||||
|
PRIMARY KEY (`sid`),
|
||||||
|
KEY (`username`),
|
||||||
|
KEY (`updated_at`)
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8;
|
||||||
|
|
||||||
|
alter table user add `login_err_num` int unsigned not null default 0 after leader_name;
|
||||||
|
|
||||||
|
alter table user add `active_begin` bigint not null default 0 after login_err_num;
|
||||||
|
alter table user add `active_end` bigint not null default 0 after active_begin;
|
||||||
|
alter table user add `locked_at` bigint not null default 0 after active_end;
|
||||||
|
alter table user add `updated_at` bigint not null default 0 after locked_at;
|
||||||
|
alter table user add `pwd_updated_at` bigint not null default 0 after updated_at;
|
||||||
|
alter table user add `logged_at` bigint not null default 0 after pwd_updated_at;
|
||||||
|
alter table user add `passwords` varchar(512) not null default '' after password;
|
||||||
|
alter table login_log add `err` varchar(128) not null default '' after loginout;
|
|
@ -6,23 +6,31 @@ use n9e_rdb;
|
||||||
|
|
||||||
CREATE TABLE `user`
|
CREATE TABLE `user`
|
||||||
(
|
(
|
||||||
`id` int unsigned not null AUTO_INCREMENT,
|
`id` int unsigned not null AUTO_INCREMENT,
|
||||||
`uuid` varchar(128) not null comment 'use in cookie',
|
`uuid` varchar(128) not null comment 'use in cookie',
|
||||||
`username` varchar(64) not null comment 'login name, cannot rename',
|
`username` varchar(64) not null comment 'login name, cannot rename',
|
||||||
`password` varchar(128) not null default '',
|
`password` varchar(128) not null default '',
|
||||||
`dispname` varchar(32) not null default '' comment 'display name, chinese name',
|
`passwords` varchar(512) not null default '',
|
||||||
`phone` varchar(16) not null default '',
|
`dispname` varchar(32) not null default '' comment 'display name, chinese name',
|
||||||
`email` varchar(64) not null default '',
|
`phone` varchar(16) not null default '',
|
||||||
`im` varchar(64) not null default '',
|
`email` varchar(64) not null default '',
|
||||||
`portrait` varchar(2048) not null default '',
|
`im` varchar(64) not null default '',
|
||||||
`intro` varchar(2048) not null default '',
|
`portrait` varchar(2048) not null default '',
|
||||||
`organization` varchar(255) not null default '',
|
`intro` varchar(2048) not null default '',
|
||||||
`typ` tinyint(1) not null default 0 comment '0: long-term account; 1: temporary account',
|
`organization` varchar(255) not null default '',
|
||||||
`status` tinyint(1) not null default 0 comment '0: active; 1: inactive 2: disable',
|
`typ` tinyint(1) not null default 0 comment '0: long-term account; 1: temporary account',
|
||||||
`is_root` tinyint(1) not null,
|
`status` tinyint(1) not null default 0 comment '0: active, 1: inactive, 2: locked, 3: frozen, 5: writen-off',
|
||||||
`leader_id` int unsigned not null default 0,
|
`is_root` tinyint(1) not null,
|
||||||
`leader_name` varchar(32) not null default '',
|
`leader_id` int unsigned not null default 0,
|
||||||
`create_at` timestamp not null default CURRENT_TIMESTAMP,
|
`leader_name` varchar(32) not null default '',
|
||||||
|
`login_err_num` int unsigned not null default 0,
|
||||||
|
`active_begin` bigint not null default 0,
|
||||||
|
`active_end` bigint not null default 0,
|
||||||
|
`locked_at` bigint not null default 0,
|
||||||
|
`updated_at` bigint not null default 0,
|
||||||
|
`pwd_updated_at` bigint not null default 0,
|
||||||
|
`logged_at` bigint not null default 0,
|
||||||
|
`create_at` timestamp not null default CURRENT_TIMESTAMP,
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
UNIQUE KEY (`username`),
|
UNIQUE KEY (`username`),
|
||||||
UNIQUE KEY (`uuid`)
|
UNIQUE KEY (`uuid`)
|
||||||
|
@ -269,6 +277,7 @@ CREATE TABLE `login_log`
|
||||||
`client` varchar(128) not null comment 'client ip',
|
`client` varchar(128) not null comment 'client ip',
|
||||||
`clock` bigint not null comment 'login timestamp',
|
`clock` bigint not null comment 'login timestamp',
|
||||||
`loginout` char(3) not null comment 'in or out',
|
`loginout` char(3) not null comment 'in or out',
|
||||||
|
`err` varchar(128) not null comment 'err msg',
|
||||||
PRIMARY KEY (`id`),
|
PRIMARY KEY (`id`),
|
||||||
KEY (`username`),
|
KEY (`username`),
|
||||||
KEY (`clock`)
|
KEY (`clock`)
|
||||||
|
@ -315,3 +324,32 @@ CREATE TABLE `captcha` (
|
||||||
KEY (`captcha_id`, `answer`),
|
KEY (`captcha_id`, `answer`),
|
||||||
KEY (`created_at`)
|
KEY (`created_at`)
|
||||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `white_list` (
|
||||||
|
`id` bigint unsigned not null AUTO_INCREMENT,
|
||||||
|
`start_ip` varchar(32) DEFAULT '0' NOT NULL,
|
||||||
|
`end_ip` varchar(32) DEFAULT '0' NOT NULL,
|
||||||
|
`start_ip_int` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`end_ip_int` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`start_time` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`end_time` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`created_at` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`updated_at` bigint DEFAULT '0' NOT NULL,
|
||||||
|
`creator` varchar(64) DEFAULT '' NOT NULL,
|
||||||
|
`updater` varchar(64) DEFAULT '' NOT NULL,
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
KEY (`start_ip_int`, `end_ip_int`),
|
||||||
|
KEY (`start_time`, `end_time`),
|
||||||
|
KEY (`created_at`)
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARSET = utf8;
|
||||||
|
|
||||||
|
CREATE TABLE `session` (
|
||||||
|
`sid` char(128) NOT NULL,
|
||||||
|
`username` varchar(64) DEFAULT '',
|
||||||
|
`remote_addr` varchar(32) DEFAULT '',
|
||||||
|
`created_at` integer unsigned DEFAULT '0',
|
||||||
|
`updated_at` integer unsigned DEFAULT '0' NOT NULL,
|
||||||
|
PRIMARY KEY (`sid`),
|
||||||
|
KEY (`username`),
|
||||||
|
KEY (`updated_at`)
|
||||||
|
) ENGINE = InnoDB DEFAULT CHARACTER SET = utf8;
|
||||||
|
|
|
@ -30,9 +30,9 @@ type MetricValue struct {
|
||||||
Step int64 `json:"step"`
|
Step int64 `json:"step"`
|
||||||
ValueUntyped interface{} `json:"value"`
|
ValueUntyped interface{} `json:"value"`
|
||||||
Value float64 `json:"-"`
|
Value float64 `json:"-"`
|
||||||
CounterType string `json:"counterType"`
|
CounterType string `json:"counterType"` // GAUGE | COUNTER | SUBTRACT | DERIVE
|
||||||
Tags string `json:"tags"`
|
Tags string `json:"tags"` // a=1,b=2,c=3
|
||||||
TagsMap map[string]string `json:"tagsMap"` //保留2种格式,方便后端组件使用
|
TagsMap map[string]string `json:"tagsMap"` // {"a":1, "b"=2, "c="3} 保留2种格式,方便后端组件使用
|
||||||
Extra string `json:"extra"`
|
Extra string `json:"extra"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ func (m *MetricValue) CheckValidity(now int64) (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.Nid == "" && m.Endpoint == "" {
|
if m.Nid == "" && m.Endpoint == "" {
|
||||||
err = fmt.Errorf("nid or endpoint should not be empty")
|
err = fmt.Errorf("nid and endpoint should not be empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ func (m *MetricValue) CheckValidity(now int64) (err error) {
|
||||||
k = filterString(k)
|
k = filterString(k)
|
||||||
v = filterString(v)
|
v = filterString(v)
|
||||||
if len(k) == 0 || len(v) == 0 {
|
if len(k) == 0 || len(v) == 0 {
|
||||||
err = fmt.Errorf("tag key and value should not be empty")
|
err = fmt.Errorf("tag key and value should not be empty key:%s value:%s", k, v)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,4 +110,5 @@ type IndexByFullTagsResp struct {
|
||||||
Tags []string `json:"tags"`
|
Tags []string `json:"tags"`
|
||||||
Step int `json:"step"`
|
Step int `json:"step"`
|
||||||
DsType string `json:"dstype"`
|
DsType string `json:"dstype"`
|
||||||
|
Count int `json:"count"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/toolkits/pkg/runner"
|
"github.com/toolkits/pkg/runner"
|
||||||
|
@ -88,3 +90,103 @@ func ConfigsGets(ckeys []string) (map[string]string, error) {
|
||||||
|
|
||||||
return kvmap, nil
|
return kvmap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AuthConfig struct {
|
||||||
|
MaxNumErr int `json:"maxNumErr"`
|
||||||
|
MaxSessionNumber int64 `json:"maxSessionNumber"`
|
||||||
|
MaxConnIdelTime int64 `json:"maxConnIdelTime" description:"minute"`
|
||||||
|
LockTime int64 `json:"lockTime" description:"minute"`
|
||||||
|
PwdHistorySize int `json:"pwdHistorySize"`
|
||||||
|
PwdMinLenght int `json:"pwdMinLenght"`
|
||||||
|
PwdExpiresIn int64 `json:"pwdExpiresIn" description:"month"`
|
||||||
|
PwdMustInclude []string `json:"pwdMustInclude" description:"upper,lower,number,specChar"`
|
||||||
|
PwdMustIncludeFlag int `json:"pwdMustIncludeFlag"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p AuthConfig) PwdRules() []string {
|
||||||
|
s := []string{}
|
||||||
|
if p.PwdMinLenght > 0 {
|
||||||
|
s = append(s, _s("Minimum password length %d", p.PwdMinLenght))
|
||||||
|
}
|
||||||
|
if rule := p.MustInclude(); rule != "" {
|
||||||
|
s = append(s, rule)
|
||||||
|
}
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p AuthConfig) MustInclude() string {
|
||||||
|
s := []string{}
|
||||||
|
if p.PwdMustIncludeFlag&PWD_INCLUDE_UPPER > 0 {
|
||||||
|
s = append(s, _s("Upper char"))
|
||||||
|
}
|
||||||
|
if p.PwdMustIncludeFlag&PWD_INCLUDE_LOWER > 0 {
|
||||||
|
s = append(s, _s("Lower char"))
|
||||||
|
}
|
||||||
|
if p.PwdMustIncludeFlag&PWD_INCLUDE_NUMBER > 0 {
|
||||||
|
s = append(s, _s("Number"))
|
||||||
|
}
|
||||||
|
if p.PwdMustIncludeFlag&PWD_INCLUDE_SPEC_CHAR > 0 {
|
||||||
|
s = append(s, _s("Special char"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s) > 0 {
|
||||||
|
return _s("Must include %s", strings.Join(s, ","))
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
PWD_INCLUDE_UPPER = 1 << iota
|
||||||
|
PWD_INCLUDE_LOWER
|
||||||
|
PWD_INCLUDE_NUMBER
|
||||||
|
PWD_INCLUDE_SPEC_CHAR
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *AuthConfig) Validate() error {
|
||||||
|
for _, v := range p.PwdMustInclude {
|
||||||
|
switch v {
|
||||||
|
case "upper":
|
||||||
|
p.PwdMustIncludeFlag |= PWD_INCLUDE_UPPER
|
||||||
|
case "lower":
|
||||||
|
p.PwdMustIncludeFlag |= PWD_INCLUDE_LOWER
|
||||||
|
case "number":
|
||||||
|
p.PwdMustIncludeFlag |= PWD_INCLUDE_NUMBER
|
||||||
|
case "specChar":
|
||||||
|
p.PwdMustIncludeFlag |= PWD_INCLUDE_SPEC_CHAR
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid pwd flags, must be 'upper', 'lower', 'number', 'specChar'")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var DefaultAuthConfig = AuthConfig{
|
||||||
|
MaxConnIdelTime: 30,
|
||||||
|
PwdMustInclude: []string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
func AuthConfigGet() (*AuthConfig, error) {
|
||||||
|
buf, err := ConfigsGet("auth.config")
|
||||||
|
if err != nil {
|
||||||
|
return &DefaultAuthConfig, nil
|
||||||
|
}
|
||||||
|
c := &AuthConfig{}
|
||||||
|
if err := json.Unmarshal([]byte(buf), c); err != nil {
|
||||||
|
return &DefaultAuthConfig, nil
|
||||||
|
}
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func AuthConfigSet(config *AuthConfig) error {
|
||||||
|
if err := config.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
buf, err := json.Marshal(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return ConfigsSet("auth.config", string(buf))
|
||||||
|
}
|
||||||
|
|
|
@ -1,11 +1,21 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||||
"github.com/toolkits/pkg/cache"
|
"github.com/toolkits/pkg/cache"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cache.InitMemoryCache(time.Hour)
|
cache.InitMemoryCache(time.Hour)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _e(format string, a ...interface{}) error {
|
||||||
|
return fmt.Errorf(i18n.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func _s(format string, a ...interface{}) string {
|
||||||
|
return i18n.Sprintf(format, a...)
|
||||||
|
}
|
||||||
|
|
|
@ -35,3 +35,8 @@ func InviteNew(token, creator string) error {
|
||||||
_, err := DB["rdb"].Insert(obj)
|
_, err := DB["rdb"].Insert(obj)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Invite) Del() error {
|
||||||
|
_, err := DB["rdb"].Where("token=?", i.Token).Delete(i)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package models
|
package models
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
type LoginLog struct {
|
type LoginLog struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
|
@ -8,18 +11,20 @@ type LoginLog struct {
|
||||||
Client string `json:"client"`
|
Client string `json:"client"`
|
||||||
Clock int64 `json:"clock"`
|
Clock int64 `json:"clock"`
|
||||||
Loginout string `json:"loginout"`
|
Loginout string `json:"loginout"`
|
||||||
|
Err string `json:"err"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoginLogNew(username, client, inout string) error {
|
func LoginLogNew(username, client, inout string, err error) error {
|
||||||
now := time.Now().Unix()
|
now := time.Now().Unix()
|
||||||
obj := LoginLog{
|
obj := LoginLog{
|
||||||
Username: username,
|
Username: username,
|
||||||
Client: client,
|
Client: client,
|
||||||
Clock: now,
|
Clock: now,
|
||||||
Loginout: inout,
|
Loginout: inout,
|
||||||
|
Err: fmt.Sprintf("%v", err),
|
||||||
}
|
}
|
||||||
_, err := DB["rdb"].Insert(obj)
|
_, e := DB["rdb"].Insert(obj)
|
||||||
return err
|
return e
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoginLogTotal(username string, btime, etime int64) (int64, error) {
|
func LoginLogTotal(username string, btime, etime int64) (int64, error) {
|
||||||
|
|
|
@ -185,12 +185,6 @@ type LogCollect struct {
|
||||||
ParseSucc bool `xorm:"-" json:"-"`
|
ParseSucc bool `xorm:"-" json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiCollectSid struct {
|
|
||||||
Id int64 `json:"id"`
|
|
||||||
Cid int64 `json:"cid"`
|
|
||||||
Sid int64 `json:"sid"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ApiCollect struct {
|
type ApiCollect struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
Nid int64 `json:"nid"`
|
Nid int64 `json:"nid"`
|
||||||
|
@ -531,58 +525,6 @@ func (a *ApiCollect) Update() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func DeleteApiCollect(id int64) error {
|
|
||||||
session := DB["mon"].NewSession()
|
|
||||||
defer session.Close()
|
|
||||||
|
|
||||||
_, err := session.Where("id = ?", id).Delete(new(ApiCollect))
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
var relCidSid ApiCollectSid
|
|
||||||
has, err := session.Where("cid = ?", id).Get(&relCidSid)
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if has {
|
|
||||||
err = StraDel(relCidSid.Sid)
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return session.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetSidByCid(cid int64) (int64, error) {
|
|
||||||
var cidSid ApiCollectSid
|
|
||||||
_, err := DB["mon"].Where("cid = ?", cid).Get(&cidSid)
|
|
||||||
return cidSid.Sid, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *ApiCollectSid) Add() error {
|
|
||||||
session := DB["mon"].NewSession()
|
|
||||||
defer session.Close()
|
|
||||||
|
|
||||||
_, err := session.Where("cid = ?", a.Cid).Delete(new(ApiCollectSid))
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = session.Insert(a)
|
|
||||||
if err != nil {
|
|
||||||
session.Rollback()
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return session.Commit()
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateCollect(collectType, creator string, collect interface{}) error {
|
func CreateCollect(collectType, creator string, collect interface{}) error {
|
||||||
session := DB["mon"].NewSession()
|
session := DB["mon"].NewSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
@ -611,126 +553,6 @@ func CreateCollect(collectType, creator string, collect interface{}) error {
|
||||||
return session.Commit()
|
return session.Commit()
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCollectByNid(collectType string, nids []int64) ([]interface{}, error) {
|
|
||||||
var res []interface{}
|
|
||||||
switch collectType {
|
|
||||||
case "port":
|
|
||||||
collects := []PortCollect{}
|
|
||||||
err := DB["mon"].In("nid", nids).Find(&collects)
|
|
||||||
for _, c := range collects {
|
|
||||||
res = append(res, c)
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
|
|
||||||
case "proc":
|
|
||||||
collects := []ProcCollect{}
|
|
||||||
err := DB["mon"].In("nid", nids).Find(&collects)
|
|
||||||
for _, c := range collects {
|
|
||||||
res = append(res, c)
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
|
|
||||||
case "log":
|
|
||||||
collects := []LogCollect{}
|
|
||||||
err := DB["mon"].In("nid", nids).Find(&collects)
|
|
||||||
for _, c := range collects {
|
|
||||||
c.Decode()
|
|
||||||
res = append(res, c)
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
|
|
||||||
case "plugin":
|
|
||||||
collects := []PluginCollect{}
|
|
||||||
err := DB["mon"].In("nid", nids).Find(&collects)
|
|
||||||
for _, c := range collects {
|
|
||||||
res = append(res, c)
|
|
||||||
}
|
|
||||||
return res, err
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("采集类型不合法")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCollectById(collectType string, cid int64) (interface{}, error) {
|
|
||||||
switch collectType {
|
|
||||||
case "port":
|
|
||||||
collect := new(PortCollect)
|
|
||||||
has, err := DB["mon"].Where("id = ?", cid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return collect, err
|
|
||||||
case "proc":
|
|
||||||
collect := new(ProcCollect)
|
|
||||||
has, err := DB["mon"].Where("id = ?", cid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return collect, err
|
|
||||||
case "log":
|
|
||||||
collect := new(LogCollect)
|
|
||||||
has, err := DB["mon"].Where("id = ?", cid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
collect.Decode()
|
|
||||||
return collect, err
|
|
||||||
case "plugin":
|
|
||||||
collect := new(PluginCollect)
|
|
||||||
has, err := DB["mon"].Where("id = ?", cid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return collect, err
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("采集类型不合法")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetCollectByNameAndNid(collectType string, name string, nid int64) (interface{}, error) {
|
|
||||||
switch collectType {
|
|
||||||
case "port":
|
|
||||||
collect := new(PortCollect)
|
|
||||||
has, err := DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return collect, err
|
|
||||||
case "proc":
|
|
||||||
collect := new(ProcCollect)
|
|
||||||
has, err := DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return collect, err
|
|
||||||
case "log":
|
|
||||||
collect := new(LogCollect)
|
|
||||||
has, err := DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
collect.Decode()
|
|
||||||
return collect, err
|
|
||||||
case "plugin":
|
|
||||||
collect := new(PluginCollect)
|
|
||||||
has, err := DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
|
||||||
if !has {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return collect, err
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("采集类型不合法")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteCollectById(collectType, creator string, cid int64) error {
|
func DeleteCollectById(collectType, creator string, cid int64) error {
|
||||||
session := DB["mon"].NewSession()
|
session := DB["mon"].NewSession()
|
||||||
defer session.Close()
|
defer session.Close()
|
||||||
|
|
|
@ -0,0 +1,104 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/dataobj"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
defaultStep = 10
|
||||||
|
)
|
||||||
|
|
||||||
|
type CollectRule struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
Nid int64 `json:"nid"`
|
||||||
|
Step int `json:"step" description:"interval"`
|
||||||
|
Timeout int `json:"timeout"`
|
||||||
|
CollectType string `json:"collect_type" description:"plugin name"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Region string `json:"region"`
|
||||||
|
Comment string `json:"comment"`
|
||||||
|
Data json.RawMessage `json:"data"`
|
||||||
|
Tags string `json:"tags" description:"k1=v1,k2=v2,k3=v3,..."`
|
||||||
|
Creator string `json:"creator" description:"just for output"`
|
||||||
|
LastUpdator string `xorm:"last_updator" json:"last_updator" description:"just for output"`
|
||||||
|
Created time.Time `xorm:"updated" json:"created" description:"just for output"`
|
||||||
|
LastUpdated time.Time `xorm:"updated" json:"last_updated" description:"just for output"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type validator interface {
|
||||||
|
Validate() error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRule) Validate(v ...interface{}) error {
|
||||||
|
if p.Name == "" {
|
||||||
|
return fmt.Errorf("invalid collectRule.name")
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Step == 0 {
|
||||||
|
p.Step = defaultStep
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err := dataobj.SplitTagsString(p.Tags); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(v) > 0 && v[0] != nil {
|
||||||
|
if err := json.Unmarshal(p.Data, v[0]); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if o, ok := v[0].(validator); ok {
|
||||||
|
if err := o.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCollectRules() ([]*CollectRule, error) {
|
||||||
|
rules := []*CollectRule{}
|
||||||
|
err := DB["mon"].Find(&rules)
|
||||||
|
return rules, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRule) Update() error {
|
||||||
|
session := DB["mon"].NewSession()
|
||||||
|
defer session.Close()
|
||||||
|
|
||||||
|
err := session.Begin()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if _, err = session.Id(p.Id).AllCols().Update(p); err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
b, err := json.Marshal(p)
|
||||||
|
if err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := saveHist(p.Id, p.CollectType, "update", p.Creator, string(b), session); err != nil {
|
||||||
|
session.Rollback()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = session.Commit(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteCollectRule(sid int64) error {
|
||||||
|
_, err := DB["mon"].Where("id=?", sid).Delete(new(CollectRule))
|
||||||
|
return err
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ type Instance struct {
|
||||||
HTTPPort string `json:"http_port" xorm:"http_port"`
|
HTTPPort string `json:"http_port" xorm:"http_port"`
|
||||||
TS int64 `json:"ts" xorm:"ts"`
|
TS int64 `json:"ts" xorm:"ts"`
|
||||||
Remark string `json:"remark"`
|
Remark string `json:"remark"`
|
||||||
|
Region string `json:"region"`
|
||||||
Active bool `xorm:"-" json:"active"`
|
Active bool `xorm:"-" json:"active"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/toolkits/pkg/cache"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
Sid string `json:"sid"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
RemoteAddr string `json:"remote_addr"`
|
||||||
|
CreatedAt int64 `json:"created_at"`
|
||||||
|
UpdatedAt int64 `json:"updated_at"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionAll() (int64, error) {
|
||||||
|
return DB["rdb"].Count(new(Session))
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionUserAll(username string) (int64, error) {
|
||||||
|
return DB["rdb"].Where("username=?", username).Count(new(Session))
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionGet(sid string) (*Session, error) {
|
||||||
|
var obj Session
|
||||||
|
has, err := DB["rdb"].Where("sid=?", sid).Get(&obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("get session err %s", err)
|
||||||
|
}
|
||||||
|
if !has {
|
||||||
|
return nil, fmt.Errorf("not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionInsert(in *Session) error {
|
||||||
|
_, err := DB["rdb"].Insert(in)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionDel(sid string) error {
|
||||||
|
_, err := DB["rdb"].Where("sid=?", sid).Delete(new(Session))
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionUpdate(in *Session) error {
|
||||||
|
_, err := DB["rdb"].Where("sid=?", in.Sid).AllCols().Update(in)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionCleanup(ts int64) error {
|
||||||
|
n, err := DB["rdb"].Where("updated_at<?", ts).Delete(new(Session))
|
||||||
|
logger.Debugf("delete before updated_at %d session %d", ts, n)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func SessionCleanupByCreatedAt(ts int64) error {
|
||||||
|
n, err := DB["rdb"].Where("created_at<?", ts).Delete(new(Session))
|
||||||
|
logger.Debugf("delete before created_at %d session %d", ts, n)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (s *Session) Update(cols ...string) error {
|
||||||
|
_, err := DB["rdb"].Where("id=?", s.Sid).Cols(cols...).Update(s)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionGetWithCache will update session.UpdatedAt
|
||||||
|
func SessionGetWithCache(sid string) (*Session, error) {
|
||||||
|
if sid == "" {
|
||||||
|
return nil, fmt.Errorf("unable to get sid")
|
||||||
|
}
|
||||||
|
|
||||||
|
sess := &Session{}
|
||||||
|
if err := cache.Get("sid."+sid, &sess); err == nil {
|
||||||
|
return sess, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
if sess, err = SessionGet(sid); err != nil {
|
||||||
|
return nil, fmt.Errorf("session not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
// update session
|
||||||
|
sess.UpdatedAt = time.Now().Unix()
|
||||||
|
sess.Update("updated_at")
|
||||||
|
|
||||||
|
if sess.Username != "" {
|
||||||
|
cache.Set("sid."+sid, sess, time.Second*30)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sess, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionGetUserWithCache(sid string) (*User, error) {
|
||||||
|
s, err := SessionGetWithCache(sid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.Username == "" {
|
||||||
|
return nil, fmt.Errorf("user not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return UserMustGet("username=?", s.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
func SessionCacheDelete(sid string) {
|
||||||
|
cache.Delete("sid." + sid)
|
||||||
|
}
|
|
@ -10,9 +10,12 @@ import (
|
||||||
|
|
||||||
// CryptoPass crypto password use salt
|
// CryptoPass crypto password use salt
|
||||||
func CryptoPass(raw string) (string, error) {
|
func CryptoPass(raw string) (string, error) {
|
||||||
|
if raw == "" {
|
||||||
|
return "", _e("Password is not set")
|
||||||
|
}
|
||||||
salt, err := ConfigsGet("salt")
|
salt, err := ConfigsGet("salt")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("query salt from mysql fail: %v", err)
|
return "", _e("query salt from mysql fail: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return str.MD5(salt + "<-*Uk30^96eY*->" + raw), nil
|
return str.MD5(salt + "<-*Uk30^96eY*->" + raw), nil
|
||||||
|
|
|
@ -21,17 +21,30 @@ import (
|
||||||
const (
|
const (
|
||||||
LOGIN_T_SMS = "sms-code"
|
LOGIN_T_SMS = "sms-code"
|
||||||
LOGIN_T_EMAIL = "email-code"
|
LOGIN_T_EMAIL = "email-code"
|
||||||
LOGIN_T_RST = "rst-code"
|
|
||||||
LOGIN_T_PWD = "password"
|
LOGIN_T_PWD = "password"
|
||||||
LOGIN_T_LDAP = "ldap"
|
LOGIN_T_LDAP = "ldap"
|
||||||
|
LOGIN_T_RST = "rst-code"
|
||||||
|
LOGIN_T_LOGIN = "login-code"
|
||||||
LOGIN_EXPIRES_IN = 300
|
LOGIN_EXPIRES_IN = 300
|
||||||
)
|
)
|
||||||
|
const (
|
||||||
|
USER_S_ACTIVE = iota
|
||||||
|
USER_S_INACTIVE
|
||||||
|
USER_S_LOCKED
|
||||||
|
USER_S_FROZEN
|
||||||
|
USER_S_WRITEN_OFF
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
USER_T_NATIVE = iota
|
||||||
|
USER_T_TEMP
|
||||||
|
)
|
||||||
|
|
||||||
type User struct {
|
type User struct {
|
||||||
Id int64 `json:"id"`
|
Id int64 `json:"id"`
|
||||||
UUID string `json:"uuid" xorm:"'uuid'"`
|
UUID string `json:"uuid" xorm:"'uuid'"`
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"-"`
|
Password string `json:"-"`
|
||||||
|
Passwords string `json:"-"`
|
||||||
Dispname string `json:"dispname"`
|
Dispname string `json:"dispname"`
|
||||||
Phone string `json:"phone"`
|
Phone string `json:"phone"`
|
||||||
Email string `json:"email"`
|
Email string `json:"email"`
|
||||||
|
@ -39,14 +52,63 @@ type User struct {
|
||||||
Portrait string `json:"portrait"`
|
Portrait string `json:"portrait"`
|
||||||
Intro string `json:"intro"`
|
Intro string `json:"intro"`
|
||||||
Organization string `json:"organization"`
|
Organization string `json:"organization"`
|
||||||
Typ int `json:"typ"`
|
Type int `json:"type" xorm:"'typ'" description:"0: long-term account; 1: temporary account"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status" description:"0: active, 1: inactive, 2: locked, 3: frozen, 4: writen-off"`
|
||||||
IsRoot int `json:"is_root"`
|
IsRoot int `json:"is_root"`
|
||||||
LeaderId int64 `json:"leader_id"`
|
LeaderId int64 `json:"leader_id"`
|
||||||
LeaderName string `json:"leader_name"`
|
LeaderName string `json:"leader_name"`
|
||||||
|
LoginErrNum int `json:"login_err_num"`
|
||||||
|
ActiveBegin int64 `json:"active_begin" description:"for temporary account"`
|
||||||
|
ActiveEnd int64 `json:"active_end" description:"for temporary account"`
|
||||||
|
LockedAt int64 `json:"locked_at" description:"locked time"`
|
||||||
|
UpdatedAt int64 `json:"updated_at" description:"user info change time"`
|
||||||
|
PwdUpdatedAt int64 `json:"pwd_updated_at" description:"password change time"`
|
||||||
|
LoggedAt int64 `json:"logged_at" description:"last logged time"`
|
||||||
CreateAt time.Time `json:"create_at" xorm:"<-"`
|
CreateAt time.Time `json:"create_at" xorm:"<-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) Validate() error {
|
||||||
|
u.Username = strings.TrimSpace(u.Username)
|
||||||
|
if u.Username == "" {
|
||||||
|
return _e("username is blank")
|
||||||
|
}
|
||||||
|
|
||||||
|
if str.Dangerous(u.Username) {
|
||||||
|
return _e("%s %s format error", _s("username"), u.Username)
|
||||||
|
}
|
||||||
|
|
||||||
|
if str.Dangerous(u.Dispname) {
|
||||||
|
return _e("%s %s format error", _s("dispname"), u.Dispname)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Phone != "" && !str.IsPhone(u.Phone) {
|
||||||
|
return _e("%s %s format error", _s("phone"), u.Phone)
|
||||||
|
}
|
||||||
|
|
||||||
|
if u.Email != "" && !str.IsMail(u.Email) {
|
||||||
|
return _e("%s %s format error", _s("email"), u.Email)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(u.Username) > 32 {
|
||||||
|
return _e("username too long (max:%d)", 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(u.Dispname) > 32 {
|
||||||
|
return _e("dispname too long (max:%d)", 32)
|
||||||
|
}
|
||||||
|
|
||||||
|
if strings.ContainsAny(u.Im, "%'") {
|
||||||
|
return _e("%s %s format error", "im", u.Im)
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt, _ := DB["rdb"].Where("((email <> '' and email=?) or (phone <> '' and phone=?)) and username=?",
|
||||||
|
u.Email, u.Phone, u.Username).Count(u)
|
||||||
|
if cnt > 0 {
|
||||||
|
return _e("email %s or phone %s is exists", u.Email, u.Phone)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *User) CopyLdapAttr(sr *ldap.SearchResult) {
|
func (u *User) CopyLdapAttr(sr *ldap.SearchResult) {
|
||||||
attrs := config.Config.LDAP.Attributes
|
attrs := config.Config.LDAP.Attributes
|
||||||
if attrs.Dispname != "" {
|
if attrs.Dispname != "" {
|
||||||
|
@ -95,59 +157,59 @@ func InitRooter() {
|
||||||
log.Println("user root init done")
|
log.Println("user root init done")
|
||||||
}
|
}
|
||||||
|
|
||||||
func LdapLogin(user, pass string) (*User, error) {
|
func LdapLogin(username, pass string) (*User, error) {
|
||||||
sr, err := ldapReq(user, pass)
|
sr, err := ldapReq(username, pass)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var u User
|
var user User
|
||||||
has, err := DB["rdb"].Where("username=?", user).Get(&u)
|
has, err := DB["rdb"].Where("username=?", username).Get(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
u.CopyLdapAttr(sr)
|
user.CopyLdapAttr(sr)
|
||||||
|
|
||||||
if has {
|
if has {
|
||||||
if config.Config.LDAP.CoverAttributes {
|
if config.Config.LDAP.CoverAttributes {
|
||||||
_, err := DB["rdb"].Where("id=?", u.Id).Update(u)
|
_, err := DB["rdb"].Where("id=?", user.Id).Update(user)
|
||||||
return &u, err
|
return &user, err
|
||||||
} else {
|
} else {
|
||||||
return &u, err
|
return &user, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u.Username = user
|
user.Username = username
|
||||||
u.Password = "******"
|
user.Password = "******"
|
||||||
u.UUID = GenUUIDForUser(user)
|
user.UUID = GenUUIDForUser(username)
|
||||||
_, err = DB["rdb"].Insert(u)
|
_, err = DB["rdb"].Insert(user)
|
||||||
return &u, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func PassLogin(user, pass string) (*User, error) {
|
func PassLogin(username, pass string) (*User, error) {
|
||||||
var u User
|
var user User
|
||||||
has, err := DB["rdb"].Where("username=?", user).Get(&u)
|
has, err := DB["rdb"].Where("username=?", username).Get(&user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, _e("Login fail, check your username and password")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !has {
|
if !has {
|
||||||
logger.Infof("password auth fail, no such user: %s", user)
|
logger.Infof("password auth fail, no such user: %s", username)
|
||||||
return nil, fmt.Errorf("login fail, check your username and password")
|
return nil, _e("Login fail, check your username and password")
|
||||||
}
|
}
|
||||||
|
|
||||||
loginPass, err := CryptoPass(pass)
|
loginPass, err := CryptoPass(pass)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return &user, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if loginPass != u.Password {
|
if loginPass != user.Password {
|
||||||
logger.Infof("password auth fail, password error, user: %s", user)
|
logger.Infof("password auth fail, password error, user: %s", username)
|
||||||
return nil, fmt.Errorf("login fail, check your username and password")
|
return &user, _e("Login fail, check your username and password")
|
||||||
}
|
}
|
||||||
|
|
||||||
return &u, nil
|
return &user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SmsCodeLogin(phone, code string) (*User, error) {
|
func SmsCodeLogin(phone, code string) (*User, error) {
|
||||||
|
@ -156,15 +218,15 @@ func SmsCodeLogin(phone, code string) (*User, error) {
|
||||||
return nil, fmt.Errorf("phone %s dose not exist", phone)
|
return nil, fmt.Errorf("phone %s dose not exist", phone)
|
||||||
}
|
}
|
||||||
|
|
||||||
lc, err := LoginCodeGet("username=? and code=? and login_type=?", user.Username, code, LOGIN_T_SMS)
|
lc, err := LoginCodeGet("username=? and code=? and login_type=?", user.Username, code, LOGIN_T_LOGIN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("sms-code auth fail, user: %s", user.Username)
|
logger.Debugf("sms-code auth fail, user: %s", user.Username)
|
||||||
return nil, fmt.Errorf("login fail, check your sms-code")
|
return user, _e("The code is incorrect")
|
||||||
}
|
}
|
||||||
|
|
||||||
if time.Now().Unix()-lc.CreatedAt > LOGIN_EXPIRES_IN {
|
if time.Now().Unix()-lc.CreatedAt > LOGIN_EXPIRES_IN {
|
||||||
logger.Infof("sms-code auth expired, user: %s", user.Username)
|
logger.Debugf("sms-code auth expired, user: %s", user.Username)
|
||||||
return nil, fmt.Errorf("login fail, the code has expired")
|
return user, _e("The code has expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.Del()
|
lc.Del()
|
||||||
|
@ -178,15 +240,15 @@ func EmailCodeLogin(email, code string) (*User, error) {
|
||||||
return nil, fmt.Errorf("email %s dose not exist", email)
|
return nil, fmt.Errorf("email %s dose not exist", email)
|
||||||
}
|
}
|
||||||
|
|
||||||
lc, err := LoginCodeGet("username=? and code=? and login_type=?", user.Username, code, LOGIN_T_EMAIL)
|
lc, err := LoginCodeGet("username=? and code=? and login_type=?", user.Username, code, LOGIN_T_LOGIN)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Infof("email-code auth fail, user: %s", user.Username)
|
logger.Debugf("email-code auth fail, user: %s", user.Username)
|
||||||
return nil, fmt.Errorf("login fail, check your email-code")
|
return user, _e("The code is incorrect")
|
||||||
}
|
}
|
||||||
|
|
||||||
if time.Now().Unix()-lc.CreatedAt > LOGIN_EXPIRES_IN {
|
if time.Now().Unix()-lc.CreatedAt > LOGIN_EXPIRES_IN {
|
||||||
logger.Infof("email-code auth expired, user: %s", user.Username)
|
logger.Debugf("email-code auth expired, user: %s", user.Username)
|
||||||
return nil, fmt.Errorf("login fail, the code has expired")
|
return user, _e("The code has expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
lc.Del()
|
lc.Del()
|
||||||
|
@ -208,56 +270,40 @@ func UserGet(where string, args ...interface{}) (*User, error) {
|
||||||
return &obj, nil
|
return &obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func UserMustGet(where string, args ...interface{}) (*User, error) {
|
||||||
|
var obj User
|
||||||
|
has, err := DB["rdb"].Where(where, args...).Get(&obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
return nil, _e("User dose not exist")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (u *User) IsRooter() bool {
|
func (u *User) IsRooter() bool {
|
||||||
return u.IsRoot == 1
|
return u.IsRoot == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) CheckFields() {
|
|
||||||
u.Username = strings.TrimSpace(u.Username)
|
|
||||||
if u.Username == "" {
|
|
||||||
errors.Bomb("username is blank")
|
|
||||||
}
|
|
||||||
|
|
||||||
if str.Dangerous(u.Username) {
|
|
||||||
errors.Bomb("username is dangerous")
|
|
||||||
}
|
|
||||||
|
|
||||||
if str.Dangerous(u.Dispname) {
|
|
||||||
errors.Bomb("dispname is dangerous")
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Phone != "" && !str.IsPhone(u.Phone) {
|
|
||||||
errors.Bomb("%s format error", u.Phone)
|
|
||||||
}
|
|
||||||
|
|
||||||
if u.Email != "" && !str.IsMail(u.Email) {
|
|
||||||
errors.Bomb("%s format error", u.Email)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(u.Username) > 32 {
|
|
||||||
errors.Bomb("username too long")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(u.Dispname) > 32 {
|
|
||||||
errors.Bomb("dispname too long")
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.ContainsAny(u.Im, "%'") {
|
|
||||||
errors.Bomb("im invalid")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *User) Update(cols ...string) error {
|
func (u *User) Update(cols ...string) error {
|
||||||
u.CheckFields()
|
if err := u.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
_, err := DB["rdb"].Where("id=?", u.Id).Cols(cols...).Update(u)
|
_, err := DB["rdb"].Where("id=?", u.Id).Cols(cols...).Update(u)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *User) Save() error {
|
func (u *User) Save() error {
|
||||||
u.CheckFields()
|
if err := u.Validate(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if u.Id > 0 {
|
if u.Id > 0 {
|
||||||
return fmt.Errorf("user.id[%d] not equal 0", u.Id)
|
return _e("user.id[%d] not equal 0", u.Id)
|
||||||
}
|
}
|
||||||
|
|
||||||
if u.UUID == "" {
|
if u.UUID == "" {
|
||||||
|
@ -270,9 +316,11 @@ func (u *User) Save() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if cnt > 0 {
|
if cnt > 0 {
|
||||||
return fmt.Errorf("username already exists")
|
return _e("Username %s already exists", u.Username)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
_, err = DB["rdb"].Insert(u)
|
_, err = DB["rdb"].Insert(u)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -440,7 +488,7 @@ func (u *User) HasPermGlobal(operation string) (bool, error) {
|
||||||
|
|
||||||
rids, err := RoleIdsHasOp(operation)
|
rids, err := RoleIdsHasOp(operation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("[CheckPermGlobal] RoleIdsHasOp fail: %v, operation: %s", err, operation)
|
return false, _e("[CheckPermGlobal] RoleIdsHasOp fail: %v, operation: %s", err, operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rids == nil || len(rids) == 0 {
|
if rids == nil || len(rids) == 0 {
|
||||||
|
@ -449,7 +497,7 @@ func (u *User) HasPermGlobal(operation string) (bool, error) {
|
||||||
|
|
||||||
has, err := UserHasGlobalRole(u.Id, rids)
|
has, err := UserHasGlobalRole(u.Id, rids)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("[CheckPermGlobal] UserHasGlobalRole fail: %v, username: %s", err, u.Username)
|
return false, _e("[CheckPermGlobal] UserHasGlobalRole fail: %v, username: %s", err, u.Username)
|
||||||
}
|
}
|
||||||
|
|
||||||
return has, nil
|
return has, nil
|
||||||
|
@ -531,7 +579,9 @@ func safeUserIds(ids []int64) ([]int64, error) {
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Deprecated
|
||||||
func UsernameByUUID(uuid string) string {
|
func UsernameByUUID(uuid string) string {
|
||||||
|
logger.Warningf("UsernameByUUID is Deprectaed, use UsernameBySid instead of it")
|
||||||
if uuid == "" {
|
if uuid == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,135 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WhiteList struct {
|
||||||
|
Id int64 `json:"id"`
|
||||||
|
StartIp string `json:"startIp"`
|
||||||
|
StartIpInt int64 `json:"-"`
|
||||||
|
EndIp string `json:"endIp"`
|
||||||
|
EndIpInt int64 `json:"-"`
|
||||||
|
StartTime int64 `json:"startTime"`
|
||||||
|
EndTime int64 `json:"endTime"`
|
||||||
|
CreatedAt int64 `json:"createdAt"`
|
||||||
|
UpdatedAt int64 `json:"updateAt"`
|
||||||
|
Creator string `json:"creator"`
|
||||||
|
Updater string `json:"updater"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func WhiteListAccess(addr string) error {
|
||||||
|
ip := parseIPv4(addr)
|
||||||
|
if ip == 0 {
|
||||||
|
return fmt.Errorf("invalid remote address %s", addr)
|
||||||
|
}
|
||||||
|
now := time.Now().Unix()
|
||||||
|
count, _ := DB["rdb"].Where("start_ip_int<? and end_ip_int>? and start_time>? and end_time<?", ip, ip, now, now).Count(new(WhiteList))
|
||||||
|
if count == 0 {
|
||||||
|
return fmt.Errorf("access deny from %s", addr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
const big = 0xFFFFFF
|
||||||
|
|
||||||
|
func dtoi(s string) (n int, i int, ok bool) {
|
||||||
|
n = 0
|
||||||
|
for i = 0; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
|
||||||
|
n = n*10 + int(s[i]-'0')
|
||||||
|
if n >= big {
|
||||||
|
return big, i, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i == 0 {
|
||||||
|
return 0, 0, false
|
||||||
|
}
|
||||||
|
return n, i, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseIPv4(s string) uint32 {
|
||||||
|
var p [4]uint32
|
||||||
|
for i := 0; i < 4; i++ {
|
||||||
|
if len(s) == 0 {
|
||||||
|
// Missing octets.
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if i > 0 {
|
||||||
|
if s[0] != '.' {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
s = s[1:]
|
||||||
|
}
|
||||||
|
n, c, ok := dtoi(s)
|
||||||
|
if !ok || n > 0xFF {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
s = s[c:]
|
||||||
|
p[i] = uint32(n)
|
||||||
|
}
|
||||||
|
if len(s) != 0 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return p[0]<<24 + p[1]<<16 + p[2]<<8 + p[3]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *WhiteList) Validate() error {
|
||||||
|
if p.StartIpInt = int64(parseIPv4(p.StartIp)); p.StartIpInt == 0 {
|
||||||
|
return fmt.Errorf("invalid start ip %s", p.StartIp)
|
||||||
|
}
|
||||||
|
if p.EndIpInt = int64(parseIPv4(p.EndIp)); p.EndIpInt == 0 {
|
||||||
|
return fmt.Errorf("invalid end ip %s", p.EndIp)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func WhiteListTotal(query string) (int64, error) {
|
||||||
|
if query != "" {
|
||||||
|
q := "%" + query + "%"
|
||||||
|
return DB["rdb"].Where("start_ip like ? or end_ip like ?", q, q).Count(new(NodeTrash))
|
||||||
|
}
|
||||||
|
|
||||||
|
return DB["rdb"].Count(new(WhiteList))
|
||||||
|
}
|
||||||
|
|
||||||
|
func WhiteListGets(query string, limit, offset int) ([]WhiteList, error) {
|
||||||
|
session := DB["rdb"].Desc("id").Limit(limit, offset)
|
||||||
|
if query != "" {
|
||||||
|
q := "%" + query + "%"
|
||||||
|
session = session.Where("start_ip like ? or end_ip like ?", q, q)
|
||||||
|
}
|
||||||
|
|
||||||
|
var objs []WhiteList
|
||||||
|
err := session.Find(&objs)
|
||||||
|
return objs, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func WhiteListGet(where string, args ...interface{}) (*WhiteList, error) {
|
||||||
|
var obj WhiteList
|
||||||
|
has, err := DB["rdb"].Where(where, args...).Get(&obj)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
return nil, errors.New("whiteList not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &obj, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *WhiteList) Save() error {
|
||||||
|
_, err := DB["rdb"].Insert(p)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (p *WhiteList) Update(cols ...string) error {
|
||||||
|
_, err := DB["rdb"].Where("id=?", p.Id).Cols(cols...).Update(p)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
func (p *WhiteList) Del() error {
|
||||||
|
_, err := DB["rdb"].Where("id=?", p.Id).Delete(new(WhiteList))
|
||||||
|
return err
|
||||||
|
}
|
|
@ -47,7 +47,7 @@ func shouldBeService() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustUsername(c *gin.Context) string {
|
func mustUsername(c *gin.Context) string {
|
||||||
username := cookieUsername(c)
|
username := sessionUsername(c)
|
||||||
if username == "" {
|
if username == "" {
|
||||||
username = headerUsername(c)
|
username = headerUsername(c)
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,12 @@ func mustUsername(c *gin.Context) string {
|
||||||
return username
|
return username
|
||||||
}
|
}
|
||||||
|
|
||||||
func cookieUsername(c *gin.Context) string {
|
func sessionUsername(c *gin.Context) string {
|
||||||
return models.UsernameByUUID(readCookieUser(c))
|
sess, err := models.SessionGetWithCache(readSessionId(c))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return sess.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
func headerUsername(c *gin.Context) string {
|
func headerUsername(c *gin.Context) string {
|
||||||
|
@ -84,11 +88,10 @@ func headerUsername(c *gin.Context) string {
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
|
|
||||||
func readCookieUser(c *gin.Context) string {
|
func readSessionId(c *gin.Context) string {
|
||||||
uuid, err := c.Cookie(config.Config.HTTP.CookieName)
|
sid, err := c.Cookie(config.Config.HTTP.CookieName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
return sid
|
||||||
return uuid
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@ func shouldBeService() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustUsername(c *gin.Context) string {
|
func mustUsername(c *gin.Context) string {
|
||||||
username := cookieUsername(c)
|
username := sessionUsername(c)
|
||||||
if username == "" {
|
if username == "" {
|
||||||
username = headerUsername(c)
|
username = headerUsername(c)
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,12 @@ func mustUsername(c *gin.Context) string {
|
||||||
return username
|
return username
|
||||||
}
|
}
|
||||||
|
|
||||||
func cookieUsername(c *gin.Context) string {
|
func sessionUsername(c *gin.Context) string {
|
||||||
return models.UsernameByUUID(readCookieUser(c))
|
sess, err := models.SessionGetWithCache(readSessionId(c))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return sess.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
func headerUsername(c *gin.Context) string {
|
func headerUsername(c *gin.Context) string {
|
||||||
|
@ -84,11 +88,10 @@ func headerUsername(c *gin.Context) string {
|
||||||
|
|
||||||
// ------------
|
// ------------
|
||||||
|
|
||||||
func readCookieUser(c *gin.Context) string {
|
func readSessionId(c *gin.Context) string {
|
||||||
uuid, err := c.Cookie(config.Config.HTTP.CookieName)
|
sid, err := c.Cookie(config.Config.HTTP.CookieName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
return sid
|
||||||
return uuid
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BaseCollector struct {
|
||||||
|
name string
|
||||||
|
category Category
|
||||||
|
newRule func() interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewBaseCollector(name string, category Category, newRule func() interface{}) *BaseCollector {
|
||||||
|
return &BaseCollector{
|
||||||
|
name: name,
|
||||||
|
category: category,
|
||||||
|
newRule: newRule,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type telegrafPlugin interface {
|
||||||
|
TelegrafInput() (telegraf.Input, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BaseCollector) Name() string { return p.name }
|
||||||
|
func (p BaseCollector) Category() Category { return p.category }
|
||||||
|
func (p BaseCollector) Template() (interface{}, error) { return Template(p.newRule()) }
|
||||||
|
|
||||||
|
func (p BaseCollector) TelegrafInput(rule *models.CollectRule) (telegraf.Input, error) {
|
||||||
|
r2 := p.newRule()
|
||||||
|
if err := json.Unmarshal(rule.Data, r2); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin, ok := r2.(telegrafPlugin)
|
||||||
|
if !ok {
|
||||||
|
return nil, errUnsupported
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin.TelegrafInput()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BaseCollector) Get(id int64) (interface{}, error) {
|
||||||
|
collect := &models.CollectRule{}
|
||||||
|
has, err := models.DB["mon"].Where("id = ?", id).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BaseCollector) Gets(nids []int64) (ret []interface{}, err error) {
|
||||||
|
collects := []models.CollectRule{}
|
||||||
|
err = models.DB["mon"].Where("collect_type=?", p.name).In("nid", nids).Find(&collects)
|
||||||
|
for _, c := range collects {
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BaseCollector) GetByNameAndNid(name string, nid int64) (interface{}, error) {
|
||||||
|
collect := &models.CollectRule{}
|
||||||
|
has, err := models.DB["mon"].Where("collect_type = ? and name = ? and nid = ?", p.name, name, nid).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BaseCollector) Create(data []byte, username string) error {
|
||||||
|
collect := &models.CollectRule{CollectType: p.name}
|
||||||
|
rule := p.newRule()
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, collect); err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := collect.Validate(rule); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_create", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(collect.Name, collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", collect.Name)
|
||||||
|
}
|
||||||
|
return models.CreateCollect(p.name, username, collect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BaseCollector) Update(data []byte, username string) error {
|
||||||
|
collect := &models.CollectRule{}
|
||||||
|
rule := p.newRule()
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, collect); err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := collect.Validate(rule); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_modify", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验采集是否存在
|
||||||
|
obj, err := p.Get(collect.Id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.name, collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpId := obj.(*models.CollectRule).Id
|
||||||
|
if tmpId == 0 {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.name, collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(collect.Name, collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil && tmpId != old.(*models.CollectRule).Id {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", collect.Name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return collect.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p BaseCollector) Delete(id int64, username string) error {
|
||||||
|
tmp, err := p.Get(id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.name, id)
|
||||||
|
}
|
||||||
|
nid := tmp.(*models.CollectRule).Nid
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_delete", int64(nid))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("models.UsernameCandoNodeOp error %s", err)
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.DeleteCollectRule(id)
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
collectors = map[string]Collector{}
|
||||||
|
remoteCollectors = []string{}
|
||||||
|
localCollectors = []string{}
|
||||||
|
errUnsupported = errors.New("unsupported")
|
||||||
|
)
|
||||||
|
|
||||||
|
type Category string
|
||||||
|
|
||||||
|
const (
|
||||||
|
RemoteCategory Category = "remote" // used for prober
|
||||||
|
LocalCategory Category = "local" // used for agent
|
||||||
|
)
|
||||||
|
|
||||||
|
type Collector interface {
|
||||||
|
Name() string
|
||||||
|
Category() Category
|
||||||
|
Get(id int64) (interface{}, error)
|
||||||
|
Gets(nids []int64) ([]interface{}, error)
|
||||||
|
GetByNameAndNid(name string, nid int64) (interface{}, error)
|
||||||
|
Create(data []byte, username string) error
|
||||||
|
Update(data []byte, username string) error
|
||||||
|
Delete(id int64, username string) error
|
||||||
|
Template() (interface{}, error)
|
||||||
|
TelegrafInput(*models.CollectRule) (telegraf.Input, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CollectorRegister(c Collector) error {
|
||||||
|
name := c.Name()
|
||||||
|
if _, ok := collectors[name]; ok {
|
||||||
|
return fmt.Errorf("collector %s exists", name)
|
||||||
|
}
|
||||||
|
collectors[name] = c
|
||||||
|
|
||||||
|
if c.Category() == RemoteCategory {
|
||||||
|
remoteCollectors = append(remoteCollectors, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Category() == LocalCategory {
|
||||||
|
localCollectors = append(localCollectors, name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetCollector(name string) (Collector, error) {
|
||||||
|
if c, ok := collectors[name]; !ok {
|
||||||
|
return nil, fmt.Errorf("collector %s does not exist", name)
|
||||||
|
} else {
|
||||||
|
return c, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRemoteCollectors() []string {
|
||||||
|
return remoteCollectors
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetLocalCollectors() []string {
|
||||||
|
return localCollectors
|
||||||
|
}
|
||||||
|
|
||||||
|
func _s(format string, a ...interface{}) string {
|
||||||
|
logger.Debugf(` "%s": "%s",`, format, format)
|
||||||
|
return i18n.Sprintf(format, a...)
|
||||||
|
}
|
|
@ -0,0 +1,227 @@
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
|
var fieldCache sync.Map // map[reflect.Type]structFields
|
||||||
|
|
||||||
|
type Field struct {
|
||||||
|
skip bool `json:"-"`
|
||||||
|
// definitions map[string][]Field `json:"-"`
|
||||||
|
|
||||||
|
Name string `json:"name,omitempty"`
|
||||||
|
Label string `json:"label,omitempty"`
|
||||||
|
Example string `json:"example,omitempty"`
|
||||||
|
Description string `json:"description,omitempty"`
|
||||||
|
Required bool `json:"required,omitempty"`
|
||||||
|
Items *Field `json:"items,omitempty" description:"arrays's items"`
|
||||||
|
Type string `json:"type,omitempty" description:"struct,boolean,integer,folat,string,array"`
|
||||||
|
Ref string `json:"$ref,omitempty" description:"name of the struct ref"`
|
||||||
|
Fields []Field `json:"fields,omitempty" description:"fields of struct type"`
|
||||||
|
Definitions map[string][]Field `json:"definitions,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Field) String() string {
|
||||||
|
return prettify(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
// cachedTypeContent is like typeFields but uses a cache to avoid repeated work.
|
||||||
|
func cachedTypeContent(t reflect.Type) Field {
|
||||||
|
if f, ok := fieldCache.Load(t); ok {
|
||||||
|
return f.(Field)
|
||||||
|
}
|
||||||
|
f, _ := fieldCache.LoadOrStore(t, typeContent(t))
|
||||||
|
return f.(Field)
|
||||||
|
}
|
||||||
|
|
||||||
|
func typeContent(t reflect.Type) Field {
|
||||||
|
definitions := map[string][]Field{t.String(): nil}
|
||||||
|
|
||||||
|
ret := Field{
|
||||||
|
// definitions: map[string][]Field{
|
||||||
|
// t.String(): nil,
|
||||||
|
// },
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < t.NumField(); i++ {
|
||||||
|
sf := t.Field(i)
|
||||||
|
isUnexported := sf.PkgPath != ""
|
||||||
|
if sf.Anonymous {
|
||||||
|
panic("unsupported anonymous field")
|
||||||
|
} else if isUnexported {
|
||||||
|
// Ignore unexported non-embedded fields.
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
field := getTagOpt(sf)
|
||||||
|
if field.skip {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
ft := sf.Type
|
||||||
|
|
||||||
|
fieldType(ft, &field, definitions)
|
||||||
|
|
||||||
|
// Record found field and index sequence.
|
||||||
|
if field.Name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||||
|
ret.Fields = append(ret.Fields, field)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
panic("unsupported anonymous, struct field")
|
||||||
|
}
|
||||||
|
|
||||||
|
definitions[t.String()] = ret.Fields
|
||||||
|
|
||||||
|
ret.Definitions = definitions
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// tagOptions is the string following a comma in a struct field's "json"
|
||||||
|
// tag, or the empty string. It does not include the leading comma.
|
||||||
|
type tagOptions string
|
||||||
|
|
||||||
|
// parseTag splits a struct field's json tag into its name and
|
||||||
|
// comma-separated options.
|
||||||
|
func parseTag(tag string) (string, tagOptions) {
|
||||||
|
if idx := strings.Index(tag, ","); idx != -1 {
|
||||||
|
return tag[:idx], tagOptions(tag[idx+1:])
|
||||||
|
}
|
||||||
|
return tag, tagOptions("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contains reports whether a comma-separated list of options
|
||||||
|
// contains a particular substr flag. substr must be surrounded by a
|
||||||
|
// string boundary or commas.
|
||||||
|
func (o tagOptions) Contains(optionName string) bool {
|
||||||
|
if len(o) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
s := string(o)
|
||||||
|
for s != "" {
|
||||||
|
var next string
|
||||||
|
i := strings.Index(s, ",")
|
||||||
|
if i >= 0 {
|
||||||
|
s, next = s[:i], s[i+1:]
|
||||||
|
}
|
||||||
|
if s == optionName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
s = next
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTagOpt(sf reflect.StructField) (opt Field) {
|
||||||
|
if sf.Anonymous {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
tag := sf.Tag.Get("json")
|
||||||
|
if tag == "-" {
|
||||||
|
opt.skip = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
name, opts := parseTag(tag)
|
||||||
|
if opts.Contains("required") {
|
||||||
|
opt.Required = true
|
||||||
|
}
|
||||||
|
|
||||||
|
opt.Name = name
|
||||||
|
opt.Label = _s(sf.Tag.Get("label"))
|
||||||
|
opt.Example = sf.Tag.Get("example")
|
||||||
|
opt.Description = _s(sf.Tag.Get("description"))
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func isValidTag(s string) bool {
|
||||||
|
if s == "" {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
for _, c := range s {
|
||||||
|
switch {
|
||||||
|
case strings.ContainsRune("!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
|
||||||
|
case !unicode.IsLetter(c) && !unicode.IsDigit(c):
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func panicType(ft reflect.Type, args ...interface{}) {
|
||||||
|
msg := fmt.Sprintf("type field %s %s", ft.PkgPath(), ft.Name())
|
||||||
|
|
||||||
|
if len(args) > 0 {
|
||||||
|
panic(fmt.Sprint(args...) + " " + msg)
|
||||||
|
}
|
||||||
|
panic(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Template(v interface{}) (interface{}, error) {
|
||||||
|
rv := reflect.Indirect(reflect.ValueOf(v))
|
||||||
|
if rv.Kind() != reflect.Struct {
|
||||||
|
return nil, fmt.Errorf("invalid argument, must be a struct")
|
||||||
|
}
|
||||||
|
|
||||||
|
content := cachedTypeContent(rv.Type())
|
||||||
|
|
||||||
|
return content, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func prettify(in interface{}) string {
|
||||||
|
b, _ := json.MarshalIndent(in, "", " ")
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fieldType(t reflect.Type, in *Field, definitions map[string][]Field) {
|
||||||
|
if t.Name() == "" && t.Kind() == reflect.Ptr {
|
||||||
|
// Follow pointer.
|
||||||
|
t = t.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t.Kind() {
|
||||||
|
case reflect.Int, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint32, reflect.Uint64:
|
||||||
|
in.Type = "integer"
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
in.Type = "float"
|
||||||
|
case reflect.Bool:
|
||||||
|
in.Type = "boolean"
|
||||||
|
case reflect.String:
|
||||||
|
in.Type = "string"
|
||||||
|
case reflect.Struct:
|
||||||
|
name := t.String()
|
||||||
|
if _, ok := definitions[name]; !ok {
|
||||||
|
f := cachedTypeContent(t)
|
||||||
|
for k, v := range f.Definitions {
|
||||||
|
definitions[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.Ref = t.String()
|
||||||
|
case reflect.Slice, reflect.Array:
|
||||||
|
t2 := t.Elem()
|
||||||
|
if t2.Kind() == reflect.Ptr {
|
||||||
|
t2 = t2.Elem()
|
||||||
|
}
|
||||||
|
if k := t2.Kind(); k == reflect.Int || k == reflect.Int32 || k == reflect.Int64 ||
|
||||||
|
k == reflect.Uint || k == reflect.Uint32 || k == reflect.Uint64 ||
|
||||||
|
k == reflect.Float32 || k == reflect.Float64 ||
|
||||||
|
k == reflect.Bool || k == reflect.String || k == reflect.Struct {
|
||||||
|
in.Type = "array"
|
||||||
|
in.Items = &Field{}
|
||||||
|
fieldType(t2, in.Items, definitions)
|
||||||
|
} else {
|
||||||
|
panic(fmt.Sprintf("unspport type %s items %s", t.String(), t2.String()))
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
panic(fmt.Sprintf("unspport type %s", t.String()))
|
||||||
|
// in.Type = "string"
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ package config
|
||||||
const Version = 1
|
const Version = 1
|
||||||
|
|
||||||
const JudgesReplicas = 500
|
const JudgesReplicas = 500
|
||||||
|
const ProbersReplicas = 500
|
||||||
const DetectorReplicas = 500
|
const DetectorReplicas = 500
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -94,7 +94,9 @@ type loggerSection struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpSection struct {
|
type httpSection struct {
|
||||||
Listen string `yaml:"listen"`
|
Mode string `yaml:"mode"`
|
||||||
|
CookieName string `yaml:"cookieName"`
|
||||||
|
CookieDomain string `yaml:"cookieDomain"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type proxySection struct {
|
type proxySection struct {
|
||||||
|
|
|
@ -5,7 +5,6 @@ import (
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/models"
|
||||||
"github.com/didi/nightingale/src/modules/monapi/config"
|
"github.com/didi/nightingale/src/modules/monapi/config"
|
||||||
"github.com/didi/nightingale/src/modules/monapi/tools"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/toolkits/pkg/errors"
|
"github.com/toolkits/pkg/errors"
|
||||||
|
@ -15,7 +14,7 @@ import (
|
||||||
// GetCookieUser 从cookie中获取username
|
// GetCookieUser 从cookie中获取username
|
||||||
func GetCookieUser() gin.HandlerFunc {
|
func GetCookieUser() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
username := cookieUser(c)
|
username := sessionUsername(c)
|
||||||
if username == "" {
|
if username == "" {
|
||||||
username = headerUser(c)
|
username = headerUser(c)
|
||||||
}
|
}
|
||||||
|
@ -29,15 +28,6 @@ func GetCookieUser() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func cookieUser(c *gin.Context) string {
|
|
||||||
uuid, err := c.Cookie("ecmc-user")
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return tools.UsernameByUUID(uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func headerUser(c *gin.Context) string {
|
func headerUser(c *gin.Context) string {
|
||||||
token := c.GetHeader("X-User-Token")
|
token := c.GetHeader("X-User-Token")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
|
@ -88,3 +78,19 @@ func getUserByToken(token string) (user *models.User, err error) {
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sessionUsername(c *gin.Context) string {
|
||||||
|
sess, err := models.SessionGetWithCache(readSessionId(c))
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return sess.Username
|
||||||
|
}
|
||||||
|
|
||||||
|
func readSessionId(c *gin.Context) string {
|
||||||
|
sid, err := c.Cookie(config.Get().HTTP.CookieName)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return sid
|
||||||
|
}
|
|
@ -2,9 +2,11 @@ package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"log"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
_ "net/http/pprof"
|
_ "net/http/pprof"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/common/address"
|
"github.com/didi/nightingale/src/common/address"
|
||||||
|
@ -31,7 +33,7 @@ func Start() {
|
||||||
loggerMid := middleware.LoggerWithConfig(middleware.LoggerConfig{SkipPaths: skipPaths})
|
loggerMid := middleware.LoggerWithConfig(middleware.LoggerConfig{SkipPaths: skipPaths})
|
||||||
recoveryMid := middleware.Recovery()
|
recoveryMid := middleware.Recovery()
|
||||||
|
|
||||||
if c.Logger.Level != "DEBUG" {
|
if strings.ToLower(c.HTTP.Mode) == "release" {
|
||||||
gin.SetMode(gin.ReleaseMode)
|
gin.SetMode(gin.ReleaseMode)
|
||||||
middleware.DisableConsoleColor()
|
middleware.DisableConsoleColor()
|
||||||
} else {
|
} else {
|
||||||
|
@ -47,9 +49,10 @@ func Start() {
|
||||||
srv.Handler = r
|
srv.Handler = r
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
log.Println("starting http server, listening on:", srv.Addr)
|
fmt.Println("http.listening:", srv.Addr)
|
||||||
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||||
log.Fatalf("listening %s occur error: %s\n", srv.Addr, err)
|
fmt.Printf("listening %s occur error: %s\n", srv.Addr, err)
|
||||||
|
os.Exit(3)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -59,14 +62,15 @@ func Shutdown() {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
if err := srv.Shutdown(ctx); err != nil {
|
if err := srv.Shutdown(ctx); err != nil {
|
||||||
log.Fatalln("cannot shutdown http server:", err)
|
fmt.Println("cannot shutdown http server:", err)
|
||||||
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
|
||||||
// catching ctx.Done(). timeout of 5 seconds.
|
// catching ctx.Done(). timeout of 5 seconds.
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
log.Println("shutdown http server timeout of 5 seconds.")
|
fmt.Println("shutdown http server timeout of 5 seconds.")
|
||||||
default:
|
default:
|
||||||
log.Println("http server stopped")
|
fmt.Println("http server stopped")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,20 +83,41 @@ func Config(r *gin.Engine) {
|
||||||
event.POST("/cur/claim", eventCurClaim)
|
event.POST("/cur/claim", eventCurClaim)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: merge to collect-rule
|
||||||
collect := r.Group("/api/mon/collect").Use(GetCookieUser())
|
collect := r.Group("/api/mon/collect").Use(GetCookieUser())
|
||||||
{
|
{
|
||||||
collect.POST("", collectPost)
|
collect.POST("", collectRulePost) // create a collect rule
|
||||||
collect.GET("/list", collectsGet)
|
collect.GET("/list", collectRulesGet) // get collect rules
|
||||||
collect.GET("", collectGet)
|
collect.GET("", collectRuleGet) // get collect rule by type & id
|
||||||
collect.PUT("", collectPut)
|
collect.PUT("", collectRulePut) // update collect rule by type & id
|
||||||
collect.DELETE("", collectsDel)
|
collect.DELETE("", collectsRuleDel) // delete collect rules by type & ids
|
||||||
collect.POST("/check", regExpCheck)
|
collect.POST("/check", regExpCheck) // check collect rule
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: merge to collect-rules, used by agent
|
||||||
collects := r.Group("/api/mon/collects")
|
collects := r.Group("/api/mon/collects")
|
||||||
{
|
{
|
||||||
collects.GET("/:endpoint", collectGetByEndpoint)
|
collects.GET("/:endpoint", collectRulesGetByLocalEndpoint) // get collect rules by endpoint, for agent
|
||||||
collects.GET("", collectsGet)
|
collects.GET("", collectRulesGet) // get collect rules
|
||||||
|
}
|
||||||
|
|
||||||
|
collectRules := r.Group("/api/mon/collect-rules").Use(GetCookieUser())
|
||||||
|
{
|
||||||
|
collectRules.POST("", collectRulePost) // create a collect rule
|
||||||
|
collectRules.GET("/list", collectRulesGet) // get collect rules
|
||||||
|
collectRules.GET("", collectRuleGet) // get collect rule by type & id
|
||||||
|
collectRules.PUT("", collectRulePut) // update collect rule by type & id
|
||||||
|
collectRules.DELETE("", collectsRuleDel) // delete collect rules by type & ids
|
||||||
|
collectRules.POST("/check", regExpCheck) // check collect rule
|
||||||
|
collectRules.GET("/types", collectRuleTypesGet) // get collect types, category: local|remote
|
||||||
|
collectRules.GET("/types/:type/template", collectRuleTemplateGet) // get collect teplate by type
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
collectRulesAnonymous := r.Group("/api/mon/collect-rules")
|
||||||
|
{
|
||||||
|
collectRulesAnonymous.GET("/endpoints/:endpoint/remote", collectRulesGetByRemoteEndpoint) // for prober
|
||||||
|
collectRulesAnonymous.GET("/endpoints/:endpoint/local", collectRulesGetByLocalEndpoint) // for agent
|
||||||
}
|
}
|
||||||
|
|
||||||
stra := r.Group("/api/mon/stra").Use(GetCookieUser())
|
stra := r.Group("/api/mon/stra").Use(GetCookieUser())
|
||||||
|
@ -151,6 +172,15 @@ func Config(r *gin.Engine) {
|
||||||
indexProxy.POST("/counter/detail", indexReq)
|
indexProxy.POST("/counter/detail", indexReq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
v1 := r.Group("/v1/mon")
|
||||||
|
{
|
||||||
|
v1.POST("/report-detector-heartbeat", detectorHeartBeat)
|
||||||
|
v1.GET("/detectors", detectorInstanceGets)
|
||||||
|
v1.GET("/rules", collectRulesGet)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if config.Get().Logger.Level == "DEBUG" {
|
if config.Get().Logger.Level == "DEBUG" {
|
||||||
pprof.Register(r, "/api/monapi/debug/pprof")
|
pprof.Register(r, "/api/monapi/debug/pprof")
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,7 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
"github.com/didi/nightingale/src/modules/monapi/config"
|
|
||||||
"github.com/didi/nightingale/src/modules/monapi/scache"
|
"github.com/didi/nightingale/src/modules/monapi/scache"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
@ -16,201 +15,44 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type CollectRecv struct {
|
type CollectRecv struct {
|
||||||
Type string `json:"type"`
|
Type string `json:"type"`
|
||||||
Data interface{} `json:"data"`
|
Data json.RawMessage `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//此处实现需要重构
|
func collectRulePost(c *gin.Context) {
|
||||||
func collectPost(c *gin.Context) {
|
|
||||||
creator := loginUsername(c)
|
|
||||||
var recv []CollectRecv
|
var recv []CollectRecv
|
||||||
errors.Dangerous(c.ShouldBind(&recv))
|
errors.Dangerous(c.ShouldBind(&recv))
|
||||||
|
|
||||||
|
creator := loginUsername(c)
|
||||||
for _, obj := range recv {
|
for _, obj := range recv {
|
||||||
switch obj.Type {
|
cl, err := collector.GetCollector(obj.Type)
|
||||||
case "port":
|
errors.Dangerous(err)
|
||||||
collect := new(models.PortCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(obj.Data)
|
if err := cl.Create([]byte(obj.Data), creator); err != nil {
|
||||||
if err != nil {
|
errors.Bomb("%s add rule err %s", obj.Type, err)
|
||||||
bomb("marshal body %s err:%v", obj, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_create", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(obj.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
errors.Dangerous(models.CreateCollect(obj.Type, creator, collect))
|
|
||||||
|
|
||||||
case "proc":
|
|
||||||
collect := new(models.ProcCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(obj.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", obj, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_create", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(obj.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
errors.Dangerous(models.CreateCollect(obj.Type, creator, collect))
|
|
||||||
case "log":
|
|
||||||
collect := new(models.LogCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(obj.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", obj, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_create", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Encode()
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(obj.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
errors.Dangerous(models.CreateCollect(obj.Type, creator, collect))
|
|
||||||
case "plugin":
|
|
||||||
collect := new(models.PluginCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(obj.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", obj, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_create", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(obj.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
errors.Dangerous(models.CreateCollect(obj.Type, creator, collect))
|
|
||||||
|
|
||||||
case "api":
|
|
||||||
collect := new(models.ApiCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(obj.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", obj, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_create", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Encode()
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(obj.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
errors.Dangerous(models.CreateCollect(obj.Type, creator, collect))
|
|
||||||
|
|
||||||
default:
|
|
||||||
bomb("collect type not support")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderData(c, "ok", nil)
|
renderData(c, "ok", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectGetByEndpoint(c *gin.Context) {
|
func collectRulesGetByLocalEndpoint(c *gin.Context) {
|
||||||
collect := scache.CollectCache.GetBy(urlParamStr(c, "endpoint"))
|
collect := scache.CollectCache.GetBy(urlParamStr(c, "endpoint"))
|
||||||
renderData(c, collect, nil)
|
renderData(c, collect, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectGet(c *gin.Context) {
|
func collectRuleGet(c *gin.Context) {
|
||||||
t := mustQueryStr(c, "type")
|
t := mustQueryStr(c, "type")
|
||||||
nid := mustQueryInt64(c, "id")
|
id := mustQueryInt64(c, "id")
|
||||||
collect, err := models.GetCollectById(t, nid)
|
|
||||||
|
cl, err := collector.GetCollector(t)
|
||||||
errors.Dangerous(err)
|
errors.Dangerous(err)
|
||||||
|
|
||||||
renderData(c, collect, nil)
|
ret, err := cl.Get(id)
|
||||||
|
renderData(c, ret, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectsGet(c *gin.Context) {
|
func collectRulesGet(c *gin.Context) {
|
||||||
nid := queryInt64(c, "nid", -1)
|
nid := queryInt64(c, "nid", -1)
|
||||||
tp := queryStr(c, "type", "")
|
tp := queryStr(c, "type", "")
|
||||||
var resp []interface{}
|
var resp []interface{}
|
||||||
|
@ -222,275 +64,36 @@ func collectsGet(c *gin.Context) {
|
||||||
types = []string{tp}
|
types = []string{tp}
|
||||||
}
|
}
|
||||||
|
|
||||||
if nid == -1 && tp != "" { //没有nid参数,tp不为空
|
nids := []int64{nid}
|
||||||
if tp == "api" {
|
for _, t := range types {
|
||||||
collects, err := models.GetApiCollects()
|
cl, err := collector.GetCollector(t)
|
||||||
errors.Dangerous(err)
|
if err != nil {
|
||||||
for _, c := range collects {
|
logger.Warning(t, err)
|
||||||
c.Decode()
|
continue
|
||||||
resp = append(resp, c)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
nids := []int64{nid}
|
ret, err := cl.Gets(nids)
|
||||||
for _, t := range types {
|
if err != nil {
|
||||||
collects, err := models.GetCollectByNid(t, nids)
|
logger.Warning(t, err)
|
||||||
if err != nil {
|
continue
|
||||||
logger.Warning(t, err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
resp = append(resp, collects...)
|
|
||||||
}
|
}
|
||||||
|
resp = append(resp, ret...)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderData(c, resp, nil)
|
renderData(c, resp, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectPut(c *gin.Context) {
|
func collectRulePut(c *gin.Context) {
|
||||||
creator := loginUsername(c)
|
|
||||||
|
|
||||||
var recv CollectRecv
|
var recv CollectRecv
|
||||||
errors.Dangerous(c.ShouldBind(&recv))
|
errors.Dangerous(c.ShouldBind(&recv))
|
||||||
|
|
||||||
switch recv.Type {
|
cl, err := collector.GetCollector(recv.Type)
|
||||||
case "port":
|
errors.Dangerous(err)
|
||||||
collect := new(models.PortCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(recv.Data)
|
creator := loginUsername(c)
|
||||||
if err != nil {
|
if err := cl.Update([]byte(recv.Data), creator); err != nil {
|
||||||
bomb("marshal body %s err:%v", recv, err)
|
errors.Bomb("%s update rule err %s", recv.Type, err)
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_modify", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
//校验采集是否存在
|
|
||||||
obj, err := models.GetCollectById(recv.Type, collect.Id) //id找不到的情况
|
|
||||||
if err != nil {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpId := obj.(*models.PortCollect).Id
|
|
||||||
if tmpId == 0 {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(recv.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil && tmpId != old.(*models.PortCollect).Id {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.Dangerous(collect.Update())
|
|
||||||
renderData(c, "ok", nil)
|
|
||||||
return
|
|
||||||
case "proc":
|
|
||||||
collect := new(models.ProcCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(recv.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", recv, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_modify", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
//校验采集是否存在
|
|
||||||
obj, err := models.GetCollectById(recv.Type, collect.Id) //id找不到的情况
|
|
||||||
if err != nil {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpId := obj.(*models.ProcCollect).Id
|
|
||||||
if tmpId == 0 {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err = models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_modify", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(recv.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil && tmpId != old.(*models.ProcCollect).Id {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.Dangerous(collect.Update())
|
|
||||||
renderData(c, "ok", nil)
|
|
||||||
return
|
|
||||||
case "log":
|
|
||||||
collect := new(models.LogCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(recv.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", recv, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_modify", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Encode()
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
//校验采集是否存在
|
|
||||||
obj, err := models.GetCollectById(recv.Type, collect.Id) //id找不到的情况
|
|
||||||
if err != nil {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpId := obj.(*models.LogCollect).Id
|
|
||||||
if tmpId == 0 {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(recv.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil && tmpId != old.(*models.LogCollect).Id {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.Dangerous(collect.Update())
|
|
||||||
renderData(c, "ok", nil)
|
|
||||||
return
|
|
||||||
case "plugin":
|
|
||||||
collect := new(models.PluginCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(recv.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", recv, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_modify", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
//校验采集是否存在
|
|
||||||
obj, err := models.GetCollectById(recv.Type, collect.Id) //id找不到的情况
|
|
||||||
if err != nil {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpId := obj.(*models.PluginCollect).Id
|
|
||||||
if tmpId == 0 {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(recv.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil && tmpId != old.(*models.PluginCollect).Id {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.Dangerous(collect.Update())
|
|
||||||
renderData(c, "ok", nil)
|
|
||||||
return
|
|
||||||
case "api":
|
|
||||||
collect := new(models.ApiCollect)
|
|
||||||
|
|
||||||
b, err := json.Marshal(recv.Data)
|
|
||||||
if err != nil {
|
|
||||||
bomb("marshal body %s err:%v", recv, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = json.Unmarshal(b, collect)
|
|
||||||
if err != nil {
|
|
||||||
bomb("unmarshal body %s err:%v", string(b), err)
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_modify", collect.Nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Encode()
|
|
||||||
nid := collect.Nid
|
|
||||||
name := collect.Name
|
|
||||||
|
|
||||||
//校验采集是否存在
|
|
||||||
obj, err := models.GetCollectById(recv.Type, collect.Id) //id找不到的情况
|
|
||||||
if err != nil {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
tmpId := obj.(*models.ApiCollect).Id
|
|
||||||
if tmpId == 0 {
|
|
||||||
bomb("采集不存在 type:%s id:%d", recv.Type, collect.Id)
|
|
||||||
}
|
|
||||||
|
|
||||||
collect.Creator = creator
|
|
||||||
collect.LastUpdator = creator
|
|
||||||
|
|
||||||
old, err := models.GetCollectByNameAndNid(recv.Type, name, nid)
|
|
||||||
errors.Dangerous(err)
|
|
||||||
if old != nil && tmpId != old.(*models.ApiCollect).Id {
|
|
||||||
bomb("same stra name %s in node", name)
|
|
||||||
}
|
|
||||||
|
|
||||||
errors.Dangerous(collect.Update())
|
|
||||||
renderData(c, "ok", nil)
|
|
||||||
return
|
|
||||||
|
|
||||||
default:
|
|
||||||
bomb("采集类型不合法")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderData(c, "ok", nil)
|
renderData(c, "ok", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,89 +102,44 @@ type CollectsDelRev struct {
|
||||||
Ids []int64 `json:"ids"`
|
Ids []int64 `json:"ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectsDel(c *gin.Context) {
|
func collectsRuleDel(c *gin.Context) {
|
||||||
username := loginUsername(c)
|
|
||||||
var recv []CollectsDelRev
|
var recv []CollectsDelRev
|
||||||
errors.Dangerous(c.ShouldBind(&recv))
|
errors.Dangerous(c.ShouldBind(&recv))
|
||||||
|
|
||||||
|
username := loginUsername(c)
|
||||||
for _, obj := range recv {
|
for _, obj := range recv {
|
||||||
|
|
||||||
for i := 0; i < len(obj.Ids); i++ {
|
for i := 0; i < len(obj.Ids); i++ {
|
||||||
tmp, err := models.GetCollectById(obj.Type, obj.Ids[i]) //id找不到的情况
|
cl, err := collector.GetCollector(obj.Type)
|
||||||
if err != nil {
|
|
||||||
bomb("采集不存在 type:%s id:%d", obj.Type, obj.Ids[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
if tmp == nil {
|
|
||||||
bomb("采集不存在 type:%s id:%d", obj.Type, obj.Ids[i])
|
|
||||||
}
|
|
||||||
|
|
||||||
var nid int64
|
|
||||||
switch obj.Type {
|
|
||||||
case "log":
|
|
||||||
nid = tmp.(*models.LogCollect).Nid
|
|
||||||
case "proc":
|
|
||||||
nid = tmp.(*models.ProcCollect).Nid
|
|
||||||
case "port":
|
|
||||||
nid = tmp.(*models.PortCollect).Nid
|
|
||||||
case "plugin":
|
|
||||||
nid = tmp.(*models.PluginCollect).Nid
|
|
||||||
}
|
|
||||||
|
|
||||||
can, err := models.UsernameCandoNodeOp(loginUsername(c), "mon_collect_delete", int64(nid))
|
|
||||||
errors.Dangerous(err)
|
errors.Dangerous(err)
|
||||||
if !can {
|
|
||||||
bomb("permission deny")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(obj.Ids); i++ {
|
if err := cl.Delete(obj.Ids[i], username); err != nil {
|
||||||
switch obj.Type {
|
|
||||||
case "api":
|
|
||||||
err := models.DeleteApiCollect(obj.Ids[i])
|
|
||||||
errors.Dangerous(err)
|
|
||||||
default:
|
|
||||||
err := models.DeleteCollectById(obj.Type, username, obj.Ids[i])
|
|
||||||
errors.Dangerous(err)
|
errors.Dangerous(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
renderData(c, "ok", nil)
|
renderData(c, "ok", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiStraRev struct {
|
func collectRuleTypesGet(c *gin.Context) {
|
||||||
Sid int64 `json:"sid"`
|
category := mustQueryStr(c, "category")
|
||||||
Cid int64 `json:"cid"`
|
switch category {
|
||||||
|
case "remote":
|
||||||
|
renderData(c, collector.GetRemoteCollectors(), nil)
|
||||||
|
case "local":
|
||||||
|
renderData(c, collector.GetLocalCollectors(), nil)
|
||||||
|
default:
|
||||||
|
renderData(c, nil, nil)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type ApiStraRes struct {
|
func collectRuleTemplateGet(c *gin.Context) {
|
||||||
Has bool `json:"has"`
|
t := urlParamStr(c, "type")
|
||||||
Sid int64 `json:"sid"`
|
collector, err := collector.GetCollector(t)
|
||||||
}
|
|
||||||
|
|
||||||
func ApiStraGet(c *gin.Context) {
|
|
||||||
cid := mustQueryInt64(c, "cid")
|
|
||||||
sid, err := models.GetSidByCid(cid)
|
|
||||||
var res ApiStraRes
|
|
||||||
errors.Dangerous(err)
|
errors.Dangerous(err)
|
||||||
if sid != 0 {
|
|
||||||
res.Has = true
|
|
||||||
res.Sid = sid
|
|
||||||
}
|
|
||||||
renderData(c, res, nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func ApiStraPost(c *gin.Context) {
|
tpl, err := collector.Template()
|
||||||
recv := new(models.ApiCollectSid)
|
renderData(c, tpl, err)
|
||||||
errors.Dangerous(c.ShouldBind(&recv))
|
|
||||||
errors.Dangerous(recv.Add())
|
|
||||||
renderData(c, "ok", nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func ApiRegionGet(c *gin.Context) {
|
|
||||||
renderData(c, config.Get().Region, nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type RegExpCheckDto struct {
|
type RegExpCheckDto struct {
|
||||||
|
@ -788,3 +346,9 @@ func genSubErrMsg(sign string) string {
|
||||||
func genIllegalCharErrMsg() string {
|
func genIllegalCharErrMsg() string {
|
||||||
return fmt.Sprintf(`正则匹配成功。但是tag的key或者value包含非法字符:[:,/=\r\n\t], 请重新调整`)
|
return fmt.Sprintf(`正则匹配成功。但是tag的key或者value包含非法字符:[:,/=\r\n\t], 请重新调整`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func collectRulesGetByRemoteEndpoint(c *gin.Context) {
|
||||||
|
rules := scache.CollectRuleCache.GetBy(urlParamStr(c, "endpoint"))
|
||||||
|
renderData(c, rules, nil)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -142,22 +142,13 @@ func renderData(c *gin.Context, data interface{}, err error) {
|
||||||
renderMessage(c, err.Error())
|
renderMessage(c, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func cookieUsername(c *gin.Context) string {
|
|
||||||
uuid, err := c.Cookie("ecmc-user")
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return models.UsernameByUUID(uuid)
|
|
||||||
}
|
|
||||||
|
|
||||||
func loginUsername(c *gin.Context) string {
|
func loginUsername(c *gin.Context) string {
|
||||||
username1, has := c.Get("username")
|
username1, has := c.Get("username")
|
||||||
if has {
|
if has {
|
||||||
return username1.(string)
|
return username1.(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
username2 := cookieUsername(c)
|
username2 := sessionUsername(c)
|
||||||
if username2 == "" {
|
if username2 == "" {
|
||||||
bomb("unauthorized")
|
bomb("unauthorized")
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,7 +129,7 @@ func effectiveStrasGet(c *gin.Context) {
|
||||||
if queryInt(c, "all", 0) == 1 {
|
if queryInt(c, "all", 0) == 1 {
|
||||||
stras = scache.StraCache.GetAll()
|
stras = scache.StraCache.GetAll()
|
||||||
} else if instance != "" {
|
} else if instance != "" {
|
||||||
node, err := scache.ActiveNode.GetNodeBy(instance)
|
node, err := scache.ActiveJudgeNode.GetNodeBy(instance)
|
||||||
errors.Dangerous(err)
|
errors.Dangerous(err)
|
||||||
|
|
||||||
stras = scache.StraCache.GetByNode(node)
|
stras = scache.StraCache.GetByNode(node)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/didi/nightingale/src/modules/monapi/scache"
|
"github.com/didi/nightingale/src/modules/monapi/scache"
|
||||||
"github.com/didi/nightingale/src/toolkits/i18n"
|
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||||
|
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/all"
|
||||||
_ "github.com/go-sql-driver/mysql"
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
|
||||||
"github.com/toolkits/pkg/cache"
|
"github.com/toolkits/pkg/cache"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
prometheus/
|
|
@ -0,0 +1,16 @@
|
||||||
|
package all
|
||||||
|
|
||||||
|
import (
|
||||||
|
// remote
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/api"
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/github"
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/mysql"
|
||||||
|
// _ "github.com/didi/nightingale/src/modules/monapi/plugins/prometheus"
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/redis"
|
||||||
|
|
||||||
|
// local
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/log"
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/plugin"
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/port"
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/proc"
|
||||||
|
)
|
|
@ -0,0 +1,147 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(&ApiCollector{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type ApiCollector struct{}
|
||||||
|
|
||||||
|
func (p ApiCollector) Name() string { return "api" }
|
||||||
|
func (p ApiCollector) Category() collector.Category { return collector.RemoteCategory }
|
||||||
|
func (p ApiCollector) Template() (interface{}, error) { return nil, nil }
|
||||||
|
func (p ApiCollector) TelegrafInput(*models.CollectRule) (telegraf.Input, error) {
|
||||||
|
return nil, errors.New("unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ApiCollector) Get(id int64) (interface{}, error) {
|
||||||
|
collect := new(models.ApiCollect)
|
||||||
|
has, err := models.DB["mon"].Where("id = ?", id).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ApiCollector) Gets(nids []int64) (ret []interface{}, err error) {
|
||||||
|
collects := []models.ApiCollect{}
|
||||||
|
err = models.DB["mon"].In("nid", nids).Find(&collects)
|
||||||
|
for _, c := range collects {
|
||||||
|
c.Decode()
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ApiCollector) GetByNameAndNid(name string, nid int64) (interface{}, error) {
|
||||||
|
collect := new(models.ApiCollect)
|
||||||
|
has, err := models.DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ApiCollector) Create(data []byte, username string) error {
|
||||||
|
collect := new(models.ApiCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_create", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Encode()
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
return models.CreateCollect(p.Name(), username, collect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ApiCollector) Update(data []byte, username string) error {
|
||||||
|
collect := new(models.ApiCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_modify", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Encode()
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
//校验采集是否存在
|
||||||
|
obj, err := p.Get(collect.Id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpId := obj.(*models.ApiCollect).Id
|
||||||
|
if tmpId == 0 {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil && tmpId != old.(*models.ApiCollect).Id {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return collect.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ApiCollector) Delete(id int64, username string) error {
|
||||||
|
tmp, err := p.Get(id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), id)
|
||||||
|
}
|
||||||
|
nid := tmp.(*models.ApiCollect).Nid
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_delete", int64(nid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.DeleteCollectById(p.Name(), username, id)
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
# GitHub Input Plugin
|
||||||
|
|
||||||
|
Gather repository information from [GitHub][] hosted repositories.
|
||||||
|
|
||||||
|
**Note:** Telegraf also contains the [webhook][] input which can be used as an
|
||||||
|
alternative method for collecting repository information.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[inputs.github]]
|
||||||
|
## List of repositories to monitor
|
||||||
|
repositories = [
|
||||||
|
"influxdata/telegraf",
|
||||||
|
"influxdata/influxdb"
|
||||||
|
]
|
||||||
|
|
||||||
|
## Github API access token. Unauthenticated requests are limited to 60 per hour.
|
||||||
|
# access_token = ""
|
||||||
|
|
||||||
|
## Github API enterprise url. Github Enterprise accounts must specify their base url.
|
||||||
|
# enterprise_base_url = ""
|
||||||
|
|
||||||
|
## Timeout for HTTP requests.
|
||||||
|
# http_timeout = "5s"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Metrics
|
||||||
|
|
||||||
|
- github_repository
|
||||||
|
- tags:
|
||||||
|
- name - The repository name
|
||||||
|
- owner - The owner of the repository
|
||||||
|
- language - The primary language of the repository
|
||||||
|
- license - The license set for the repository
|
||||||
|
- fields:
|
||||||
|
- forks (int)
|
||||||
|
- open_issues (int)
|
||||||
|
- networks (int)
|
||||||
|
- size (int)
|
||||||
|
- subscribers (int)
|
||||||
|
- stars (int)
|
||||||
|
- watchers (int)
|
||||||
|
|
||||||
|
When the [internal][] input is enabled:
|
||||||
|
|
||||||
|
+ internal_github
|
||||||
|
- tags:
|
||||||
|
- access_token - An obfuscated reference to the configured access token or "Unauthenticated"
|
||||||
|
- fields:
|
||||||
|
- limit - How many requests you are limited to (per hour)
|
||||||
|
- remaining - How many requests you have remaining (per hour)
|
||||||
|
- blocks - How many requests have been blocked due to rate limit
|
||||||
|
|
||||||
|
### Example Output
|
||||||
|
|
||||||
|
```
|
||||||
|
github_repository,language=Go,license=MIT\ License,name=telegraf,owner=influxdata forks=2679i,networks=2679i,open_issues=794i,size=23263i,stars=7091i,subscribers=316i,watchers=7091i 1563901372000000000
|
||||||
|
internal_github,access_token=Unauthenticated rate_limit_remaining=59i,rate_limit_limit=60i,rate_limit_blocks=0i 1552653551000000000
|
||||||
|
```
|
||||||
|
|
||||||
|
[GitHub]: https://www.github.com
|
||||||
|
[internal]: /plugins/inputs/internal
|
||||||
|
[webhook]: /plugins/inputs/webhooks/github
|
|
@ -0,0 +1,55 @@
|
||||||
|
package github
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(NewGitHubCollector()) // for monapi
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitHubCollector struct {
|
||||||
|
*collector.BaseCollector
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewGitHubCollector() *GitHubCollector {
|
||||||
|
return &GitHubCollector{BaseCollector: collector.NewBaseCollector(
|
||||||
|
"github",
|
||||||
|
collector.RemoteCategory,
|
||||||
|
func() interface{} { return &GitHubRule{} },
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type GitHubRule struct {
|
||||||
|
Repositories []string `label:"Repositories" json:"repositories" description:"List of repositories to monitor"`
|
||||||
|
AccessToken string `label:"Access token" json:"access_token" description:"Github API access token. Unauthenticated requests are limited to 60 per hour"`
|
||||||
|
EnterpriseBaseURL string `label:"Enterprise base url" json:"enterprise_base_url" description:"Github API enterprise url. Github Enterprise accounts must specify their base url"`
|
||||||
|
HTTPTimeout int `label:"HTTP timeout" json:"http_timeout" description:"Timeout for HTTP requests"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GitHubRule) Validate() error {
|
||||||
|
if len(p.Repositories) == 0 || p.Repositories[0] == "" {
|
||||||
|
return fmt.Errorf("github.rule.repositories must be set")
|
||||||
|
}
|
||||||
|
if p.HTTPTimeout == 0 {
|
||||||
|
p.HTTPTimeout = 5
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *GitHubRule) TelegrafInput() (telegraf.Input, error) {
|
||||||
|
if err := p.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &GitHub{
|
||||||
|
Repositories: p.Repositories,
|
||||||
|
AccessToken: p.AccessToken,
|
||||||
|
EnterpriseBaseURL: p.EnterpriseBaseURL,
|
||||||
|
HTTPTimeout: time.Second * time.Duration(p.HTTPTimeout),
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,200 @@
|
||||||
|
package github
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/google/go-github/v32/github"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/selfstat"
|
||||||
|
"golang.org/x/oauth2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GitHub - plugin main structure
|
||||||
|
type GitHub struct {
|
||||||
|
Repositories []string `toml:"repositories"`
|
||||||
|
AccessToken string `toml:"access_token"`
|
||||||
|
EnterpriseBaseURL string `toml:"enterprise_base_url"`
|
||||||
|
HTTPTimeout time.Duration `toml:"http_timeout"`
|
||||||
|
githubClient *github.Client
|
||||||
|
|
||||||
|
obfuscatedToken string
|
||||||
|
|
||||||
|
RateLimit selfstat.Stat
|
||||||
|
RateLimitErrors selfstat.Stat
|
||||||
|
RateRemaining selfstat.Stat
|
||||||
|
}
|
||||||
|
|
||||||
|
const sampleConfig = `
|
||||||
|
## List of repositories to monitor.
|
||||||
|
repositories = [
|
||||||
|
"influxdata/telegraf",
|
||||||
|
"influxdata/influxdb"
|
||||||
|
]
|
||||||
|
|
||||||
|
## Github API access token. Unauthenticated requests are limited to 60 per hour.
|
||||||
|
# access_token = ""
|
||||||
|
|
||||||
|
## Github API enterprise url. Github Enterprise accounts must specify their base url.
|
||||||
|
# enterprise_base_url = ""
|
||||||
|
|
||||||
|
## Timeout for HTTP requests.
|
||||||
|
# http_timeout = "5s"
|
||||||
|
`
|
||||||
|
|
||||||
|
// SampleConfig returns sample configuration for this plugin.
|
||||||
|
func (g *GitHub) SampleConfig() string {
|
||||||
|
return sampleConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// Description returns the plugin description.
|
||||||
|
func (g *GitHub) Description() string {
|
||||||
|
return "Gather repository information from GitHub hosted repositories."
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create GitHub Client
|
||||||
|
func (g *GitHub) createGitHubClient(ctx context.Context) (*github.Client, error) {
|
||||||
|
httpClient := &http.Client{
|
||||||
|
Transport: &http.Transport{
|
||||||
|
Proxy: http.ProxyFromEnvironment,
|
||||||
|
},
|
||||||
|
Timeout: g.HTTPTimeout,
|
||||||
|
}
|
||||||
|
|
||||||
|
g.obfuscatedToken = "Unauthenticated"
|
||||||
|
|
||||||
|
if g.AccessToken != "" {
|
||||||
|
tokenSource := oauth2.StaticTokenSource(
|
||||||
|
&oauth2.Token{AccessToken: g.AccessToken},
|
||||||
|
)
|
||||||
|
oauthClient := oauth2.NewClient(ctx, tokenSource)
|
||||||
|
_ = context.WithValue(ctx, oauth2.HTTPClient, oauthClient)
|
||||||
|
|
||||||
|
g.obfuscatedToken = g.AccessToken[0:4] + "..." + g.AccessToken[len(g.AccessToken)-3:]
|
||||||
|
|
||||||
|
return g.newGithubClient(oauthClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
return g.newGithubClient(httpClient)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GitHub) newGithubClient(httpClient *http.Client) (*github.Client, error) {
|
||||||
|
if g.EnterpriseBaseURL != "" {
|
||||||
|
return github.NewEnterpriseClient(g.EnterpriseBaseURL, "", httpClient)
|
||||||
|
}
|
||||||
|
return github.NewClient(httpClient), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gather GitHub Metrics
|
||||||
|
func (g *GitHub) Gather(acc telegraf.Accumulator) error {
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
|
if g.githubClient == nil {
|
||||||
|
githubClient, err := g.createGitHubClient(ctx)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
g.githubClient = githubClient
|
||||||
|
|
||||||
|
tokenTags := map[string]string{
|
||||||
|
"access_token": g.obfuscatedToken,
|
||||||
|
}
|
||||||
|
|
||||||
|
g.RateLimitErrors = selfstat.Register("github", "rate_limit_blocks", tokenTags)
|
||||||
|
g.RateLimit = selfstat.Register("github", "rate_limit_limit", tokenTags)
|
||||||
|
g.RateRemaining = selfstat.Register("github", "rate_limit_remaining", tokenTags)
|
||||||
|
}
|
||||||
|
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(len(g.Repositories))
|
||||||
|
|
||||||
|
for _, repository := range g.Repositories {
|
||||||
|
go func(repositoryName string, acc telegraf.Accumulator) {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
owner, repository, err := splitRepositoryName(repositoryName)
|
||||||
|
if err != nil {
|
||||||
|
acc.AddError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
repositoryInfo, response, err := g.githubClient.Repositories.Get(ctx, owner, repository)
|
||||||
|
|
||||||
|
if _, ok := err.(*github.RateLimitError); ok {
|
||||||
|
g.RateLimitErrors.Incr(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
acc.AddError(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
g.RateLimit.Set(int64(response.Rate.Limit))
|
||||||
|
g.RateRemaining.Set(int64(response.Rate.Remaining))
|
||||||
|
|
||||||
|
now := time.Now()
|
||||||
|
tags := getTags(repositoryInfo)
|
||||||
|
fields := getFields(repositoryInfo)
|
||||||
|
|
||||||
|
acc.AddFields("github_repository", fields, tags, now)
|
||||||
|
}(repository, acc)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func splitRepositoryName(repositoryName string) (string, string, error) {
|
||||||
|
splits := strings.SplitN(repositoryName, "/", 2)
|
||||||
|
|
||||||
|
if len(splits) != 2 {
|
||||||
|
return "", "", fmt.Errorf("%v is not of format 'owner/repository'", repositoryName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return splits[0], splits[1], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getLicense(rI *github.Repository) string {
|
||||||
|
if licenseName := rI.GetLicense().GetName(); licenseName != "" {
|
||||||
|
return licenseName
|
||||||
|
}
|
||||||
|
|
||||||
|
return "None"
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTags(repositoryInfo *github.Repository) map[string]string {
|
||||||
|
return map[string]string{
|
||||||
|
"owner": repositoryInfo.GetOwner().GetLogin(),
|
||||||
|
"name": repositoryInfo.GetName(),
|
||||||
|
"language": repositoryInfo.GetLanguage(),
|
||||||
|
"license": getLicense(repositoryInfo),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFields(repositoryInfo *github.Repository) map[string]interface{} {
|
||||||
|
return map[string]interface{}{
|
||||||
|
"stars": repositoryInfo.GetStargazersCount(),
|
||||||
|
"subscribers": repositoryInfo.GetSubscribersCount(),
|
||||||
|
"watchers": repositoryInfo.GetWatchersCount(),
|
||||||
|
"networks": repositoryInfo.GetNetworkCount(),
|
||||||
|
"forks": repositoryInfo.GetForksCount(),
|
||||||
|
"open_issues": repositoryInfo.GetOpenIssuesCount(),
|
||||||
|
"size": repositoryInfo.GetSize(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func init() {
|
||||||
|
inputs.Add("github", func() telegraf.Input {
|
||||||
|
return &GitHub{
|
||||||
|
HTTPTimeout: time.Second * 5,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,140 @@
|
||||||
|
package github
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
gh "github.com/google/go-github/v32/github"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestNewGithubClient(t *testing.T) {
|
||||||
|
httpClient := &http.Client{}
|
||||||
|
g := &GitHub{}
|
||||||
|
client, err := g.newGithubClient(httpClient)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Contains(t, client.BaseURL.String(), "api.github.com")
|
||||||
|
g.EnterpriseBaseURL = "api.example.com/"
|
||||||
|
enterpriseClient, err := g.newGithubClient(httpClient)
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Contains(t, enterpriseClient.BaseURL.String(), "api.example.com")
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSplitRepositoryNameWithWorkingExample(t *testing.T) {
|
||||||
|
var validRepositoryNames = []struct {
|
||||||
|
fullName string
|
||||||
|
owner string
|
||||||
|
repository string
|
||||||
|
}{
|
||||||
|
{"influxdata/telegraf", "influxdata", "telegraf"},
|
||||||
|
{"influxdata/influxdb", "influxdata", "influxdb"},
|
||||||
|
{"rawkode/saltstack-dotfiles", "rawkode", "saltstack-dotfiles"},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range validRepositoryNames {
|
||||||
|
t.Run(tt.fullName, func(t *testing.T) {
|
||||||
|
owner, repository, _ := splitRepositoryName(tt.fullName)
|
||||||
|
|
||||||
|
require.Equal(t, tt.owner, owner)
|
||||||
|
require.Equal(t, tt.repository, repository)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSplitRepositoryNameWithNoSlash(t *testing.T) {
|
||||||
|
var invalidRepositoryNames = []string{
|
||||||
|
"influxdata-influxdb",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range invalidRepositoryNames {
|
||||||
|
t.Run(tt, func(t *testing.T) {
|
||||||
|
_, _, err := splitRepositoryName(tt)
|
||||||
|
|
||||||
|
require.Error(t, err)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetLicenseWhenExists(t *testing.T) {
|
||||||
|
licenseName := "MIT"
|
||||||
|
license := gh.License{Name: &licenseName}
|
||||||
|
repository := gh.Repository{License: &license}
|
||||||
|
|
||||||
|
getLicenseReturn := getLicense(&repository)
|
||||||
|
|
||||||
|
require.Equal(t, "MIT", getLicenseReturn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetLicenseWhenMissing(t *testing.T) {
|
||||||
|
repository := gh.Repository{}
|
||||||
|
|
||||||
|
getLicenseReturn := getLicense(&repository)
|
||||||
|
|
||||||
|
require.Equal(t, "None", getLicenseReturn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetTags(t *testing.T) {
|
||||||
|
licenseName := "MIT"
|
||||||
|
license := gh.License{Name: &licenseName}
|
||||||
|
|
||||||
|
ownerName := "influxdata"
|
||||||
|
owner := gh.User{Login: &ownerName}
|
||||||
|
|
||||||
|
fullName := "influxdata/influxdb"
|
||||||
|
repositoryName := "influxdb"
|
||||||
|
|
||||||
|
language := "Go"
|
||||||
|
|
||||||
|
repository := gh.Repository{
|
||||||
|
FullName: &fullName,
|
||||||
|
Name: &repositoryName,
|
||||||
|
License: &license,
|
||||||
|
Owner: &owner,
|
||||||
|
Language: &language,
|
||||||
|
}
|
||||||
|
|
||||||
|
getTagsReturn := getTags(&repository)
|
||||||
|
|
||||||
|
correctTagsReturn := map[string]string{
|
||||||
|
"owner": ownerName,
|
||||||
|
"name": repositoryName,
|
||||||
|
"language": language,
|
||||||
|
"license": licenseName,
|
||||||
|
}
|
||||||
|
|
||||||
|
require.Equal(t, true, reflect.DeepEqual(getTagsReturn, correctTagsReturn))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetFields(t *testing.T) {
|
||||||
|
stars := 1
|
||||||
|
forks := 2
|
||||||
|
openIssues := 3
|
||||||
|
size := 4
|
||||||
|
subscribers := 5
|
||||||
|
watchers := 6
|
||||||
|
|
||||||
|
repository := gh.Repository{
|
||||||
|
StargazersCount: &stars,
|
||||||
|
ForksCount: &forks,
|
||||||
|
OpenIssuesCount: &openIssues,
|
||||||
|
Size: &size,
|
||||||
|
NetworkCount: &forks,
|
||||||
|
SubscribersCount: &subscribers,
|
||||||
|
WatchersCount: &watchers,
|
||||||
|
}
|
||||||
|
|
||||||
|
getFieldsReturn := getFields(&repository)
|
||||||
|
|
||||||
|
correctFieldReturn := make(map[string]interface{})
|
||||||
|
|
||||||
|
correctFieldReturn["stars"] = 1
|
||||||
|
correctFieldReturn["forks"] = 2
|
||||||
|
correctFieldReturn["networks"] = 2
|
||||||
|
correctFieldReturn["open_issues"] = 3
|
||||||
|
correctFieldReturn["size"] = 4
|
||||||
|
correctFieldReturn["subscribers"] = 5
|
||||||
|
correctFieldReturn["watchers"] = 6
|
||||||
|
|
||||||
|
require.Equal(t, true, reflect.DeepEqual(getFieldsReturn, correctFieldReturn))
|
||||||
|
}
|
|
@ -0,0 +1,147 @@
|
||||||
|
package log
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(&LogCollector{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogCollector struct{}
|
||||||
|
|
||||||
|
func (p LogCollector) Name() string { return "log" }
|
||||||
|
func (p LogCollector) Category() collector.Category { return collector.LocalCategory }
|
||||||
|
func (p LogCollector) Template() (interface{}, error) { return nil, nil }
|
||||||
|
func (p LogCollector) TelegrafInput(*models.CollectRule) (telegraf.Input, error) {
|
||||||
|
return nil, errors.New("unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p LogCollector) Get(id int64) (interface{}, error) {
|
||||||
|
collect := new(models.LogCollect)
|
||||||
|
has, err := models.DB["mon"].Where("id = ?", id).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p LogCollector) Gets(nids []int64) (ret []interface{}, err error) {
|
||||||
|
collects := []models.LogCollect{}
|
||||||
|
err = models.DB["mon"].In("nid", nids).Find(&collects)
|
||||||
|
for _, c := range collects {
|
||||||
|
c.Decode()
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p LogCollector) GetByNameAndNid(name string, nid int64) (interface{}, error) {
|
||||||
|
collect := new(models.LogCollect)
|
||||||
|
has, err := models.DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p LogCollector) Create(data []byte, username string) error {
|
||||||
|
collector := new(models.LogCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collector)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_create", collector.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collector.Encode()
|
||||||
|
collector.Creator = username
|
||||||
|
collector.LastUpdator = username
|
||||||
|
|
||||||
|
nid := collector.Nid
|
||||||
|
name := collector.Name
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
return models.CreateCollect(p.Name(), username, collector)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p LogCollector) Update(data []byte, username string) error {
|
||||||
|
collector := new(models.LogCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collector)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_modify", collector.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collector.Encode()
|
||||||
|
nid := collector.Nid
|
||||||
|
name := collector.Name
|
||||||
|
|
||||||
|
//校验采集是否存在
|
||||||
|
obj, err := p.Get(collector.Id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collector.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpId := obj.(*models.LogCollect).Id
|
||||||
|
if tmpId == 0 {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collector.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
collector.Creator = username
|
||||||
|
collector.LastUpdator = username
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil && tmpId != old.(*models.LogCollect).Id {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return collector.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p LogCollector) Delete(id int64, username string) error {
|
||||||
|
tmp, err := p.Get(id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), id)
|
||||||
|
}
|
||||||
|
nid := tmp.(*models.LogCollect).Nid
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_delete", int64(nid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.DeleteCollectById(p.Name(), username, id)
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(NewRedisCollector()) // for monapi
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisCollector struct {
|
||||||
|
*collector.BaseCollector
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRedisCollector() *RedisCollector {
|
||||||
|
return &RedisCollector{BaseCollector: collector.NewBaseCollector(
|
||||||
|
"redis",
|
||||||
|
collector.RemoteCategory,
|
||||||
|
func() interface{} { return &RedisRule{} },
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisRule struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RedisRule) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RedisRule) TelegrafInput() (telegraf.Input, error) {
|
||||||
|
if err := p.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &redis.Redis{}, nil
|
||||||
|
}
|
|
@ -0,0 +1,86 @@
|
||||||
|
package mysql
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs/mysql"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(NewMysqlCollector()) // for monapi
|
||||||
|
}
|
||||||
|
|
||||||
|
type MysqlCollector struct {
|
||||||
|
*collector.BaseCollector
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMysqlCollector() *MysqlCollector {
|
||||||
|
return &MysqlCollector{BaseCollector: collector.NewBaseCollector(
|
||||||
|
"mysql",
|
||||||
|
collector.RemoteCategory,
|
||||||
|
func() interface{} { return &MysqlRule{} },
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type MysqlRule struct {
|
||||||
|
Servers []string `label:"Servers" json:"servers,required" description:"specify servers via a url matching\n[username[:password]@][protocol[(address)]]/[?tls=[true|false|skip-verify|custom]]\nsee https://github.com/go-sql-driver/mysql#dsn-data-source-name" example:"servers = ['user:passwd@tcp(127.0.0.1:3306)/?tls=false']\nservers = ["user@tcp(127.0.0.1:3306)/?tls=false"]"`
|
||||||
|
PerfEventsStatementsDigestTextLimit int64 `label:"-" json:"-"`
|
||||||
|
PerfEventsStatementsLimit int64 `label:"-" json:"-"`
|
||||||
|
PerfEventsStatementsTimeLimit int64 `label:"-" json:"-"`
|
||||||
|
TableSchemaDatabases []string `label:"Databases" json:"table_schema_databases" description:"if the list is empty, then metrics are gathered from all database tables"`
|
||||||
|
GatherProcessList bool `label:"Process List" json:"gather_process_list" description:"gather thread state counts from INFORMATION_SCHEMA.PROCESSLIST"`
|
||||||
|
GatherUserStatistics bool `label:"User Statistics" json:"gather_user_statistics" description:"gather user statistics from INFORMATION_SCHEMA.USER_STATISTICS"`
|
||||||
|
GatherInfoSchemaAutoInc bool `label:"Auto Increment" json:"gather_info_schema_auto_inc" description:"gather auto_increment columns and max values from information schema"`
|
||||||
|
GatherInnoDBMetrics bool `label:"Innodb Metrics" json:"gather_innodb_metrics" description:"gather metrics from INFORMATION_SCHEMA.INNODB_METRICS"`
|
||||||
|
GatherSlaveStatus bool `label:"Slave Status" json:"gather_slave_status" description:"gather metrics from SHOW SLAVE STATUS command output"`
|
||||||
|
GatherBinaryLogs bool `label:"Binary Logs" json:"gather_binary_logs" description:"gather metrics from SHOW BINARY LOGS command output"`
|
||||||
|
GatherTableIOWaits bool `label:"Table IO Waits" json:"gather_table_io_waits" description:"gather metrics from PERFORMANCE_SCHEMA.TABLE_IO_WAITS_SUMMARY_BY_TABLE"`
|
||||||
|
GatherTableLockWaits bool `label:"Table Lock Waits" json:"gather_table_lock_waits" description:"gather metrics from PERFORMANCE_SCHEMA.TABLE_LOCK_WAITS"`
|
||||||
|
GatherIndexIOWaits bool `label:"Index IO Waits" json:"gather_index_io_waits" description:"gather metrics from PERFORMANCE_SCHEMA.TABLE_IO_WAITS_SUMMARY_BY_INDEX_USAGE"`
|
||||||
|
GatherEventWaits bool `label:"Event Waits" json:"gather_event_waits" description:"gather metrics from PERFORMANCE_SCHEMA.EVENT_WAITS"`
|
||||||
|
GatherTableSchema bool `label:"Tables" json:"gather_table_schema" description:"gather metrics from INFORMATION_SCHEMA.TABLES for databases provided above list"`
|
||||||
|
GatherFileEventsStats bool `label:"File Events Stats" json:"gather_file_events_stats" description:"gather metrics from PERFORMANCE_SCHEMA.FILE_SUMMARY_BY_EVENT_NAME"`
|
||||||
|
GatherPerfEventsStatements bool `label:"Perf Events Statements" json:"gather_perf_events_statements" description:"gather metrics from PERFORMANCE_SCHEMA.EVENTS_STATEMENTS_SUMMARY_BY_DIGEST"`
|
||||||
|
GatherGlobalVars bool `label:"-" json:"-"`
|
||||||
|
IntervalSlow string `label:"Interval Slow" json:"interval_slow" desc:"Some queries we may want to run less often (such as SHOW GLOBAL VARIABLES)" example:"interval_slow = '30m'" json:"-"`
|
||||||
|
MetricVersion int `label:"-" json:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MysqlRule) Validate() error {
|
||||||
|
if len(p.Servers) == 0 || p.Servers[0] == "" {
|
||||||
|
return fmt.Errorf("mysql.rule.servers must be set")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MysqlRule) TelegrafInput() (telegraf.Input, error) {
|
||||||
|
if err := p.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mysql.Mysql{
|
||||||
|
Servers: p.Servers,
|
||||||
|
PerfEventsStatementsDigestTextLimit: 120,
|
||||||
|
PerfEventsStatementsLimit: 250,
|
||||||
|
PerfEventsStatementsTimeLimit: 86400,
|
||||||
|
TableSchemaDatabases: p.TableSchemaDatabases,
|
||||||
|
GatherProcessList: p.GatherProcessList,
|
||||||
|
GatherUserStatistics: p.GatherUserStatistics,
|
||||||
|
GatherInfoSchemaAutoInc: p.GatherInfoSchemaAutoInc,
|
||||||
|
GatherInnoDBMetrics: p.GatherInnoDBMetrics,
|
||||||
|
GatherSlaveStatus: p.GatherSlaveStatus,
|
||||||
|
GatherBinaryLogs: p.GatherBinaryLogs,
|
||||||
|
GatherTableIOWaits: p.GatherTableIOWaits,
|
||||||
|
GatherTableLockWaits: p.GatherTableLockWaits,
|
||||||
|
GatherIndexIOWaits: p.GatherIndexIOWaits,
|
||||||
|
GatherEventWaits: p.GatherEventWaits,
|
||||||
|
GatherTableSchema: p.GatherTableSchema,
|
||||||
|
GatherFileEventsStats: p.GatherFileEventsStats,
|
||||||
|
GatherPerfEventsStatements: p.GatherPerfEventsStatements,
|
||||||
|
GatherGlobalVars: true,
|
||||||
|
IntervalSlow: "0m",
|
||||||
|
MetricVersion: 2,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(&PluginCollector{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginCollector struct{}
|
||||||
|
|
||||||
|
func (p PluginCollector) Name() string { return "plugin" }
|
||||||
|
func (p PluginCollector) Category() collector.Category { return collector.LocalCategory }
|
||||||
|
func (p PluginCollector) Template() (interface{}, error) { return nil, nil }
|
||||||
|
func (p PluginCollector) TelegrafInput(*models.CollectRule) (telegraf.Input, error) {
|
||||||
|
return nil, errors.New("unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PluginCollector) Get(id int64) (interface{}, error) {
|
||||||
|
collect := new(models.PluginCollect)
|
||||||
|
has, err := models.DB["mon"].Where("id = ?", id).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PluginCollector) Gets(nids []int64) (ret []interface{}, err error) {
|
||||||
|
collects := []models.PluginCollect{}
|
||||||
|
err = models.DB["mon"].In("nid", nids).Find(&collects)
|
||||||
|
for _, c := range collects {
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PluginCollector) GetByNameAndNid(name string, nid int64) (interface{}, error) {
|
||||||
|
collect := new(models.PluginCollect)
|
||||||
|
has, err := models.DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PluginCollector) Create(data []byte, username string) error {
|
||||||
|
collect := new(models.PluginCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_create", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
return models.CreateCollect(p.Name(), username, collect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PluginCollector) Update(data []byte, username string) error {
|
||||||
|
collect := new(models.PluginCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_modify", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
//校验采集是否存在
|
||||||
|
obj, err := p.Get(collect.Id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpId := obj.(*models.PluginCollect).Id
|
||||||
|
if tmpId == 0 {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil && tmpId != old.(*models.PluginCollect).Id {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return collect.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PluginCollector) Delete(id int64, username string) error {
|
||||||
|
tmp, err := p.Get(id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), id)
|
||||||
|
}
|
||||||
|
nid := tmp.(*models.PluginCollect).Nid
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_delete", int64(nid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.DeleteCollectById(p.Name(), username, id)
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(&PortCollector{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type PortCollector struct{}
|
||||||
|
|
||||||
|
func (p PortCollector) Name() string { return "port" }
|
||||||
|
func (p PortCollector) Category() collector.Category { return collector.LocalCategory }
|
||||||
|
func (p PortCollector) Template() (interface{}, error) { return nil, nil }
|
||||||
|
func (p PortCollector) TelegrafInput(*models.CollectRule) (telegraf.Input, error) {
|
||||||
|
return nil, errors.New("unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PortCollector) Get(id int64) (interface{}, error) {
|
||||||
|
collect := new(models.PortCollect)
|
||||||
|
has, err := models.DB["mon"].Where("id = ?", id).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PortCollector) Gets(nids []int64) (ret []interface{}, err error) {
|
||||||
|
collects := []models.PortCollect{}
|
||||||
|
err = models.DB["mon"].In("nid", nids).Find(&collects)
|
||||||
|
for _, c := range collects {
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PortCollector) GetByNameAndNid(name string, nid int64) (interface{}, error) {
|
||||||
|
collect := new(models.PortCollect)
|
||||||
|
has, err := models.DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PortCollector) Create(data []byte, username string) error {
|
||||||
|
collect := new(models.PortCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_create", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
return models.CreateCollect(p.Name(), username, collect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PortCollector) Update(data []byte, username string) error {
|
||||||
|
collect := new(models.PortCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_modify", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
//校验采集是否存在
|
||||||
|
obj, err := p.Get(collect.Id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpId := obj.(*models.PortCollect).Id
|
||||||
|
if tmpId == 0 {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil && tmpId != old.(*models.PortCollect).Id {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return collect.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p PortCollector) Delete(id int64, username string) error {
|
||||||
|
tmp, err := p.Get(id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), id)
|
||||||
|
}
|
||||||
|
nid := tmp.(*models.PortCollect).Nid
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_delete", int64(nid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.DeleteCollectById(p.Name(), username, id)
|
||||||
|
}
|
|
@ -0,0 +1,144 @@
|
||||||
|
package collector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(&ProcCollector{})
|
||||||
|
}
|
||||||
|
|
||||||
|
type ProcCollector struct{}
|
||||||
|
|
||||||
|
func (p ProcCollector) Name() string { return "proc" }
|
||||||
|
func (p ProcCollector) Category() collector.Category { return collector.LocalCategory }
|
||||||
|
func (p ProcCollector) Template() (interface{}, error) { return nil, nil }
|
||||||
|
func (p ProcCollector) TelegrafInput(*models.CollectRule) (telegraf.Input, error) {
|
||||||
|
return nil, errors.New("unsupported")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ProcCollector) Get(id int64) (interface{}, error) {
|
||||||
|
collect := new(models.ProcCollect)
|
||||||
|
has, err := models.DB["mon"].Where("id = ?", id).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ProcCollector) Gets(nids []int64) (ret []interface{}, err error) {
|
||||||
|
collects := []models.ProcCollect{}
|
||||||
|
err = models.DB["mon"].In("nid", nids).Find(&collects)
|
||||||
|
for _, c := range collects {
|
||||||
|
ret = append(ret, c)
|
||||||
|
}
|
||||||
|
return ret, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ProcCollector) GetByNameAndNid(name string, nid int64) (interface{}, error) {
|
||||||
|
collect := new(models.ProcCollect)
|
||||||
|
has, err := models.DB["mon"].Where("name = ? and nid = ?", name, nid).Get(collect)
|
||||||
|
if !has {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return collect, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ProcCollector) Create(data []byte, username string) error {
|
||||||
|
collect := new(models.ProcCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_create", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
return models.CreateCollect(p.Name(), username, collect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ProcCollector) Update(data []byte, username string) error {
|
||||||
|
collect := new(models.ProcCollect)
|
||||||
|
|
||||||
|
err := json.Unmarshal(data, collect)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("unmarshal body %s err:%v", string(data), err)
|
||||||
|
}
|
||||||
|
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_modify", collect.Nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
nid := collect.Nid
|
||||||
|
name := collect.Name
|
||||||
|
|
||||||
|
//校验采集是否存在
|
||||||
|
obj, err := p.Get(collect.Id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpId := obj.(*models.ProcCollect).Id
|
||||||
|
if tmpId == 0 {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), collect.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
collect.Creator = username
|
||||||
|
collect.LastUpdator = username
|
||||||
|
|
||||||
|
old, err := p.GetByNameAndNid(name, nid)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if old != nil && tmpId != old.(*models.ProcCollect).Id {
|
||||||
|
return fmt.Errorf("同节点下策略名称 %s 已存在", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return collect.Update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p ProcCollector) Delete(id int64, username string) error {
|
||||||
|
tmp, err := p.Get(id) //id找不到的情况
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("采集不存在 type:%s id:%d", p.Name(), id)
|
||||||
|
}
|
||||||
|
nid := tmp.(*models.ProcCollect).Nid
|
||||||
|
can, err := models.UsernameCandoNodeOp(username, "mon_collect_delete", int64(nid))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if !can {
|
||||||
|
return fmt.Errorf("permission deny")
|
||||||
|
}
|
||||||
|
|
||||||
|
return models.DeleteCollectById(p.Name(), username, id)
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/influxdata/telegraf/plugins/inputs/redis"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
collector.CollectorRegister(NewRedisCollector()) // for monapi
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisCollector struct {
|
||||||
|
*collector.BaseCollector
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRedisCollector() *RedisCollector {
|
||||||
|
return &RedisCollector{BaseCollector: collector.NewBaseCollector(
|
||||||
|
"redis",
|
||||||
|
collector.RemoteCategory,
|
||||||
|
func() interface{} { return &RedisRule{} },
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisCommand struct {
|
||||||
|
Command []string `label:"Command" json:"command,required" description:"" `
|
||||||
|
Field string `label:"Field" json:"field,required" description:"metric name"`
|
||||||
|
Type string `label:"Type" json:"type" description:"integer|string|float"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RedisRule struct {
|
||||||
|
Servers []string `label:"Servers" json:"servers,required" description:"If no servers are specified, then localhost is used as the host." example:"tcp://localhost:6379"`
|
||||||
|
Commands []*RedisCommand `label:"Commands" json:"commands" description:"Optional. Specify redis commands to retrieve values"`
|
||||||
|
Password string `label:"Password" json:"password" description:"specify server password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RedisRule) Validate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *RedisRule) TelegrafInput() (telegraf.Input, error) {
|
||||||
|
if err := p.Validate(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
commands := make([]*redis.RedisCommand, len(p.Commands))
|
||||||
|
for i, c := range p.Commands {
|
||||||
|
cmd := &redis.RedisCommand{
|
||||||
|
Field: c.Field,
|
||||||
|
Type: c.Type,
|
||||||
|
}
|
||||||
|
for _, v := range c.Command {
|
||||||
|
cmd.Command = append(cmd.Command, v)
|
||||||
|
}
|
||||||
|
commands[i] = cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
return &redis.Redis{
|
||||||
|
Servers: p.Servers,
|
||||||
|
Commands: commands,
|
||||||
|
Password: p.Password,
|
||||||
|
}, nil
|
||||||
|
}
|
|
@ -0,0 +1,210 @@
|
||||||
|
package scache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/report"
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/config"
|
||||||
|
"github.com/toolkits/pkg/consistent"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type collectRuleCache struct {
|
||||||
|
sync.RWMutex
|
||||||
|
Region []string
|
||||||
|
Data map[string][]*models.CollectRule // map: node Identity
|
||||||
|
HashRing map[string]*ConsistentHashRing // map: region
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCollectRuleCache() *collectRuleCache {
|
||||||
|
return &collectRuleCache{
|
||||||
|
Region: config.Get().Region,
|
||||||
|
Data: make(map[string][]*models.CollectRule),
|
||||||
|
HashRing: make(map[string]*ConsistentHashRing),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) Start(ctx context.Context) {
|
||||||
|
go func() {
|
||||||
|
p.initHashRing()
|
||||||
|
|
||||||
|
p.syncPlacement()
|
||||||
|
go p.syncPlacementLoop(ctx)
|
||||||
|
|
||||||
|
p.syncCollectRules()
|
||||||
|
go p.syncCollectRulesLoop(ctx)
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) initHashRing() {
|
||||||
|
for _, region := range p.Region {
|
||||||
|
p.HashRing[region] = NewConsistentHashRing(int32(config.DetectorReplicas), []string{})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) GetBy(node string) []*models.CollectRule {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
|
||||||
|
return p.Data[node]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) Set(node string, rules []*models.CollectRule) {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
|
||||||
|
p.Data[node] = rules
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) SetAll(data map[string][]*models.CollectRule) {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
|
||||||
|
p.Data = data
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) GetAll() []*models.CollectRule {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
|
||||||
|
data := []*models.CollectRule{}
|
||||||
|
for nodeId, rules := range p.Data {
|
||||||
|
logger.Debugf("get nodeId %s rules %d", nodeId, len(rules))
|
||||||
|
for _, s := range rules {
|
||||||
|
data = append(data, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) syncCollectRulesLoop(ctx context.Context) {
|
||||||
|
t1 := time.NewTicker(time.Duration(CHECK_INTERVAL) * time.Second)
|
||||||
|
defer t1.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-t1.C:
|
||||||
|
p.syncCollectRules()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func str(in interface{}) string {
|
||||||
|
b, _ := json.Marshal(in)
|
||||||
|
return string(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) syncCollectRules() {
|
||||||
|
rules, err := models.GetCollectRules()
|
||||||
|
if err != nil {
|
||||||
|
logger.Warningf("get log collectRules err:%v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debugf("get collectRules %d %s", len(rules), str(rules))
|
||||||
|
|
||||||
|
rulesMap := make(map[string][]*models.CollectRule)
|
||||||
|
for _, rule := range rules {
|
||||||
|
if _, exists := p.HashRing[rule.Region]; !exists {
|
||||||
|
logger.Warningf("get node err, hash ring do noe exists %v", rule)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
node, err := p.HashRing[rule.Region].GetNode(strconv.FormatInt(rule.Id, 10))
|
||||||
|
if err != nil {
|
||||||
|
logger.Warningf("get node err:%v %v", err, rule)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
key := node
|
||||||
|
if _, exists := rulesMap[key]; exists {
|
||||||
|
rulesMap[key] = append(rulesMap[key], rule)
|
||||||
|
} else {
|
||||||
|
rulesMap[key] = []*models.CollectRule{rule}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
CollectRuleCache.SetAll(rulesMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) syncPlacementLoop(ctx context.Context) {
|
||||||
|
t1 := time.NewTicker(time.Duration(CHECK_INTERVAL) * time.Second)
|
||||||
|
defer t1.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-t1.C:
|
||||||
|
p.syncPlacement()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *collectRuleCache) syncPlacement() error {
|
||||||
|
instances, err := report.GetAlive("prober", "rdb")
|
||||||
|
if err != nil {
|
||||||
|
logger.Warning("get prober err:", err)
|
||||||
|
return fmt.Errorf("report.GetAlive prober fail: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debugf("get placement %d %s", len(instances), str(instances))
|
||||||
|
|
||||||
|
if len(instances) < 1 {
|
||||||
|
logger.Warningf("probers count is zero")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
nodesMap := make(map[string]map[string]struct{})
|
||||||
|
for _, d := range instances {
|
||||||
|
if d.Active {
|
||||||
|
if _, exists := nodesMap[d.Region]; !exists {
|
||||||
|
nodesMap[d.Region] = make(map[string]struct{})
|
||||||
|
}
|
||||||
|
nodesMap[d.Region][d.Identity+":"+d.RPCPort] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for region, nodes := range nodesMap {
|
||||||
|
rehash := false
|
||||||
|
if _, exists := p.HashRing[region]; !exists {
|
||||||
|
logger.Warningf("hash ring do not exists %v", region)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
oldNodes := p.HashRing[region].GetRing().Members()
|
||||||
|
if len(oldNodes) != len(nodes) {
|
||||||
|
rehash = true
|
||||||
|
} else {
|
||||||
|
for _, node := range oldNodes {
|
||||||
|
if _, exists := nodes[node]; !exists {
|
||||||
|
rehash = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if rehash {
|
||||||
|
//重建 hash环
|
||||||
|
r := consistent.New()
|
||||||
|
r.NumberOfReplicas = config.DetectorReplicas
|
||||||
|
for node, _ := range nodes {
|
||||||
|
r.Add(node)
|
||||||
|
}
|
||||||
|
logger.Warningf("detector hash ring rebuild old:%v new:%v", oldNodes, r.Members())
|
||||||
|
p.HashRing[region].Set(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package scache
|
package scache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/common/report"
|
"github.com/didi/nightingale/src/common/report"
|
||||||
|
@ -9,8 +10,9 @@ import (
|
||||||
"github.com/toolkits/pkg/logger"
|
"github.com/toolkits/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var CollectRuleCache *collectRuleCache
|
||||||
var JudgeHashRing *ConsistentHashRing
|
var JudgeHashRing *ConsistentHashRing
|
||||||
var ActiveNode = NewNodeMap()
|
var ActiveJudgeNode = NewNodeMap()
|
||||||
|
|
||||||
const CHECK_INTERVAL = 9
|
const CHECK_INTERVAL = 9
|
||||||
|
|
||||||
|
@ -22,8 +24,10 @@ func Init() {
|
||||||
|
|
||||||
InitJudgeHashRing()
|
InitJudgeHashRing()
|
||||||
|
|
||||||
go CheckJudgeNodes()
|
CollectRuleCache = NewCollectRuleCache()
|
||||||
|
CollectRuleCache.Start(context.Background())
|
||||||
|
|
||||||
|
go CheckJudgeNodes()
|
||||||
go SyncStras()
|
go SyncStras()
|
||||||
go SyncCollects()
|
go SyncCollects()
|
||||||
go CleanCollectLoop()
|
go CleanCollectLoop()
|
||||||
|
|
|
@ -40,11 +40,11 @@ func CheckJudge() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
rehash := false
|
rehash := false
|
||||||
if ActiveNode.Len() != len(judgeNode) { //scache.ActiveNode中的node数量和新获取的不同,重新rehash
|
if ActiveJudgeNode.Len() != len(judgeNode) { //scache.ActiveJudgeNode中的node数量和新获取的不同,重新rehash
|
||||||
rehash = true
|
rehash = true
|
||||||
} else {
|
} else {
|
||||||
for node, instance := range judgeNode {
|
for node, instance := range judgeNode {
|
||||||
v, exists := ActiveNode.GetInstanceBy(node)
|
v, exists := ActiveJudgeNode.GetInstanceBy(node)
|
||||||
if !exists || (exists && instance != v) {
|
if !exists || (exists && instance != v) {
|
||||||
rehash = true
|
rehash = true
|
||||||
break
|
break
|
||||||
|
@ -52,12 +52,12 @@ func CheckJudge() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if rehash {
|
if rehash {
|
||||||
ActiveNode.Set(judgeNode)
|
ActiveJudgeNode.Set(judgeNode)
|
||||||
|
|
||||||
//重建judge hash环
|
//重建judge hash环
|
||||||
r := consistent.New()
|
r := consistent.New()
|
||||||
r.NumberOfReplicas = config.JudgesReplicas
|
r.NumberOfReplicas = config.JudgesReplicas
|
||||||
nodes := ActiveNode.GetNodes()
|
nodes := ActiveJudgeNode.GetNodes()
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
r.Add(node)
|
r.Add(node)
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ func (s *StraCacheMap) GetAll() []*models.Stra {
|
||||||
|
|
||||||
data := []*models.Stra{}
|
data := []*models.Stra{}
|
||||||
for node, stras := range s.Data {
|
for node, stras := range s.Data {
|
||||||
instance, exists := ActiveNode.GetInstanceBy(node)
|
instance, exists := ActiveJudgeNode.GetInstanceBy(node)
|
||||||
if !exists {
|
if !exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CollectRule *CollectRuleCache // collectrule.go
|
||||||
|
var MetricHistory *history // history.go
|
||||||
|
|
||||||
|
func Init(ctx context.Context) error {
|
||||||
|
CollectRule = NewCollectRuleCache(&config.Config.CollectRule)
|
||||||
|
CollectRule.start(ctx)
|
||||||
|
MetricHistory = NewHistory()
|
||||||
|
InitPluginsConfig(config.Config)
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,159 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"math/rand"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/address"
|
||||||
|
"github.com/didi/nightingale/src/common/identity"
|
||||||
|
"github.com/didi/nightingale/src/common/report"
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/config"
|
||||||
|
"github.com/didi/nightingale/src/toolkits/stats"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
"github.com/toolkits/pkg/net/httplib"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CollectRuleCache struct {
|
||||||
|
sync.RWMutex
|
||||||
|
*config.CollectRuleSection
|
||||||
|
Data map[int64]*models.CollectRule
|
||||||
|
TS map[int64]int64
|
||||||
|
C chan time.Time
|
||||||
|
timeout time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCollectRuleCache(cf *config.CollectRuleSection) *CollectRuleCache {
|
||||||
|
return &CollectRuleCache{
|
||||||
|
CollectRuleSection: cf,
|
||||||
|
Data: make(map[int64]*models.CollectRule),
|
||||||
|
TS: make(map[int64]int64),
|
||||||
|
timeout: time.Duration(cf.Timeout) * time.Millisecond,
|
||||||
|
C: make(chan time.Time, 1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRuleCache) start(ctx context.Context) error {
|
||||||
|
go func() {
|
||||||
|
p.syncCollectRule()
|
||||||
|
p.syncCollectRuleLoop(ctx)
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRuleCache) Set(id int64, rule *models.CollectRule) {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
p.Data[id] = rule
|
||||||
|
p.TS[id] = time.Now().Unix()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRuleCache) Get(id int64) (*models.CollectRule, bool) {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
|
||||||
|
rule, exists := p.Data[id]
|
||||||
|
return rule, exists
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRuleCache) GetAll() []*models.CollectRule {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
var rules []*models.CollectRule
|
||||||
|
for _, rule := range p.Data {
|
||||||
|
rules = append(rules, rule)
|
||||||
|
}
|
||||||
|
return rules
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRuleCache) Clean() {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
now := time.Now().Unix()
|
||||||
|
for id, ts := range p.TS {
|
||||||
|
if now-ts > 60 {
|
||||||
|
stats.Counter.Set("collectrule.clean", 1)
|
||||||
|
delete(p.Data, id)
|
||||||
|
delete(p.TS, id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRuleCache) syncCollectRuleLoop(ctx context.Context) {
|
||||||
|
t1 := time.NewTicker(time.Duration(p.UpdateInterval) * time.Millisecond)
|
||||||
|
defer t1.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case t := <-t1.C:
|
||||||
|
if err := p.syncCollectRule(); err != nil {
|
||||||
|
logger.Errorf("syncCollectRule err %s", err)
|
||||||
|
} else {
|
||||||
|
p.C <- t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type collectRulesResp struct {
|
||||||
|
Data []*models.CollectRule `json:"dat"`
|
||||||
|
Err string `json:"err"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CollectRuleCache) syncCollectRule() error {
|
||||||
|
addrs := address.GetHTTPAddresses(p.Mod)
|
||||||
|
if len(addrs) == 0 {
|
||||||
|
return fmt.Errorf("empty config addr")
|
||||||
|
}
|
||||||
|
|
||||||
|
var resp collectRulesResp
|
||||||
|
perm := rand.Perm(len(addrs))
|
||||||
|
for i := range perm {
|
||||||
|
ident, err := identity.GetIdent()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("getIdent err %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
url := fmt.Sprintf("http://%s/api/mon/collect-rules/endpoints/%s:%s/remote",
|
||||||
|
addrs[perm[i]], ident, report.Config.RPCPort)
|
||||||
|
err = httplib.Get(url).SetTimeout(p.timeout).ToJSON(&resp)
|
||||||
|
if err != nil {
|
||||||
|
logger.Warningf("get %s collect rule from remote failed, error:%v", url, err)
|
||||||
|
stats.Counter.Set("collectrule.get.err", 1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if resp.Err != "" {
|
||||||
|
logger.Warningf("get collect rule from remote failed, error:%v", resp.Err)
|
||||||
|
stats.Counter.Set("collectrule.get.err", 1)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(resp.Data) > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
collectRuleCount := len(resp.Data)
|
||||||
|
stats.Counter.Set("collectrule.count", collectRuleCount)
|
||||||
|
if collectRuleCount == 0 { //获取策略数为0,不正常,不更新策略缓存
|
||||||
|
return fmt.Errorf("clloect rule count is 0")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rule := range resp.Data {
|
||||||
|
if err := rule.Validate(); err != nil {
|
||||||
|
logger.Debugf("rule.Validate err %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
stats.Counter.Set("collectrule.common", 1)
|
||||||
|
p.Set(rule.Id, rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Clean()
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/dataobj"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewHistory() *history {
|
||||||
|
h := history{
|
||||||
|
Data: make(map[string]dataobj.MetricValue),
|
||||||
|
}
|
||||||
|
|
||||||
|
go h.Clean()
|
||||||
|
return &h
|
||||||
|
}
|
||||||
|
|
||||||
|
type history struct {
|
||||||
|
sync.RWMutex
|
||||||
|
Data map[string]dataobj.MetricValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *history) Set(key string, item dataobj.MetricValue) {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
|
h.Data[key] = item
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *history) Get(key string) (dataobj.MetricValue, bool) {
|
||||||
|
h.RLock()
|
||||||
|
defer h.RUnlock()
|
||||||
|
|
||||||
|
item, exists := h.Data[key]
|
||||||
|
return item, exists
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *history) Clean() {
|
||||||
|
ticker := time.NewTicker(10 * time.Minute)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
h.clean()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *history) clean() {
|
||||||
|
h.Lock()
|
||||||
|
defer h.Unlock()
|
||||||
|
now := time.Now().Unix()
|
||||||
|
for key, item := range h.Data {
|
||||||
|
if now-item.Timestamp > 10*item.Step {
|
||||||
|
delete(h.Data, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/config"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/expr"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
"gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MetricConfig struct {
|
||||||
|
Name string `yaml:"name"`
|
||||||
|
Type string `yaml:"type"`
|
||||||
|
Comment string `yaml:"comment"`
|
||||||
|
Expr string `yaml:"expr"`
|
||||||
|
notations expr.Notations `yaml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PluginConfig struct {
|
||||||
|
Metrics []MetricConfig `metrics`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
metricsConfig map[string]MetricConfig
|
||||||
|
metricsExpr map[string]map[string]MetricConfig
|
||||||
|
ignoreConfig bool
|
||||||
|
)
|
||||||
|
|
||||||
|
func InitPluginsConfig(cf *config.ConfYaml) {
|
||||||
|
metricsConfig = make(map[string]MetricConfig)
|
||||||
|
metricsExpr = make(map[string]map[string]MetricConfig)
|
||||||
|
ignoreConfig = cf.IgnoreConfig
|
||||||
|
plugins := collector.GetRemoteCollectors()
|
||||||
|
for _, plugin := range plugins {
|
||||||
|
metricsExpr[plugin] = make(map[string]MetricConfig)
|
||||||
|
pluginConfig := PluginConfig{}
|
||||||
|
|
||||||
|
file := filepath.Join(cf.PluginsConfig, plugin+".yml")
|
||||||
|
b, err := ioutil.ReadFile(file)
|
||||||
|
if err != nil {
|
||||||
|
logger.Debugf("readfile %s err %s", plugin, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := yaml.Unmarshal(b, &pluginConfig); err != nil {
|
||||||
|
logger.Warningf("yaml.Unmarshal %s err %s", plugin, err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range pluginConfig.Metrics {
|
||||||
|
if _, ok := metricsConfig[v.Name]; ok {
|
||||||
|
panic(fmt.Sprintf("plugin %s metrics %s is already exists", plugin, v.Name))
|
||||||
|
}
|
||||||
|
if v.Expr == "" {
|
||||||
|
// nomore
|
||||||
|
metricsConfig[v.Name] = v
|
||||||
|
} else {
|
||||||
|
err := v.parse()
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("plugin %s metrics %s expr %s parse err %s",
|
||||||
|
plugin, v.Name, v.Expr, err))
|
||||||
|
}
|
||||||
|
metricsExpr[plugin][v.Name] = v
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Infof("loaded plugin config %s", file)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MetricConfig) parse() (err error) {
|
||||||
|
p.notations, err = expr.NewNotations([]byte(p.Expr))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *MetricConfig) Calc(vars map[string]float64) (float64, error) {
|
||||||
|
return p.notations.Calc(vars)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Metric(metric string, typ telegraf.ValueType) (c MetricConfig, ok bool) {
|
||||||
|
c, ok = metricsConfig[metric]
|
||||||
|
if !ok && !ignoreConfig {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Type == "" {
|
||||||
|
c.Type = metricType(typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMetricExprs(pluginName string) (c map[string]MetricConfig, ok bool) {
|
||||||
|
c, ok = metricsExpr[pluginName]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func metricType(typ telegraf.ValueType) string {
|
||||||
|
switch typ {
|
||||||
|
case telegraf.Counter:
|
||||||
|
return "COUNTER"
|
||||||
|
case telegraf.Gauge:
|
||||||
|
return "GAUGE"
|
||||||
|
case telegraf.Untyped:
|
||||||
|
return "GAUGE"
|
||||||
|
case telegraf.Summary: // TODO
|
||||||
|
return "SUMMARY"
|
||||||
|
case telegraf.Histogram: // TODO
|
||||||
|
return "HISTOGRAM"
|
||||||
|
default:
|
||||||
|
return "GAUGE"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/address"
|
||||||
|
"github.com/didi/nightingale/src/common/loggeri"
|
||||||
|
"github.com/didi/nightingale/src/common/report"
|
||||||
|
|
||||||
|
// "github.com/didi/nightingale/src/modules/prober/backend/transfer"
|
||||||
|
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/toolkits/pkg/file"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ConfYaml struct {
|
||||||
|
CollectRule CollectRuleSection `yaml:"collectRule"`
|
||||||
|
Logger loggeri.Config `yaml:"logger"`
|
||||||
|
Report report.ReportSection `yaml:"report"`
|
||||||
|
WorkerProcesses int `yaml:"workerProcesses"`
|
||||||
|
PluginsConfig string `yaml:"pluginsConfig"`
|
||||||
|
IgnoreConfig bool `yaml:"ignoreConfig"`
|
||||||
|
HTTP HTTPSection `yaml:"http"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type CollectRuleSection struct {
|
||||||
|
Timeout int `yaml:"timeout"`
|
||||||
|
Token string `yaml:"token"`
|
||||||
|
UpdateInterval int `yaml:"updateInterval"`
|
||||||
|
IndexInterval int `yaml:"indexInterval"`
|
||||||
|
ReportInterval int `yaml:"reportInterval"`
|
||||||
|
Mod string `yaml:"mod"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
Config *ConfYaml
|
||||||
|
)
|
||||||
|
|
||||||
|
type HTTPSection struct {
|
||||||
|
Mode string `yaml:"mode"`
|
||||||
|
CookieName string `yaml:"cookieName"`
|
||||||
|
CookieDomain string `yaml:"cookieDomain"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Parse(conf string) error {
|
||||||
|
bs, err := file.ReadBytes(conf)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot read yml[%s]: %v", conf, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.SetConfigType("yaml")
|
||||||
|
err = viper.ReadConfig(bytes.NewBuffer(bs))
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot read yml[%s]: %v", conf, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
viper.SetDefault("http.enabled", true)
|
||||||
|
|
||||||
|
viper.SetDefault("collectRule", map[string]interface{}{
|
||||||
|
"updateInterval": 9000,
|
||||||
|
"indexInterval": 60000,
|
||||||
|
"timeout": 5000,
|
||||||
|
"mod": "monapi",
|
||||||
|
"eventPrefix": "n9e",
|
||||||
|
})
|
||||||
|
|
||||||
|
viper.SetDefault("report", map[string]interface{}{
|
||||||
|
"mod": "prober",
|
||||||
|
"enabled": true,
|
||||||
|
"interval": 4000,
|
||||||
|
"timeout": 3000,
|
||||||
|
"api": "api/hbs/heartbeat",
|
||||||
|
"remark": "",
|
||||||
|
"region": "default",
|
||||||
|
})
|
||||||
|
|
||||||
|
viper.SetDefault("workerProcesses", 5)
|
||||||
|
|
||||||
|
viper.SetDefault("pluginsConfig", "etc/plugins")
|
||||||
|
|
||||||
|
viper.SetDefault("pushUrl", "http://127.0.0.1:2058/v1/push")
|
||||||
|
|
||||||
|
err = viper.Unmarshal(&Config)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("cannot read yml[%s]: %v\n", conf, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
Config.Report.HTTPPort = strconv.Itoa(address.GetHTTPPort("prober"))
|
||||||
|
Config.Report.RPCPort = strconv.Itoa(address.GetRPCPort("prober"))
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/rpc"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RpcClientContainer struct {
|
||||||
|
M map[string]*rpc.Client
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
var rpcClients *RpcClientContainer
|
||||||
|
|
||||||
|
func InitRpcClients() {
|
||||||
|
rpcClients = &RpcClientContainer{
|
||||||
|
M: make(map[string]*rpc.Client),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcc *RpcClientContainer) Get(addr string) *rpc.Client {
|
||||||
|
rcc.RLock()
|
||||||
|
defer rcc.RUnlock()
|
||||||
|
|
||||||
|
client, has := rcc.M[addr]
|
||||||
|
if !has {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
|
|
||||||
|
// Put 返回的bool表示affected,确实把自己塞进去了
|
||||||
|
func (rcc *RpcClientContainer) Put(addr string, client *rpc.Client) bool {
|
||||||
|
rcc.Lock()
|
||||||
|
defer rcc.Unlock()
|
||||||
|
|
||||||
|
oc, has := rcc.M[addr]
|
||||||
|
if has && oc != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
rcc.M[addr] = client
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rcc *RpcClientContainer) Del(addr string) {
|
||||||
|
rcc.Lock()
|
||||||
|
defer rcc.Unlock()
|
||||||
|
delete(rcc.M, addr)
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/dataobj"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewMetricValue(metric string, val interface{}, dataType string, tags ...string) *dataobj.MetricValue {
|
||||||
|
mv := dataobj.MetricValue{
|
||||||
|
Metric: metric,
|
||||||
|
ValueUntyped: val,
|
||||||
|
CounterType: dataType,
|
||||||
|
}
|
||||||
|
|
||||||
|
size := len(tags)
|
||||||
|
|
||||||
|
if size > 0 {
|
||||||
|
mv.Tags = strings.Join(tags, ",")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &mv
|
||||||
|
}
|
||||||
|
|
||||||
|
func GaugeValue(metric string, val interface{}, tags ...string) *dataobj.MetricValue {
|
||||||
|
return NewMetricValue(metric, val, "GAUGE", tags...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CounterValue(metric string, val interface{}, tags ...string) *dataobj.MetricValue {
|
||||||
|
return NewMetricValue(metric, val, "COUNTER", tags...)
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
package core
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"net/rpc"
|
||||||
|
"reflect"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
"github.com/ugorji/go/codec"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/address"
|
||||||
|
"github.com/didi/nightingale/src/common/dataobj"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/cache"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Push(metricItems []*dataobj.MetricValue) {
|
||||||
|
var err error
|
||||||
|
var items []*dataobj.MetricValue
|
||||||
|
now := time.Now().Unix()
|
||||||
|
|
||||||
|
for _, item := range metricItems {
|
||||||
|
// logger.Debugf("->recv:%+v", item)
|
||||||
|
err = item.CheckValidity(now)
|
||||||
|
if err != nil {
|
||||||
|
msg := fmt.Errorf("metric:%v err:%v", item, err)
|
||||||
|
logger.Warning(msg)
|
||||||
|
// 如果数据有问题,直接跳过吧,比如mymon采集的到的数据,其实只有一个有问题,剩下的都没问题
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if item.CounterType == dataobj.COUNTER {
|
||||||
|
item = CounterToGauge(item)
|
||||||
|
if item == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if item.CounterType == dataobj.SUBTRACT {
|
||||||
|
item = SubtractToGauge(item)
|
||||||
|
if item == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// logger.Debugf("push item: %+v", item)
|
||||||
|
items = append(items, item)
|
||||||
|
}
|
||||||
|
|
||||||
|
addrs := address.GetRPCAddresses("transfer")
|
||||||
|
count := len(addrs)
|
||||||
|
retry := 0
|
||||||
|
for {
|
||||||
|
for _, i := range rand.Perm(count) {
|
||||||
|
addr := addrs[i]
|
||||||
|
reply, err := rpcCall(addr, items)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(err)
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
if reply.Msg != "ok" {
|
||||||
|
err = fmt.Errorf("some item push err: %s", reply.Msg)
|
||||||
|
logger.Error(err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Millisecond * 500)
|
||||||
|
|
||||||
|
retry += 1
|
||||||
|
if retry == 3 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func rpcCall(addr string, items []*dataobj.MetricValue) (dataobj.TransferResp, error) {
|
||||||
|
var reply dataobj.TransferResp
|
||||||
|
var err error
|
||||||
|
|
||||||
|
client := rpcClients.Get(addr)
|
||||||
|
if client == nil {
|
||||||
|
client, err = rpcClient(addr)
|
||||||
|
if err != nil {
|
||||||
|
return reply, err
|
||||||
|
}
|
||||||
|
affected := rpcClients.Put(addr, client)
|
||||||
|
if !affected {
|
||||||
|
defer func() {
|
||||||
|
// 我尝试把自己这个client塞进map失败,说明已经有一个client塞进去了,那我自己用完了就关闭
|
||||||
|
client.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout := time.Duration(8) * time.Second
|
||||||
|
done := make(chan error, 1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
err := client.Call("Transfer.Push", items, &reply)
|
||||||
|
done <- err
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-time.After(timeout):
|
||||||
|
logger.Warningf("rpc call timeout, transfer addr: %s\n", addr)
|
||||||
|
rpcClients.Put(addr, nil)
|
||||||
|
client.Close()
|
||||||
|
return reply, fmt.Errorf("%s rpc call timeout", addr)
|
||||||
|
case err := <-done:
|
||||||
|
if err != nil {
|
||||||
|
rpcClients.Del(addr)
|
||||||
|
client.Close()
|
||||||
|
return reply, fmt.Errorf("%s rpc call done, but fail: %v", addr, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return reply, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func rpcClient(addr string) (*rpc.Client, error) {
|
||||||
|
conn, err := net.DialTimeout("tcp", addr, time.Second*3)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("dial transfer %s fail: %v", addr, err)
|
||||||
|
logger.Error(err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var bufConn = struct {
|
||||||
|
io.Closer
|
||||||
|
*bufio.Reader
|
||||||
|
*bufio.Writer
|
||||||
|
}{conn, bufio.NewReader(conn), bufio.NewWriter(conn)}
|
||||||
|
|
||||||
|
var mh codec.MsgpackHandle
|
||||||
|
mh.MapType = reflect.TypeOf(map[string]interface{}(nil))
|
||||||
|
|
||||||
|
rpcCodec := codec.MsgpackSpecRpc.ClientCodec(bufConn, &mh)
|
||||||
|
client := rpc.NewClientWithCodec(rpcCodec)
|
||||||
|
return client, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func CounterToGauge(item *dataobj.MetricValue) *dataobj.MetricValue {
|
||||||
|
key := item.PK()
|
||||||
|
|
||||||
|
old, exists := cache.MetricHistory.Get(key)
|
||||||
|
cache.MetricHistory.Set(key, *item)
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
logger.Debugf("not found old item:%v, maybe this is the first item", item)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if old.Value > item.Value {
|
||||||
|
logger.Warningf("item:%v old value:%v greater than new value:%v", item, old.Value, item.Value)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if old.Timestamp >= item.Timestamp {
|
||||||
|
logger.Warningf("item:%v old timestamp:%v greater than new timestamp:%v", item, old.Timestamp, item.Timestamp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
item.ValueUntyped = (item.Value - old.Value) / float64(item.Timestamp-old.Timestamp)
|
||||||
|
item.CounterType = dataobj.GAUGE
|
||||||
|
return item
|
||||||
|
}
|
||||||
|
|
||||||
|
func SubtractToGauge(item *dataobj.MetricValue) *dataobj.MetricValue {
|
||||||
|
key := item.PK()
|
||||||
|
|
||||||
|
old, exists := cache.MetricHistory.Get(key)
|
||||||
|
cache.MetricHistory.Set(key, *item)
|
||||||
|
|
||||||
|
if !exists {
|
||||||
|
logger.Debugf("not found old item:%v, maybe this is the first item", item)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if old.Timestamp >= item.Timestamp {
|
||||||
|
logger.Warningf("item:%v old timestamp:%v greater than new timestamp:%v", item, old.Timestamp, item.Timestamp)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if old.Timestamp <= item.Timestamp-2*item.Step {
|
||||||
|
logger.Warningf("item:%v old timestamp:%v too old <= %v = (new timestamp: %v - 2 * step: %v), maybe some point lost", item, old.Timestamp, item.Timestamp-2*item.Step, item.Timestamp, item.Step)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
item.ValueUntyped = item.Value - old.Value
|
||||||
|
item.CounterType = dataobj.GAUGE
|
||||||
|
return item
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
package expr
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/scanner"
|
||||||
|
"go/token"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tokenType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
tokenOperator tokenType = iota
|
||||||
|
tokenVar
|
||||||
|
tokenConst
|
||||||
|
)
|
||||||
|
|
||||||
|
type TokenNotation struct {
|
||||||
|
tokenType tokenType
|
||||||
|
o token.Token // operator
|
||||||
|
v string // variable
|
||||||
|
c float64 // const
|
||||||
|
}
|
||||||
|
|
||||||
|
type Notations []*TokenNotation
|
||||||
|
|
||||||
|
func (s *Notations) Push(tn *TokenNotation) { *s = append(*s, tn) }
|
||||||
|
func (s *Notations) Pop() *TokenNotation { n := (*s)[len(*s)-1]; *s = (*s)[:len(*s)-1]; return n }
|
||||||
|
func (s *Notations) Top() *TokenNotation { return (*s)[len(*s)-1] }
|
||||||
|
func (s *Notations) Len() int { return len(*s) }
|
||||||
|
|
||||||
|
func (s Notations) String() string {
|
||||||
|
out := bytes.NewBuffer(nil)
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
tn := s[i]
|
||||||
|
switch tn.tokenType {
|
||||||
|
case tokenOperator:
|
||||||
|
out.WriteString(tn.o.String() + " ")
|
||||||
|
case tokenVar:
|
||||||
|
out.WriteString(tn.v + " ")
|
||||||
|
case tokenConst:
|
||||||
|
out.WriteString(fmt.Sprintf("%.0f ", tn.c))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
type StackOp []token.Token
|
||||||
|
|
||||||
|
func (s *StackOp) Push(t token.Token) { *s = append(*s, t) }
|
||||||
|
func (s *StackOp) Pop() token.Token { n := (*s)[len(*s)-1]; *s = (*s)[:len(*s)-1]; return n }
|
||||||
|
func (s *StackOp) Top() token.Token { return (*s)[len(*s)-1] }
|
||||||
|
func (s *StackOp) Len() int { return len(*s) }
|
||||||
|
|
||||||
|
type StackFloat []float64
|
||||||
|
|
||||||
|
func (s *StackFloat) Push(f float64) { *s = append(*s, f) }
|
||||||
|
func (s *StackFloat) Pop() float64 { n := (*s)[len(*s)-1]; *s = (*s)[:len(*s)-1]; return n }
|
||||||
|
func (s *StackFloat) Len() int { return len(*s) }
|
||||||
|
|
||||||
|
func (rpn Notations) Calc(vars map[string]float64) (float64, error) {
|
||||||
|
var s StackFloat
|
||||||
|
for i := 0; i < rpn.Len(); i++ {
|
||||||
|
tn := rpn[i]
|
||||||
|
switch tn.tokenType {
|
||||||
|
case tokenVar:
|
||||||
|
if v, ok := vars[tn.v]; !ok {
|
||||||
|
return 0, fmt.Errorf("variable %s is not set", tn.v)
|
||||||
|
} else {
|
||||||
|
logger.Debugf("get %s %f", tn.v, v)
|
||||||
|
s.Push(v)
|
||||||
|
}
|
||||||
|
case tokenConst:
|
||||||
|
s.Push(tn.c)
|
||||||
|
case tokenOperator:
|
||||||
|
op2 := s.Pop()
|
||||||
|
op1 := s.Pop()
|
||||||
|
switch tn.o {
|
||||||
|
case token.ADD:
|
||||||
|
s.Push(op1 + op2)
|
||||||
|
case token.SUB:
|
||||||
|
s.Push(op1 - op2)
|
||||||
|
case token.MUL:
|
||||||
|
s.Push(op1 * op2)
|
||||||
|
case token.QUO:
|
||||||
|
s.Push(op1 / op2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if s.Len() == 1 {
|
||||||
|
return s[0], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0, fmt.Errorf("invalid calc, stack len %d expect 1", s.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
// return reverse polish notation stack
|
||||||
|
func NewNotations(src []byte) (output Notations, err error) {
|
||||||
|
var scan scanner.Scanner
|
||||||
|
var s StackOp
|
||||||
|
|
||||||
|
fset := token.NewFileSet()
|
||||||
|
file := fset.AddFile("", fset.Base(), len(src))
|
||||||
|
|
||||||
|
scan.Init(file, src, errorHandler, scanner.ScanComments)
|
||||||
|
var (
|
||||||
|
pos token.Pos
|
||||||
|
tok token.Token
|
||||||
|
lit string
|
||||||
|
)
|
||||||
|
for {
|
||||||
|
pos, tok, lit = scan.Scan()
|
||||||
|
|
||||||
|
switch tok {
|
||||||
|
case token.EOF, token.SEMICOLON:
|
||||||
|
goto out
|
||||||
|
case token.INT, token.FLOAT:
|
||||||
|
c, err := strconv.ParseFloat(lit, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("parseFloat error %s\t%s\t%q",
|
||||||
|
fset.Position(pos), tok, lit)
|
||||||
|
}
|
||||||
|
output.Push(&TokenNotation{tokenType: tokenConst, c: c})
|
||||||
|
case token.IDENT:
|
||||||
|
output.Push(&TokenNotation{tokenType: tokenVar, v: lit})
|
||||||
|
case token.LPAREN: // (
|
||||||
|
s.Push(tok)
|
||||||
|
case token.ADD, token.SUB, token.MUL, token.QUO: // + - * /
|
||||||
|
opRetry:
|
||||||
|
if s.Len() == 0 {
|
||||||
|
s.Push(tok)
|
||||||
|
} else if op := s.Top(); op == token.LPAREN || priority(tok) > priority(op) {
|
||||||
|
s.Push(tok)
|
||||||
|
} else {
|
||||||
|
output.Push(&TokenNotation{tokenType: tokenOperator, o: s.Pop()})
|
||||||
|
goto opRetry
|
||||||
|
}
|
||||||
|
case token.RPAREN: // )
|
||||||
|
for s.Len() > 0 {
|
||||||
|
if op := s.Pop(); op == token.LPAREN {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
output.Push(&TokenNotation{tokenType: tokenOperator, o: op})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unsupport token %s", tok)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
for i, l := 0, s.Len(); i < l; i++ {
|
||||||
|
output.Push(&TokenNotation{tokenType: tokenOperator, o: s.Pop()})
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func errorHandler(pos token.Position, msg string) {
|
||||||
|
logger.Errorf("error %s\t%s\n", pos, msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
func priority(tok token.Token) int {
|
||||||
|
switch tok {
|
||||||
|
case token.ADD, token.SUB:
|
||||||
|
return 1
|
||||||
|
case token.MUL, token.QUO:
|
||||||
|
return 2
|
||||||
|
default:
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/address"
|
||||||
|
"github.com/didi/nightingale/src/common/middleware"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var srv = &http.Server{
|
||||||
|
ReadTimeout: 10 * time.Second,
|
||||||
|
WriteTimeout: 10 * time.Second,
|
||||||
|
MaxHeaderBytes: 1 << 20,
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start() {
|
||||||
|
c := config.Config
|
||||||
|
|
||||||
|
recoveryMid := middleware.Recovery()
|
||||||
|
|
||||||
|
if strings.ToLower(c.HTTP.Mode) == "release" {
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
middleware.DisableConsoleColor()
|
||||||
|
}
|
||||||
|
|
||||||
|
r := gin.New()
|
||||||
|
r.Use(recoveryMid)
|
||||||
|
|
||||||
|
Config(r)
|
||||||
|
|
||||||
|
srv.Addr = address.GetHTTPListen("prober")
|
||||||
|
srv.Handler = r
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
fmt.Println("http.listening:", srv.Addr)
|
||||||
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||||
|
fmt.Printf("listening %s occur error: %s\n", srv.Addr, err)
|
||||||
|
os.Exit(3)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown http server
|
||||||
|
func Shutdown() {
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
if err := srv.Shutdown(ctx); err != nil {
|
||||||
|
fmt.Println("cannot shutdown http server:", err)
|
||||||
|
os.Exit(2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// catching ctx.Done(). timeout of 5 seconds.
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
fmt.Println("shutdown http server timeout of 5 seconds.")
|
||||||
|
default:
|
||||||
|
fmt.Println("http server stopped")
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/cache"
|
||||||
|
"github.com/gin-contrib/pprof"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Config(r *gin.Engine) {
|
||||||
|
|
||||||
|
notLogin := r.Group("/api/rdb")
|
||||||
|
{
|
||||||
|
notLogin.GET("/ping", ping)
|
||||||
|
notLogin.GET("/pid", pid)
|
||||||
|
notLogin.GET("/addr", addr)
|
||||||
|
notLogin.GET("/collect-rule/:id", getCollectRule)
|
||||||
|
// notLogin.POST("/data", getData)
|
||||||
|
}
|
||||||
|
|
||||||
|
pprof.Register(r, "/api/prober/debug/pprof")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ping(c *gin.Context) {
|
||||||
|
c.String(200, "pong")
|
||||||
|
}
|
||||||
|
|
||||||
|
func addr(c *gin.Context) {
|
||||||
|
c.String(200, c.Request.RemoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func pid(c *gin.Context) {
|
||||||
|
c.String(200, fmt.Sprintf("%d", os.Getpid()))
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCollectRule(c *gin.Context) {
|
||||||
|
rule, _ := cache.CollectRule.Get(urlParamInt64(c, "id"))
|
||||||
|
renderData(c, rule, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO: get last collect data
|
||||||
|
func getData(c *gin.Context) {
|
||||||
|
var input dataobj.JudgeItem
|
||||||
|
errors.Dangerous(c.ShouldBind(&input))
|
||||||
|
pk := input.MD5()
|
||||||
|
linkedList, _ := cache.HistoryBigMap[pk[0:2]].Get(pk)
|
||||||
|
data := linkedList.HistoryData()
|
||||||
|
renderData(c, data, nil)
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,282 @@
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/toolkits/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||||
|
)
|
||||||
|
|
||||||
|
func dangerous(v interface{}) {
|
||||||
|
errors.Dangerous(v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func bomb(format string, a ...interface{}) {
|
||||||
|
errors.Bomb(i18n.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func bind(c *gin.Context, ptr interface{}) {
|
||||||
|
dangerous(c.ShouldBindJSON(ptr))
|
||||||
|
}
|
||||||
|
|
||||||
|
func urlParamStr(c *gin.Context, field string) string {
|
||||||
|
val := c.Param(field)
|
||||||
|
|
||||||
|
if val == "" {
|
||||||
|
bomb("url param[%s] is blank", field)
|
||||||
|
}
|
||||||
|
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
func urlParamInt64(c *gin.Context, field string) int64 {
|
||||||
|
strval := urlParamStr(c, field)
|
||||||
|
intval, err := strconv.ParseInt(strval, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
bomb("cannot convert %s to int64", strval)
|
||||||
|
}
|
||||||
|
|
||||||
|
return intval
|
||||||
|
}
|
||||||
|
|
||||||
|
func urlParamInt(c *gin.Context, field string) int {
|
||||||
|
return int(urlParamInt64(c, field))
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryStr(c *gin.Context, key string, defaultVal ...string) string {
|
||||||
|
val := c.Query(key)
|
||||||
|
if val != "" {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(defaultVal) == 0 {
|
||||||
|
bomb("query param[%s] is necessary", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryInt(c *gin.Context, key string, defaultVal ...int) int {
|
||||||
|
strv := c.Query(key)
|
||||||
|
if strv != "" {
|
||||||
|
intv, err := strconv.Atoi(strv)
|
||||||
|
if err != nil {
|
||||||
|
bomb("cannot convert [%s] to int", strv)
|
||||||
|
}
|
||||||
|
return intv
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(defaultVal) == 0 {
|
||||||
|
bomb("query param[%s] is necessary", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func queryInt64(c *gin.Context, key string, defaultVal ...int64) int64 {
|
||||||
|
strv := c.Query(key)
|
||||||
|
if strv != "" {
|
||||||
|
intv, err := strconv.ParseInt(strv, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
bomb("cannot convert [%s] to int64", strv)
|
||||||
|
}
|
||||||
|
return intv
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(defaultVal) == 0 {
|
||||||
|
bomb("query param[%s] is necessary", key)
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaultVal[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
func offset(c *gin.Context, limit int) int {
|
||||||
|
if limit <= 0 {
|
||||||
|
limit = 10
|
||||||
|
}
|
||||||
|
|
||||||
|
page := queryInt(c, "p", 1)
|
||||||
|
return (page - 1) * limit
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderMessage(c *gin.Context, v interface{}) {
|
||||||
|
if v == nil {
|
||||||
|
c.JSON(200, gin.H{"err": ""})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch t := v.(type) {
|
||||||
|
case string:
|
||||||
|
c.JSON(200, gin.H{"err": i18n.Sprintf(t)})
|
||||||
|
case error:
|
||||||
|
c.JSON(200, gin.H{"err": t.Error()})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderData(c *gin.Context, data interface{}, err error) {
|
||||||
|
if err == nil {
|
||||||
|
c.JSON(200, gin.H{"dat": data, "err": ""})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMessage(c, err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
func renderZeroPage(c *gin.Context) {
|
||||||
|
renderData(c, gin.H{
|
||||||
|
"list": []int{},
|
||||||
|
"total": 0,
|
||||||
|
}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
|
||||||
|
type idsForm struct {
|
||||||
|
Ids []int64 `json:"ids"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPassword(passwd string) error {
|
||||||
|
indNum := [4]int{0, 0, 0, 0}
|
||||||
|
spCode := []byte{'!', '@', '#', '$', '%', '^', '&', '*', '_', '-', '~', '.', ',', '<', '>', '/', ';', ':', '|', '?', '+', '='}
|
||||||
|
|
||||||
|
if len(passwd) < 6 {
|
||||||
|
return fmt.Errorf("password too short")
|
||||||
|
}
|
||||||
|
|
||||||
|
passwdByte := []byte(passwd)
|
||||||
|
|
||||||
|
for _, i := range passwdByte {
|
||||||
|
|
||||||
|
if i >= 'A' && i <= 'Z' {
|
||||||
|
indNum[0] = 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= 'a' && i <= 'z' {
|
||||||
|
indNum[1] = 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= '0' && i <= '9' {
|
||||||
|
indNum[2] = 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
has := false
|
||||||
|
for _, s := range spCode {
|
||||||
|
if i == s {
|
||||||
|
indNum[3] = 1
|
||||||
|
has = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
return fmt.Errorf("character: %s not supported", string(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
codeCount := 0
|
||||||
|
|
||||||
|
for _, i := range indNum {
|
||||||
|
codeCount += i
|
||||||
|
}
|
||||||
|
|
||||||
|
if codeCount < 4 {
|
||||||
|
return fmt.Errorf("password too simple")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------
|
||||||
|
|
||||||
|
func loginUsername(c *gin.Context) string {
|
||||||
|
value, has := c.Get("username")
|
||||||
|
if !has {
|
||||||
|
bomb("unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
if value == nil {
|
||||||
|
bomb("unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
func loginUser(c *gin.Context) *models.User {
|
||||||
|
username := loginUsername(c)
|
||||||
|
|
||||||
|
user, err := models.UserGet("username=?", username)
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
if user == nil {
|
||||||
|
bomb("unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
func loginRoot(c *gin.Context) *models.User {
|
||||||
|
value, has := c.Get("user")
|
||||||
|
if !has {
|
||||||
|
bomb("unauthorized")
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.(*models.User)
|
||||||
|
}
|
||||||
|
|
||||||
|
func User(id int64) *models.User {
|
||||||
|
user, err := models.UserGet("id=?", id)
|
||||||
|
if err != nil {
|
||||||
|
bomb("cannot retrieve user[%d]: %v", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user == nil {
|
||||||
|
bomb("no such user[%d]", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return user
|
||||||
|
}
|
||||||
|
|
||||||
|
func Team(id int64) *models.Team {
|
||||||
|
team, err := models.TeamGet("id=?", id)
|
||||||
|
if err != nil {
|
||||||
|
bomb("cannot retrieve team[%d]: %v", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if team == nil {
|
||||||
|
bomb("no such team[%d]", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return team
|
||||||
|
}
|
||||||
|
|
||||||
|
func Role(id int64) *models.Role {
|
||||||
|
role, err := models.RoleGet("id=?", id)
|
||||||
|
if err != nil {
|
||||||
|
bomb("cannot retrieve role[%d]: %v", id, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if role == nil {
|
||||||
|
bomb("no such role[%d]", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return role
|
||||||
|
}
|
||||||
|
|
||||||
|
func Node(id int64) *models.Node {
|
||||||
|
node, err := models.NodeGet("id=?", id)
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
if node == nil {
|
||||||
|
bomb("no such node[%d]", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return node
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
package manager
|
||||||
|
|
||||||
|
type ruleSummary struct {
|
||||||
|
id int64 // collect rule id
|
||||||
|
executeAt int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type ruleSummaryHeap []*ruleSummary
|
||||||
|
|
||||||
|
func (h ruleSummaryHeap) Len() int {
|
||||||
|
return len(h)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ruleSummaryHeap) Less(i, j int) bool {
|
||||||
|
return h[i].executeAt < h[j].executeAt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h ruleSummaryHeap) Swap(i, j int) {
|
||||||
|
h[i], h[j] = h[j], h[i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ruleSummaryHeap) Push(x interface{}) {
|
||||||
|
*h = append(*h, x.(*ruleSummary))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ruleSummaryHeap) Pop() interface{} {
|
||||||
|
x := (*h)[len(*h)-1]
|
||||||
|
*h = (*h)[:len(*h)-1]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *ruleSummaryHeap) Top() *ruleSummary {
|
||||||
|
return (*h)[len(*h)-1]
|
||||||
|
}
|
|
@ -0,0 +1,194 @@
|
||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"container/heap"
|
||||||
|
"context"
|
||||||
|
"log"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/cache"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/config"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/core"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type manager struct {
|
||||||
|
ctx context.Context
|
||||||
|
cache *cache.CollectRuleCache
|
||||||
|
config *config.ConfYaml
|
||||||
|
heap ruleSummaryHeap
|
||||||
|
index map[int64]*ruleEntity // add at cache.C , del at executeAt check
|
||||||
|
worker []worker
|
||||||
|
tx chan *ruleEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewManager(cfg *config.ConfYaml, cache *cache.CollectRuleCache) *manager {
|
||||||
|
return &manager{
|
||||||
|
cache: cache,
|
||||||
|
config: cfg,
|
||||||
|
index: make(map[int64]*ruleEntity),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *manager) Start(ctx context.Context) error {
|
||||||
|
workerProcesses := p.config.WorkerProcesses
|
||||||
|
|
||||||
|
p.ctx = ctx
|
||||||
|
p.tx = make(chan *ruleEntity, 1)
|
||||||
|
heap.Init(&p.heap)
|
||||||
|
|
||||||
|
p.worker = make([]worker, workerProcesses)
|
||||||
|
for i := 0; i < workerProcesses; i++ {
|
||||||
|
p.worker[i].rx = p.tx
|
||||||
|
p.worker[i].ctx = ctx
|
||||||
|
// p.worker[i].acc = p.acc
|
||||||
|
|
||||||
|
p.worker[i].loop(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.loop()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// loop schedule collect job and send the metric to transfer
|
||||||
|
func (p *manager) loop() {
|
||||||
|
// main
|
||||||
|
go func() {
|
||||||
|
tick := time.NewTicker(1 * time.Second)
|
||||||
|
defer tick.Stop()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-p.ctx.Done():
|
||||||
|
return
|
||||||
|
case <-p.cache.C:
|
||||||
|
if err := p.SyncRules(); err != nil {
|
||||||
|
log.Printf("manager.SyncRules err %s", err)
|
||||||
|
}
|
||||||
|
case <-tick.C:
|
||||||
|
if err := p.schedule(); err != nil {
|
||||||
|
log.Printf("manager.schedule err %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
// schedule return until there are no jobs
|
||||||
|
func (p *manager) schedule() error {
|
||||||
|
for {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
if p.heap.Len() == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if p.heap.Top().executeAt > now {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
summary := heap.Pop(&p.heap).(*ruleSummary)
|
||||||
|
rule, ok := p.cache.Get(summary.id)
|
||||||
|
if !ok {
|
||||||
|
// drop it if not exist in cache
|
||||||
|
delete(p.index, summary.id)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
entity, ok := p.index[rule.Id]
|
||||||
|
if !ok {
|
||||||
|
// impossible
|
||||||
|
log.Printf("manager.index[%d] not exists", rule.Id)
|
||||||
|
// let's fix it
|
||||||
|
p.index[entity.rule.Id] = entity
|
||||||
|
}
|
||||||
|
|
||||||
|
// update rule
|
||||||
|
if err := entity.update(rule); err != nil {
|
||||||
|
logger.Warningf("ruleEntity update err %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
p.tx <- entity
|
||||||
|
|
||||||
|
summary.executeAt = now + int64(rule.Step)
|
||||||
|
heap.Push(&p.heap, summary)
|
||||||
|
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *manager) SyncRules() error {
|
||||||
|
for _, v := range p.cache.GetAll() {
|
||||||
|
if _, ok := p.index[v.Id]; !ok {
|
||||||
|
p.AddRule(v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *manager) AddRule(rule *models.CollectRule) error {
|
||||||
|
ruleEntity, err := newRuleEntity(rule)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.index[rule.Id] = ruleEntity
|
||||||
|
heap.Push(&p.heap, &ruleSummary{
|
||||||
|
id: rule.Id,
|
||||||
|
executeAt: time.Now().Unix() + int64(rule.Step),
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type collectRule interface {
|
||||||
|
telegraf.Input
|
||||||
|
tags() map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func telegrafInput(rule *models.CollectRule) (telegraf.Input, error) {
|
||||||
|
c, err := collector.GetCollector(rule.CollectType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return c.TelegrafInput(rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
type worker struct {
|
||||||
|
ctx context.Context
|
||||||
|
cache *cache.CollectRuleCache
|
||||||
|
rx chan *ruleEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *worker) loop(id int) {
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-p.ctx.Done():
|
||||||
|
return
|
||||||
|
case entity := <-p.rx:
|
||||||
|
if err := p.do(entity); err != nil {
|
||||||
|
log.Printf("work[%d].do err %s", id, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *worker) do(entity *ruleEntity) error {
|
||||||
|
entity.metrics = entity.metrics[:0]
|
||||||
|
|
||||||
|
// telegraf
|
||||||
|
err := entity.Input.Gather(entity)
|
||||||
|
if len(entity.metrics) == 0 {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// eval expression metrics
|
||||||
|
entity.calc()
|
||||||
|
|
||||||
|
// send
|
||||||
|
core.Push(entity.metrics)
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
|
@ -0,0 +1,398 @@
|
||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
|
"sort"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
)
|
||||||
|
|
||||||
|
type metric struct {
|
||||||
|
name string
|
||||||
|
tags []*telegraf.Tag
|
||||||
|
fields []*telegraf.Field
|
||||||
|
tm time.Time
|
||||||
|
|
||||||
|
tp telegraf.ValueType
|
||||||
|
aggregate bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMetric(
|
||||||
|
name string,
|
||||||
|
tags map[string]string,
|
||||||
|
fields map[string]interface{},
|
||||||
|
tm time.Time,
|
||||||
|
tp ...telegraf.ValueType,
|
||||||
|
) (telegraf.Metric, error) {
|
||||||
|
var vtype telegraf.ValueType
|
||||||
|
if len(tp) > 0 {
|
||||||
|
vtype = tp[0]
|
||||||
|
} else {
|
||||||
|
vtype = telegraf.Untyped
|
||||||
|
}
|
||||||
|
|
||||||
|
m := &metric{
|
||||||
|
name: name,
|
||||||
|
tags: nil,
|
||||||
|
fields: nil,
|
||||||
|
tm: tm,
|
||||||
|
tp: vtype,
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(tags) > 0 {
|
||||||
|
m.tags = make([]*telegraf.Tag, 0, len(tags))
|
||||||
|
for k, v := range tags {
|
||||||
|
m.tags = append(m.tags,
|
||||||
|
&telegraf.Tag{Key: k, Value: v})
|
||||||
|
}
|
||||||
|
sort.Slice(m.tags, func(i, j int) bool { return m.tags[i].Key < m.tags[j].Key })
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fields) > 0 {
|
||||||
|
m.fields = make([]*telegraf.Field, 0, len(fields))
|
||||||
|
for k, v := range fields {
|
||||||
|
v := convertField(v)
|
||||||
|
if v == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
m.AddField(k, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromMetric returns a deep copy of the metric with any tracking information
|
||||||
|
// removed.
|
||||||
|
func FromMetric(other telegraf.Metric) telegraf.Metric {
|
||||||
|
m := &metric{
|
||||||
|
name: other.Name(),
|
||||||
|
tags: make([]*telegraf.Tag, len(other.TagList())),
|
||||||
|
fields: make([]*telegraf.Field, len(other.FieldList())),
|
||||||
|
tm: other.Time(),
|
||||||
|
tp: other.Type(),
|
||||||
|
aggregate: other.IsAggregate(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tag := range other.TagList() {
|
||||||
|
m.tags[i] = &telegraf.Tag{Key: tag.Key, Value: tag.Value}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, field := range other.FieldList() {
|
||||||
|
m.fields[i] = &telegraf.Field{Key: field.Key, Value: field.Value}
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) String() string {
|
||||||
|
return fmt.Sprintf("%s %v %v %d", m.name, m.Tags(), m.Fields(), m.tm.UnixNano())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Name() string {
|
||||||
|
return m.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Tags() map[string]string {
|
||||||
|
tags := make(map[string]string, len(m.tags))
|
||||||
|
for _, tag := range m.tags {
|
||||||
|
tags[tag.Key] = tag.Value
|
||||||
|
}
|
||||||
|
return tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) TagList() []*telegraf.Tag {
|
||||||
|
return m.tags
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Fields() map[string]interface{} {
|
||||||
|
fields := make(map[string]interface{}, len(m.fields))
|
||||||
|
for _, field := range m.fields {
|
||||||
|
fields[field.Key] = field.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
return fields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) FieldList() []*telegraf.Field {
|
||||||
|
return m.fields
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Time() time.Time {
|
||||||
|
return m.tm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Type() telegraf.ValueType {
|
||||||
|
return m.tp
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) SetName(name string) {
|
||||||
|
m.name = name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) AddPrefix(prefix string) {
|
||||||
|
m.name = prefix + m.name
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) AddSuffix(suffix string) {
|
||||||
|
m.name = m.name + suffix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) AddTag(key, value string) {
|
||||||
|
for i, tag := range m.tags {
|
||||||
|
if key > tag.Key {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if key == tag.Key {
|
||||||
|
tag.Value = value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.tags = append(m.tags, nil)
|
||||||
|
copy(m.tags[i+1:], m.tags[i:])
|
||||||
|
m.tags[i] = &telegraf.Tag{Key: key, Value: value}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
m.tags = append(m.tags, &telegraf.Tag{Key: key, Value: value})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) HasTag(key string) bool {
|
||||||
|
for _, tag := range m.tags {
|
||||||
|
if tag.Key == key {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) GetTag(key string) (string, bool) {
|
||||||
|
for _, tag := range m.tags {
|
||||||
|
if tag.Key == key {
|
||||||
|
return tag.Value, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) RemoveTag(key string) {
|
||||||
|
for i, tag := range m.tags {
|
||||||
|
if tag.Key == key {
|
||||||
|
copy(m.tags[i:], m.tags[i+1:])
|
||||||
|
m.tags[len(m.tags)-1] = nil
|
||||||
|
m.tags = m.tags[:len(m.tags)-1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) AddField(key string, value interface{}) {
|
||||||
|
for i, field := range m.fields {
|
||||||
|
if key == field.Key {
|
||||||
|
m.fields[i] = &telegraf.Field{Key: key, Value: convertField(value)}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m.fields = append(m.fields, &telegraf.Field{Key: key, Value: convertField(value)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) HasField(key string) bool {
|
||||||
|
for _, field := range m.fields {
|
||||||
|
if field.Key == key {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) GetField(key string) (interface{}, bool) {
|
||||||
|
for _, field := range m.fields {
|
||||||
|
if field.Key == key {
|
||||||
|
return field.Value, true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) RemoveField(key string) {
|
||||||
|
for i, field := range m.fields {
|
||||||
|
if field.Key == key {
|
||||||
|
copy(m.fields[i:], m.fields[i+1:])
|
||||||
|
m.fields[len(m.fields)-1] = nil
|
||||||
|
m.fields = m.fields[:len(m.fields)-1]
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) SetTime(t time.Time) {
|
||||||
|
m.tm = t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Copy() telegraf.Metric {
|
||||||
|
m2 := &metric{
|
||||||
|
name: m.name,
|
||||||
|
tags: make([]*telegraf.Tag, len(m.tags)),
|
||||||
|
fields: make([]*telegraf.Field, len(m.fields)),
|
||||||
|
tm: m.tm,
|
||||||
|
tp: m.tp,
|
||||||
|
aggregate: m.aggregate,
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, tag := range m.tags {
|
||||||
|
m2.tags[i] = &telegraf.Tag{Key: tag.Key, Value: tag.Value}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, field := range m.fields {
|
||||||
|
m2.fields[i] = &telegraf.Field{Key: field.Key, Value: field.Value}
|
||||||
|
}
|
||||||
|
return m2
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) SetAggregate(b bool) {
|
||||||
|
m.aggregate = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) IsAggregate() bool {
|
||||||
|
return m.aggregate
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) HashID() uint64 {
|
||||||
|
h := fnv.New64a()
|
||||||
|
h.Write([]byte(m.name))
|
||||||
|
h.Write([]byte("\n"))
|
||||||
|
for _, tag := range m.tags {
|
||||||
|
h.Write([]byte(tag.Key))
|
||||||
|
h.Write([]byte("\n"))
|
||||||
|
h.Write([]byte(tag.Value))
|
||||||
|
h.Write([]byte("\n"))
|
||||||
|
}
|
||||||
|
return h.Sum64()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Accept() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Reject() {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *metric) Drop() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert field to a supported type or nil if unconvertible
|
||||||
|
// tranfer to float64
|
||||||
|
func convertField(v interface{}) interface{} {
|
||||||
|
switch v := v.(type) {
|
||||||
|
case float64:
|
||||||
|
return v
|
||||||
|
case int64:
|
||||||
|
return float64(v)
|
||||||
|
case string:
|
||||||
|
return atof(v)
|
||||||
|
case bool:
|
||||||
|
return btof(v)
|
||||||
|
case int:
|
||||||
|
return float64(v)
|
||||||
|
case uint:
|
||||||
|
return float64(v)
|
||||||
|
case uint64:
|
||||||
|
return float64(v)
|
||||||
|
case []byte:
|
||||||
|
return atof(string(v))
|
||||||
|
case int32:
|
||||||
|
return float64(v)
|
||||||
|
case int16:
|
||||||
|
return float64(v)
|
||||||
|
case int8:
|
||||||
|
return float64(v)
|
||||||
|
case uint32:
|
||||||
|
return float64(v)
|
||||||
|
case uint16:
|
||||||
|
return float64(v)
|
||||||
|
case uint8:
|
||||||
|
return float64(v)
|
||||||
|
case float32:
|
||||||
|
return float64(v)
|
||||||
|
case *float64:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *int64:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *string:
|
||||||
|
if v != nil {
|
||||||
|
return atof(*v)
|
||||||
|
}
|
||||||
|
case *bool:
|
||||||
|
if v != nil {
|
||||||
|
return btof(*v)
|
||||||
|
}
|
||||||
|
case *int:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *uint:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *uint64:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *[]byte:
|
||||||
|
if v != nil {
|
||||||
|
return atof(string(*v))
|
||||||
|
}
|
||||||
|
case *int32:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *int16:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *int8:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *uint32:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *uint16:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *uint8:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
case *float32:
|
||||||
|
if v != nil {
|
||||||
|
return float64(*v)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func atof(s string) interface{} {
|
||||||
|
if f, err := strconv.ParseFloat(s, 64); err != nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func btof(b bool) interface{} {
|
||||||
|
if b {
|
||||||
|
return float64(1)
|
||||||
|
}
|
||||||
|
return float64(0)
|
||||||
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
package manager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"strconv"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/dataobj"
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/monapi/collector"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/cache"
|
||||||
|
"github.com/influxdata/telegraf"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// not thread-safe
|
||||||
|
type ruleEntity struct {
|
||||||
|
sync.RWMutex
|
||||||
|
telegraf.Input
|
||||||
|
rule *models.CollectRule
|
||||||
|
tags map[string]string
|
||||||
|
precision time.Duration
|
||||||
|
metrics []*dataobj.MetricValue
|
||||||
|
}
|
||||||
|
|
||||||
|
func newRuleEntity(rule *models.CollectRule) (*ruleEntity, error) {
|
||||||
|
c, err := collector.GetCollector(rule.CollectType)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
input, err := c.TelegrafInput(rule)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
tags, err := dataobj.SplitTagsString(rule.Tags)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &ruleEntity{
|
||||||
|
Input: input,
|
||||||
|
rule: rule,
|
||||||
|
tags: tags,
|
||||||
|
metrics: []*dataobj.MetricValue{},
|
||||||
|
precision: time.Second,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// calc metrics with expression
|
||||||
|
func (p *ruleEntity) calc() error {
|
||||||
|
if len(p.metrics) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
sample := p.metrics[0]
|
||||||
|
|
||||||
|
configs, ok := cache.GetMetricExprs(p.rule.CollectType)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
vars := map[string]float64{}
|
||||||
|
for _, v := range p.metrics {
|
||||||
|
logger.Debugf("get v[%s] %f", v.Metric, v.Value)
|
||||||
|
vars[v.Metric] = v.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: add some variable from system or rule
|
||||||
|
for _, config := range configs {
|
||||||
|
f, err := config.Calc(vars)
|
||||||
|
if err != nil {
|
||||||
|
logger.Debugf("calc err %s", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
p.metrics = append(p.metrics, &dataobj.MetricValue{
|
||||||
|
Nid: sample.Nid,
|
||||||
|
Metric: config.Name,
|
||||||
|
Timestamp: sample.Timestamp,
|
||||||
|
Step: sample.Step,
|
||||||
|
CounterType: config.Type,
|
||||||
|
TagsMap: sample.TagsMap,
|
||||||
|
Value: f,
|
||||||
|
ValueUntyped: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) update(rule *models.CollectRule) error {
|
||||||
|
if p.rule.LastUpdated == rule.LastUpdated {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
input, err := telegrafInput(rule)
|
||||||
|
if err != nil {
|
||||||
|
// ignore error, use old config
|
||||||
|
log.Printf("telegrafInput() id %d type %s name %s err %s",
|
||||||
|
rule.Id, rule.CollectType, rule.Name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
tags, err := dataobj.SplitTagsString(rule.Tags)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Input = input
|
||||||
|
p.rule = rule
|
||||||
|
p.tags = tags
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://docs.influxdata.com/telegraf/v1.14/data_formats/output/prometheus/
|
||||||
|
func (p *ruleEntity) MakeMetric(metric telegraf.Metric) []*dataobj.MetricValue {
|
||||||
|
tags := map[string]string{}
|
||||||
|
for _, v := range metric.TagList() {
|
||||||
|
tags[v.Key] = v.Value
|
||||||
|
}
|
||||||
|
|
||||||
|
for k, v := range p.tags {
|
||||||
|
tags[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
nid := strconv.FormatInt(p.rule.Nid, 10)
|
||||||
|
name := metric.Name()
|
||||||
|
ts := metric.Time().Unix()
|
||||||
|
step := int64(p.rule.Step) // deprecated
|
||||||
|
|
||||||
|
fields := metric.Fields()
|
||||||
|
ms := make([]*dataobj.MetricValue, 0, len(fields))
|
||||||
|
for k, v := range fields {
|
||||||
|
f, ok := v.(float64)
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
c, ok := cache.Metric(name+"_"+k, metric.Type())
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
ms = append(ms, &dataobj.MetricValue{
|
||||||
|
Nid: nid,
|
||||||
|
Metric: c.Name,
|
||||||
|
Timestamp: ts,
|
||||||
|
Step: step,
|
||||||
|
CounterType: c.Type,
|
||||||
|
TagsMap: tags,
|
||||||
|
Value: f,
|
||||||
|
ValueUntyped: f,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return ms
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) AddFields(
|
||||||
|
measurement string,
|
||||||
|
fields map[string]interface{},
|
||||||
|
tags map[string]string,
|
||||||
|
t ...time.Time,
|
||||||
|
) {
|
||||||
|
p.addFields(measurement, tags, fields, telegraf.Untyped, t...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) AddGauge(
|
||||||
|
measurement string,
|
||||||
|
fields map[string]interface{},
|
||||||
|
tags map[string]string,
|
||||||
|
t ...time.Time,
|
||||||
|
) {
|
||||||
|
p.addFields(measurement, tags, fields, telegraf.Gauge, t...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) AddCounter(
|
||||||
|
measurement string,
|
||||||
|
fields map[string]interface{},
|
||||||
|
tags map[string]string,
|
||||||
|
t ...time.Time,
|
||||||
|
) {
|
||||||
|
p.addFields(measurement, tags, fields, telegraf.Counter, t...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) AddSummary(
|
||||||
|
measurement string,
|
||||||
|
fields map[string]interface{},
|
||||||
|
tags map[string]string,
|
||||||
|
t ...time.Time,
|
||||||
|
) {
|
||||||
|
p.addFields(measurement, tags, fields, telegraf.Summary, t...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) AddHistogram(
|
||||||
|
measurement string,
|
||||||
|
fields map[string]interface{},
|
||||||
|
tags map[string]string,
|
||||||
|
t ...time.Time,
|
||||||
|
) {
|
||||||
|
p.addFields(measurement, tags, fields, telegraf.Histogram, t...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) AddMetric(m telegraf.Metric) {
|
||||||
|
m.SetTime(m.Time().Round(p.precision))
|
||||||
|
if metrics := p.MakeMetric(m); m != nil {
|
||||||
|
p.pushMetrics(metrics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) pushMetrics(metrics []*dataobj.MetricValue) {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
p.metrics = append(p.metrics, metrics...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) addFields(
|
||||||
|
measurement string,
|
||||||
|
tags map[string]string,
|
||||||
|
fields map[string]interface{},
|
||||||
|
tp telegraf.ValueType,
|
||||||
|
t ...time.Time,
|
||||||
|
) {
|
||||||
|
m, err := NewMetric(measurement, tags, fields, p.getTime(t), tp)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if metrics := p.MakeMetric(m); m != nil {
|
||||||
|
p.pushMetrics(metrics)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AddError passes a runtime error to the accumulator.
|
||||||
|
// The error will be tagged with the plugin name and written to the log.
|
||||||
|
func (p *ruleEntity) AddError(err error) {
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("Error in plugin: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) SetPrecision(precision time.Duration) {
|
||||||
|
p.precision = precision
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) getTime(t []time.Time) time.Time {
|
||||||
|
var timestamp time.Time
|
||||||
|
if len(t) > 0 {
|
||||||
|
timestamp = t[0]
|
||||||
|
} else {
|
||||||
|
timestamp = time.Now()
|
||||||
|
}
|
||||||
|
return timestamp.Round(p.precision)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *ruleEntity) WithTracking(maxTracked int) telegraf.TrackingAccumulator {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,132 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/common/identity"
|
||||||
|
"github.com/didi/nightingale/src/common/loggeri"
|
||||||
|
"github.com/didi/nightingale/src/common/report"
|
||||||
|
"github.com/didi/nightingale/src/toolkits/stats"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/cache"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/config"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/core"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/http"
|
||||||
|
"github.com/didi/nightingale/src/modules/prober/manager"
|
||||||
|
|
||||||
|
_ "github.com/didi/nightingale/src/modules/monapi/plugins/all"
|
||||||
|
_ "github.com/go-sql-driver/mysql"
|
||||||
|
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/toolkits/pkg/file"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
"github.com/toolkits/pkg/runner"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
vers *bool
|
||||||
|
help *bool
|
||||||
|
conf *string
|
||||||
|
|
||||||
|
version = "No Version Provided"
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
vers = flag.Bool("v", false, "display the version.")
|
||||||
|
help = flag.Bool("h", false, "print this help.")
|
||||||
|
conf = flag.String("f", "", "specify configuration file.")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *vers {
|
||||||
|
fmt.Println("Version:", version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *help {
|
||||||
|
flag.Usage()
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
aconf()
|
||||||
|
pconf()
|
||||||
|
start()
|
||||||
|
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
cfg := config.Config
|
||||||
|
identity.Parse()
|
||||||
|
loggeri.Init(cfg.Logger)
|
||||||
|
|
||||||
|
go stats.Init("n9e.prober")
|
||||||
|
go report.Init(cfg.Report, "rdb")
|
||||||
|
|
||||||
|
cache.Init(ctx)
|
||||||
|
|
||||||
|
if cfg.Logger.Level != "DEBUG" {
|
||||||
|
gin.SetMode(gin.ReleaseMode)
|
||||||
|
}
|
||||||
|
|
||||||
|
core.InitRpcClients()
|
||||||
|
|
||||||
|
manager.NewManager(cfg, cache.CollectRule).Start(ctx)
|
||||||
|
|
||||||
|
http.Start()
|
||||||
|
|
||||||
|
ending(cancel)
|
||||||
|
}
|
||||||
|
|
||||||
|
// auto detect configuration file
|
||||||
|
func aconf() {
|
||||||
|
if *conf != "" && file.IsExist(*conf) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
*conf = "etc/prober.local.yml"
|
||||||
|
if file.IsExist(*conf) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
*conf = "etc/prober.yml"
|
||||||
|
if file.IsExist(*conf) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println("no configuration file for prober")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// parse configuration file
|
||||||
|
func pconf() {
|
||||||
|
if err := config.Parse(*conf); err != nil {
|
||||||
|
fmt.Println("cannot parse configuration file:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func start() {
|
||||||
|
runner.Init()
|
||||||
|
fmt.Println("prober start, use configuration file:", *conf)
|
||||||
|
fmt.Println("runner.Cwd:", runner.Cwd)
|
||||||
|
fmt.Println("runner.Hostname:", runner.Hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ending(cancel context.CancelFunc) {
|
||||||
|
c := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||||
|
select {
|
||||||
|
case <-c:
|
||||||
|
fmt.Printf("stop signal caught, stopping... pid=%d\n", os.Getpid())
|
||||||
|
}
|
||||||
|
|
||||||
|
cancel()
|
||||||
|
logger.Close()
|
||||||
|
http.Shutdown()
|
||||||
|
fmt.Printf("%s stopped successfully\n", os.Args[0])
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/config"
|
||||||
|
)
|
||||||
|
|
||||||
|
var defaultAuth Authenticator
|
||||||
|
|
||||||
|
func Init(cf config.AuthExtraSection) {
|
||||||
|
defaultAuth = *New(cf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WhiteListAccess(remoteAddr string) error {
|
||||||
|
return defaultAuth.WhiteListAccess(remoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostLogin check user status after login
|
||||||
|
func PostLogin(user *models.User, loginErr error) error {
|
||||||
|
return defaultAuth.PostLogin(user, loginErr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ChangePassword(user *models.User, password string) error {
|
||||||
|
return defaultAuth.ChangePassword(user, password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckPassword(password string) error {
|
||||||
|
return defaultAuth.CheckPassword(password)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangePasswordRedirect check user should change password before login
|
||||||
|
// return change password redirect url
|
||||||
|
func ChangePasswordRedirect(user *models.User, redirect string) string {
|
||||||
|
return defaultAuth.ChangePasswordRedirect(user, redirect)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start() error {
|
||||||
|
return defaultAuth.Start()
|
||||||
|
}
|
|
@ -0,0 +1,363 @@
|
||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/cache"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/config"
|
||||||
|
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
ChangePasswordURL = "/change-password"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Authenticator struct {
|
||||||
|
extraMode bool
|
||||||
|
whiteList bool
|
||||||
|
frozenTime int64
|
||||||
|
writenOffTime int64
|
||||||
|
userExpire bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// description:"enable user expire control, active -> frozen -> writen-off"
|
||||||
|
func New(cf config.AuthExtraSection) *Authenticator {
|
||||||
|
if !cf.Enable {
|
||||||
|
return &Authenticator{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Authenticator{
|
||||||
|
extraMode: true,
|
||||||
|
whiteList: cf.WhiteList,
|
||||||
|
frozenTime: 86400 * int64(cf.FrozenDays),
|
||||||
|
writenOffTime: 86400 * int64(cf.WritenOffDays),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Authenticator) WhiteListAccess(remoteAddr string) error {
|
||||||
|
if !p.whiteList {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return models.WhiteListAccess(remoteAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ChangePasswordRedirect check user should change password before login
|
||||||
|
// return change password redirect url
|
||||||
|
func (p *Authenticator) ChangePasswordRedirect(user *models.User, redirect string) string {
|
||||||
|
if !p.extraMode {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
cf := cache.AuthConfig()
|
||||||
|
|
||||||
|
var reason string
|
||||||
|
if user.PwdUpdatedAt == 0 {
|
||||||
|
reason = _s("First Login, please change the password in time")
|
||||||
|
} else if user.PwdUpdatedAt+cf.PwdExpiresIn*86400*30 < time.Now().Unix() {
|
||||||
|
reason = _s("Password expired, please change the password in time")
|
||||||
|
} else {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
v := url.Values{
|
||||||
|
"redirect": {redirect},
|
||||||
|
"username": {user.Username},
|
||||||
|
"reason": {reason},
|
||||||
|
"pwdRules": cf.PwdRules(),
|
||||||
|
}
|
||||||
|
return ChangePasswordURL + "?" + v.Encode()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Authenticator) PostLogin(user *models.User, loginErr error) (err error) {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
defer func() {
|
||||||
|
if user == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
user.LoggedAt = now
|
||||||
|
}
|
||||||
|
user.Update("status", "login_err_num", "locked_at", "updated_at", "logged_at")
|
||||||
|
}()
|
||||||
|
|
||||||
|
if !p.extraMode || user == nil {
|
||||||
|
err = loginErr
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cf := cache.AuthConfig()
|
||||||
|
|
||||||
|
if user.Type == models.USER_T_TEMP && (now < user.ActiveBegin || user.ActiveEnd < now) {
|
||||||
|
err = _e("Temporary user has expired")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
status := user.Status
|
||||||
|
retry:
|
||||||
|
switch user.Status {
|
||||||
|
case models.USER_S_ACTIVE:
|
||||||
|
err = activeUserAccess(cf, user, loginErr)
|
||||||
|
case models.USER_S_INACTIVE:
|
||||||
|
err = inactiveUserAccess(cf, user, loginErr)
|
||||||
|
case models.USER_S_LOCKED:
|
||||||
|
err = lockedUserAccess(cf, user, loginErr)
|
||||||
|
case models.USER_S_FROZEN:
|
||||||
|
err = frozenUserAccess(cf, user, loginErr)
|
||||||
|
case models.USER_S_WRITEN_OFF:
|
||||||
|
err = writenOffUserAccess(cf, user, loginErr)
|
||||||
|
default:
|
||||||
|
err = _e("Invalid user status %d", user.Status)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if user's status has been changed goto retry
|
||||||
|
if user.Status != status {
|
||||||
|
status = user.Status
|
||||||
|
goto retry
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Authenticator) ChangePassword(user *models.User, password string) (err error) {
|
||||||
|
defer func() {
|
||||||
|
if err == nil {
|
||||||
|
err = user.Update("password", "passwords",
|
||||||
|
"pwd_updated_at", "updated_at")
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
changePassword := func() error {
|
||||||
|
pwd, err := models.CryptoPass(password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
now := time.Now().Unix()
|
||||||
|
user.Password = pwd
|
||||||
|
user.PwdUpdatedAt = now
|
||||||
|
user.UpdatedAt = now
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if !p.extraMode {
|
||||||
|
return changePassword()
|
||||||
|
}
|
||||||
|
|
||||||
|
// precheck
|
||||||
|
cf := cache.AuthConfig()
|
||||||
|
if err = checkPassword(cf, password); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = changePassword(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var passwords []string
|
||||||
|
err = json.Unmarshal([]byte(user.Passwords), &passwords)
|
||||||
|
if err != nil {
|
||||||
|
// reset passwords
|
||||||
|
passwords = []string{user.Password}
|
||||||
|
b, _ := json.Marshal(passwords)
|
||||||
|
user.Passwords = string(b)
|
||||||
|
err = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, v := range passwords {
|
||||||
|
if user.Password == v {
|
||||||
|
err = _e("The password is the same as the old password")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
passwords = append(passwords, user.Password)
|
||||||
|
if n := len(passwords) - cf.PwdHistorySize; n > 0 {
|
||||||
|
passwords = passwords[n:]
|
||||||
|
}
|
||||||
|
|
||||||
|
b, _ := json.Marshal(passwords)
|
||||||
|
user.Passwords = string(b)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Authenticator) CheckPassword(password string) error {
|
||||||
|
if !p.extraMode {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return checkPassword(cache.AuthConfig(), password)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Authenticator) Start() error {
|
||||||
|
if !p.extraMode {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
if p.frozenTime > 0 {
|
||||||
|
// 3个月以上未登录,用户自动变为休眠状态
|
||||||
|
if _, err := models.DB["rdb"].Exec("update user set status=?, updated_at=?, locked_at=? where ((logged_at > 0 and logged_at<?) or (logged_at == 0 and created_at < ?)) and status in (?,?,?)",
|
||||||
|
models.USER_S_FROZEN, now, now, now-p.frozenTime,
|
||||||
|
models.USER_S_ACTIVE, models.USER_S_INACTIVE, models.USER_S_LOCKED); err != nil {
|
||||||
|
logger.Errorf("update user status error %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.writenOffTime > 0 {
|
||||||
|
// 变为休眠状态后1年未激活,用户自动变为已注销状态
|
||||||
|
if _, err := models.DB["rdb"].Exec("update user set status=?, updated_at=? where locked_at<? and status=?",
|
||||||
|
models.USER_S_WRITEN_OFF, now, now-p.writenOffTime, models.USER_S_FROZEN); err != nil {
|
||||||
|
logger.Errorf("update user status error %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset login err num before 24 hours ago
|
||||||
|
if _, err := models.DB["rdb"].Exec("update user set login_err_num=0, updated_at=? where updated_at<? and login_err_num>0", now, now-86400); err != nil {
|
||||||
|
logger.Errorf("update user login err num error %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(time.Hour)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func activeUserAccess(cf *models.AuthConfig, user *models.User, loginErr error) error {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
|
||||||
|
if loginErr != nil {
|
||||||
|
if cf.MaxNumErr > 0 {
|
||||||
|
user.UpdatedAt = now
|
||||||
|
user.LoginErrNum++
|
||||||
|
if user.LoginErrNum >= cf.MaxNumErr {
|
||||||
|
user.Status = models.USER_S_LOCKED
|
||||||
|
user.LockedAt = now
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return _e("Incorrect login/password %s times, you still have %s chances",
|
||||||
|
user.LoginErrNum, cf.MaxNumErr-user.LoginErrNum)
|
||||||
|
} else {
|
||||||
|
return loginErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
user.LoginErrNum = 0
|
||||||
|
user.UpdatedAt = now
|
||||||
|
|
||||||
|
if cf.MaxSessionNumber > 0 {
|
||||||
|
if n, err := models.SessionUserAll(user.Username); err != nil {
|
||||||
|
return err
|
||||||
|
} else if n >= cf.MaxSessionNumber {
|
||||||
|
return _e("The limited sessions %d", cf.MaxSessionNumber)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cf.PwdExpiresIn > 0 && user.PwdUpdatedAt > 0 {
|
||||||
|
// debug account
|
||||||
|
// TODO: remove me
|
||||||
|
if user.Username == "Demo.2022" {
|
||||||
|
if now-user.PwdUpdatedAt > cf.PwdExpiresIn*60 {
|
||||||
|
return _e("Password has been expired")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if now-user.PwdUpdatedAt > cf.PwdExpiresIn*30*86400 {
|
||||||
|
return _e("Password has been expired")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func inactiveUserAccess(cf *models.AuthConfig, user *models.User, loginErr error) error {
|
||||||
|
return _e("User is inactive")
|
||||||
|
}
|
||||||
|
func lockedUserAccess(cf *models.AuthConfig, user *models.User, loginErr error) error {
|
||||||
|
now := time.Now().Unix()
|
||||||
|
if now-user.LockedAt > cf.LockTime*60 {
|
||||||
|
user.Status = models.USER_S_ACTIVE
|
||||||
|
user.LoginErrNum = 0
|
||||||
|
user.UpdatedAt = now
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return _e("User is locked")
|
||||||
|
}
|
||||||
|
|
||||||
|
func frozenUserAccess(cf *models.AuthConfig, user *models.User, loginErr error) error {
|
||||||
|
return _e("User is frozen")
|
||||||
|
}
|
||||||
|
|
||||||
|
func writenOffUserAccess(cf *models.AuthConfig, user *models.User, loginErr error) error {
|
||||||
|
return _e("User is writen off")
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkPassword(cf *models.AuthConfig, passwd string) error {
|
||||||
|
indNum := [4]int{0, 0, 0, 0}
|
||||||
|
spCode := []byte{'!', '@', '#', '$', '%', '^', '&', '*', '_', '-', '~', '.', ',', '<', '>', '/', ';', ':', '|', '?', '+', '='}
|
||||||
|
|
||||||
|
if cf.PwdMinLenght > 0 && len(passwd) < cf.PwdMinLenght {
|
||||||
|
return _e("Password too short (min:%d) %s", cf.PwdMinLenght, cf.MustInclude())
|
||||||
|
}
|
||||||
|
|
||||||
|
passwdByte := []byte(passwd)
|
||||||
|
|
||||||
|
for _, i := range passwdByte {
|
||||||
|
|
||||||
|
if i >= 'A' && i <= 'Z' {
|
||||||
|
indNum[0] = 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= 'a' && i <= 'z' {
|
||||||
|
indNum[1] = 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if i >= '0' && i <= '9' {
|
||||||
|
indNum[2] = 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
has := false
|
||||||
|
for _, s := range spCode {
|
||||||
|
if i == s {
|
||||||
|
indNum[3] = 1
|
||||||
|
has = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !has {
|
||||||
|
return _e("character: %s not supported", string(i))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if cf.PwdMustIncludeFlag&models.PWD_INCLUDE_UPPER > 0 && indNum[0] == 0 {
|
||||||
|
return _e("Invalid Password, %s", cf.MustInclude())
|
||||||
|
}
|
||||||
|
|
||||||
|
if cf.PwdMustIncludeFlag&models.PWD_INCLUDE_LOWER > 0 && indNum[1] == 0 {
|
||||||
|
return _e("Invalid Password, %s", cf.MustInclude())
|
||||||
|
}
|
||||||
|
|
||||||
|
if cf.PwdMustIncludeFlag&models.PWD_INCLUDE_NUMBER > 0 && indNum[2] == 0 {
|
||||||
|
return _e("Invalid Password, %s", cf.MustInclude())
|
||||||
|
}
|
||||||
|
|
||||||
|
if cf.PwdMustIncludeFlag&models.PWD_INCLUDE_SPEC_CHAR > 0 && indNum[3] == 0 {
|
||||||
|
return _e("Invalid Password, %s", cf.MustInclude())
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _e(format string, a ...interface{}) error {
|
||||||
|
return fmt.Errorf(i18n.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func _s(format string, a ...interface{}) string {
|
||||||
|
return i18n.Sprintf(format, a...)
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultCache = &Cache{
|
||||||
|
interval: 10, // Seconds
|
||||||
|
config: configCache{
|
||||||
|
authConfig: &models.DefaultAuthConfig,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCache(interval int) *Cache {
|
||||||
|
return &Cache{
|
||||||
|
interval: interval,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func AuthConfig() *models.AuthConfig {
|
||||||
|
return DefaultCache.config.AuthConfig()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start() {
|
||||||
|
DefaultCache.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stop() {
|
||||||
|
DefaultCache.Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
type Cache struct {
|
||||||
|
session sessionCache
|
||||||
|
config configCache
|
||||||
|
|
||||||
|
interval int
|
||||||
|
ctx context.Context
|
||||||
|
cancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Cache) Start() {
|
||||||
|
p.ctx, p.cancel = context.WithCancel(context.Background())
|
||||||
|
|
||||||
|
p.config.loop(p.ctx, p.interval)
|
||||||
|
// p.session.loop(ctx, p.interval)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Cache) Stop() {
|
||||||
|
p.cancel()
|
||||||
|
}
|
|
@ -0,0 +1,52 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type configCache struct {
|
||||||
|
sync.RWMutex
|
||||||
|
authConfig *models.AuthConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *configCache) AuthConfig() *models.AuthConfig {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
return p.authConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *configCache) loop(ctx context.Context, interval int) {
|
||||||
|
go func() {
|
||||||
|
t := time.NewTicker(time.Duration(interval) * time.Second)
|
||||||
|
defer t.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-t.C:
|
||||||
|
if err := p.update(); err != nil {
|
||||||
|
logger.Errorf("configCache update err %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *configCache) update() error {
|
||||||
|
authConfig, err := models.AuthConfigGet()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
p.Lock()
|
||||||
|
p.authConfig = authConfig
|
||||||
|
p.Unlock()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package cache
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type sessionCache struct {
|
||||||
|
sync.RWMutex
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *sessionCache) loop(ctx context.Context, interval int) {
|
||||||
|
func() {
|
||||||
|
t := time.NewTicker(time.Duration(interval) * time.Second)
|
||||||
|
defer t.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case <-t.C:
|
||||||
|
if err := p.update(); err != nil {
|
||||||
|
logger.Errorf("sessionCache update err %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *sessionCache) update() error {
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -19,8 +19,20 @@ type ConfigT struct {
|
||||||
Sender map[string]senderSection `yaml:"sender"`
|
Sender map[string]senderSection `yaml:"sender"`
|
||||||
RabbitMQ rabbitmqSection `yaml:"rabbitmq"`
|
RabbitMQ rabbitmqSection `yaml:"rabbitmq"`
|
||||||
WeChat wechatSection `yaml:"wechat"`
|
WeChat wechatSection `yaml:"wechat"`
|
||||||
Captcha bool `yaml:"captcha"`
|
|
||||||
I18n i18n.I18nSection `yaml:"i18n"`
|
I18n i18n.I18nSection `yaml:"i18n"`
|
||||||
|
Auth authSection `yaml:"auth"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type authSection struct {
|
||||||
|
Captcha bool `yaml:"captcha"`
|
||||||
|
ExtraMode AuthExtraSection `yaml:"extraMode"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthExtraSection struct {
|
||||||
|
Enable bool `yaml:"enable"`
|
||||||
|
WhiteList bool `yaml:"whiteList"`
|
||||||
|
FrozenDays int `yaml:"frozenDays"`
|
||||||
|
WritenOffDays int `yaml:"writenOffDays"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type wechatSection struct {
|
type wechatSection struct {
|
||||||
|
@ -47,9 +59,18 @@ type ssoSection struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type httpSection struct {
|
type httpSection struct {
|
||||||
Mode string `yaml:"mode"`
|
Mode string `yaml:"mode"`
|
||||||
CookieName string `yaml:"cookieName"`
|
Session SessionSection `yaml:"session"`
|
||||||
CookieDomain string `yaml:"cookieDomain"`
|
}
|
||||||
|
|
||||||
|
type SessionSection struct {
|
||||||
|
CookieName string `yaml:"cookieName"`
|
||||||
|
SidLength int `yaml:"sidLength"`
|
||||||
|
HttpOnly bool `yaml:"httpOnly"`
|
||||||
|
Domain string `yaml:"domain"`
|
||||||
|
GcInterval int64 `yaml:"gcInterval"`
|
||||||
|
CookieLifetime int64 `yaml:"cookieLifetime"`
|
||||||
|
Storage string `yaml:"storage" description:"mem|db(defualt)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ldapSection struct {
|
type ldapSection struct {
|
||||||
|
@ -129,6 +150,17 @@ func Parse() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// if Config.HTTP.Session.CookieLifetime == 0 {
|
||||||
|
// Config.HTTP.Session.CookieLifetime = 24 * 3600
|
||||||
|
// }
|
||||||
|
|
||||||
|
if Config.HTTP.Session.GcInterval == 0 {
|
||||||
|
Config.HTTP.Session.GcInterval = 60
|
||||||
|
}
|
||||||
|
|
||||||
|
if Config.HTTP.Session.SidLength == 0 {
|
||||||
|
Config.HTTP.Session.SidLength = 32
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,17 +12,31 @@ import (
|
||||||
"github.com/didi/nightingale/src/common/address"
|
"github.com/didi/nightingale/src/common/address"
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/models"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/config"
|
"github.com/didi/nightingale/src/modules/rdb/config"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/session"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func shouldStartSession() gin.HandlerFunc {
|
||||||
|
return func(c *gin.Context) {
|
||||||
|
sessionStart(c)
|
||||||
|
c.Next()
|
||||||
|
sessionUpdate(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func shouldBeLogin() gin.HandlerFunc {
|
func shouldBeLogin() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
c.Set("username", mustUsername(c))
|
sessionStart(c)
|
||||||
|
username := mustUsername(c)
|
||||||
|
logger.Debugf("set username %s", username)
|
||||||
|
c.Set("username", username)
|
||||||
c.Next()
|
c.Next()
|
||||||
|
sessionUpdate(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func shouldBeRoot() gin.HandlerFunc {
|
func shouldBeRoot() gin.HandlerFunc {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
|
sessionStart(c)
|
||||||
username := mustUsername(c)
|
username := mustUsername(c)
|
||||||
|
|
||||||
user, err := models.UserGet("username=?", username)
|
user, err := models.UserGet("username=?", username)
|
||||||
|
@ -35,6 +49,7 @@ func shouldBeRoot() gin.HandlerFunc {
|
||||||
c.Set("username", username)
|
c.Set("username", username)
|
||||||
c.Set("user", user)
|
c.Set("user", user)
|
||||||
c.Next()
|
c.Next()
|
||||||
|
sessionUpdate(c)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +88,7 @@ func shouldBeService() gin.HandlerFunc {
|
||||||
}
|
}
|
||||||
|
|
||||||
func mustUsername(c *gin.Context) string {
|
func mustUsername(c *gin.Context) string {
|
||||||
username := cookieUsername(c)
|
username := sessionUsername(c)
|
||||||
if username == "" {
|
if username == "" {
|
||||||
username = headerUsername(c)
|
username = headerUsername(c)
|
||||||
}
|
}
|
||||||
|
@ -85,10 +100,6 @@ func mustUsername(c *gin.Context) string {
|
||||||
return username
|
return username
|
||||||
}
|
}
|
||||||
|
|
||||||
func cookieUsername(c *gin.Context) string {
|
|
||||||
return models.UsernameByUUID(readCookieUser(c))
|
|
||||||
}
|
|
||||||
|
|
||||||
func headerUsername(c *gin.Context) string {
|
func headerUsername(c *gin.Context) string {
|
||||||
token := c.GetHeader("X-User-Token")
|
token := c.GetHeader("X-User-Token")
|
||||||
if token == "" {
|
if token == "" {
|
||||||
|
@ -108,17 +119,52 @@ func headerUsername(c *gin.Context) string {
|
||||||
return ut.Username
|
return ut.Username
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------
|
func sessionStart(c *gin.Context) error {
|
||||||
|
s, err := session.Start(c.Writer, c.Request)
|
||||||
func readCookieUser(c *gin.Context) string {
|
|
||||||
uuid, err := c.Cookie(config.Config.HTTP.CookieName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return err
|
||||||
|
}
|
||||||
|
c.Request = c.Request.WithContext(session.NewContext(c.Request.Context(), s))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sessionUpdate(c *gin.Context) {
|
||||||
|
if store, ok := session.FromContext(c.Request.Context()); ok {
|
||||||
|
err := store.Update(c.Writer)
|
||||||
|
if err != nil {
|
||||||
|
logger.Errorf("session update err %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sessionDestory(c *gin.Context) (sid string, err error) {
|
||||||
|
if sid, err = session.Destroy(c.Writer, c.Request); sid != "" {
|
||||||
|
models.SessionCacheDelete(sid)
|
||||||
}
|
}
|
||||||
|
|
||||||
return uuid
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeCookieUser(c *gin.Context, uuid string) {
|
func sessionUsername(c *gin.Context) string {
|
||||||
c.SetCookie(config.Config.HTTP.CookieName, uuid, 3600*24, "/", config.Config.HTTP.CookieDomain, false, true)
|
s, ok := session.FromContext(c.Request.Context())
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return s.Get("username")
|
||||||
|
}
|
||||||
|
|
||||||
|
func sessionLogin(c *gin.Context, username, remoteAddr string) {
|
||||||
|
s, ok := session.FromContext(c.Request.Context())
|
||||||
|
if !ok {
|
||||||
|
logger.Warningf("session.Start() err not found sessionStore")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := s.Set("username", username); err != nil {
|
||||||
|
logger.Warningf("session.Set() err %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if err := s.Set("remoteAddr", remoteAddr); err != nil {
|
||||||
|
logger.Warningf("session.Set() err %s", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,25 +10,29 @@ func Config(r *gin.Engine) {
|
||||||
{
|
{
|
||||||
notLogin.GET("/ping", ping)
|
notLogin.GET("/ping", ping)
|
||||||
notLogin.GET("/ldap/used", ldapUsed)
|
notLogin.GET("/ldap/used", ldapUsed)
|
||||||
notLogin.POST("/auth/login", login)
|
|
||||||
notLogin.GET("/auth/logout", logout)
|
|
||||||
notLogin.GET("/ops/global", globalOpsGet)
|
notLogin.GET("/ops/global", globalOpsGet)
|
||||||
notLogin.GET("/ops/local", localOpsGet)
|
notLogin.GET("/ops/local", localOpsGet)
|
||||||
notLogin.GET("/roles/global", globalRoleGet)
|
notLogin.GET("/roles/global", globalRoleGet)
|
||||||
notLogin.GET("/roles/local", localRoleGet)
|
notLogin.GET("/roles/local", localRoleGet)
|
||||||
notLogin.POST("/users/invite", userInvitePost)
|
notLogin.POST("/users/invite", userInvitePost)
|
||||||
|
|
||||||
notLogin.GET("/auth/v2/authorize", authAuthorizeV2)
|
notLogin.POST("/auth/send-login-code", sendLoginCode)
|
||||||
notLogin.GET("/auth/v2/callback", authCallbackV2)
|
notLogin.POST("/auth/send-rst-code", sendRstCode)
|
||||||
notLogin.GET("/auth/v2/logout", logoutV2)
|
|
||||||
|
|
||||||
notLogin.POST("/auth/send-login-code-by-sms", v1SendLoginCodeBySms)
|
|
||||||
notLogin.POST("/auth/send-login-code-by-email", v1SendLoginCodeByEmail)
|
|
||||||
notLogin.POST("/auth/send-rst-code-by-sms", sendRstCodeBySms)
|
|
||||||
notLogin.POST("/auth/rst-password", rstPassword)
|
notLogin.POST("/auth/rst-password", rstPassword)
|
||||||
notLogin.GET("/auth/captcha", captchaGet)
|
notLogin.GET("/auth/captcha", captchaGet)
|
||||||
|
|
||||||
notLogin.GET("/v2/nodes", nodeGets)
|
notLogin.GET("/v2/nodes", nodeGets)
|
||||||
|
notLogin.GET("/pwd-rules", pwdRulesGet)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStarted := r.Group("/api/rdb").Use(shouldStartSession())
|
||||||
|
{
|
||||||
|
sessionStarted.POST("/auth/login", login)
|
||||||
|
sessionStarted.GET("/auth/logout", logout)
|
||||||
|
sessionStarted.GET("/auth/v2/authorize", authAuthorizeV2)
|
||||||
|
sessionStarted.GET("/auth/v2/callback", authCallbackV2)
|
||||||
|
sessionStarted.GET("/auth/v2/logout", logoutV2)
|
||||||
}
|
}
|
||||||
|
|
||||||
hbs := r.Group("/api/hbs")
|
hbs := r.Group("/api/hbs")
|
||||||
|
@ -43,6 +47,14 @@ func Config(r *gin.Engine) {
|
||||||
rootLogin.POST("/configs/smtp/test", smtpTest)
|
rootLogin.POST("/configs/smtp/test", smtpTest)
|
||||||
rootLogin.PUT("/configs/smtp", smtpConfigsPut)
|
rootLogin.PUT("/configs/smtp", smtpConfigsPut)
|
||||||
|
|
||||||
|
rootLogin.GET("/configs/auth", authConfigsGet)
|
||||||
|
rootLogin.PUT("/configs/auth", authConfigsPut)
|
||||||
|
rootLogin.POST("/auth/white-list", whiteListPost)
|
||||||
|
rootLogin.GET("/auth/white-list", whiteListsGet)
|
||||||
|
rootLogin.GET("/auth/white-list/:id", whiteListGet)
|
||||||
|
rootLogin.PUT("/auth/white-list/:id", whiteListPut)
|
||||||
|
rootLogin.DELETE("/auth/white-list/:id", whiteListDel)
|
||||||
|
|
||||||
rootLogin.GET("/log/login", loginLogGets)
|
rootLogin.GET("/log/login", loginLogGets)
|
||||||
rootLogin.GET("/log/operation", operationLogGets)
|
rootLogin.GET("/log/operation", operationLogGets)
|
||||||
|
|
||||||
|
@ -83,12 +95,13 @@ func Config(r *gin.Engine) {
|
||||||
|
|
||||||
userLogin.GET("/self/profile", selfProfileGet)
|
userLogin.GET("/self/profile", selfProfileGet)
|
||||||
userLogin.PUT("/self/profile", selfProfilePut)
|
userLogin.PUT("/self/profile", selfProfilePut)
|
||||||
userLogin.PUT("/self/password", selfPasswordPut)
|
|
||||||
userLogin.GET("/self/token", selfTokenGets)
|
userLogin.GET("/self/token", selfTokenGets)
|
||||||
userLogin.POST("/self/token", selfTokenPost)
|
userLogin.POST("/self/token", selfTokenPost)
|
||||||
userLogin.PUT("/self/token", selfTokenPut)
|
userLogin.PUT("/self/token", selfTokenPut)
|
||||||
userLogin.GET("/self/perms/global", permGlobalOps)
|
userLogin.GET("/self/perms/global", permGlobalOps)
|
||||||
|
|
||||||
|
notLogin.PUT("/self/password", selfPasswordPut)
|
||||||
|
|
||||||
userLogin.GET("/users", userListGet)
|
userLogin.GET("/users", userListGet)
|
||||||
userLogin.GET("/users/invite", userInviteGet)
|
userLogin.GET("/users/invite", userInviteGet)
|
||||||
|
|
||||||
|
@ -167,7 +180,6 @@ func Config(r *gin.Engine) {
|
||||||
v1.GET("/can-do-node-ops", v1CandoNodeOps)
|
v1.GET("/can-do-node-ops", v1CandoNodeOps)
|
||||||
|
|
||||||
// 获取用户、团队相关信息
|
// 获取用户、团队相关信息
|
||||||
v1.GET("/get-username-by-uuid", v1UsernameGetByUUID)
|
|
||||||
v1.GET("/get-user-by-uuid", v1UserGetByUUID)
|
v1.GET("/get-user-by-uuid", v1UserGetByUUID)
|
||||||
v1.GET("/get-users-by-uuids", v1UserGetByUUIDs)
|
v1.GET("/get-users-by-uuids", v1UserGetByUUIDs)
|
||||||
v1.GET("/get-users-by-ids", v1UserGetByIds)
|
v1.GET("/get-users-by-ids", v1UserGetByIds)
|
||||||
|
@ -180,12 +192,16 @@ func Config(r *gin.Engine) {
|
||||||
v1.GET("/users", v1UserListGet)
|
v1.GET("/users", v1UserListGet)
|
||||||
|
|
||||||
v1.POST("/login", v1Login)
|
v1.POST("/login", v1Login)
|
||||||
v1.POST("/send-login-code-by-sms", v1SendLoginCodeBySms)
|
v1.POST("/send-login-code", sendLoginCode)
|
||||||
v1.POST("/send-login-code-by-email", v1SendLoginCodeByEmail)
|
|
||||||
|
|
||||||
// 第三方系统获取某个用户的所有权限点
|
// 第三方系统获取某个用户的所有权限点
|
||||||
v1.GET("/perms/global", v1PermGlobalOps)
|
v1.GET("/perms/global", v1PermGlobalOps)
|
||||||
|
|
||||||
|
// session
|
||||||
|
v1.GET("/sessions/:sid", v1SessionGet)
|
||||||
|
v1.GET("/sessions/:sid/user", v1SessionGetUser)
|
||||||
|
v1.DELETE("/sessions/:sid", v1SessionDelete)
|
||||||
|
|
||||||
// 第三方系统同步权限表的数据
|
// 第三方系统同步权限表的数据
|
||||||
v1.GET("/table/sync/role-operation", v1RoleOperationGets)
|
v1.GET("/table/sync/role-operation", v1RoleOperationGets)
|
||||||
v1.GET("/table/sync/role-global-user", v1RoleGlobalUserGets)
|
v1.GET("/table/sync/role-global-user", v1RoleGlobalUserGets)
|
||||||
|
|
|
@ -14,10 +14,13 @@ import (
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/mojocn/base64Captcha"
|
"github.com/mojocn/base64Captcha"
|
||||||
"github.com/toolkits/pkg/file"
|
"github.com/toolkits/pkg/file"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
"github.com/toolkits/pkg/str"
|
"github.com/toolkits/pkg/str"
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/common/dataobj"
|
"github.com/didi/nightingale/src/common/dataobj"
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/auth"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/cache"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/config"
|
"github.com/didi/nightingale/src/modules/rdb/config"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/redisc"
|
"github.com/didi/nightingale/src/modules/rdb/redisc"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/ssoc"
|
"github.com/didi/nightingale/src/modules/rdb/ssoc"
|
||||||
|
@ -27,7 +30,6 @@ var (
|
||||||
loginCodeSmsTpl *template.Template
|
loginCodeSmsTpl *template.Template
|
||||||
loginCodeEmailTpl *template.Template
|
loginCodeEmailTpl *template.Template
|
||||||
errUnsupportCaptcha = errors.New("unsupported captcha")
|
errUnsupportCaptcha = errors.New("unsupported captcha")
|
||||||
errInvalidAnswer = errors.New("Invalid captcha answer")
|
|
||||||
|
|
||||||
// TODO: set false
|
// TODO: set false
|
||||||
debug = true
|
debug = true
|
||||||
|
@ -76,49 +78,49 @@ func init() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// login for UI
|
||||||
func login(c *gin.Context) {
|
func login(c *gin.Context) {
|
||||||
var f loginInput
|
var in loginInput
|
||||||
bind(c, &f)
|
bind(c, &in)
|
||||||
f.validate()
|
in.RemoteAddr = c.ClientIP()
|
||||||
|
|
||||||
if config.Config.Captcha {
|
err := func() error {
|
||||||
c, err := models.CaptchaGet("captcha_id=?", f.CaptchaId)
|
if err := in.Validate(); err != nil {
|
||||||
dangerous(err)
|
return err
|
||||||
if strings.ToLower(c.Answer) != strings.ToLower(f.Answer) {
|
|
||||||
dangerous(errInvalidAnswer)
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
user, err := authLogin(f)
|
if config.Config.Auth.Captcha {
|
||||||
dangerous(err)
|
c, err := models.CaptchaGet("captcha_id=?", in.CaptchaId)
|
||||||
|
if err != nil {
|
||||||
|
return _e("Unable to get captcha")
|
||||||
|
}
|
||||||
|
if strings.ToLower(c.Answer) != strings.ToLower(in.Answer) {
|
||||||
|
return _e("Invalid captcha answer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writeCookieUser(c, user.UUID)
|
user, err := authLogin(in.v1LoginInput())
|
||||||
|
if err != nil {
|
||||||
|
logger.Debugf("login error %s", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
renderMessage(c, "")
|
sessionLogin(c, user.Username, in.RemoteAddr)
|
||||||
|
return nil
|
||||||
go models.LoginLogNew(user.Username, c.ClientIP(), "in")
|
}()
|
||||||
|
renderMessage(c, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func logout(c *gin.Context) {
|
func logout(c *gin.Context) {
|
||||||
func() {
|
func() {
|
||||||
uuid := readCookieUser(c)
|
username := sessionUsername(c)
|
||||||
if uuid == "" {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
username := models.UsernameByUUID(uuid)
|
|
||||||
if username == "" {
|
if username == "" {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
writeCookieUser(c, "")
|
sessionDestory(c)
|
||||||
go models.LoginLogNew(username, c.ClientIP(), "out")
|
models.LoginLogNew(username, c.ClientIP(), "out", nil)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
if config.Config.SSO.Enable {
|
|
||||||
redirect := queryStr(c, "redirect", "/")
|
|
||||||
c.Redirect(302, ssoc.LogoutLocation(redirect))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if redirect := queryStr(c, "redirect", ""); redirect != "" {
|
if redirect := queryStr(c, "redirect", ""); redirect != "" {
|
||||||
c.Redirect(302, redirect)
|
c.Redirect(302, redirect)
|
||||||
return
|
return
|
||||||
|
@ -128,27 +130,31 @@ func logout(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type authRedirect struct {
|
type authRedirect struct {
|
||||||
Redirect string `json:"redirect"`
|
Redirect string `json:"redirect"`
|
||||||
Msg string `json:"msg"`
|
User *models.User `json:"user"`
|
||||||
|
Msg string `json:"msg"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func authAuthorizeV2(c *gin.Context) {
|
func authAuthorizeV2(c *gin.Context) {
|
||||||
redirect := queryStr(c, "redirect", "/")
|
resp, err := func() (*authRedirect, error) {
|
||||||
ret := &authRedirect{Redirect: redirect}
|
redirect := queryStr(c, "redirect", "/")
|
||||||
|
|
||||||
username := cookieUsername(c)
|
username := sessionUsername(c)
|
||||||
if username != "" { // alread login
|
if username != "" { // alread login
|
||||||
renderData(c, ret, nil)
|
return &authRedirect{Redirect: redirect}, nil
|
||||||
return
|
}
|
||||||
}
|
|
||||||
|
|
||||||
var err error
|
if !config.Config.SSO.Enable {
|
||||||
if config.Config.SSO.Enable {
|
return &authRedirect{Redirect: "/login"}, nil
|
||||||
ret.Redirect, err = ssoc.Authorize(redirect)
|
}
|
||||||
} else {
|
|
||||||
ret.Redirect = "/login"
|
if redirect, err := ssoc.Authorize(redirect); err != nil {
|
||||||
}
|
return nil, err
|
||||||
renderData(c, ret, err)
|
} else {
|
||||||
|
return &authRedirect{Redirect: redirect}, nil
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
renderData(c, resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func authCallbackV2(c *gin.Context) {
|
func authCallbackV2(c *gin.Context) {
|
||||||
|
@ -158,19 +164,28 @@ func authCallbackV2(c *gin.Context) {
|
||||||
|
|
||||||
ret := &authRedirect{Redirect: redirect}
|
ret := &authRedirect{Redirect: redirect}
|
||||||
if code == "" && redirect != "" {
|
if code == "" && redirect != "" {
|
||||||
|
logger.Debugf("sso.callback() can't get code and redirect is not set")
|
||||||
renderData(c, ret, nil)
|
renderData(c, ret, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var user *models.User
|
|
||||||
var err error
|
var err error
|
||||||
ret.Redirect, user, err = ssoc.Callback(code, state)
|
ret.Redirect, ret.User, err = ssoc.Callback(code, state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Debugf("sso.callback() error %s", err)
|
||||||
renderData(c, ret, err)
|
renderData(c, ret, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
writeCookieUser(c, user.UUID)
|
if redirect := auth.ChangePasswordRedirect(ret.User, ret.Redirect); redirect != "" {
|
||||||
|
logger.Debugf("sso.callback() redirect to changePassword %s", redirect)
|
||||||
|
ret.Redirect = redirect
|
||||||
|
renderData(c, ret, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Debugf("sso.callback() successfully, set username %s", ret.User.Username)
|
||||||
|
sessionLogin(c, ret.User.Username, c.ClientIP())
|
||||||
renderData(c, ret, nil)
|
renderData(c, ret, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,131 +193,197 @@ func logoutV2(c *gin.Context) {
|
||||||
redirect := queryStr(c, "redirect", "")
|
redirect := queryStr(c, "redirect", "")
|
||||||
ret := &authRedirect{Redirect: redirect}
|
ret := &authRedirect{Redirect: redirect}
|
||||||
|
|
||||||
uuid := readCookieUser(c)
|
username := sessionUsername(c)
|
||||||
if uuid == "" {
|
|
||||||
renderData(c, ret, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
username := models.UsernameByUUID(uuid)
|
|
||||||
if username == "" {
|
if username == "" {
|
||||||
renderData(c, ret, nil)
|
renderData(c, ret, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
writeCookieUser(c, "")
|
sessionDestory(c)
|
||||||
ret.Msg = "logout successfully"
|
ret.Msg = "logout successfully"
|
||||||
|
|
||||||
if config.Config.SSO.Enable {
|
|
||||||
if redirect == "" {
|
|
||||||
redirect = "/"
|
|
||||||
}
|
|
||||||
ret.Redirect = ssoc.LogoutLocation(redirect)
|
|
||||||
}
|
|
||||||
|
|
||||||
renderData(c, ret, nil)
|
renderData(c, ret, nil)
|
||||||
|
|
||||||
go models.LoginLogNew(username, c.ClientIP(), "out")
|
models.LoginLogNew(username, c.ClientIP(), "out", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
type loginInput struct {
|
type loginInput struct {
|
||||||
Username string `json:"username"`
|
Username string `json:"username"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Phone string `json:"phone"`
|
CaptchaId string `json:"captcha_id"`
|
||||||
Email string `json:"email"`
|
Answer string `json:"answer" description:"captcha answer"`
|
||||||
Code string `json:"code"`
|
Type string `json:"type" description:"sms-code|email-code|password|ldap"`
|
||||||
CaptchaId string `json:"captcha_id"`
|
Args []string `json:"args" description:""`
|
||||||
Answer string `json:"answer" description:"captcha answer"`
|
RemoteAddr string `json:"remote_addr" description:"use for server account(v1)"`
|
||||||
Type string `json:"type" description:"sms-code|email-code|password|ldap"`
|
IsLDAP int `json:"is_ldap" description:"deprecated"`
|
||||||
RemoteAddr string `json:"remote_addr" description:"use for server account(v1)"`
|
|
||||||
IsLDAP int `json:"is_ldap" description:"deprecated"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *loginInput) validate() {
|
func (p *loginInput) Validate() error {
|
||||||
if f.IsLDAP == 1 {
|
if p.IsLDAP == 1 {
|
||||||
f.Type = models.LOGIN_T_LDAP
|
p.Type = models.LOGIN_T_LDAP
|
||||||
}
|
}
|
||||||
if f.Type == "" {
|
if p.Type == "" {
|
||||||
f.Type = models.LOGIN_T_PWD
|
p.Type = models.LOGIN_T_PWD
|
||||||
}
|
}
|
||||||
if f.Type == models.LOGIN_T_PWD {
|
if p.Type == models.LOGIN_T_PWD || p.Type == models.LOGIN_T_LDAP {
|
||||||
if str.Dangerous(f.Username) {
|
if len(p.Args) == 0 {
|
||||||
bomb("%s invalid", f.Username)
|
if str.Dangerous(p.Username) {
|
||||||
}
|
return _e("Username %s is invalid", p.Username)
|
||||||
if len(f.Username) > 64 {
|
}
|
||||||
bomb("%s too long > 64", f.Username)
|
if len(p.Username) > 64 {
|
||||||
|
return _e("Username %s too long > 64", p.Username)
|
||||||
|
}
|
||||||
|
p.Args = []string{p.Username, p.Password}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(p.Args) == 0 {
|
||||||
|
return _e("Unable to get login arguments")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *loginInput) v1LoginInput() *v1LoginInput {
|
||||||
|
return &v1LoginInput{
|
||||||
|
Type: p.Type,
|
||||||
|
Args: p.Args,
|
||||||
|
RemoteAddr: p.RemoteAddr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type v1LoginInput struct {
|
||||||
|
Type string `param:"data" json:"type"`
|
||||||
|
Args []string `param:"data" json:"args"`
|
||||||
|
RemoteAddr string `param:"data" json:"remote_addr"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *v1LoginInput) Validate() error {
|
||||||
|
if p.Type == "" {
|
||||||
|
p.Type = models.LOGIN_T_PWD
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(p.Args) == 0 {
|
||||||
|
return _e("Unable to get login arguments")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// v1Login called by sso.rdb module
|
// v1Login called by sso.rdb module
|
||||||
func v1Login(c *gin.Context) {
|
func v1Login(c *gin.Context) {
|
||||||
var f loginInput
|
var in v1LoginInput
|
||||||
bind(c, &f)
|
bind(c, &in)
|
||||||
|
|
||||||
user, err := authLogin(f)
|
user, err := authLogin(&in)
|
||||||
renderData(c, *user, err)
|
renderData(c, user, err)
|
||||||
|
|
||||||
go models.LoginLogNew(user.Username, f.RemoteAddr, "in")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// authLogin called by /v1/rdb/login, /api/rdb/auth/login
|
// authLogin called by /v1/rdb/login, /api/rdb/auth/login
|
||||||
func authLogin(in loginInput) (user *models.User, err error) {
|
func authLogin(in *v1LoginInput) (user *models.User, err error) {
|
||||||
|
if err = in.Validate(); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := auth.WhiteListAccess(in.RemoteAddr); err != nil {
|
||||||
|
return nil, _e("Deny Access from %s with whitelist control", in.RemoteAddr)
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
models.LoginLogNew(in.Args[0], in.RemoteAddr, "in", err)
|
||||||
|
}()
|
||||||
|
|
||||||
switch strings.ToLower(in.Type) {
|
switch strings.ToLower(in.Type) {
|
||||||
case models.LOGIN_T_LDAP:
|
case models.LOGIN_T_LDAP:
|
||||||
return models.LdapLogin(in.Username, in.Password)
|
user, err = models.LdapLogin(in.Args[0], in.Args[1])
|
||||||
case models.LOGIN_T_PWD:
|
case models.LOGIN_T_PWD:
|
||||||
return models.PassLogin(in.Username, in.Password)
|
user, err = models.PassLogin(in.Args[0], in.Args[1])
|
||||||
case models.LOGIN_T_SMS:
|
case models.LOGIN_T_SMS:
|
||||||
return models.SmsCodeLogin(in.Phone, in.Code)
|
user, err = models.SmsCodeLogin(in.Args[0], in.Args[1])
|
||||||
case models.LOGIN_T_EMAIL:
|
case models.LOGIN_T_EMAIL:
|
||||||
return models.EmailCodeLogin(in.Email, in.Code)
|
user, err = models.EmailCodeLogin(in.Args[0], in.Args[1])
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("invalid login type %s", in.Type)
|
err = _e("Invalid login type %s", in.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err = auth.PostLogin(user, err); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return user, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type v1SendLoginCodeBySmsInput struct {
|
type sendCodeInput struct {
|
||||||
Phone string `json:"phone"`
|
Type string `json:"type" description:"sms-code, email-code"`
|
||||||
|
Arg string `json:"arg"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func v1SendLoginCodeBySms(c *gin.Context) {
|
func (p *sendCodeInput) Validate() error {
|
||||||
var f v1SendLoginCodeBySmsInput
|
if p.Type == "" {
|
||||||
bind(c, &f)
|
return _e("Unable to get type, sms-code | email-code")
|
||||||
|
}
|
||||||
|
if p.Arg == "" {
|
||||||
|
return _e("Unable to get code arg")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func sendLoginCode(c *gin.Context) {
|
||||||
|
var in sendCodeInput
|
||||||
|
bind(c, &in)
|
||||||
|
|
||||||
msg, err := func() (string, error) {
|
msg, err := func() (string, error) {
|
||||||
if !config.Config.Redis.Enable {
|
if err := in.Validate(); err != nil {
|
||||||
return "", fmt.Errorf("sms sender is disabled")
|
return "", err
|
||||||
}
|
}
|
||||||
phone := f.Phone
|
if !config.Config.Redis.Enable {
|
||||||
user, _ := models.UserGet("phone=?", phone)
|
return "", _e("sms/email sender is disabled")
|
||||||
if user == nil {
|
}
|
||||||
return "", fmt.Errorf("phone %s dose not exist", phone)
|
|
||||||
|
if err := in.Validate(); err != nil {
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// general a random code and add cache
|
// general a random code and add cache
|
||||||
code := fmt.Sprintf("%06d", rand.Intn(1000000))
|
code := fmt.Sprintf("%06d", rand.Intn(1000000))
|
||||||
|
|
||||||
loginCode := &models.LoginCode{
|
loginCode := &models.LoginCode{
|
||||||
Username: user.Username,
|
|
||||||
Code: code,
|
Code: code,
|
||||||
LoginType: models.LOGIN_T_SMS,
|
LoginType: models.LOGIN_T_LOGIN,
|
||||||
CreatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
user *models.User
|
||||||
|
buf bytes.Buffer
|
||||||
|
queueName string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch in.Type {
|
||||||
|
case models.LOGIN_T_SMS:
|
||||||
|
user, _ = models.UserGet("phone=?", in.Arg)
|
||||||
|
if err := loginCodeSmsTpl.Execute(&buf, loginCode); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
queueName = config.SMS_QUEUE_NAME
|
||||||
|
case models.LOGIN_T_EMAIL:
|
||||||
|
user, _ = models.UserGet("email=?", in.Arg)
|
||||||
|
if err := loginCodeEmailTpl.Execute(&buf, loginCode); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
queueName = config.MAIL_QUEUE_NAME
|
||||||
|
default:
|
||||||
|
return "", _e("Invalid code type %s", in.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user == nil {
|
||||||
|
return "", _e("Cannot find the user by %s", in.Arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
loginCode.Username = user.Username
|
||||||
if err := loginCode.Save(); err != nil {
|
if err := loginCode.Save(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
if err := redisc.Write(&dataobj.Message{Tos: []string{in.Arg}, Content: buf.String()}, queueName); err != nil {
|
||||||
if err := loginCodeSmsTpl.Execute(&buf, loginCode); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := redisc.Write(&dataobj.Message{
|
|
||||||
Tos: []string{phone},
|
|
||||||
Content: buf.String(),
|
|
||||||
}, config.SMS_QUEUE_NAME); err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,100 +397,65 @@ func v1SendLoginCodeBySms(c *gin.Context) {
|
||||||
renderData(c, msg, err)
|
renderData(c, msg, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type v1SendLoginCodeByEmailInput struct {
|
func sendRstCode(c *gin.Context) {
|
||||||
Email string `json:"email"`
|
var in sendCodeInput
|
||||||
}
|
bind(c, &in)
|
||||||
|
logger.Debugf("rst code input %#v", in)
|
||||||
func v1SendLoginCodeByEmail(c *gin.Context) {
|
|
||||||
var f v1SendLoginCodeByEmailInput
|
|
||||||
bind(c, &f)
|
|
||||||
|
|
||||||
msg, err := func() (string, error) {
|
msg, err := func() (string, error) {
|
||||||
if !config.Config.Redis.Enable {
|
if err := in.Validate(); err != nil {
|
||||||
return "", fmt.Errorf("mail sender is disabled")
|
return "", err
|
||||||
}
|
}
|
||||||
email := f.Email
|
if !config.Config.Redis.Enable {
|
||||||
user, _ := models.UserGet("email=?", email)
|
return "", _e("email/sms sender is disabled")
|
||||||
if user == nil {
|
}
|
||||||
return "", fmt.Errorf("email %s dose not exist", email)
|
|
||||||
|
if err := in.Validate(); err != nil {
|
||||||
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// general a random code and add cache
|
// general a random code and add cache
|
||||||
code := fmt.Sprintf("%06d", rand.Intn(1000000))
|
code := fmt.Sprintf("%06d", rand.Intn(1000000))
|
||||||
|
|
||||||
loginCode := &models.LoginCode{
|
loginCode := &models.LoginCode{
|
||||||
Username: user.Username,
|
|
||||||
Code: code,
|
|
||||||
LoginType: models.LOGIN_T_EMAIL,
|
|
||||||
CreatedAt: time.Now().Unix(),
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := loginCode.Save(); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
var buf bytes.Buffer
|
|
||||||
if err := loginCodeEmailTpl.Execute(&buf, loginCode); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := redisc.Write(&dataobj.Message{
|
|
||||||
Tos: []string{email},
|
|
||||||
Content: buf.String(),
|
|
||||||
}, config.SMS_QUEUE_NAME); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if debug {
|
|
||||||
return fmt.Sprintf("[debug]: %s", buf.String()), nil
|
|
||||||
}
|
|
||||||
return "successed", nil
|
|
||||||
}()
|
|
||||||
renderData(c, msg, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
type sendRstCodeBySmsInput struct {
|
|
||||||
Username string `json:"username"`
|
|
||||||
Phone string `json:"phone"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendRstCodeBySms(c *gin.Context) {
|
|
||||||
var f sendRstCodeBySmsInput
|
|
||||||
bind(c, &f)
|
|
||||||
|
|
||||||
msg, err := func() (string, error) {
|
|
||||||
if !config.Config.Redis.Enable {
|
|
||||||
return "", fmt.Errorf("sms sender is disabled")
|
|
||||||
}
|
|
||||||
phone := f.Phone
|
|
||||||
user, _ := models.UserGet("username=? and phone=?", f.Username, phone)
|
|
||||||
if user == nil {
|
|
||||||
return "", fmt.Errorf("user %s phone %s dose not exist", f.Username, phone)
|
|
||||||
}
|
|
||||||
|
|
||||||
// general a random code and add cache
|
|
||||||
code := fmt.Sprintf("%06d", rand.Intn(1000000))
|
|
||||||
|
|
||||||
loginCode := &models.LoginCode{
|
|
||||||
Username: user.Username,
|
|
||||||
Code: code,
|
Code: code,
|
||||||
LoginType: models.LOGIN_T_RST,
|
LoginType: models.LOGIN_T_RST,
|
||||||
CreatedAt: time.Now().Unix(),
|
CreatedAt: time.Now().Unix(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
user *models.User
|
||||||
|
buf bytes.Buffer
|
||||||
|
queueName string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch in.Type {
|
||||||
|
case models.LOGIN_T_SMS:
|
||||||
|
user, _ = models.UserGet("phone=?", in.Arg)
|
||||||
|
if err := loginCodeSmsTpl.Execute(&buf, loginCode); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
queueName = config.SMS_QUEUE_NAME
|
||||||
|
case models.LOGIN_T_EMAIL:
|
||||||
|
user, _ = models.UserGet("email=?", in.Arg)
|
||||||
|
if err := loginCodeEmailTpl.Execute(&buf, loginCode); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
queueName = config.MAIL_QUEUE_NAME
|
||||||
|
default:
|
||||||
|
return "", _e("Invalid code type %s", in.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user == nil {
|
||||||
|
return "", _e("Cannot find the user by %s", in.Arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
loginCode.Username = user.Username
|
||||||
if err := loginCode.Save(); err != nil {
|
if err := loginCode.Save(); err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
var buf bytes.Buffer
|
if err := redisc.Write(&dataobj.Message{Tos: []string{in.Arg}, Content: buf.String()}, queueName); err != nil {
|
||||||
if err := loginCodeSmsTpl.Execute(&buf, loginCode); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := redisc.Write(&dataobj.Message{
|
|
||||||
Tos: []string{phone},
|
|
||||||
Content: buf.String(),
|
|
||||||
}, config.SMS_QUEUE_NAME); err != nil {
|
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,17 +464,29 @@ func sendRstCodeBySms(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return "successed", nil
|
return "successed", nil
|
||||||
|
|
||||||
}()
|
}()
|
||||||
renderData(c, msg, err)
|
renderData(c, msg, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
type rstPasswordInput struct {
|
type rstPasswordInput struct {
|
||||||
Username string `json:"username"`
|
Type string `json:"type"`
|
||||||
Phone string `json:"phone"`
|
Arg string `json:"arg"`
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
Password string `json:"password"`
|
Password string `json:"password"`
|
||||||
Type string `json:"type"`
|
DryRun bool `json:"dryRun"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *rstPasswordInput) Validate() error {
|
||||||
|
if p.Type == "" {
|
||||||
|
return _e("Unable to get type, sms-code | email-code")
|
||||||
|
}
|
||||||
|
if p.Arg == "" {
|
||||||
|
return _e("Unable to get code arg")
|
||||||
|
}
|
||||||
|
if !p.DryRun && p.Password == "" {
|
||||||
|
return _e("Unable to get password")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func rstPassword(c *gin.Context) {
|
func rstPassword(c *gin.Context) {
|
||||||
|
@ -436,39 +494,43 @@ func rstPassword(c *gin.Context) {
|
||||||
bind(c, &in)
|
bind(c, &in)
|
||||||
|
|
||||||
err := func() error {
|
err := func() error {
|
||||||
user, _ := models.UserGet("username=? and phone=?", in.Username, in.Phone)
|
if err := in.Validate(); err != nil {
|
||||||
if user == nil {
|
return err
|
||||||
return fmt.Errorf("user's phone not exist")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lc, err := models.LoginCodeGet("username=? and code=? and login_type=?",
|
var user *models.User
|
||||||
user.Username, in.Code, models.LOGIN_T_RST)
|
|
||||||
|
switch in.Type {
|
||||||
|
case models.LOGIN_T_SMS:
|
||||||
|
user, _ = models.UserGet("phone=?", in.Arg)
|
||||||
|
case models.LOGIN_T_EMAIL:
|
||||||
|
user, _ = models.UserGet("email=?", in.Arg)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("invalid type %s", in.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if user == nil {
|
||||||
|
return _e("Cannot find the user by %s", in.Arg)
|
||||||
|
}
|
||||||
|
|
||||||
|
lc, err := models.LoginCodeGet("code=? and login_type=?", in.Code, models.LOGIN_T_RST)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("invalid code")
|
return _e("Invalid code")
|
||||||
}
|
}
|
||||||
|
|
||||||
if time.Now().Unix()-lc.CreatedAt > models.LOGIN_EXPIRES_IN {
|
if time.Now().Unix()-lc.CreatedAt > models.LOGIN_EXPIRES_IN {
|
||||||
return fmt.Errorf("the code has expired")
|
return _e("The code has expired")
|
||||||
}
|
}
|
||||||
|
|
||||||
if in.Type == "verify-code" {
|
if in.DryRun {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
defer lc.Del()
|
|
||||||
|
|
||||||
// update password
|
// update password
|
||||||
if user.Password, err = models.CryptoPass(in.Password); err != nil {
|
if err := auth.ChangePassword(user, in.Password); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
lc.Del()
|
||||||
if err = checkPassword(in.Password); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if err = user.Update("password"); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -481,7 +543,7 @@ func rstPassword(c *gin.Context) {
|
||||||
|
|
||||||
func captchaGet(c *gin.Context) {
|
func captchaGet(c *gin.Context) {
|
||||||
ret, err := func() (*models.Captcha, error) {
|
ret, err := func() (*models.Captcha, error) {
|
||||||
if !config.Config.Captcha {
|
if !config.Config.Auth.Captcha {
|
||||||
return nil, errUnsupportCaptcha
|
return nil, errUnsupportCaptcha
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -516,3 +578,129 @@ func authSettings(c *gin.Context) {
|
||||||
Sso: config.Config.SSO.Enable,
|
Sso: config.Config.SSO.Enable,
|
||||||
}, nil)
|
}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func authConfigsGet(c *gin.Context) {
|
||||||
|
config, err := models.AuthConfigGet()
|
||||||
|
renderData(c, config, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func authConfigsPut(c *gin.Context) {
|
||||||
|
var in models.AuthConfig
|
||||||
|
bind(c, &in)
|
||||||
|
|
||||||
|
err := models.AuthConfigSet(&in)
|
||||||
|
renderData(c, "", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type createWhiteListInput struct {
|
||||||
|
StartIp string `json:"startIp"`
|
||||||
|
EndIp string `json:"endIp"`
|
||||||
|
StartTime int64 `json:"startTime"`
|
||||||
|
EndTime int64 `json:"endTime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func whiteListPost(c *gin.Context) {
|
||||||
|
var in createWhiteListInput
|
||||||
|
bind(c, &in)
|
||||||
|
|
||||||
|
username := loginUser(c).Username
|
||||||
|
ts := time.Now().Unix()
|
||||||
|
|
||||||
|
wl := models.WhiteList{
|
||||||
|
StartIp: in.StartIp,
|
||||||
|
EndIp: in.EndIp,
|
||||||
|
StartTime: in.StartTime,
|
||||||
|
EndTime: in.EndTime,
|
||||||
|
CreatedAt: ts,
|
||||||
|
UpdatedAt: ts,
|
||||||
|
Creator: username,
|
||||||
|
Updater: username,
|
||||||
|
}
|
||||||
|
if err := wl.Validate(); err != nil {
|
||||||
|
bomb("Invalid arguments %s", err)
|
||||||
|
}
|
||||||
|
dangerous(wl.Save())
|
||||||
|
|
||||||
|
renderData(c, gin.H{"id": wl.Id}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func whiteListsGet(c *gin.Context) {
|
||||||
|
limit := queryInt(c, "limit", 20)
|
||||||
|
query := queryStr(c, "query", "")
|
||||||
|
|
||||||
|
total, err := models.WhiteListTotal(query)
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
list, err := models.WhiteListGets(query, limit, offset(c, limit))
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
renderData(c, gin.H{
|
||||||
|
"list": list,
|
||||||
|
"total": total,
|
||||||
|
}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func whiteListGet(c *gin.Context) {
|
||||||
|
id := urlParamInt64(c, "id")
|
||||||
|
ret, err := models.WhiteListGet("id=?", id)
|
||||||
|
renderData(c, ret, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
type updateWhiteListInput struct {
|
||||||
|
StartIp string `json:"startIp"`
|
||||||
|
EndIp string `json:"endIp"`
|
||||||
|
StartTime int64 `json:"startTime"`
|
||||||
|
EndTime int64 `json:"endTime"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func whiteListPut(c *gin.Context) {
|
||||||
|
var in updateWhiteListInput
|
||||||
|
bind(c, &in)
|
||||||
|
|
||||||
|
wl, err := models.WhiteListGet("id=?", urlParamInt64(c, "id"))
|
||||||
|
if err != nil {
|
||||||
|
bomb("Cannot found white list")
|
||||||
|
}
|
||||||
|
|
||||||
|
wl.StartIp = in.StartIp
|
||||||
|
wl.EndIp = in.EndIp
|
||||||
|
wl.StartTime = in.StartTime
|
||||||
|
wl.EndTime = in.EndTime
|
||||||
|
wl.UpdatedAt = time.Now().Unix()
|
||||||
|
wl.Updater = loginUser(c).Username
|
||||||
|
|
||||||
|
if err := wl.Validate(); err != nil {
|
||||||
|
bomb("Invalid arguments %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
renderMessage(c, wl.Update("start_ip", "end_ip", "start_time", "end_time", "updated_at", "updater"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func whiteListDel(c *gin.Context) {
|
||||||
|
wl, err := models.WhiteListGet("id=?", urlParamInt64(c, "id"))
|
||||||
|
dangerous(err)
|
||||||
|
|
||||||
|
renderMessage(c, wl.Del())
|
||||||
|
}
|
||||||
|
|
||||||
|
func v1SessionGet(c *gin.Context) {
|
||||||
|
sess, err := models.SessionGetWithCache(urlParamStr(c, "sid"))
|
||||||
|
renderData(c, sess, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func v1SessionGetUser(c *gin.Context) {
|
||||||
|
user, err := models.SessionGetUserWithCache(urlParamStr(c, "sid"))
|
||||||
|
renderData(c, user, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func v1SessionDelete(c *gin.Context) {
|
||||||
|
sid := urlParamStr(c, "sid")
|
||||||
|
logger.Debugf("session del sid %s", sid)
|
||||||
|
renderMessage(c, models.SessionDel(sid))
|
||||||
|
}
|
||||||
|
|
||||||
|
// pwdRulesGet return pwd rules
|
||||||
|
func pwdRulesGet(c *gin.Context) {
|
||||||
|
cf := cache.AuthConfig()
|
||||||
|
renderData(c, cf.PwdRules(), nil)
|
||||||
|
}
|
||||||
|
|
|
@ -4,11 +4,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/toolkits/pkg/errors"
|
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/models"
|
||||||
"github.com/didi/nightingale/src/toolkits/i18n"
|
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/toolkits/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dangerous(v interface{}) {
|
func dangerous(v interface{}) {
|
||||||
|
@ -133,69 +132,10 @@ func renderZeroPage(c *gin.Context) {
|
||||||
}, nil)
|
}, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ------------
|
|
||||||
|
|
||||||
type idsForm struct {
|
type idsForm struct {
|
||||||
Ids []int64 `json:"ids"`
|
Ids []int64 `json:"ids"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkPassword(passwd string) error {
|
|
||||||
indNum := [4]int{0, 0, 0, 0}
|
|
||||||
spCode := []byte{'!', '@', '#', '$', '%', '^', '&', '*', '_', '-', '~', '.', ',', '<', '>', '/', ';', ':', '|', '?', '+', '='}
|
|
||||||
|
|
||||||
if len(passwd) < 6 {
|
|
||||||
return fmt.Errorf("password too short")
|
|
||||||
}
|
|
||||||
|
|
||||||
passwdByte := []byte(passwd)
|
|
||||||
|
|
||||||
for _, i := range passwdByte {
|
|
||||||
|
|
||||||
if i >= 'A' && i <= 'Z' {
|
|
||||||
indNum[0] = 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i >= 'a' && i <= 'z' {
|
|
||||||
indNum[1] = 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if i >= '0' && i <= '9' {
|
|
||||||
indNum[2] = 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
has := false
|
|
||||||
for _, s := range spCode {
|
|
||||||
if i == s {
|
|
||||||
indNum[3] = 1
|
|
||||||
has = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !has {
|
|
||||||
return fmt.Errorf("character: %s not supported", string(i))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
codeCount := 0
|
|
||||||
|
|
||||||
for _, i := range indNum {
|
|
||||||
codeCount += i
|
|
||||||
}
|
|
||||||
|
|
||||||
if codeCount < 4 {
|
|
||||||
return fmt.Errorf("password too simple")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------------
|
|
||||||
|
|
||||||
func loginUsername(c *gin.Context) string {
|
func loginUsername(c *gin.Context) string {
|
||||||
value, has := c.Get("username")
|
value, has := c.Get("username")
|
||||||
if !has {
|
if !has {
|
||||||
|
@ -280,3 +220,11 @@ func Node(id int64) *models.Node {
|
||||||
|
|
||||||
return node
|
return node
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _e(format string, a ...interface{}) error {
|
||||||
|
return fmt.Errorf(i18n.Sprintf(format, a...))
|
||||||
|
}
|
||||||
|
|
||||||
|
func _s(format string, a ...interface{}) string {
|
||||||
|
return i18n.Sprintf(format, a...)
|
||||||
|
}
|
||||||
|
|
|
@ -23,12 +23,14 @@ func heartBeat(c *gin.Context) {
|
||||||
Module: rev.Module,
|
Module: rev.Module,
|
||||||
RPCPort: rev.RPCPort,
|
RPCPort: rev.RPCPort,
|
||||||
HTTPPort: rev.HTTPPort,
|
HTTPPort: rev.HTTPPort,
|
||||||
|
Region: rev.Region,
|
||||||
TS: now,
|
TS: now,
|
||||||
}
|
}
|
||||||
errors.Dangerous(instance.Add())
|
errors.Dangerous(instance.Add())
|
||||||
} else {
|
} else {
|
||||||
instance.TS = now
|
instance.TS = now
|
||||||
instance.HTTPPort = rev.HTTPPort
|
instance.HTTPPort = rev.HTTPPort
|
||||||
|
instance.Region = rev.Region
|
||||||
errors.Dangerous(instance.Update())
|
errors.Dangerous(instance.Update())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/auth"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/config"
|
"github.com/didi/nightingale/src/modules/rdb/config"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
@ -35,28 +36,32 @@ func selfProfilePut(c *gin.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type selfPasswordForm struct {
|
type selfPasswordForm struct {
|
||||||
OldPass string `json:"oldpass" binding:"required"`
|
Username string `json:"username" binding:"required"`
|
||||||
NewPass string `json:"newpass" binding:"required"`
|
OldPass string `json:"oldpass" binding:"required"`
|
||||||
|
NewPass string `json:"newpass" binding:"required"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func selfPasswordPut(c *gin.Context) {
|
func selfPasswordPut(c *gin.Context) {
|
||||||
var f selfPasswordForm
|
var f selfPasswordForm
|
||||||
bind(c, &f)
|
bind(c, &f)
|
||||||
dangerous(checkPassword(f.NewPass))
|
|
||||||
|
|
||||||
oldpass, err := models.CryptoPass(f.OldPass)
|
err := func() error {
|
||||||
dangerous(err)
|
user, err := models.UserMustGet("username=?", f.Username)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
oldpass, err := models.CryptoPass(f.OldPass)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if user.Password != oldpass {
|
||||||
|
return _e("Incorrect old password")
|
||||||
|
}
|
||||||
|
|
||||||
newpass, err := models.CryptoPass(f.NewPass)
|
return auth.ChangePassword(user, f.NewPass)
|
||||||
dangerous(err)
|
}()
|
||||||
|
|
||||||
user := loginUser(c)
|
renderMessage(c, err)
|
||||||
if user.Password != oldpass {
|
|
||||||
bomb("old password error")
|
|
||||||
}
|
|
||||||
|
|
||||||
user.Password = newpass
|
|
||||||
renderMessage(c, user.Update("password"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func selfTokenGets(c *gin.Context) {
|
func selfTokenGets(c *gin.Context) {
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -9,6 +10,7 @@ import (
|
||||||
"github.com/toolkits/pkg/str"
|
"github.com/toolkits/pkg/str"
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/auth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 通讯录,只要登录用户就可以看,超管要修改某个用户的信息,也是调用这个接口获取列表先
|
// 通讯录,只要登录用户就可以看,超管要修改某个用户的信息,也是调用这个接口获取列表先
|
||||||
|
@ -64,21 +66,25 @@ func userAddPost(c *gin.Context) {
|
||||||
|
|
||||||
var f userProfileForm
|
var f userProfileForm
|
||||||
bind(c, &f)
|
bind(c, &f)
|
||||||
dangerous(checkPassword(f.Password))
|
dangerous(auth.CheckPassword(f.Password))
|
||||||
|
|
||||||
pass, err := models.CryptoPass(f.Password)
|
pass, err := models.CryptoPass(f.Password)
|
||||||
dangerous(err)
|
dangerous(err)
|
||||||
|
|
||||||
|
now := time.Now().Unix()
|
||||||
|
b, _ := json.Marshal([]string{pass})
|
||||||
u := models.User{
|
u := models.User{
|
||||||
Username: f.Username,
|
Username: f.Username,
|
||||||
Password: pass,
|
Password: pass,
|
||||||
Dispname: f.Dispname,
|
Passwords: string(b),
|
||||||
Phone: f.Phone,
|
Dispname: f.Dispname,
|
||||||
Email: f.Email,
|
Phone: f.Phone,
|
||||||
Im: f.Im,
|
Email: f.Email,
|
||||||
IsRoot: f.IsRoot,
|
Im: f.Im,
|
||||||
LeaderId: f.LeaderId,
|
IsRoot: f.IsRoot,
|
||||||
UUID: models.GenUUIDForUser(f.Username),
|
LeaderId: f.LeaderId,
|
||||||
|
UpdatedAt: now,
|
||||||
|
UUID: models.GenUUIDForUser(f.Username),
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.LeaderId != 0 {
|
if f.LeaderId != 0 {
|
||||||
|
@ -144,19 +150,17 @@ func userProfilePut(c *gin.Context) {
|
||||||
target.IsRoot = f.IsRoot
|
target.IsRoot = f.IsRoot
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Typ != target.Typ {
|
if f.Typ != target.Type {
|
||||||
arr = append(arr, fmt.Sprintf("typ: %d -> %d", target.Typ, f.Typ))
|
arr = append(arr, fmt.Sprintf("typ: %d -> %d", target.Type, f.Typ))
|
||||||
target.Typ = f.Typ
|
target.Type = f.Typ
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Status != target.Status {
|
if f.Status != target.Status {
|
||||||
arr = append(arr, fmt.Sprintf("typ: %d -> %d", target.Status, f.Status))
|
arr = append(arr, fmt.Sprintf("typ: %d -> %d", target.Status, f.Status))
|
||||||
target.Status = f.Status
|
target.Status = f.Status
|
||||||
}
|
if target.Status == models.USER_S_ACTIVE {
|
||||||
|
target.LoginErrNum = 0
|
||||||
if f.Status != target.Status {
|
}
|
||||||
arr = append(arr, fmt.Sprintf("typ: %s -> %s", target.Status, f.Status))
|
|
||||||
target.Status = f.Status
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if f.Organization != target.Organization {
|
if f.Organization != target.Organization {
|
||||||
|
@ -164,7 +168,9 @@ func userProfilePut(c *gin.Context) {
|
||||||
target.Organization = f.Organization
|
target.Organization = f.Organization
|
||||||
}
|
}
|
||||||
|
|
||||||
err := target.Update("dispname", "phone", "email", "im", "is_root", "leader_id", "leader_name", "typ", "status", "organization")
|
target.UpdatedAt = time.Now().Unix()
|
||||||
|
|
||||||
|
err := target.Update("dispname", "phone", "email", "im", "is_root", "leader_id", "leader_name", "typ", "status", "organization", "login_err_num", "updated_at")
|
||||||
if err == nil && len(arr) > 0 {
|
if err == nil && len(arr) > 0 {
|
||||||
content := strings.Join(arr, ",")
|
content := strings.Join(arr, ",")
|
||||||
go models.OperationLogNew(root.Username, "user", target.Id, fmt.Sprintf("UserModify %s %s", target.Username, content))
|
go models.OperationLogNew(root.Username, "user", target.Id, fmt.Sprintf("UserModify %s %s", target.Username, content))
|
||||||
|
@ -182,17 +188,13 @@ func userPasswordPut(c *gin.Context) {
|
||||||
|
|
||||||
var f userPasswordForm
|
var f userPasswordForm
|
||||||
bind(c, &f)
|
bind(c, &f)
|
||||||
dangerous(checkPassword(f.Password))
|
dangerous(auth.CheckPassword(f.Password))
|
||||||
|
|
||||||
target := User(urlParamInt64(c, "id"))
|
user := User(urlParamInt64(c, "id"))
|
||||||
|
err := auth.ChangePassword(user, f.Password)
|
||||||
|
|
||||||
pass, err := models.CryptoPass(f.Password)
|
|
||||||
dangerous(err)
|
|
||||||
|
|
||||||
target.Password = pass
|
|
||||||
err = target.Update("password")
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
go models.OperationLogNew(root.Username, "user", target.Id, fmt.Sprintf("UserChangePassword %s", target.Username))
|
go models.OperationLogNew(root.Username, "user", user.Id, fmt.Sprintf("UserChangePassword %s", user.Username))
|
||||||
}
|
}
|
||||||
renderMessage(c, err)
|
renderMessage(c, err)
|
||||||
}
|
}
|
||||||
|
@ -221,10 +223,6 @@ func userDel(c *gin.Context) {
|
||||||
renderMessage(c, err)
|
renderMessage(c, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func v1UsernameGetByUUID(c *gin.Context) {
|
|
||||||
renderData(c, models.UsernameByUUID(queryStr(c, "uuid")), nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
func v1UserGetByUUID(c *gin.Context) {
|
func v1UserGetByUUID(c *gin.Context) {
|
||||||
user, err := models.UserGet("uuid=?", queryStr(c, "uuid"))
|
user, err := models.UserGet("uuid=?", queryStr(c, "uuid"))
|
||||||
dangerous(err)
|
dangerous(err)
|
||||||
|
@ -302,26 +300,40 @@ type userInviteForm struct {
|
||||||
func userInvitePost(c *gin.Context) {
|
func userInvitePost(c *gin.Context) {
|
||||||
var f userInviteForm
|
var f userInviteForm
|
||||||
bind(c, &f)
|
bind(c, &f)
|
||||||
dangerous(checkPassword(f.Password))
|
|
||||||
|
|
||||||
inv, err := models.InviteGet("token=?", f.Token)
|
err := func() error {
|
||||||
dangerous(err)
|
if err := auth.CheckPassword(f.Password); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if inv.Expire < time.Now().Unix() {
|
inv, err := models.InviteGet("token=?", f.Token)
|
||||||
dangerous("invite url already expired")
|
if err != nil {
|
||||||
}
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
u := models.User{
|
if inv.Expire < time.Now().Unix() {
|
||||||
Username: f.Username,
|
return _e("invite url already expired")
|
||||||
Dispname: f.Dispname,
|
}
|
||||||
Phone: f.Phone,
|
|
||||||
Email: f.Email,
|
|
||||||
Im: f.Im,
|
|
||||||
UUID: models.GenUUIDForUser(f.Username),
|
|
||||||
}
|
|
||||||
|
|
||||||
u.Password, err = models.CryptoPass(f.Password)
|
u := models.User{
|
||||||
dangerous(err)
|
Username: f.Username,
|
||||||
|
Dispname: f.Dispname,
|
||||||
|
Phone: f.Phone,
|
||||||
|
Email: f.Email,
|
||||||
|
Im: f.Im,
|
||||||
|
UUID: models.GenUUIDForUser(f.Username),
|
||||||
|
}
|
||||||
|
|
||||||
renderMessage(c, u.Save())
|
u.Password, err = models.CryptoPass(f.Password)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err = u.Save(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return inv.Del()
|
||||||
|
}()
|
||||||
|
|
||||||
|
renderMessage(c, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,14 @@ import (
|
||||||
|
|
||||||
"github.com/didi/nightingale/src/common/loggeri"
|
"github.com/didi/nightingale/src/common/loggeri"
|
||||||
"github.com/didi/nightingale/src/models"
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/auth"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/cache"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/config"
|
"github.com/didi/nightingale/src/modules/rdb/config"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/cron"
|
"github.com/didi/nightingale/src/modules/rdb/cron"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/http"
|
"github.com/didi/nightingale/src/modules/rdb/http"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/rabbitmq"
|
"github.com/didi/nightingale/src/modules/rdb/rabbitmq"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/redisc"
|
"github.com/didi/nightingale/src/modules/rdb/redisc"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/session"
|
||||||
"github.com/didi/nightingale/src/modules/rdb/ssoc"
|
"github.com/didi/nightingale/src/modules/rdb/ssoc"
|
||||||
"github.com/didi/nightingale/src/toolkits/i18n"
|
"github.com/didi/nightingale/src/toolkits/i18n"
|
||||||
)
|
)
|
||||||
|
@ -72,6 +75,12 @@ func main() {
|
||||||
// 初始化 rabbitmq 处理部分异步逻辑
|
// 初始化 rabbitmq 处理部分异步逻辑
|
||||||
rabbitmq.Init()
|
rabbitmq.Init()
|
||||||
|
|
||||||
|
cache.Start()
|
||||||
|
session.Init()
|
||||||
|
|
||||||
|
auth.Init(config.Config.Auth.ExtraMode)
|
||||||
|
auth.Start()
|
||||||
|
|
||||||
go cron.ConsumeMail()
|
go cron.ConsumeMail()
|
||||||
go cron.ConsumeSms()
|
go cron.ConsumeSms()
|
||||||
go cron.ConsumeVoice()
|
go cron.ConsumeVoice()
|
||||||
|
@ -102,6 +111,8 @@ func endingProc() {
|
||||||
http.Shutdown()
|
http.Shutdown()
|
||||||
redisc.CloseRedis()
|
redisc.CloseRedis()
|
||||||
rabbitmq.Shutdown()
|
rabbitmq.Shutdown()
|
||||||
|
session.Stop()
|
||||||
|
cache.Stop()
|
||||||
|
|
||||||
fmt.Println("process stopped successfully")
|
fmt.Println("process stopped successfully")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,288 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/didi/nightingale/src/models"
|
||||||
|
"github.com/didi/nightingale/src/modules/rdb/config"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/toolkits/pkg/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
type storage interface {
|
||||||
|
all() int
|
||||||
|
get(sid string) (*models.Session, error)
|
||||||
|
insert(*models.Session) error
|
||||||
|
del(sid string) error
|
||||||
|
update(*models.Session) error
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
DefaultSession *Manager
|
||||||
|
)
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
var err error
|
||||||
|
DefaultSession, err = StartSession(&config.Config.HTTP.Session)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stop() {
|
||||||
|
DefaultSession.StopGC()
|
||||||
|
}
|
||||||
|
|
||||||
|
func Start(w http.ResponseWriter, r *http.Request) (store *SessionStore, err error) {
|
||||||
|
return DefaultSession.Start(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Destroy(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||||
|
return DefaultSession.Destroy(w, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Get(sid string) (*SessionStore, error) {
|
||||||
|
return DefaultSession.Get(sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func Exist(sid string) bool {
|
||||||
|
return DefaultSession.Exist(sid)
|
||||||
|
}
|
||||||
|
|
||||||
|
func All() int {
|
||||||
|
return DefaultSession.All()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartSession(cf *config.SessionSection, opts_ ...Option) (*Manager, error) {
|
||||||
|
opts := &options{}
|
||||||
|
|
||||||
|
for _, opt := range opts_ {
|
||||||
|
opt.apply(opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.ctx == nil {
|
||||||
|
opts.ctx, opts.cancel = context.WithCancel(context.Background())
|
||||||
|
}
|
||||||
|
|
||||||
|
var storage storage
|
||||||
|
var err error
|
||||||
|
if cf.Storage == "mem" {
|
||||||
|
storage, err = newMemStorage(cf, opts)
|
||||||
|
} else {
|
||||||
|
storage, err = newDbStorage(cf, opts)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Manager{
|
||||||
|
storage: storage,
|
||||||
|
options: opts,
|
||||||
|
config: cf,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Manager struct {
|
||||||
|
storage
|
||||||
|
*options
|
||||||
|
config *config.SessionSection
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionStart generate or read the session id from http request.
|
||||||
|
// if session id exists, return SessionStore with this id.
|
||||||
|
func (p *Manager) Start(w http.ResponseWriter, r *http.Request) (store *SessionStore, err error) {
|
||||||
|
var sid string
|
||||||
|
|
||||||
|
if sid, err = p.getSid(r); err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if sid != "" {
|
||||||
|
if store, err := p.getSessionStore(sid, false); err == nil {
|
||||||
|
return store, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a new session
|
||||||
|
sid = uuid.New().String()
|
||||||
|
|
||||||
|
store, err = p.getSessionStore(sid, true)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
cookie := &http.Cookie{
|
||||||
|
Name: p.config.CookieName,
|
||||||
|
Value: url.QueryEscape(sid),
|
||||||
|
Path: "/",
|
||||||
|
HttpOnly: p.config.HttpOnly,
|
||||||
|
Domain: p.config.Domain,
|
||||||
|
}
|
||||||
|
if p.config.CookieLifetime > 0 {
|
||||||
|
cookie.MaxAge = int(p.config.CookieLifetime)
|
||||||
|
cookie.Expires = time.Now().Add(time.Duration(p.config.CookieLifetime) * time.Second)
|
||||||
|
}
|
||||||
|
http.SetCookie(w, cookie)
|
||||||
|
r.AddCookie(cookie)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Manager) StopGC() {
|
||||||
|
if p.cancel != nil {
|
||||||
|
p.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Manager) Destroy(w http.ResponseWriter, r *http.Request) (string, error) {
|
||||||
|
cookie, err := r.Cookie(p.config.CookieName)
|
||||||
|
if err != nil || cookie.Value == "" {
|
||||||
|
return "", fmt.Errorf("Have not login yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
sid, _ := url.QueryUnescape(cookie.Value)
|
||||||
|
logger.Debugf("session Destory sid %s", sid)
|
||||||
|
p.del(sid)
|
||||||
|
|
||||||
|
cookie = &http.Cookie{Name: p.config.CookieName,
|
||||||
|
Path: "/",
|
||||||
|
HttpOnly: p.config.HttpOnly,
|
||||||
|
Expires: time.Now(),
|
||||||
|
MaxAge: -1}
|
||||||
|
|
||||||
|
http.SetCookie(w, cookie)
|
||||||
|
return sid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Manager) Get(sid string) (*SessionStore, error) {
|
||||||
|
return p.getSessionStore(sid, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Manager) Exist(sid string) bool {
|
||||||
|
_, err := p.get(sid)
|
||||||
|
return err == nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// All count values in mysql session
|
||||||
|
func (p *Manager) All() int {
|
||||||
|
return p.all()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Manager) getSid(r *http.Request) (sid string, err error) {
|
||||||
|
var cookie *http.Cookie
|
||||||
|
|
||||||
|
cookie, err = r.Cookie(p.config.CookieName)
|
||||||
|
if err != nil || cookie.Value == "" {
|
||||||
|
return sid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return url.QueryUnescape(cookie.Value)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Manager) getSessionStore(sid string, create bool) (*SessionStore, error) {
|
||||||
|
sc, err := p.get(sid)
|
||||||
|
if sc == nil && create {
|
||||||
|
ts := time.Now().Unix()
|
||||||
|
sc = &models.Session{
|
||||||
|
Sid: sid,
|
||||||
|
CreatedAt: ts,
|
||||||
|
UpdatedAt: ts,
|
||||||
|
}
|
||||||
|
err = p.insert(sc)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &SessionStore{manager: p, session: sc}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// SessionStore mysql session store
|
||||||
|
type SessionStore struct {
|
||||||
|
sync.RWMutex
|
||||||
|
session *models.Session
|
||||||
|
manager *Manager
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set value in mysql session.
|
||||||
|
// it is temp value in map.
|
||||||
|
func (p *SessionStore) Set(k, v string) error {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
switch k {
|
||||||
|
case "username":
|
||||||
|
p.session.Username = v
|
||||||
|
case "remoteAddr":
|
||||||
|
p.session.RemoteAddr = v
|
||||||
|
default:
|
||||||
|
fmt.Errorf("unsupported session field %s", k)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get value from mysql session
|
||||||
|
func (p *SessionStore) Get(k string) string {
|
||||||
|
p.RLock()
|
||||||
|
defer p.RUnlock()
|
||||||
|
switch k {
|
||||||
|
case "username":
|
||||||
|
return p.session.Username
|
||||||
|
case "remoteAddr":
|
||||||
|
return p.session.RemoteAddr
|
||||||
|
default:
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SessionStore) CreatedAt() int64 {
|
||||||
|
return p.session.CreatedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete value in mysql session
|
||||||
|
func (p *SessionStore) Delete(k string) error {
|
||||||
|
return p.Set(k, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset clear all values in mysql session
|
||||||
|
func (p *SessionStore) Reset() error {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
p.session.Username = ""
|
||||||
|
p.session.RemoteAddr = ""
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sid get session id of this mysql session store
|
||||||
|
func (p *SessionStore) Sid() string {
|
||||||
|
return p.session.Sid
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *SessionStore) Update(w http.ResponseWriter) error {
|
||||||
|
p.session.UpdatedAt = time.Now().Unix()
|
||||||
|
return p.manager.update(p.session)
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessionKey = "context-session-key"
|
||||||
|
|
||||||
|
type contextKeyT string
|
||||||
|
|
||||||
|
var contextKey = contextKeyT("session")
|
||||||
|
|
||||||
|
/*
|
||||||
|
ctx := NewContext(req.Context(), p)
|
||||||
|
req = req.WithContext(ctx)
|
||||||
|
*/
|
||||||
|
// NewContext returns a copy of the parent context
|
||||||
|
// and associates it with an sessionStore.
|
||||||
|
func NewContext(ctx context.Context, s *SessionStore) context.Context {
|
||||||
|
return context.WithValue(ctx, contextKey, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FromContext returns the Auth bound to the context, if any.
|
||||||
|
func FromContext(ctx context.Context) (s *SessionStore, ok bool) {
|
||||||
|
s, ok = ctx.Value(contextKey).(*SessionStore)
|
||||||
|
return
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue