cmdbox 0.6.3.2__py3-none-any.whl → 0.6.4__py3-none-any.whl

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 cmdbox might be problematic. Click here for more details.

Files changed (133) hide show
  1. cmdbox/app/app.py +16 -7
  2. cmdbox/app/common.py +2 -2
  3. cmdbox/app/commons/redis_client.py +1 -1
  4. cmdbox/app/edge.py +1 -1
  5. cmdbox/app/feature.py +1 -1
  6. cmdbox/app/features/cli/cmdbox_audit_createdb.py +224 -224
  7. cmdbox/app/features/cli/cmdbox_audit_delete.py +4 -4
  8. cmdbox/app/features/cli/cmdbox_audit_search.py +4 -4
  9. cmdbox/app/features/cli/cmdbox_audit_write.py +6 -8
  10. cmdbox/app/features/cli/cmdbox_client_file_copy.py +3 -3
  11. cmdbox/app/features/cli/cmdbox_client_file_download.py +3 -3
  12. cmdbox/app/features/cli/cmdbox_client_file_list.py +3 -3
  13. cmdbox/app/features/cli/cmdbox_client_file_mkdir.py +3 -3
  14. cmdbox/app/features/cli/cmdbox_client_file_move.py +3 -3
  15. cmdbox/app/features/cli/cmdbox_client_file_remove.py +3 -3
  16. cmdbox/app/features/cli/cmdbox_client_file_rmdir.py +3 -3
  17. cmdbox/app/features/cli/cmdbox_client_file_upload.py +3 -3
  18. cmdbox/app/features/cli/cmdbox_client_http.py +7 -6
  19. cmdbox/app/features/cli/cmdbox_client_server_info.py +4 -4
  20. cmdbox/app/features/cli/cmdbox_cmd_list.py +3 -3
  21. cmdbox/app/features/cli/cmdbox_cmd_load.py +5 -5
  22. cmdbox/app/features/cli/cmdbox_edge_config.py +1 -1
  23. cmdbox/app/features/cli/cmdbox_edge_start.py +3 -3
  24. cmdbox/app/features/cli/cmdbox_mcp_client.py +174 -174
  25. cmdbox/app/features/cli/cmdbox_mcp_proxy.py +96 -96
  26. cmdbox/app/features/cli/cmdbox_server_list.py +2 -2
  27. cmdbox/app/features/cli/cmdbox_server_start.py +103 -103
  28. cmdbox/app/features/cli/cmdbox_server_stop.py +4 -4
  29. cmdbox/app/features/cli/cmdbox_tts_install.py +307 -0
  30. cmdbox/app/features/cli/cmdbox_tts_say.py +179 -0
  31. cmdbox/app/features/cli/cmdbox_tts_start.py +329 -0
  32. cmdbox/app/features/cli/cmdbox_tts_stop.py +108 -0
  33. cmdbox/app/features/cli/cmdbox_web_apikey_add.py +91 -91
  34. cmdbox/app/features/cli/cmdbox_web_apikey_del.py +91 -91
  35. cmdbox/app/features/cli/cmdbox_web_gencert.py +6 -6
  36. cmdbox/app/features/cli/cmdbox_web_genpass.py +168 -168
  37. cmdbox/app/features/cli/cmdbox_web_group_add.py +94 -94
  38. cmdbox/app/features/cli/cmdbox_web_group_del.py +87 -87
  39. cmdbox/app/features/cli/cmdbox_web_group_edit.py +94 -94
  40. cmdbox/app/features/cli/cmdbox_web_group_list.py +87 -87
  41. cmdbox/app/features/cli/cmdbox_web_start.py +235 -235
  42. cmdbox/app/features/cli/cmdbox_web_stop.py +72 -72
  43. cmdbox/app/features/cli/cmdbox_web_user_add.py +104 -104
  44. cmdbox/app/features/cli/cmdbox_web_user_del.py +87 -87
  45. cmdbox/app/features/cli/cmdbox_web_user_edit.py +104 -104
  46. cmdbox/app/features/cli/cmdbox_web_user_list.py +87 -87
  47. cmdbox/app/filer.py +9 -9
  48. cmdbox/app/mcp.py +15 -7
  49. cmdbox/app/options.py +46 -43
  50. cmdbox/app/server.py +224 -224
  51. cmdbox/extensions/features.yml +3 -0
  52. cmdbox/extensions/sample_project/sample/app/features/cli/sample_client_time.py +2 -2
  53. cmdbox/extensions/sample_project/sample/app/features/cli/sample_server_time.py +3 -3
  54. cmdbox/licenses/LICENSE_Werkzeug_3_1_1_BSD_License.txt +28 -0
  55. cmdbox/licenses/LICENSE_absolufy-imports_0_3_1_MIT_License.txt +21 -0
  56. cmdbox/licenses/LICENSE_cyclopts_3_22_5_Apache_Software_License.txt +201 -0
  57. cmdbox/licenses/LICENSE_isodate_0_7_2_BSD_License.txt +26 -0
  58. cmdbox/licenses/LICENSE_lazy-object-proxy_1_11_0_BSD_License.txt +20 -0
  59. cmdbox/licenses/LICENSE_openapi-core_0_19_5_BSD_License.txt +29 -0
  60. cmdbox/licenses/LICENSE_openapi-schema-validator_0_6_3_BSD_License.txt +29 -0
  61. cmdbox/licenses/LICENSE_openapi-spec-validator_0_7_2_Apache_Software_License.txt +201 -0
  62. cmdbox/licenses/LICENSE_opentelemetry-semantic-conventions_0_57b0_UNKNOWN.txt +201 -0
  63. cmdbox/licenses/LICENSE_parse_1_20_2_MIT_License.txt +19 -0
  64. cmdbox/licenses/LICENSE_pathable_0_4_4_Apache_Software_License.txt +201 -0
  65. cmdbox/licenses/{LICENSE_pillow_11_2_1_UNKNOWN.txt → LICENSE_pillow_11_3_0_UNKNOWN.txt} +393 -3
  66. cmdbox/licenses/LICENSE_pyperclip_1_9_0_BSD_License.txt +27 -0
  67. cmdbox/licenses/LICENSE_rfc3339-validator_0_1_4_MIT_License.txt +22 -0
  68. cmdbox/licenses/LICENSE_rich-rst_1_3_1_MIT_License.txt +7 -0
  69. cmdbox/licenses/{LICENSE_setuptools_65_5_0_MIT_License.txt → LICENSE_setuptools_80_9_0_UNKNOWN.txt} +0 -2
  70. cmdbox/licenses/LICENSE_tokenizers_0_21_4_Apache_Software_License.txt +1 -0
  71. cmdbox/licenses/LICENSE_voicevox_core_0_16_0_MIT.txt +20 -0
  72. cmdbox/licenses/LICENSE_watchdog_6_0_0_Apache_Software_License.txt +16 -0
  73. cmdbox/licenses/{LICENSE_typer_0_16_0_MIT_License.txt → LICENSE_wsproto_1_2_0_MIT_License.txt} +2 -2
  74. cmdbox/licenses/files.txt +56 -42
  75. cmdbox/logconf_cmdbox.yml +104 -0
  76. cmdbox/version.py +2 -2
  77. cmdbox/web/agent.html +8 -2
  78. cmdbox/web/assets/cmdbox/agent.js +182 -1
  79. cmdbox/web/assets/cmdbox/common.js +16 -3
  80. cmdbox/web/assets/cmdbox/svgicon.js +18 -0
  81. {cmdbox-0.6.3.2.dist-info → cmdbox-0.6.4.dist-info}/METADATA +28 -20
  82. {cmdbox-0.6.3.2.dist-info → cmdbox-0.6.4.dist-info}/RECORD +122 -112
  83. {cmdbox-0.6.3.2.dist-info → cmdbox-0.6.4.dist-info}/WHEEL +1 -1
  84. cmdbox/config.yml +0 -3
  85. cmdbox/licenses/LICENSE_httptools_0_6_4_MIT_License.txt +0 -21
  86. cmdbox/licenses/LICENSE_shellingham_1_5_4_ISC_License-ISCL.txt +0 -13
  87. cmdbox/licenses/LICENSE_watchfiles_1_1_0_MIT_License.txt +0 -21
  88. cmdbox/logconf_audit.yml +0 -43
  89. cmdbox/logconf_client.yml +0 -43
  90. cmdbox/logconf_edge.yml +0 -43
  91. cmdbox/logconf_gui.yml +0 -43
  92. cmdbox/logconf_mcp.yml +0 -43
  93. cmdbox/logconf_server.yml +0 -43
  94. cmdbox/logconf_web.yml +0 -43
  95. /cmdbox/licenses/{LICENSE_Authlib_1_6_0_BSD_License.txt → LICENSE_Authlib_1_6_1_BSD_License.txt} +0 -0
  96. /cmdbox/licenses/{LICENSE_SQLAlchemy_2_0_41_MIT.txt → LICENSE_SQLAlchemy_2_0_42_MIT.txt} +0 -0
  97. /cmdbox/licenses/{LICENSE_aiohttp_3_12_13_Apache-2_0.txt → LICENSE_aiohttp_3_12_15_Apache-2_0_AND_MIT.txt} +0 -0
  98. /cmdbox/licenses/{LICENSE_aiosignal_1_3_2_Apache_Software_License.txt → LICENSE_aiosignal_1_4_0_Apache_Software_License.txt} +0 -0
  99. /cmdbox/licenses/{LICENSE_certifi_2025_6_15_Mozilla_Public_License_2_0-MPL_2_0.txt → LICENSE_certifi_2025_7_14_Mozilla_Public_License_2_0-MPL_2_0.txt} +0 -0
  100. /cmdbox/licenses/{LICENSE_cryptography_45_0_4_Apache-2_0_OR_BSD-3-Clause.txt → LICENSE_cryptography_45_0_5_Apache-2_0_OR_BSD-3-Clause.txt} +0 -0
  101. /cmdbox/licenses/{LICENSE_docstring_parser_0_16_MIT_License.txt → LICENSE_docstring_parser_0_17_0_MIT_License.txt} +0 -0
  102. /cmdbox/licenses/{LICENSE_fastapi_0_115_14_MIT_License.txt → LICENSE_fastapi_0_116_1_MIT_License.txt} +0 -0
  103. /cmdbox/licenses/{LICENSE_fastmcp_2_10_1_Apache_Software_License.txt → LICENSE_fastmcp_2_11_0_Apache_Software_License.txt} +0 -0
  104. /cmdbox/licenses/{LICENSE_fsspec_2025_5_1_BSD_License.txt → LICENSE_fsspec_2025_7_0_BSD_License.txt} +0 -0
  105. /cmdbox/licenses/{LICENSE_google-adk_1_5_0_Apache_Software_License.txt → LICENSE_google-adk_1_9_0_Apache_Software_License.txt} +0 -0
  106. /cmdbox/licenses/{LICENSE_google-api-python-client_2_174_0_Apache_Software_License.txt → LICENSE_google-api-python-client_2_177_0_Apache_Software_License.txt} +0 -0
  107. /cmdbox/licenses/{LICENSE_google-cloud-aiplatform_1_100_0_Apache_2_0.txt → LICENSE_google-cloud-aiplatform_1_106_0_Apache_2_0.txt} +0 -0
  108. /cmdbox/licenses/{LICENSE_google-cloud-bigquery_3_34_0_Apache_Software_License.txt → LICENSE_google-cloud-bigquery_3_35_1_Apache_Software_License.txt} +0 -0
  109. /cmdbox/licenses/{LICENSE_google-genai_1_23_0_Apache_Software_License.txt → LICENSE_google-genai_1_28_0_Apache_Software_License.txt} +0 -0
  110. /cmdbox/licenses/{LICENSE_grpcio-status_1_73_1_Apache_Software_License.txt → LICENSE_grpcio-status_1_74_0_Apache_Software_License.txt} +0 -0
  111. /cmdbox/licenses/{LICENSE_grpcio_1_73_1_Apache_Software_License.txt → LICENSE_grpcio_1_74_0_Apache_Software_License.txt} +0 -0
  112. /cmdbox/licenses/{LICENSE_huggingface-hub_0_33_1_Apache_Software_License.txt → LICENSE_huggingface-hub_0_34_3_Apache_Software_License.txt} +0 -0
  113. /cmdbox/licenses/{LICENSE_opentelemetry-api_1_34_1_Apache_Software_License.txt → LICENSE_jsonschema-path_0_3_4_Apache_Software_License.txt} +0 -0
  114. /cmdbox/licenses/{LICENSE_jsonschema_4_24_0_UNKNOWN.txt → LICENSE_jsonschema_4_25_0_UNKNOWN.txt} +0 -0
  115. /cmdbox/licenses/{LICENSE_litellm_1_73_6_MIT_License.txt → LICENSE_litellm_1_74_12_MIT_License.txt} +0 -0
  116. /cmdbox/licenses/{LICENSE_mcp_1_10_1_MIT_License.txt → LICENSE_mcp_1_12_3_MIT_License.txt} +0 -0
  117. /cmdbox/licenses/{LICENSE_multidict_6_6_2_Apache_License_2_0.txt → LICENSE_multidict_6_6_3_Apache_License_2_0.txt} +0 -0
  118. /cmdbox/licenses/{LICENSE_nh3_0_2_21_MIT.txt → LICENSE_nh3_0_3_0_MIT.txt} +0 -0
  119. /cmdbox/licenses/{LICENSE_numpy_2_3_1_BSD_License.txt → LICENSE_numpy_2_3_2_BSD_License.txt} +0 -0
  120. /cmdbox/licenses/{LICENSE_openai_1_93_0_Apache_Software_License.txt → LICENSE_openai_1_98_0_Apache_Software_License.txt} +0 -0
  121. /cmdbox/licenses/{LICENSE_opentelemetry-sdk_1_34_1_Apache_Software_License.txt → LICENSE_opentelemetry-api_1_36_0_UNKNOWN.txt} +0 -0
  122. /cmdbox/licenses/{LICENSE_opentelemetry-semantic-conventions_0_55b1_Apache_Software_License.txt → LICENSE_opentelemetry-sdk_1_36_0_UNKNOWN.txt} +0 -0
  123. /cmdbox/licenses/{LICENSE_tokenizers_0_21_2_Apache_Software_License.txt → LICENSE_pywin32_311_Python_Software_Foundation_License.txt} +0 -0
  124. /cmdbox/licenses/{LICENSE_regex_2024_11_6_Apache_Software_License.txt → LICENSE_regex_2025_7_34_UNKNOWN.txt} +0 -0
  125. /cmdbox/licenses/{LICENSE_rich_14_0_0_MIT_License.txt → LICENSE_rich_14_1_0_MIT_License.txt} +0 -0
  126. /cmdbox/licenses/{LICENSE_rpds-py_0_25_1_MIT.txt → LICENSE_rpds-py_0_26_0_MIT.txt} +0 -0
  127. /cmdbox/licenses/{LICENSE_sse-starlette_2_3_6_BSD_License.txt → LICENSE_sse-starlette_3_0_2_UNKNOWN.txt} +0 -0
  128. /cmdbox/licenses/{LICENSE_starlette_0_46_2_BSD_License.txt → LICENSE_starlette_0_47_2_BSD_License.txt} +0 -0
  129. /cmdbox/licenses/{LICENSE_typing_extensions_4_14_0_UNKNOWN.txt → LICENSE_typing_extensions_4_14_1_UNKNOWN.txt} +0 -0
  130. /cmdbox/licenses/{LICENSE_zope_event_5_1_Zope_Public_License.txt → LICENSE_zope_event_5_1_1_Zope_Public_License.txt} +0 -0
  131. {cmdbox-0.6.3.2.dist-info → cmdbox-0.6.4.dist-info}/entry_points.txt +0 -0
  132. {cmdbox-0.6.3.2.dist-info → cmdbox-0.6.4.dist-info/licenses}/LICENSE +0 -0
  133. {cmdbox-0.6.3.2.dist-info → cmdbox-0.6.4.dist-info}/top_level.txt +0 -0
