pytbox 0.2.4__tar.gz → 0.2.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of pytbox might be problematic. Click here for more details.

Files changed (89) hide show
  1. {pytbox-0.2.4/src/pytbox.egg-info → pytbox-0.2.6}/PKG-INFO +1 -1
  2. {pytbox-0.2.4 → pytbox-0.2.6}/pyproject.toml +1 -1
  3. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/base.py +8 -1
  4. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/database/victoriametrics.py +35 -31
  5. pytbox-0.2.6/src/pytbox/mingdao.py +164 -0
  6. pytbox-0.2.6/src/pytbox/notion.py +731 -0
  7. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/pyjira.py +14 -7
  8. {pytbox-0.2.4 → pytbox-0.2.6/src/pytbox.egg-info}/PKG-INFO +1 -1
  9. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox.egg-info/SOURCES.txt +5 -0
  10. pytbox-0.2.6/tests/test_jira_connection.py +55 -0
  11. pytbox-0.2.6/tests/test_mingdao.py +37 -0
  12. pytbox-0.2.6/tests/test_notion.py +279 -0
  13. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_victoriametrics.py +10 -4
  14. {pytbox-0.2.4 → pytbox-0.2.6}/MANIFEST.in +0 -0
  15. {pytbox-0.2.4 → pytbox-0.2.6}/README.md +0 -0
  16. {pytbox-0.2.4 → pytbox-0.2.6}/setup.cfg +0 -0
  17. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/alert/alert_handler.py +0 -0
  18. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/alert/ping.py +0 -0
  19. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/alicloud/sls.py +0 -0
  20. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/build_config.py +0 -0
  21. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/instances.toml +0 -0
  22. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/__init__.py +0 -0
  23. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.cpu/cpu.toml.j2 +0 -0
  24. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.disk/disk.toml.j2 +0 -0
  25. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.diskio/diskio.toml.j2 +0 -0
  26. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.dns_query/dns_query.toml.j2 +0 -0
  27. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.http_response/http_response.toml.j2 +0 -0
  28. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.mem/mem.toml.j2 +0 -0
  29. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.net/net.toml.j2 +0 -0
  30. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.net_response/net_response.toml.j2 +0 -0
  31. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.ping/ping.toml.j2 +0 -0
  32. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.prometheus/prometheus.toml.j2 +0 -0
  33. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/cisco_interface.toml.j2 +0 -0
  34. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/cisco_system.toml.j2 +0 -0
  35. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/h3c_interface.toml.j2 +0 -0
  36. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/h3c_system.toml.j2 +0 -0
  37. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/huawei_interface.toml.j2 +0 -0
  38. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/huawei_system.toml.j2 +0 -0
  39. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/ruijie_interface.toml.j2 +0 -0
  40. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.snmp/ruijie_system.toml.j2 +0 -0
  41. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/categraf/jinja2/input.vsphere/vsphere.toml.j2 +0 -0
  42. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/__init__.py +0 -0
  43. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/categraf/__init__.py +0 -0
  44. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/categraf/commands.py +0 -0
  45. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/commands/vm.py +0 -0
  46. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/common/__init__.py +0 -0
  47. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/common/options.py +0 -0
  48. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/common/utils.py +0 -0
  49. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/formatters/__init__.py +0 -0
  50. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/formatters/output.py +0 -0
  51. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli/main.py +0 -0
  52. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/cli.py +0 -0
  53. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/common/__init__.py +0 -0
  54. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/database/mongo.py +0 -0
  55. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/dida365.py +0 -0
  56. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/excel.py +0 -0
  57. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/feishu/client.py +0 -0
  58. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/feishu/endpoints.py +0 -0
  59. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/feishu/errors.py +0 -0
  60. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/feishu/helpers.py +0 -0
  61. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/feishu/typing.py +0 -0
  62. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/log/logger.py +0 -0
  63. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/log/victorialog.py +0 -0
  64. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/mail/alimail.py +0 -0
  65. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/mail/client.py +0 -0
  66. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/mail/mail_detail.py +0 -0
  67. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/network/meraki.py +0 -0
  68. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/onepassword_connect.py +0 -0
  69. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/onepassword_sa.py +0 -0
  70. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/utils/cronjob.py +0 -0
  71. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/utils/env.py +0 -0
  72. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/utils/load_config.py +0 -0
  73. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/utils/load_vm_devfile.py +0 -0
  74. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/utils/response.py +0 -0
  75. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/utils/richutils.py +0 -0
  76. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/utils/timeutils.py +0 -0
  77. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/vmware.py +0 -0
  78. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox/win/ad.py +0 -0
  79. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox.egg-info/dependency_links.txt +0 -0
  80. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox.egg-info/entry_points.txt +0 -0
  81. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox.egg-info/requires.txt +0 -0
  82. {pytbox-0.2.4 → pytbox-0.2.6}/src/pytbox.egg-info/top_level.txt +0 -0
  83. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_base.py +0 -0
  84. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_feishu.py +0 -0
  85. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_load_jsonfile.py +0 -0
  86. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_logger.py +0 -0
  87. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_onepassword_connect.py +0 -0
  88. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_onepassword_sa.py +0 -0
  89. {pytbox-0.2.4 → pytbox-0.2.6}/tests/test_vmware.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pytbox
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: A collection of Python integrations and utilities (Feishu, Dida365, VictoriaMetrics, ...)
5
5
  Author-email: mingming hou <houm01@foxmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pytbox"
7
- version = "0.2.4"
7
+ version = "0.2.6"
8
8
  description = "A collection of Python integrations and utilities (Feishu, Dida365, VictoriaMetrics, ...)"
9
9
  authors = [{ name = "mingming hou", email = "houm01@foxmail.com" }]
10
10
  license = "MIT"
@@ -16,6 +16,8 @@ from pytbox.mail.client import MailClient
16
16
  from pytbox.mail.alimail import AliMail
17
17
  from pytbox.alicloud.sls import AliCloudSls
18
18
  from pytbox.utils.cronjob import cronjob_counter
19
+ from pytbox.notion import Notion
20
+ from pytbox.mingdao import Mingdao
19
21
 
20
22
 
21
23
  config = load_config_by_file(path='/workspaces/pytbox/tests/alert/config_dev.toml', oc_vault_id=os.environ.get('oc_vault_id'))
@@ -96,6 +98,7 @@ vmware_test = VMwareClient(
96
98
 
97
99
  pyjira = PyJira(
98
100
  base_url=config['jira']['base_url'],
101
+ username=config['jira']['username'],
99
102
  token=config['jira']['token']
100
103
  )
101
104
 
@@ -111,4 +114,8 @@ sls = AliCloudSls(
111
114
  )
112
115
 
113
116
  def get_cronjob_counter(app_type='', app='', comment=None, schedule_interval=None, schedule_cron=None):
114
- return cronjob_counter(vm=vm, log=get_logger('cronjob_counter'), app_type=app_type, app=app, comment=comment, schedule_interval=schedule_interval, schedule_cron=schedule_cron)
117
+ return cronjob_counter(vm=vm, log=get_logger('cronjob_counter'), app_type=app_type, app=app, comment=comment, schedule_interval=schedule_interval, schedule_cron=schedule_cron)
118
+
119
+
120
+ notion = Notion(token=config['notion']['api_secrets'], proxy=config['notion']['proxy'])
121
+ mingdao = Mingdao(app_key=config['mingdao']['app_key'], sign=config['mingdao']['sign'])
@@ -168,41 +168,19 @@ class VictoriaMetrics:
168
168
  ReturnResponse:
169
169
  code = 0 正常, code = 1 异常, code = 2 没有查询到数据, 建议将其判断为正常
170
170
  '''
171
- if target:
172
- # 这里需要在字符串中保留 {},同时插入 target,可以用双大括号转义
173
- query = f"ping_result_code{{target='{target}'}}"
174
- else:
175
- query = "ping_result_code"
176
-
177
- if last_minute:
178
- query = query + f"[{last_minute}m]"
179
-
180
- if env == 'dev':
171
+ query = f'avg_over_time((ping_result_code{{target="{target}"}})[{last_minute}m])'
172
+ if self.env == 'dev':
181
173
  r = load_dev_file(dev_file)
182
174
  else:
183
175
  r = self.query(query=query)
184
-
185
176
  if r.code == 0:
186
- values = r.data[0]['values']
187
- if len(values) == 2 and values[1] == "0":
188
- code = 0
189
- msg = f"已检查 {target} 最近 {last_minute} 分钟是正常的!"
177
+ value = r.data[0]['value'][1]
178
+ if value == '0':
179
+ return ReturnResponse(code=0, msg=f"已检查 {target} 最近 {last_minute} 分钟是正常的!", data=r.data)
190
180
  else:
191
- if all(str(item[1]) == "1" for item in values):
192
- code = 1
193
- msg = f"已检查 {target} 最近 {last_minute} 分钟是异常的!"
194
- else:
195
- code = 0
196
- msg = f"已检查 {target} 最近 {last_minute} 分钟是正常的!"
197
- elif r.code == 2:
198
- code = 2
199
- msg = f"没有查询到 {target} 最近 {last_minute} 分钟的ping结果!"
200
- try:
201
- data = r.data[0]
202
- except KeyError:
203
- data = r.data
204
-
205
- return ReturnResponse(code=code, msg=msg, data=data)
181
+ return ReturnResponse(code=1, msg=f"已检查 {target} 最近 {last_minute} 分钟是异常的!", data=r.data)
182
+ else:
183
+ return r
206
184
 
207
185
  def check_unreachable_ping_result(self, dev_file: str='') -> ReturnResponse:
208
186
  '''
@@ -396,4 +374,30 @@ class VictoriaMetrics:
396
374
  labels['schedule_type'] = 'cron'
397
375
  labels['schedule_cron'] = schedule_cron
398
376
  r = self.insert(metric_name="cronjob_run_duration_seconds", labels=labels, value=duration_seconds)
399
- return r
377
+ return r
378
+
379
+ def get_vmware_esxhostnames(self, vcenter: str=None) -> list:
380
+ '''
381
+ _summary_
382
+ '''
383
+ esxhostnames = []
384
+ query = f'vsphere_host_sys_uptime_latest{{vcenter="{vcenter}"}}'
385
+ metrics = self.query(query=query).data
386
+ for metric in metrics:
387
+ esxhostname = metric['metric']['esxhostname']
388
+ esxhostnames.append(esxhostname)
389
+ return esxhostnames
390
+
391
+ def get_vmware_cpu_usage(self, vcenter: str=None, esxhostname: str=None) -> float:
392
+ '''
393
+ _summary_
394
+ '''
395
+ query = f'vsphere_host_cpu_usage_average{{vcenter="{vcenter}", esxhostname="{esxhostname}"}}'
396
+ return self.query(query=query).data[0]['value'][1]
397
+
398
+ def get_vmware_memory_usage(self, vcenter: str=None, esxhostname: str=None) -> float:
399
+ '''
400
+ _summary_
401
+ '''
402
+ query = f'vsphere_host_mem_usage_average{{vcenter="{vcenter}", esxhostname="{esxhostname}"}}'
403
+ return self.query(query=query).data[0]['value'][1]
@@ -0,0 +1,164 @@
1
+ #!/usr/bin/env python3
2
+
3
+ from typing import Literal, Type
4
+
5
+ import requests
6
+
7
+ from .utils.response import ReturnResponse
8
+
9
+
10
+ class Mingdao:
11
+ '''
12
+ _summary_
13
+ '''
14
+ def __init__(self, app_key: str=None, sign: str=None, timeout: int=5):
15
+ self.base_url = "https://api.mingdao.com"
16
+ self.headers = {
17
+ 'Content-Type': 'application/json;charset=UTF-8',
18
+ 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36'
19
+ }
20
+ self.timeout = timeout
21
+ self.app_key = app_key
22
+ self.sign = sign
23
+
24
+ def _build_api_request(self, api_url: str, method: Literal['GET', 'POST'], params: dict=None, body: dict=None, api_version: Literal['v1', 'v2']='v2'):
25
+ body['appKey'] = self.app_key
26
+ body['sign'] = self.sign
27
+ if not api_url.startswith('/'):
28
+ url = f'{self.base_url}/{api_version}/{api_url}'
29
+ else:
30
+ url = f'{self.base_url}/{api_version}{api_url}'
31
+ params = {
32
+ "appKey": self.app_key,
33
+ "sign": self.sign,
34
+ }
35
+ return requests.request(method, url, params=params, headers=self.headers, json=body, timeout=self.timeout)
36
+
37
+ def get_app_info(self) -> ReturnResponse:
38
+ '''
39
+ _summary_
40
+
41
+ Returns:
42
+ ReturnResponse: _description_
43
+ '''
44
+ r = self._build_api_request(api_url='/open/app/get', method='GET', body={}, api_version='v1')
45
+ return ReturnResponse(code=0, msg='获取应用信息成功', data=r.json())
46
+
47
+ def get_work_sheet_info(self, worksheet_id: str=None, table_name: str=None, worksheet_name: str=None):
48
+ if worksheet_name:
49
+ worksheet_id = self.get_work_sheet_id_by_name(table_name=table_name, worksheet_name=worksheet_name)
50
+
51
+ r = self._build_api_request(
52
+ api_url='open/worksheet/getWorksheetInfo',
53
+ method='POST',
54
+ body={
55
+ "worksheetId": worksheet_id,
56
+ }
57
+ )
58
+ return r.json()
59
+
60
+ def get_project_info(self, worksheet_id: str, keywords: str):
61
+ r = self._build_api_request(
62
+ api_url='open/worksheet/getFilterRows',
63
+ method='POST',
64
+ body={
65
+ "pageIndex": 1,
66
+ "pageSize": 100,
67
+ "worksheetId": worksheet_id,
68
+ "keyWords": keywords,
69
+ }
70
+ )
71
+ return r.json()
72
+
73
+ def get_work_sheet_id_by_name(self, table_name: str, worksheet_name: str, child_section: bool=False):
74
+ r = self.get_app_info()
75
+ for i in r.data['data']['sections']:
76
+ if table_name == i['name']:
77
+ if child_section:
78
+ for child in i['childSections'][0]['items']:
79
+ if child['name'] == worksheet_name:
80
+ return child['id']
81
+ else:
82
+ for item in i['items']:
83
+ if item['name'] == worksheet_name:
84
+ return item['id']
85
+
86
+ def get_control_id(self, table_name: str=None, worksheet_name: str=None, control_name: str=None):
87
+ r = self.get_work_sheet_info(table_name=table_name, worksheet_name=worksheet_name)
88
+ for control in r['data']['controls']:
89
+ if control['controlName'] == control_name:
90
+ return control['controlId']
91
+ return None
92
+
93
+ def get_value(self, table_name: str=None, worksheet_name: str=None, control_name: str=None, value_name: str=None):
94
+ control_id = self.get_control_id(table_name=table_name, worksheet_name=worksheet_name, control_name=control_name)
95
+
96
+ r = self._build_api_request(
97
+ api_url='open/worksheet/getFilterRows',
98
+ method='POST',
99
+ body={
100
+ "pageIndex": 1,
101
+ "pageSize": 100,
102
+ "worksheetId": self.get_work_sheet_id_by_name(table_name=table_name, worksheet_name=worksheet_name),
103
+ # "filters": filters
104
+ }
105
+ )
106
+ for row in r.json()['data']['rows']:
107
+ if row[control_id] == value_name:
108
+ return row['rowid']
109
+
110
+ def get_work_record(self,
111
+ worksheet_id: str=None,
112
+ project_control_id: str=None,
113
+ project_value: str=None,
114
+ complete_date_control_id: str=None,
115
+ complete_date: Literal['Today', '上个月', 'Last7Day', 'Last30Day']=None,
116
+ parse_control_id: bool=False,
117
+ page_size: int=100,
118
+ ):
119
+
120
+ filters = []
121
+ if project_value:
122
+ filters.append({
123
+ "controlId": project_control_id,
124
+ "dataType": 29,
125
+ "spliceType": 1,
126
+ "filterType": 24,
127
+ "dateRange": 0,
128
+ "dateRangeType": 0,
129
+ "value": "",
130
+ "values": [
131
+ project_value
132
+ ],
133
+ "minValue": "",
134
+ "maxValue": ""
135
+ })
136
+
137
+ if complete_date:
138
+ if complete_date == '上个月':
139
+ data_range = 8
140
+ elif complete_date == 'Today':
141
+ data_range = 1
142
+ elif complete_date == 'Last7Day':
143
+ data_range = 21
144
+ else:
145
+ data_range = 1
146
+
147
+ filters.append({
148
+ "controlId": complete_date_control_id,
149
+ "dataType": 15,
150
+ "spliceType": 1,
151
+ "filterType": 17,
152
+ "dateRange": data_range,
153
+ })
154
+ r = self._build_api_request(
155
+ api_url='open/worksheet/getFilterRows',
156
+ method='POST',
157
+ body={
158
+ "pageIndex": 1,
159
+ "pageSize": page_size,
160
+ "worksheetId": worksheet_id,
161
+ "filters": filters
162
+ }
163
+ )
164
+ return r.json()