holmesgpt 0.12.6__py3-none-any.whl → 0.13.1__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 holmesgpt might be problematic. Click here for more details.
- holmes/__init__.py +1 -1
- holmes/clients/robusta_client.py +19 -1
- holmes/common/env_vars.py +17 -0
- holmes/config.py +69 -9
- holmes/core/conversations.py +11 -0
- holmes/core/investigation.py +16 -3
- holmes/core/investigation_structured_output.py +12 -0
- holmes/core/llm.py +13 -1
- holmes/core/models.py +9 -1
- holmes/core/openai_formatting.py +72 -12
- holmes/core/prompt.py +13 -0
- holmes/core/supabase_dal.py +3 -0
- holmes/core/todo_manager.py +88 -0
- holmes/core/tool_calling_llm.py +230 -157
- holmes/core/tools.py +10 -1
- holmes/core/tools_utils/tool_executor.py +7 -2
- holmes/core/tools_utils/toolset_utils.py +7 -2
- holmes/core/toolset_manager.py +1 -5
- holmes/core/tracing.py +4 -3
- holmes/interactive.py +1 -0
- holmes/main.py +9 -2
- holmes/plugins/prompts/__init__.py +7 -1
- holmes/plugins/prompts/_current_date_time.jinja2 +1 -0
- holmes/plugins/prompts/_default_log_prompt.jinja2 +4 -2
- holmes/plugins/prompts/_fetch_logs.jinja2 +10 -1
- holmes/plugins/prompts/_general_instructions.jinja2 +14 -0
- holmes/plugins/prompts/_permission_errors.jinja2 +1 -1
- holmes/plugins/prompts/_toolsets_instructions.jinja2 +4 -4
- holmes/plugins/prompts/generic_ask.jinja2 +4 -3
- holmes/plugins/prompts/investigation_procedure.jinja2 +210 -0
- holmes/plugins/prompts/kubernetes_workload_ask.jinja2 +2 -0
- holmes/plugins/runbooks/CLAUDE.md +85 -0
- holmes/plugins/runbooks/README.md +24 -0
- holmes/plugins/toolsets/__init__.py +19 -6
- holmes/plugins/toolsets/atlas_mongodb/mongodb_atlas.py +27 -0
- holmes/plugins/toolsets/azure_sql/tools/analyze_connection_failures.py +2 -2
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_connections.py +2 -1
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_health_status.py +3 -1
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_performance.py +2 -1
- holmes/plugins/toolsets/azure_sql/tools/analyze_database_storage.py +2 -1
- holmes/plugins/toolsets/azure_sql/tools/get_active_alerts.py +3 -1
- holmes/plugins/toolsets/azure_sql/tools/get_slow_queries.py +2 -1
- holmes/plugins/toolsets/azure_sql/tools/get_top_cpu_queries.py +2 -1
- holmes/plugins/toolsets/azure_sql/tools/get_top_data_io_queries.py +2 -1
- holmes/plugins/toolsets/azure_sql/tools/get_top_log_io_queries.py +2 -1
- holmes/plugins/toolsets/bash/argocd/__init__.py +65 -0
- holmes/plugins/toolsets/bash/argocd/constants.py +120 -0
- holmes/plugins/toolsets/bash/aws/__init__.py +66 -0
- holmes/plugins/toolsets/bash/aws/constants.py +529 -0
- holmes/plugins/toolsets/bash/azure/__init__.py +56 -0
- holmes/plugins/toolsets/bash/azure/constants.py +339 -0
- holmes/plugins/toolsets/bash/bash_instructions.jinja2 +6 -7
- holmes/plugins/toolsets/bash/bash_toolset.py +47 -13
- holmes/plugins/toolsets/bash/common/bash_command.py +131 -0
- holmes/plugins/toolsets/bash/common/stringify.py +14 -1
- holmes/plugins/toolsets/bash/common/validators.py +91 -0
- holmes/plugins/toolsets/bash/docker/__init__.py +59 -0
- holmes/plugins/toolsets/bash/docker/constants.py +255 -0
- holmes/plugins/toolsets/bash/helm/__init__.py +61 -0
- holmes/plugins/toolsets/bash/helm/constants.py +92 -0
- holmes/plugins/toolsets/bash/kubectl/__init__.py +80 -79
- holmes/plugins/toolsets/bash/kubectl/constants.py +0 -14
- holmes/plugins/toolsets/bash/kubectl/kubectl_describe.py +38 -56
- holmes/plugins/toolsets/bash/kubectl/kubectl_events.py +28 -76
- holmes/plugins/toolsets/bash/kubectl/kubectl_get.py +39 -99
- holmes/plugins/toolsets/bash/kubectl/kubectl_logs.py +34 -15
- holmes/plugins/toolsets/bash/kubectl/kubectl_run.py +1 -1
- holmes/plugins/toolsets/bash/kubectl/kubectl_top.py +38 -77
- holmes/plugins/toolsets/bash/parse_command.py +106 -32
- holmes/plugins/toolsets/bash/utilities/__init__.py +0 -0
- holmes/plugins/toolsets/bash/utilities/base64_util.py +12 -0
- holmes/plugins/toolsets/bash/utilities/cut.py +12 -0
- holmes/plugins/toolsets/bash/utilities/grep/__init__.py +10 -0
- holmes/plugins/toolsets/bash/utilities/head.py +12 -0
- holmes/plugins/toolsets/bash/utilities/jq.py +79 -0
- holmes/plugins/toolsets/bash/utilities/sed.py +164 -0
- holmes/plugins/toolsets/bash/utilities/sort.py +15 -0
- holmes/plugins/toolsets/bash/utilities/tail.py +12 -0
- holmes/plugins/toolsets/bash/utilities/tr.py +57 -0
- holmes/plugins/toolsets/bash/utilities/uniq.py +12 -0
- holmes/plugins/toolsets/bash/utilities/wc.py +12 -0
- holmes/plugins/toolsets/coralogix/api.py +6 -6
- holmes/plugins/toolsets/coralogix/toolset_coralogix_logs.py +7 -1
- holmes/plugins/toolsets/datadog/datadog_api.py +20 -8
- holmes/plugins/toolsets/datadog/datadog_metrics_instructions.jinja2 +8 -1
- holmes/plugins/toolsets/datadog/datadog_rds_instructions.jinja2 +82 -0
- holmes/plugins/toolsets/datadog/toolset_datadog_logs.py +12 -5
- holmes/plugins/toolsets/datadog/toolset_datadog_metrics.py +20 -11
- holmes/plugins/toolsets/datadog/toolset_datadog_rds.py +735 -0
- holmes/plugins/toolsets/datadog/toolset_datadog_traces.py +18 -11
- holmes/plugins/toolsets/git.py +15 -15
- holmes/plugins/toolsets/grafana/grafana_api.py +12 -1
- holmes/plugins/toolsets/grafana/toolset_grafana.py +5 -1
- holmes/plugins/toolsets/grafana/toolset_grafana_loki.py +9 -4
- holmes/plugins/toolsets/grafana/toolset_grafana_tempo.py +12 -5
- holmes/plugins/toolsets/internet/internet.py +2 -1
- holmes/plugins/toolsets/internet/notion.py +2 -1
- holmes/plugins/toolsets/investigator/__init__.py +0 -0
- holmes/plugins/toolsets/investigator/core_investigation.py +157 -0
- holmes/plugins/toolsets/investigator/investigator_instructions.jinja2 +253 -0
- holmes/plugins/toolsets/investigator/model.py +15 -0
- holmes/plugins/toolsets/kafka.py +14 -7
- holmes/plugins/toolsets/kubernetes_logs.py +454 -25
- holmes/plugins/toolsets/logging_utils/logging_api.py +115 -55
- holmes/plugins/toolsets/mcp/toolset_mcp.py +1 -1
- holmes/plugins/toolsets/newrelic.py +8 -3
- holmes/plugins/toolsets/opensearch/opensearch.py +8 -4
- holmes/plugins/toolsets/opensearch/opensearch_logs.py +9 -2
- holmes/plugins/toolsets/opensearch/opensearch_traces.py +6 -2
- holmes/plugins/toolsets/prometheus/prometheus.py +179 -44
- holmes/plugins/toolsets/rabbitmq/toolset_rabbitmq.py +8 -2
- holmes/plugins/toolsets/robusta/robusta.py +4 -4
- holmes/plugins/toolsets/runbook/runbook_fetcher.py +6 -5
- holmes/plugins/toolsets/servicenow/servicenow.py +18 -3
- holmes/plugins/toolsets/utils.py +8 -1
- holmes/utils/console/logging.py +6 -1
- holmes/utils/llms.py +20 -0
- holmes/utils/stream.py +90 -0
- {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/METADATA +47 -34
- {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/RECORD +123 -91
- holmes/plugins/toolsets/bash/grep/__init__.py +0 -52
- holmes/utils/robusta.py +0 -9
- {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/LICENSE.txt +0 -0
- {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/WHEEL +0 -0
- {holmesgpt-0.12.6.dist-info → holmesgpt-0.13.1.dist-info}/entry_points.txt +0 -0
|
@@ -20,7 +20,12 @@ from holmes.plugins.toolsets.datadog.toolset_datadog_logs import DatadogLogsTool
|
|
|
20
20
|
from holmes.plugins.toolsets.datadog.toolset_datadog_metrics import (
|
|
21
21
|
DatadogMetricsToolset,
|
|
22
22
|
)
|
|
23
|
-
from holmes.plugins.toolsets.datadog.toolset_datadog_traces import
|
|
23
|
+
from holmes.plugins.toolsets.datadog.toolset_datadog_traces import (
|
|
24
|
+
DatadogTracesToolset,
|
|
25
|
+
)
|
|
26
|
+
from holmes.plugins.toolsets.datadog.toolset_datadog_rds import (
|
|
27
|
+
DatadogRDSToolset,
|
|
28
|
+
)
|
|
24
29
|
from holmes.plugins.toolsets.git import GitToolset
|
|
25
30
|
from holmes.plugins.toolsets.grafana.toolset_grafana import GrafanaToolset
|
|
26
31
|
from holmes.plugins.toolsets.grafana.toolset_grafana_loki import GrafanaLokiToolset
|
|
@@ -39,6 +44,9 @@ from holmes.plugins.toolsets.rabbitmq.toolset_rabbitmq import RabbitMQToolset
|
|
|
39
44
|
from holmes.plugins.toolsets.robusta.robusta import RobustaToolset
|
|
40
45
|
from holmes.plugins.toolsets.runbook.runbook_fetcher import RunbookToolset
|
|
41
46
|
from holmes.plugins.toolsets.servicenow.servicenow import ServiceNowToolset
|
|
47
|
+
from holmes.plugins.toolsets.investigator.core_investigation import (
|
|
48
|
+
CoreInvestigationToolset,
|
|
49
|
+
)
|
|
42
50
|
|
|
43
51
|
THIS_DIR = os.path.abspath(os.path.dirname(__file__))
|
|
44
52
|
|
|
@@ -63,6 +71,7 @@ def load_toolsets_from_file(
|
|
|
63
71
|
def load_python_toolsets(dal: Optional[SupabaseDal]) -> List[Toolset]:
|
|
64
72
|
logging.debug("loading python toolsets")
|
|
65
73
|
toolsets: list[Toolset] = [
|
|
74
|
+
CoreInvestigationToolset(), # Load first for higher priority
|
|
66
75
|
InternetToolset(),
|
|
67
76
|
RobustaToolset(dal),
|
|
68
77
|
OpenSearchToolset(),
|
|
@@ -75,6 +84,7 @@ def load_python_toolsets(dal: Optional[SupabaseDal]) -> List[Toolset]:
|
|
|
75
84
|
DatadogLogsToolset(),
|
|
76
85
|
DatadogMetricsToolset(),
|
|
77
86
|
DatadogTracesToolset(),
|
|
87
|
+
DatadogRDSToolset(),
|
|
78
88
|
PrometheusToolset(),
|
|
79
89
|
OpenSearchLogsToolset(),
|
|
80
90
|
OpenSearchTracesToolset(),
|
|
@@ -152,8 +162,15 @@ def load_toolsets_from_config(
|
|
|
152
162
|
for name, config in toolsets.items():
|
|
153
163
|
try:
|
|
154
164
|
toolset_type = config.get("type", ToolsetType.BUILTIN.value)
|
|
155
|
-
|
|
165
|
+
|
|
166
|
+
# Resolve env var placeholders before creating the Toolset.
|
|
167
|
+
# If done after, .override_with() will overwrite resolved values with placeholders
|
|
168
|
+
# because model_dump() returns the original, unprocessed config from YAML.
|
|
169
|
+
if config:
|
|
170
|
+
config = env_utils.replace_env_vars_values(config)
|
|
171
|
+
|
|
156
172
|
validated_toolset: Optional[Toolset] = None
|
|
173
|
+
# MCP server is not a built-in toolset, so we need to set the type explicitly
|
|
157
174
|
if toolset_type == ToolsetType.MCP.value:
|
|
158
175
|
validated_toolset = RemoteMCPToolset(**config, name=name)
|
|
159
176
|
elif strict_check:
|
|
@@ -163,10 +180,6 @@ def load_toolsets_from_config(
|
|
|
163
180
|
**config, name=name
|
|
164
181
|
)
|
|
165
182
|
|
|
166
|
-
if validated_toolset.config:
|
|
167
|
-
validated_toolset.config = env_utils.replace_env_vars_values(
|
|
168
|
-
validated_toolset.config
|
|
169
|
-
)
|
|
170
183
|
loaded_toolsets.append(validated_toolset)
|
|
171
184
|
except ValidationError as e:
|
|
172
185
|
logging.warning(f"Toolset '{name}' is invalid: {e}")
|
|
@@ -18,6 +18,8 @@ from datetime import datetime, timedelta, timezone
|
|
|
18
18
|
import os
|
|
19
19
|
from collections import Counter
|
|
20
20
|
|
|
21
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
22
|
+
|
|
21
23
|
|
|
22
24
|
class MongoDBConfig(BaseModel):
|
|
23
25
|
public_key: str
|
|
@@ -103,6 +105,7 @@ class MongoDBAtlasBaseTool(Tool):
|
|
|
103
105
|
)
|
|
104
106
|
|
|
105
107
|
def get_parameterized_one_liner(self, params) -> str:
|
|
108
|
+
# Default implementation - will be overridden by subclasses
|
|
106
109
|
return f"MongoDB {self.name} project {self.toolset.config.get('project_id')} {params}"
|
|
107
110
|
|
|
108
111
|
|
|
@@ -111,6 +114,10 @@ class ReturnProjectAlerts(MongoDBAtlasBaseTool):
|
|
|
111
114
|
name: str = "atlas_return_project_alerts"
|
|
112
115
|
description: str = "Returns all project alerts. These alerts apply to all components in one project. You receive an alert when a monitored component meets or exceeds a value you set."
|
|
113
116
|
|
|
117
|
+
def get_parameterized_one_liner(self, params) -> str:
|
|
118
|
+
project_id = self.toolset.config.get("project_id", "")
|
|
119
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Project Alerts ({project_id})"
|
|
120
|
+
|
|
114
121
|
def _invoke(self, params: Any) -> StructuredToolResult:
|
|
115
122
|
try:
|
|
116
123
|
url = "https://cloud.mongodb.com/api/atlas/v2/groups/{project_id}/alerts".format(
|
|
@@ -132,6 +139,10 @@ class ReturnProjectProcesses(MongoDBAtlasBaseTool):
|
|
|
132
139
|
name: str = "atlas_return_project_processes"
|
|
133
140
|
description: str = "Returns details of all processes for the specified project. Useful for getting logs and data for specific project"
|
|
134
141
|
|
|
142
|
+
def get_parameterized_one_liner(self, params) -> str:
|
|
143
|
+
project_id = self.toolset.config.get("project_id", "")
|
|
144
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Project Processes ({project_id})"
|
|
145
|
+
|
|
135
146
|
def _invoke(self, params: Any) -> StructuredToolResult:
|
|
136
147
|
try:
|
|
137
148
|
url = "https://cloud.mongodb.com/api/atlas/v2/groups/{project_id}/processes".format(
|
|
@@ -161,6 +172,10 @@ class ReturnProjectSlowQueries(MongoDBAtlasBaseTool):
|
|
|
161
172
|
),
|
|
162
173
|
}
|
|
163
174
|
|
|
175
|
+
def get_parameterized_one_liner(self, params) -> str:
|
|
176
|
+
process_id = params.get("process_id", "")
|
|
177
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Slow Queries ({process_id})"
|
|
178
|
+
|
|
164
179
|
def _invoke(self, params: Any) -> StructuredToolResult:
|
|
165
180
|
try:
|
|
166
181
|
url = self.url.format(
|
|
@@ -184,6 +199,10 @@ class ReturnEventsFromProject(MongoDBAtlasBaseTool):
|
|
|
184
199
|
description: str = "Returns all events occurrences for the specified project. Events identify significant database, security activities or status changes. can only query the last 4 hours."
|
|
185
200
|
url: str = "https://cloud.mongodb.com/api/atlas/v2/groups/{projectId}/events"
|
|
186
201
|
|
|
202
|
+
def get_parameterized_one_liner(self, params) -> str:
|
|
203
|
+
project_id = self.toolset.config.get("project_id", "")
|
|
204
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Project Events ({project_id})"
|
|
205
|
+
|
|
187
206
|
def _invoke(self, params: Any) -> StructuredToolResult:
|
|
188
207
|
params.update({"itemsPerPage": 500})
|
|
189
208
|
try:
|
|
@@ -237,6 +256,10 @@ class ReturnLogsForProcessInProject(MongoDBAtlasBaseTool):
|
|
|
237
256
|
),
|
|
238
257
|
}
|
|
239
258
|
|
|
259
|
+
def get_parameterized_one_liner(self, params) -> str:
|
|
260
|
+
hostname = params.get("hostName", "")
|
|
261
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Host Logs ({hostname})"
|
|
262
|
+
|
|
240
263
|
def _invoke(self, params: Any) -> StructuredToolResult:
|
|
241
264
|
one_hour_ago = datetime.now(timezone.utc) - timedelta(hours=1)
|
|
242
265
|
try:
|
|
@@ -285,6 +308,10 @@ class ReturnEventTypeFromProject(MongoDBAtlasBaseTool):
|
|
|
285
308
|
),
|
|
286
309
|
}
|
|
287
310
|
|
|
311
|
+
def get_parameterized_one_liner(self, params) -> str:
|
|
312
|
+
event_type = params.get("eventType", "")
|
|
313
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Event Details ({event_type})"
|
|
314
|
+
|
|
288
315
|
def _invoke(self, params: Any) -> StructuredToolResult:
|
|
289
316
|
try:
|
|
290
317
|
url = self.url.format(projectId=self.toolset.config.get("project_id"))
|
|
@@ -12,6 +12,7 @@ from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClie
|
|
|
12
12
|
from holmes.plugins.toolsets.azure_sql.apis.connection_failure_api import (
|
|
13
13
|
ConnectionFailureAPI,
|
|
14
14
|
)
|
|
15
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class AnalyzeConnectionFailures(BaseAzureSQLTool):
|
|
@@ -267,8 +268,7 @@ class AnalyzeConnectionFailures(BaseAzureSQLTool):
|
|
|
267
268
|
|
|
268
269
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
269
270
|
db_config = self.toolset.database_config()
|
|
270
|
-
|
|
271
|
-
return f"Analyze connection failures for {db_config.server_name}/{db_config.database_name} over {hours_back} hours"
|
|
271
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Analyze Connection Failures ({db_config.server_name}/{db_config.database_name})"
|
|
272
272
|
|
|
273
273
|
@staticmethod
|
|
274
274
|
def validate_config(
|
|
@@ -12,6 +12,7 @@ from holmes.plugins.toolsets.azure_sql.apis.connection_monitoring_api import (
|
|
|
12
12
|
ConnectionMonitoringAPI,
|
|
13
13
|
)
|
|
14
14
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
15
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class AnalyzeDatabaseConnections(BaseAzureSQLTool):
|
|
@@ -212,7 +213,7 @@ class AnalyzeDatabaseConnections(BaseAzureSQLTool):
|
|
|
212
213
|
|
|
213
214
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
214
215
|
db_config = self.toolset.database_config()
|
|
215
|
-
return f"Analyze
|
|
216
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Analyze Database Connections ({db_config.server_name}/{db_config.database_name})"
|
|
216
217
|
|
|
217
218
|
@staticmethod
|
|
218
219
|
def validate_config(
|
|
@@ -11,6 +11,8 @@ from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
|
|
|
11
11
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
12
12
|
from typing import Tuple
|
|
13
13
|
|
|
14
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
15
|
+
|
|
14
16
|
|
|
15
17
|
class AnalyzeDatabaseHealthStatus(BaseAzureSQLTool):
|
|
16
18
|
def __init__(self, toolset: "BaseAzureSQLToolset"):
|
|
@@ -156,7 +158,7 @@ class AnalyzeDatabaseHealthStatus(BaseAzureSQLTool):
|
|
|
156
158
|
|
|
157
159
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
158
160
|
db_config = self.toolset.database_config()
|
|
159
|
-
return f"Analyze
|
|
161
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Analyze Health Status ({db_config.server_name}/{db_config.database_name})"
|
|
160
162
|
|
|
161
163
|
@staticmethod
|
|
162
164
|
def validate_config(
|
|
@@ -9,6 +9,7 @@ from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
|
|
|
9
9
|
AzureSQLDatabaseConfig,
|
|
10
10
|
)
|
|
11
11
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
12
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class AnalyzeDatabasePerformance(BaseAzureSQLTool):
|
|
@@ -218,7 +219,7 @@ class AnalyzeDatabasePerformance(BaseAzureSQLTool):
|
|
|
218
219
|
|
|
219
220
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
220
221
|
db_config = self.toolset.database_config()
|
|
221
|
-
return f"Analyze
|
|
222
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Analyze Database Performance ({db_config.server_name}/{db_config.database_name})"
|
|
222
223
|
|
|
223
224
|
@staticmethod
|
|
224
225
|
def validate_config(
|
|
@@ -12,6 +12,7 @@ from holmes.plugins.toolsets.azure_sql.apis.storage_analysis_api import (
|
|
|
12
12
|
StorageAnalysisAPI,
|
|
13
13
|
)
|
|
14
14
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
15
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
15
16
|
|
|
16
17
|
|
|
17
18
|
class AnalyzeDatabaseStorage(BaseAzureSQLTool):
|
|
@@ -319,7 +320,7 @@ class AnalyzeDatabaseStorage(BaseAzureSQLTool):
|
|
|
319
320
|
|
|
320
321
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
321
322
|
db_config = self.toolset.database_config()
|
|
322
|
-
return f"
|
|
323
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Analyze Database Storage ({db_config.server_name}/{db_config.database_name})"
|
|
323
324
|
|
|
324
325
|
@staticmethod
|
|
325
326
|
def validate_config(
|
|
@@ -14,6 +14,8 @@ from holmes.plugins.toolsets.azure_sql.apis.alert_monitoring_api import (
|
|
|
14
14
|
)
|
|
15
15
|
from typing import Tuple
|
|
16
16
|
|
|
17
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
18
|
+
|
|
17
19
|
|
|
18
20
|
class GetActiveAlerts(BaseAzureSQLTool):
|
|
19
21
|
def __init__(self, toolset: "BaseAzureSQLToolset"):
|
|
@@ -190,7 +192,7 @@ class GetActiveAlerts(BaseAzureSQLTool):
|
|
|
190
192
|
|
|
191
193
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
192
194
|
db_config = self.toolset.database_config()
|
|
193
|
-
return f"
|
|
195
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Active Alerts ({db_config.server_name}/{db_config.database_name})"
|
|
194
196
|
|
|
195
197
|
@staticmethod
|
|
196
198
|
def validate_config(
|
|
@@ -9,6 +9,7 @@ from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
|
|
|
9
9
|
)
|
|
10
10
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
11
11
|
from holmes.plugins.toolsets.azure_sql.utils import format_timing
|
|
12
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class GetSlowQueries(BaseAzureSQLTool):
|
|
@@ -137,7 +138,7 @@ class GetSlowQueries(BaseAzureSQLTool):
|
|
|
137
138
|
|
|
138
139
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
139
140
|
db_config = self.toolset.database_config()
|
|
140
|
-
return f"
|
|
141
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Slow Queries ({db_config.server_name}/{db_config.database_name})"
|
|
141
142
|
|
|
142
143
|
@staticmethod
|
|
143
144
|
def validate_config(
|
|
@@ -9,6 +9,7 @@ from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
|
|
|
9
9
|
)
|
|
10
10
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
11
11
|
from holmes.plugins.toolsets.azure_sql.utils import format_timing
|
|
12
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class GetTopCPUQueries(BaseAzureSQLTool):
|
|
@@ -135,7 +136,7 @@ class GetTopCPUQueries(BaseAzureSQLTool):
|
|
|
135
136
|
|
|
136
137
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
137
138
|
db_config = self.toolset.database_config()
|
|
138
|
-
return f"
|
|
139
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Top CPU Queries ({db_config.server_name}/{db_config.database_name})"
|
|
139
140
|
|
|
140
141
|
@staticmethod
|
|
141
142
|
def validate_config(
|
|
@@ -9,6 +9,7 @@ from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
|
|
|
9
9
|
)
|
|
10
10
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
11
11
|
from holmes.plugins.toolsets.azure_sql.utils import format_timing
|
|
12
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class GetTopDataIOQueries(BaseAzureSQLTool):
|
|
@@ -153,7 +154,7 @@ class GetTopDataIOQueries(BaseAzureSQLTool):
|
|
|
153
154
|
|
|
154
155
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
155
156
|
db_config = self.toolset.database_config()
|
|
156
|
-
return f"
|
|
157
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Top Data I/O Queries ({db_config.server_name}/{db_config.database_name})"
|
|
157
158
|
|
|
158
159
|
@staticmethod
|
|
159
160
|
def validate_config(
|
|
@@ -9,6 +9,7 @@ from holmes.plugins.toolsets.azure_sql.azure_base_toolset import (
|
|
|
9
9
|
)
|
|
10
10
|
from holmes.plugins.toolsets.azure_sql.apis.azure_sql_api import AzureSQLAPIClient
|
|
11
11
|
from holmes.plugins.toolsets.azure_sql.utils import format_timing
|
|
12
|
+
from holmes.plugins.toolsets.utils import toolset_name_for_one_liner
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
class GetTopLogIOQueries(BaseAzureSQLTool):
|
|
@@ -145,7 +146,7 @@ class GetTopLogIOQueries(BaseAzureSQLTool):
|
|
|
145
146
|
|
|
146
147
|
def get_parameterized_one_liner(self, params: Dict) -> str:
|
|
147
148
|
db_config = self.toolset.database_config()
|
|
148
|
-
return f"
|
|
149
|
+
return f"{toolset_name_for_one_liner(self.toolset.name)}: Get Top Log I/O Queries ({db_config.server_name}/{db_config.database_name})"
|
|
149
150
|
|
|
150
151
|
@staticmethod
|
|
151
152
|
def validate_config(
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
|
|
5
|
+
from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
|
|
6
|
+
from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
|
|
7
|
+
from holmes.plugins.toolsets.bash.argocd.constants import (
|
|
8
|
+
ALLOWED_ARGOCD_COMMANDS,
|
|
9
|
+
DENIED_ARGOCD_COMMANDS,
|
|
10
|
+
)
|
|
11
|
+
from holmes.plugins.toolsets.bash.common.validators import (
|
|
12
|
+
validate_command_and_operations,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ArgocdCommand(BashCommand):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super().__init__("argocd")
|
|
19
|
+
|
|
20
|
+
def add_parser(self, parent_parser: Any):
|
|
21
|
+
"""Create Argo CD CLI parser with safe command validation."""
|
|
22
|
+
argocd_parser = parent_parser.add_parser(
|
|
23
|
+
"argocd", help="Argo CD Command Line Interface", exit_on_error=False
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Add command subparser
|
|
27
|
+
argocd_parser.add_argument(
|
|
28
|
+
"command", help="Argo CD command (e.g., app, cluster, proj, repo)"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
# Capture remaining arguments
|
|
32
|
+
argocd_parser.add_argument(
|
|
33
|
+
"options",
|
|
34
|
+
nargs=argparse.REMAINDER,
|
|
35
|
+
default=[],
|
|
36
|
+
help="Argo CD CLI subcommands, operations, and options",
|
|
37
|
+
)
|
|
38
|
+
return argocd_parser
|
|
39
|
+
|
|
40
|
+
def validate_command(
|
|
41
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
42
|
+
) -> None:
|
|
43
|
+
if hasattr(command, "options"):
|
|
44
|
+
validate_command_and_operations(
|
|
45
|
+
command.command,
|
|
46
|
+
command.options,
|
|
47
|
+
ALLOWED_ARGOCD_COMMANDS,
|
|
48
|
+
DENIED_ARGOCD_COMMANDS,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
def stringify_command(
|
|
52
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
53
|
+
) -> str:
|
|
54
|
+
"""Convert parsed Argo CD command back to safe command string."""
|
|
55
|
+
parts = ["argocd", command.command]
|
|
56
|
+
|
|
57
|
+
if hasattr(command, "options") and command.options:
|
|
58
|
+
parts.extend(command.options)
|
|
59
|
+
|
|
60
|
+
return " ".join(escape_shell_args(parts))
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def create_argocd_parser(parent_parser: Any):
|
|
64
|
+
argocd_command = ArgocdCommand()
|
|
65
|
+
return argocd_command.add_parser(parent_parser)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
ALLOWED_ARGOCD_COMMANDS: dict[str, dict] = {
|
|
2
|
+
# Application management (read-only)
|
|
3
|
+
"app": {
|
|
4
|
+
"list": {},
|
|
5
|
+
"get": {},
|
|
6
|
+
"resources": {},
|
|
7
|
+
"diff": {},
|
|
8
|
+
"history": {},
|
|
9
|
+
"manifests": {},
|
|
10
|
+
"logs": {},
|
|
11
|
+
"wait": {}, # Wait for app to reach desired state (read-only monitoring)
|
|
12
|
+
},
|
|
13
|
+
# Cluster management (read-only)
|
|
14
|
+
"cluster": {
|
|
15
|
+
"list": {},
|
|
16
|
+
"get": {},
|
|
17
|
+
},
|
|
18
|
+
# Project management (read-only)
|
|
19
|
+
"proj": {
|
|
20
|
+
"list": {},
|
|
21
|
+
"get": {},
|
|
22
|
+
},
|
|
23
|
+
# Repository management (read-only)
|
|
24
|
+
"repo": {
|
|
25
|
+
"list": {},
|
|
26
|
+
"get": {},
|
|
27
|
+
},
|
|
28
|
+
# Context management (read-only operations)
|
|
29
|
+
"context": {},
|
|
30
|
+
# Version information (completely safe)
|
|
31
|
+
"version": {},
|
|
32
|
+
# Account information (read-only)
|
|
33
|
+
"account": {
|
|
34
|
+
"list": {},
|
|
35
|
+
"get": {},
|
|
36
|
+
"get-user-info": {},
|
|
37
|
+
"can-i": {},
|
|
38
|
+
},
|
|
39
|
+
# Administrative commands (limited read-only)
|
|
40
|
+
"admin": {
|
|
41
|
+
"dashboard": {}, # Starts read-only web UI
|
|
42
|
+
"settings": {}, # Shows/validates settings (read-only)
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
DENIED_ARGOCD_COMMANDS: dict[str, dict] = {
|
|
47
|
+
# Authentication operations (sensitive)
|
|
48
|
+
"login": {},
|
|
49
|
+
"logout": {},
|
|
50
|
+
"relogin": {},
|
|
51
|
+
# Application lifecycle operations (state-modifying)
|
|
52
|
+
"app": {
|
|
53
|
+
"create": {},
|
|
54
|
+
"delete": {},
|
|
55
|
+
"sync": {},
|
|
56
|
+
"rollback": {},
|
|
57
|
+
"edit": {},
|
|
58
|
+
"set": {},
|
|
59
|
+
"unset": {},
|
|
60
|
+
"patch": {},
|
|
61
|
+
"delete-resource": {},
|
|
62
|
+
"terminate-op": {},
|
|
63
|
+
"actions": {}, # Custom resource actions
|
|
64
|
+
},
|
|
65
|
+
# Account management (sensitive)
|
|
66
|
+
"account": {
|
|
67
|
+
"generate-token": {},
|
|
68
|
+
"delete-token": {},
|
|
69
|
+
"update-password": {},
|
|
70
|
+
"bcrypt": {},
|
|
71
|
+
},
|
|
72
|
+
# Cluster management (state-modifying)
|
|
73
|
+
"cluster": {
|
|
74
|
+
"add": {},
|
|
75
|
+
"rm": {},
|
|
76
|
+
"set": {},
|
|
77
|
+
"rotate-auth": {},
|
|
78
|
+
},
|
|
79
|
+
# Project management (state-modifying)
|
|
80
|
+
"proj": {
|
|
81
|
+
"create": {},
|
|
82
|
+
"delete": {},
|
|
83
|
+
"edit": {},
|
|
84
|
+
"add-source": {},
|
|
85
|
+
"remove-source": {},
|
|
86
|
+
"add-destination": {},
|
|
87
|
+
"remove-destination": {},
|
|
88
|
+
"add-cluster-resource-whitelist": {},
|
|
89
|
+
"remove-cluster-resource-whitelist": {},
|
|
90
|
+
"add-namespace-resource-blacklist": {},
|
|
91
|
+
"remove-namespace-resource-blacklist": {},
|
|
92
|
+
"add-cluster-resource-blacklist": {},
|
|
93
|
+
"remove-cluster-resource-blacklist": {},
|
|
94
|
+
"add-namespace-resource-whitelist": {},
|
|
95
|
+
"remove-namespace-resource-whitelist": {},
|
|
96
|
+
"add-orphaned-ignore": {},
|
|
97
|
+
"remove-orphaned-ignore": {},
|
|
98
|
+
"add-signature-key": {},
|
|
99
|
+
"remove-signature-key": {},
|
|
100
|
+
"set-orphaned-ignore": {},
|
|
101
|
+
"add-role": {},
|
|
102
|
+
"remove-role": {},
|
|
103
|
+
"add-role-token": {},
|
|
104
|
+
"delete-role-token": {},
|
|
105
|
+
"set-role": {},
|
|
106
|
+
},
|
|
107
|
+
# Repository management (state-modifying)
|
|
108
|
+
"repo": {
|
|
109
|
+
"add": {},
|
|
110
|
+
"rm": {},
|
|
111
|
+
},
|
|
112
|
+
# Certificate management
|
|
113
|
+
"cert": {},
|
|
114
|
+
# GPG key management
|
|
115
|
+
"gpg": {},
|
|
116
|
+
# Application set operations
|
|
117
|
+
"appset": {},
|
|
118
|
+
# Notification operations
|
|
119
|
+
"notifications": {},
|
|
120
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from typing import Any, Optional
|
|
3
|
+
|
|
4
|
+
from holmes.plugins.toolsets.bash.common.bash_command import BashCommand
|
|
5
|
+
from holmes.plugins.toolsets.bash.common.config import BashExecutorConfig
|
|
6
|
+
from holmes.plugins.toolsets.bash.common.stringify import escape_shell_args
|
|
7
|
+
from holmes.plugins.toolsets.bash.common.validators import (
|
|
8
|
+
validate_command_and_operations,
|
|
9
|
+
)
|
|
10
|
+
from holmes.plugins.toolsets.bash.aws.constants import (
|
|
11
|
+
ALLOWED_AWS_COMMANDS,
|
|
12
|
+
DENIED_AWS_COMMANDS,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class AWSCommand(BashCommand):
|
|
17
|
+
def __init__(self):
|
|
18
|
+
super().__init__("aws")
|
|
19
|
+
|
|
20
|
+
def add_parser(self, parent_parser: Any):
|
|
21
|
+
"""Create AWS CLI parser with safe command validation."""
|
|
22
|
+
aws_parser = parent_parser.add_parser(
|
|
23
|
+
"aws",
|
|
24
|
+
help="Amazon Web Services Command Line Interface",
|
|
25
|
+
exit_on_error=False,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
aws_parser.add_argument(
|
|
29
|
+
"service",
|
|
30
|
+
help="AWS service name (e.g., ec2, s3, lambda)",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
aws_parser.add_argument("operation", help="AWS operation to perform")
|
|
34
|
+
|
|
35
|
+
aws_parser.add_argument(
|
|
36
|
+
"options",
|
|
37
|
+
nargs=argparse.REMAINDER,
|
|
38
|
+
default=[],
|
|
39
|
+
help="Additional AWS CLI options and parameters",
|
|
40
|
+
)
|
|
41
|
+
return aws_parser
|
|
42
|
+
|
|
43
|
+
def validate_command(
|
|
44
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
45
|
+
) -> None:
|
|
46
|
+
# Build options list with operation and remaining arguments
|
|
47
|
+
options = [command.operation] + (
|
|
48
|
+
command.options if hasattr(command, "options") else []
|
|
49
|
+
)
|
|
50
|
+
validate_command_and_operations(
|
|
51
|
+
command=command.service,
|
|
52
|
+
options=options,
|
|
53
|
+
allowed_commands=ALLOWED_AWS_COMMANDS,
|
|
54
|
+
denied_commands=DENIED_AWS_COMMANDS,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def stringify_command(
|
|
58
|
+
self, command: Any, original_command: str, config: Optional[BashExecutorConfig]
|
|
59
|
+
) -> str:
|
|
60
|
+
"""Convert parsed AWS command back to safe command string."""
|
|
61
|
+
parts = ["aws", command.service, command.operation]
|
|
62
|
+
|
|
63
|
+
if hasattr(command, "options") and command.options:
|
|
64
|
+
parts.extend(command.options)
|
|
65
|
+
|
|
66
|
+
return " ".join(escape_shell_args(parts))
|