cmdbox/app/app.py CHANGED
@@ -58,6 +58,8 @@ class CmdBoxApp:
58
58
 
59
59
  # プラグイン読込み
60
60
  sfeatureloadtime = time.perf_counter()
61
+ self.options._load_features_yml(self.ver, logger=self.default_logger)
62
+ self.options.load_features_agentrule(self.default_logger)
61
63
  self.options.load_svcmd('cmdbox.app.features.cli', prefix="cmdbox_", excludes=[], appcls=self.appcls, ver=self.ver, logger=self.default_logger,
62
64
  isloaded=self.options.is_features_loaded('cli'))
63
65
  if self.cli_features_packages is not None:
@@ -92,7 +94,7 @@ class CmdBoxApp:
92
94
  except argparse.ArgumentError as e:
93
95
  msg = dict(warn=f"ArgumentError: {e}")
94
96
  common.print_format(msg, False, 0, None, False)
95
- return 1, msg, None
97
+ return feature.Feature.RESP_WARN, msg, None
96
98
  # 起動時引数で指定されたオプションをファイルから読み込んだオプションで上書きする
97
99
  args_dict = vars(args)
98
100
  for key, val in file_dict.items():
@@ -120,7 +122,7 @@ class CmdBoxApp:
120
122
  if args.useopt is None:
121
123
  msg = dict(warn=f"Please specify the --useopt option.")
122
124
  common.print_format(msg, args.format, smaintime, args.output_json, args.output_json_append)
123
- return 1, msg, None
125
+ return feature.Feature.RESP_WARN, msg, None
124
126
  common.saveopt(opt, args.useopt)
125
127
  ret = dict(success=f"Save options file. {args.useopt}")
126
128
 
@@ -133,15 +135,15 @@ class CmdBoxApp:
133
135
  if args.version:
134
136
  v = self.ver.__logo__ + '\n' + self.ver.__description__
135
137
  common.print_format(v, False, smaintime, None, False)
136
- return 0, v, None
138
+ return feature.Feature.RESP_SUCCESS, v, None
137
139
 
138
140
  if args.mode is None:
139
141
  msg = dict(warn=f"mode is None. Please specify the --help option.")
140
142
  common.print_format(msg, args.format, smaintime, args.output_json, args.output_json_append)
141
- return 1, msg, None
143
+ return feature.Feature.RESP_WARN, msg, None
142
144
 
143
145
  sloggerinittime = time.perf_counter()
144
- logger, _ = common.load_config(args.mode, debug=args.debug, data=args.data, webcall=webcall if args.cmd != 'webcap' else True, ver=self.ver)
146
+ logger = self.load_config(args, webcall=webcall if args.cmd != 'webcap' else True)
145
147
  try:
146
148
  eloggerinittime = time.perf_counter()
147
149
  if logger.level == logging.DEBUG:
@@ -168,7 +170,14 @@ class CmdBoxApp:
168
170
  else:
169
171
  msg = dict(warn=f"Unkown mode or cmd. mode={args.mode}, cmd={args.cmd}")
170
172
  common.print_format(msg, args.format, smaintime, args.output_json, args.output_json_append)
171
- return 1, msg, None
173
+ return feature.Feature.RESP_WARN, msg, None
172
174
  finally:
173
175
  # ログの状態をwebcallから戻す
174
- common.load_config(args.mode, debug=args.debug, data=args.data, webcall=False, ver=self.ver)
176
+ self.load_config(args, webcall=False)
177
+
178
+ def load_config(self, args:argparse.Namespace, webcall:bool=False) -> logging.Logger:
179
+ """
180
+ アプリケーションの設定を読み込みます。
181
+ """
182
+ logger, _ = common.load_config(args.mode, debug=args.debug, data=args.data, webcall=webcall if args.cmd != 'webcap' else True, ver=self.ver)
183
+ return logger
cmdbox/app/common.py CHANGED
@@ -245,13 +245,13 @@ def load_config(mode:str, debug:bool=False, data=HOME_DIR, webcall:bool=False, v
245
245
  log_name = mode
246
246
  if not log_conf_path.exists():
247
247
  log_conf_path = Path(ver.__file__).parent / f"logconf_{ver.__appid__}.yml"
248
- log_name = ver.__appid__
248
+ log_name = mode
249
249
  if not log_conf_path.exists():
250
250
  log_conf_path = Path(version.__file__).parent / f"logconf_{mode}.yml"
251
251
  log_name = mode
252
252
  if not log_conf_path.exists():
253
253
  log_conf_path = Path(version.__file__).parent / f"logconf_{ver.__appid__}.yml"
254
- log_name = ver.__appid__
254
+ log_name = mode
255
255
  with open(log_conf_path) as f:
256
256
  log_config = yaml.safe_load(f)
257
257
  std_key = None
@@ -104,7 +104,7 @@ class RedisClient(object):
104
104
  i = 0
105
105
  return True
106
106
  except redis.exceptions.ConnectionError as e:
107
- self.logger.warning(f"fail to ping server. {e}")
107
+ self.logger.warning(f"fail to ping server. {self.host}:{self.port}, error={e}")
108
108
  if i >= retry_count and retry_count > 0:
109
109
  return False
110
110
  time.sleep(retry_interval if retry_interval > 0 else 5)
cmdbox/app/edge.py CHANGED
@@ -676,7 +676,7 @@ class Edge(object):
676
676
  if time.time() - tm > oauth2_timeout:
677
677
  return 1, dict(warn="Signin Timeout.")
678
678
  time.sleep(1)
679
- return 0, dict(success="Signin success.")
679
+ return feature.Feature.RESP_SUCCESS, dict(success="Signin success.")
680
680
 
681
681
  # saml認証を使用する場合
682
682
  elif auth_type == "saml":
cmdbox/app/feature.py CHANGED
@@ -14,7 +14,7 @@ class Feature(object):
14
14
  USE_REDIS_FALSE:int = -1
15
15
  USE_REDIS_MEIGHT:int = 0
16
16
  USE_REDIS_TRUE:int = 1
17
- RESP_SCCESS:int = 0
17
+ RESP_SUCCESS:int = 0
18
18
  RESP_WARN:int = 1
19
19
  RESP_ERROR:int = 2
20
20
  DEFAULT_CAPTURE_MAXSIZE:int = 1024 * 1024 * 10
@@ -1,224 +1,224 @@
1
- from cmdbox.app import common, client, feature
2
- from cmdbox.app.commons import convert, redis_client
3
- from cmdbox.app.features.cli import audit_base
4
- from cmdbox.app.options import Options
5
- from datetime import datetime
6
- from pathlib import Path
7
- from typing import Dict, Any, Tuple, List, Union
8
- import argparse
9
- import logging
10
- import json
11
- import psycopg
12
-
13
-
14
- class AuditCreatedb(feature.UnsupportEdgeFeature):
15
- def get_mode(self) -> Union[str, List[str]]:
16
- """
17
- この機能のモードを返します
18
-
19
- Returns:
20
- Union[str, List[str]]: モード
21
- """
22
- return 'audit'
23
-
24
- def get_cmd(self):
25
- """
26
- この機能のコマンドを返します
27
-
28
- Returns:
29
- str: コマンド
30
- """
31
- return 'createdb'
32
-
33
- def get_option(self):
34
- """
35
- この機能のオプションを返します
36
-
37
- Returns:
38
- Dict[str, Any]: オプション
39
- """
40
- return dict(
41
- use_redis=self.USE_REDIS_MEIGHT, nouse_webmode=True,
42
- description_ja="監査を記録するデータベースを作成します。",
43
- description_en="Create a database to record audits.",
44
- choice=[
45
- dict(opt="pg_host", type=Options.T_STR, default='localhost', required=True, multi=False, hide=False, choice=None,
46
- description_ja="postgresqlホストを指定する。",
47
- description_en="Specify the postgresql host."),
48
- dict(opt="pg_port", type=Options.T_INT, default=5432, required=True, multi=False, hide=False, choice=None,
49
- description_ja="postgresqlのポートを指定する。",
50
- description_en="Specify the postgresql port."),
51
- dict(opt="pg_user", type=Options.T_STR, default='postgres', required=True, multi=False, hide=False, choice=None,
52
- description_ja="postgresqlのユーザー名を指定する。",
53
- description_en="Specify the postgresql user name."),
54
- dict(opt="pg_password", type=Options.T_STR, default='postgres', required=True, multi=False, hide=False, choice=None,
55
- description_ja="postgresqlのパスワードを指定する。",
56
- description_en="Specify the postgresql password."),
57
- dict(opt="pg_dbname", type=Options.T_STR, default='audit', required=True, multi=False, hide=False, choice=None,
58
- description_ja="postgresqlデータベース名を指定します。",
59
- description_en="Specify the postgresql database name."),
60
- dict(opt="new_pg_dbname", type=Options.T_STR, default='audit', required=True, multi=False, hide=False, choice=None,
61
- description_ja="新しいpostgresqlデータベース名を指定します。",
62
- description_en="Specify a new postgresql database name."),
63
-
64
- dict(opt="host", type=Options.T_STR, default=self.default_host, required=True, multi=False, hide=True, choice=None, web="mask",
65
- description_ja="Redisサーバーのサービスホストを指定します。",
66
- description_en="Specify the service host of the Redis server."),
67
- dict(opt="port", type=Options.T_INT, default=self.default_port, required=True, multi=False, hide=True, choice=None, web="mask",
68
- description_ja="Redisサーバーのサービスポートを指定します。",
69
- description_en="Specify the service port of the Redis server."),
70
- dict(opt="password", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None, web="mask",
71
- description_ja=f"Redisサーバーのアクセスパスワード(任意)を指定します。省略時は `{self.default_pass}` を使用します。",
72
- description_en=f"Specify the access password of the Redis server (optional). If omitted, `{self.default_pass}` is used."),
73
- dict(opt="svname", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None, web="readonly",
74
- description_ja="サーバーのサービス名を指定します。省略時は `server` を使用します。",
75
- description_en="Specify the service name of the inference server. If omitted, `server` is used."),
76
- dict(opt="retry_count", type=Options.T_INT, default=3, required=False, multi=False, hide=True, choice=None,
77
- description_ja="Redisサーバーへの再接続回数を指定します。0以下を指定すると永遠に再接続を行います。",
78
- description_en="Specifies the number of reconnections to the Redis server.If less than 0 is specified, reconnection is forever."),
79
- dict(opt="retry_interval", type=Options.T_INT, default=5, required=False, multi=False, hide=True, choice=None,
80
- description_ja="Redisサーバーに再接続までの秒数を指定します。",
81
- description_en="Specifies the number of seconds before reconnecting to the Redis server."),
82
- dict(opt="timeout", type=Options.T_INT, default="15", required=False, multi=False, hide=True, choice=None,
83
- description_ja="サーバーの応答が返ってくるまでの最大待ち時間を指定。",
84
- description_en="Specify the maximum waiting time until the server responds."),
85
- ]
86
- )
87
-
88
-
89
- def get_svcmd(self):
90
- """
91
- この機能のサーバー側のコマンドを返します
92
-
93
- Returns:
94
- str: サーバー側のコマンド
95
- """
96
- return 'audit_create'
97
-
98
- def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:
99
- """
100
- この機能の実行を行います
101
-
102
- Args:
103
- logger (logging.Logger): ロガー
104
- args (argparse.Namespace): 引数
105
- tm (float): 実行開始時間
106
- pf (List[Dict[str, float]]): 呼出元のパフォーマンス情報
107
-
108
- Returns:
109
- Tuple[int, Dict[str, Any], Any]: 終了コード, 結果, オブジェクト
110
- """
111
- if args.svname is None:
112
- msg = dict(warn=f"Please specify the --svname option.")
113
- common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
114
- return 1, msg, None
115
- if args.pg_host is None:
116
- msg = dict(warn=f"Please specify the --pg_host option.")
117
- common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
118
- return 1, msg, None
119
- if args.pg_port is None:
120
- msg = dict(warn=f"Please specify the --pg_port option.")
121
- common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
122
- return 1, msg, None
123
- if args.pg_user is None:
124
- msg = dict(warn=f"Please specify the --pg_user option.")
125
- common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
126
- return 1, msg, None
127
- if args.pg_password is None:
128
- msg = dict(warn=f"Please specify the --pg_password option.")
129
- common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
130
- return 1, msg, None
131
- if args.pg_dbname is None:
132
- msg = dict(warn=f"Please specify the --pg_dbname option.")
133
- common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
134
- return 1, msg, None
135
- if args.new_pg_dbname is None:
136
- msg = dict(warn=f"Please specify the --new_pg_dbname option.")
137
- common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
138
- return 1, msg, None
139
-
140
- pg_host_b64 = convert.str2b64str(args.pg_host)
141
- pg_port = args.pg_port if isinstance(args.pg_port, int) else None
142
- pg_user_b64 = convert.str2b64str(args.pg_user)
143
- pg_password_b64 = convert.str2b64str(args.pg_password)
144
- pg_dbname_b64 = convert.str2b64str(args.pg_dbname)
145
- new_pg_dbname_b64 = convert.str2b64str(args.new_pg_dbname)
146
-
147
- cl = client.Client(logger, redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname)
148
- ret = cl.redis_cli.send_cmd(self.get_svcmd(),
149
- [pg_host_b64, pg_port, pg_user_b64, pg_password_b64, pg_dbname_b64, new_pg_dbname_b64],
150
- retry_count=args.retry_count, retry_interval=args.retry_interval, timeout=args.timeout)
151
- common.print_format(ret, False, tm, None, False, pf=pf)
152
- if 'success' not in ret:
153
- return 1, ret, cl
154
- return 0, ret, cl
155
-
156
- def is_cluster_redirect(self):
157
- """
158
- クラスター宛のメッセージの場合、メッセージを転送するかどうかを返します
159
-
160
- Returns:
161
- bool: メッセージを転送する場合はTrue
162
- """
163
- return False
164
-
165
- def svrun(self, data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient, msg:List[str],
166
- sessions:Dict[str, Dict[str, Any]]) -> int:
167
- """
168
- この機能のサーバー側の実行を行います
169
-
170
- Args:
171
- data_dir (Path): データディレクトリ
172
- logger (logging.Logger): ロガー
173
- redis_cli (redis_client.RedisClient): Redisクライアント
174
- msg (List[str]): 受信メッセージ
175
- sessions (Dict[str, Dict[str, Any]]): セッション情報
176
-
177
- Returns:
178
- int: 終了コード
179
- """
180
- pg_host = convert.b64str2str(msg[2])
181
- pg_port = int(msg[3]) if msg[3]!='None' else None
182
- pg_user = convert.b64str2str(msg[4])
183
- pg_password = convert.b64str2str(msg[5])
184
- pg_dbname = convert.b64str2str(msg[6])
185
- new_pg_dbname = convert.b64str2str(msg[7])
186
- st = self.createdb(msg[1], pg_host, pg_port, pg_user, pg_password, pg_dbname, new_pg_dbname,
187
- data_dir, logger, redis_cli)
188
- return st
189
-
190
- def createdb(self, reskey:str, pg_host:str, pg_port:int, pg_user:str, pg_password:str, pg_dbname:str, new_pg_dbname:str,
191
- data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient) -> int:
192
- """
193
- 監査ログデータベースを作成する
194
-
195
- Args:
196
- reskey (str): レスポンスキー
197
- pg_host (str): PostgreSQLホスト
198
- pg_port (int): PostgreSQLポート
199
- pg_user (str): PostgreSQLユーザー
200
- pg_password (str): PostgreSQLパスワード
201
- pg_dbname (str): PostgreSQLデータベース名
202
- new_pg_dbname (str): 新しいPostgreSQLデータベース名
203
- data_dir (Path): データディレクトリ
204
- logger (logging.Logger): ロガー
205
- redis_cli (redis_client.RedisClient): Redisクライアント
206
-
207
- Returns:
208
- int: レスポンスコード
209
- """
210
- try:
211
- constr = f"host={pg_host} port={pg_port} user={pg_user} password={pg_password} dbname={pg_dbname} connect_timeout=5"
212
- with psycopg.connect(constr, autocommit=True) as conn:
213
- cursor = conn.cursor()
214
- try:
215
- cursor.execute(f'create database {new_pg_dbname}')
216
- rescode, msg = (self.RESP_SCCESS, dict(success=True))
217
- redis_cli.rpush(reskey, msg)
218
- return rescode
219
- finally:
220
- cursor.close()
221
- except Exception as e:
222
- logger.warning(f"Failed to createdb: {e}", exc_info=True)
223
- redis_cli.rpush(reskey, dict(warn=f"Failed to createdb: {e}"))
224
- return self.RESP_WARN
1
+ from cmdbox.app import common, client, feature
2
+ from cmdbox.app.commons import convert, redis_client
3
+ from cmdbox.app.features.cli import audit_base
4
+ from cmdbox.app.options import Options
5
+ from datetime import datetime
6
+ from pathlib import Path
7
+ from typing import Dict, Any, Tuple, List, Union
8
+ import argparse
9
+ import logging
10
+ import json
11
+ import psycopg
12
+
13
+
14
+ class AuditCreatedb(feature.UnsupportEdgeFeature):
15
+ def get_mode(self) -> Union[str, List[str]]:
16
+ """
17
+ この機能のモードを返します
18
+
19
+ Returns:
20
+ Union[str, List[str]]: モード
21
+ """
22
+ return 'audit'
23
+
24
+ def get_cmd(self):
25
+ """
26
+ この機能のコマンドを返します
27
+
28
+ Returns:
29
+ str: コマンド
30
+ """
31
+ return 'createdb'
32
+
33
+ def get_option(self):
34
+ """
35
+ この機能のオプションを返します
36
+
37
+ Returns:
38
+ Dict[str, Any]: オプション
39
+ """
40
+ return dict(
41
+ use_redis=self.USE_REDIS_MEIGHT, nouse_webmode=True,
42
+ description_ja="監査を記録するデータベースを作成します。",
43
+ description_en="Create a database to record audits.",
44
+ choice=[
45
+ dict(opt="pg_host", type=Options.T_STR, default='localhost', required=True, multi=False, hide=False, choice=None,
46
+ description_ja="postgresqlホストを指定する。",
47
+ description_en="Specify the postgresql host."),
48
+ dict(opt="pg_port", type=Options.T_INT, default=5432, required=True, multi=False, hide=False, choice=None,
49
+ description_ja="postgresqlのポートを指定する。",
50
+ description_en="Specify the postgresql port."),
51
+ dict(opt="pg_user", type=Options.T_STR, default='postgres', required=True, multi=False, hide=False, choice=None,
52
+ description_ja="postgresqlのユーザー名を指定する。",
53
+ description_en="Specify the postgresql user name."),
54
+ dict(opt="pg_password", type=Options.T_STR, default='postgres', required=True, multi=False, hide=False, choice=None,
55
+ description_ja="postgresqlのパスワードを指定する。",
56
+ description_en="Specify the postgresql password."),
57
+ dict(opt="pg_dbname", type=Options.T_STR, default='audit', required=True, multi=False, hide=False, choice=None,
58
+ description_ja="postgresqlデータベース名を指定します。",
59
+ description_en="Specify the postgresql database name."),
60
+ dict(opt="new_pg_dbname", type=Options.T_STR, default='audit', required=True, multi=False, hide=False, choice=None,
61
+ description_ja="新しいpostgresqlデータベース名を指定します。",
62
+ description_en="Specify a new postgresql database name."),
63
+
64
+ dict(opt="host", type=Options.T_STR, default=self.default_host, required=True, multi=False, hide=True, choice=None, web="mask",
65
+ description_ja="Redisサーバーのサービスホストを指定します。",
66
+ description_en="Specify the service host of the Redis server."),
67
+ dict(opt="port", type=Options.T_INT, default=self.default_port, required=True, multi=False, hide=True, choice=None, web="mask",
68
+ description_ja="Redisサーバーのサービスポートを指定します。",
69
+ description_en="Specify the service port of the Redis server."),
70
+ dict(opt="password", type=Options.T_STR, default=self.default_pass, required=True, multi=False, hide=True, choice=None, web="mask",
71
+ description_ja=f"Redisサーバーのアクセスパスワード(任意)を指定します。省略時は `{self.default_pass}` を使用します。",
72
+ description_en=f"Specify the access password of the Redis server (optional). If omitted, `{self.default_pass}` is used."),
73
+ dict(opt="svname", type=Options.T_STR, default=self.default_svname, required=True, multi=False, hide=True, choice=None, web="readonly",
74
+ description_ja="サーバーのサービス名を指定します。省略時は `server` を使用します。",
75
+ description_en="Specify the service name of the inference server. If omitted, `server` is used."),
76
+ dict(opt="retry_count", type=Options.T_INT, default=3, required=False, multi=False, hide=True, choice=None,
77
+ description_ja="Redisサーバーへの再接続回数を指定します。0以下を指定すると永遠に再接続を行います。",
78
+ description_en="Specifies the number of reconnections to the Redis server.If less than 0 is specified, reconnection is forever."),
79
+ dict(opt="retry_interval", type=Options.T_INT, default=5, required=False, multi=False, hide=True, choice=None,
80
+ description_ja="Redisサーバーに再接続までの秒数を指定します。",
81
+ description_en="Specifies the number of seconds before reconnecting to the Redis server."),
82
+ dict(opt="timeout", type=Options.T_INT, default="15", required=False, multi=False, hide=True, choice=None,
83
+ description_ja="サーバーの応答が返ってくるまでの最大待ち時間を指定。",
84
+ description_en="Specify the maximum waiting time until the server responds."),
85
+ ]
86
+ )
87
+
88
+
89
+ def get_svcmd(self):
90
+ """
91
+ この機能のサーバー側のコマンドを返します
92
+
93
+ Returns:
94
+ str: サーバー側のコマンド
95
+ """
96
+ return 'audit_create'
97
+
98
+ def apprun(self, logger:logging.Logger, args:argparse.Namespace, tm:float, pf:List[Dict[str, float]]=[]) -> Tuple[int, Dict[str, Any], Any]:
99
+ """
100
+ この機能の実行を行います
101
+
102
+ Args:
103
+ logger (logging.Logger): ロガー
104
+ args (argparse.Namespace): 引数
105
+ tm (float): 実行開始時間
106
+ pf (List[Dict[str, float]]): 呼出元のパフォーマンス情報
107
+
108
+ Returns:
109
+ Tuple[int, Dict[str, Any], Any]: 終了コード, 結果, オブジェクト
110
+ """
111
+ if args.svname is None:
112
+ msg = dict(warn=f"Please specify the --svname option.")
113
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
114
+ return self.RESP_WARN, msg, None
115
+ if args.pg_host is None:
116
+ msg = dict(warn=f"Please specify the --pg_host option.")
117
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
118
+ return self.RESP_WARN, msg, None
119
+ if args.pg_port is None:
120
+ msg = dict(warn=f"Please specify the --pg_port option.")
121
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
122
+ return self.RESP_WARN, msg, None
123
+ if args.pg_user is None:
124
+ msg = dict(warn=f"Please specify the --pg_user option.")
125
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
126
+ return self.RESP_WARN, msg, None
127
+ if args.pg_password is None:
128
+ msg = dict(warn=f"Please specify the --pg_password option.")
129
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
130
+ return self.RESP_WARN, msg, None
131
+ if args.pg_dbname is None:
132
+ msg = dict(warn=f"Please specify the --pg_dbname option.")
133
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
134
+ return self.RESP_WARN, msg, None
135
+ if args.new_pg_dbname is None:
136
+ msg = dict(warn=f"Please specify the --new_pg_dbname option.")
137
+ common.print_format(msg, args.format, tm, args.output_json, args.output_json_append, pf=pf)
138
+ return self.RESP_WARN, msg, None
139
+
140
+ pg_host_b64 = convert.str2b64str(args.pg_host)
141
+ pg_port = args.pg_port if isinstance(args.pg_port, int) else None
142
+ pg_user_b64 = convert.str2b64str(args.pg_user)
143
+ pg_password_b64 = convert.str2b64str(args.pg_password)
144
+ pg_dbname_b64 = convert.str2b64str(args.pg_dbname)
145
+ new_pg_dbname_b64 = convert.str2b64str(args.new_pg_dbname)
146
+
147
+ cl = client.Client(logger, redis_host=args.host, redis_port=args.port, redis_password=args.password, svname=args.svname)
148
+ ret = cl.redis_cli.send_cmd(self.get_svcmd(),
149
+ [pg_host_b64, pg_port, pg_user_b64, pg_password_b64, pg_dbname_b64, new_pg_dbname_b64],
150
+ retry_count=args.retry_count, retry_interval=args.retry_interval, timeout=args.timeout)
151
+ common.print_format(ret, False, tm, None, False, pf=pf)
152
+ if 'success' not in ret:
153
+ return self.RESP_WARN, ret, cl
154
+ return self.RESP_SUCCESS, ret, cl
155
+
156
+ def is_cluster_redirect(self):
157
+ """
158
+ クラスター宛のメッセージの場合、メッセージを転送するかどうかを返します
159
+
160
+ Returns:
161
+ bool: メッセージを転送する場合はTrue
162
+ """
163
+ return False
164
+
165
+ def svrun(self, data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient, msg:List[str],
166
+ sessions:Dict[str, Dict[str, Any]]) -> int:
167
+ """
168
+ この機能のサーバー側の実行を行います
169
+
170
+ Args:
171
+ data_dir (Path): データディレクトリ
172
+ logger (logging.Logger): ロガー
173
+ redis_cli (redis_client.RedisClient): Redisクライアント
174
+ msg (List[str]): 受信メッセージ
175
+ sessions (Dict[str, Dict[str, Any]]): セッション情報
176
+
177
+ Returns:
178
+ int: 終了コード
179
+ """
180
+ pg_host = convert.b64str2str(msg[2])
181
+ pg_port = int(msg[3]) if msg[3]!='None' else None
182
+ pg_user = convert.b64str2str(msg[4])
183
+ pg_password = convert.b64str2str(msg[5])
184
+ pg_dbname = convert.b64str2str(msg[6])
185
+ new_pg_dbname = convert.b64str2str(msg[7])
186
+ st = self.createdb(msg[1], pg_host, pg_port, pg_user, pg_password, pg_dbname, new_pg_dbname,
187
+ data_dir, logger, redis_cli)
188
+ return st
189
+
190
+ def createdb(self, reskey:str, pg_host:str, pg_port:int, pg_user:str, pg_password:str, pg_dbname:str, new_pg_dbname:str,
191
+ data_dir:Path, logger:logging.Logger, redis_cli:redis_client.RedisClient) -> int:
192
+ """
193
+ 監査ログデータベースを作成する
194
+
195
+ Args:
196
+ reskey (str): レスポンスキー
197
+ pg_host (str): PostgreSQLホスト
198
+ pg_port (int): PostgreSQLポート
199
+ pg_user (str): PostgreSQLユーザー
200
+ pg_password (str): PostgreSQLパスワード
201
+ pg_dbname (str): PostgreSQLデータベース名
202
+ new_pg_dbname (str): 新しいPostgreSQLデータベース名
203
+ data_dir (Path): データディレクトリ
204
+ logger (logging.Logger): ロガー
205
+ redis_cli (redis_client.RedisClient): Redisクライアント
206
+
207
+ Returns:
208
+ int: レスポンスコード
209
+ """
210
+ try:
211
+ constr = f"host={pg_host} port={pg_port} user={pg_user} password={pg_password} dbname={pg_dbname} connect_timeout=5"
212
+ with psycopg.connect(constr, autocommit=True) as conn:
213
+ cursor = conn.cursor()
214
+ try:
215
+ cursor.execute(f'create database {new_pg_dbname}')
216
+ rescode, msg = (self.RESP_SUCCESS, dict(success=True))
217
+ redis_cli.rpush(reskey, msg)
218
+ return rescode
219
+ finally:
220
+ cursor.close()
221
+ except Exception as e:
222
+ logger.warning(f"Failed to createdb: {e}", exc_info=True)
223
+ redis_cli.rpush(reskey, dict(warn=f"Failed to createdb: {e}"))
224
+ return self.RESP_WARN
@@ -105,7 +105,7 @@ class AuditDelete(audit_base.AuditBase):
105
105
  if args.svname is None:
106
106
  msg = dict(warn=f"Please specify the --svname option.")
107
107
  common.print_format(msg, args.format, tm, None, False, pf=pf)
108
- return 1, msg, None
108
+ return self.RESP_WARN, msg, None
109
109
 
110
110
  delete_audit_type_b64 = convert.str2b64str(args.delete_audit_type)
111
111
  delete_clmsg_id_b64 = convert.str2b64str(args.delete_clmsg_id)
@@ -140,7 +140,7 @@ class AuditDelete(audit_base.AuditBase):
140
140
  common.print_format(ret, args.format, tm, None, False, pf=pf)
141
141
 
142
142
  if 'success' not in ret:
143
- return 1, ret, cl
143
+ return self.RESP_WARN, ret, cl
144
144
 
145
145
  if 'data' in ret['success']:
146
146
  for row in ret['success']['data']:
@@ -153,7 +153,7 @@ class AuditDelete(audit_base.AuditBase):
153
153
  except:
154
154
  pass
155
155
 
156
- return 0, ret, cl
156
+ return self.RESP_SUCCESS, ret, cl
157
157
 
158
158
  def is_cluster_redirect(self):
159
159
  """
@@ -297,7 +297,7 @@ class AuditDelete(audit_base.AuditBase):
297
297
  redis_cli.rpush(reskey, msg)
298
298
  return rescode
299
299
  else:
300
- rescode, msg = (self.RESP_SCCESS, dict(success=dict(msg=f"{delete_count} records deleted.", count=delete_count)))
300
+ rescode, msg = (self.RESP_SUCCESS, dict(success=dict(msg=f"{delete_count} records deleted.", count=delete_count)))
301
301
  redis_cli.rpush(reskey, msg)
302
302
  return rescode
303
303
  finally:
@@ -153,7 +153,7 @@ class AuditSearch(audit_base.AuditBase):
153
153
  if args.svname is None:
154
154
  msg = dict(warn=f"Please specify the --svname option.")
155
155
  common.print_format(msg, args.format, tm, None, False, pf=pf)
156
- return 1, msg, None
156
+ return self.RESP_WARN, msg, None
157
157
 
158
158
  select_str = json.dumps(args.select, default=common.default_json_enc, ensure_ascii=False) if getattr(args, 'select', None) else '{}'
159
159
  select_b64 = convert.str2b64str(select_str)
@@ -202,7 +202,7 @@ class AuditSearch(audit_base.AuditBase):
202
202
 
203
203
  if 'success' not in ret:
204
204
  common.print_format(ret, getattr(args, 'format', False), tm, None, False, pf=pf)
205
- return 1, ret, cl
205
+ return self.RESP_WARN, ret, cl
206
206
 
207
207
  if 'data' in ret['success']:
208
208
  cols = list()
@@ -232,7 +232,7 @@ class AuditSearch(audit_base.AuditBase):
232
232
  ret = ret.replace('\r\n', '\n') if ret is not None else ''
233
233
 
234
234
  common.print_format(ret, args.format, tm, args.output_json, args.output_json_append, pf=pf)
235
- return 0, ret, cl
235
+ return self.RESP_SUCCESS, ret, cl
236
236
 
237
237
  def is_cluster_redirect(self):
238
238
  """
@@ -464,7 +464,7 @@ class AuditSearch(audit_base.AuditBase):
464
464
  redis_cli.rpush(reskey, msg)
465
465
  return rescode
466
466
  else:
467
- rescode, msg = (self.RESP_SCCESS, dict(success=rows))
467
+ rescode, msg = (self.RESP_SUCCESS, dict(success=rows))
468
468
  redis_cli.rpush(reskey, msg)
469
469
  return rescode
470
470
  finally: