codemie-test-harness 0.1.163__py3-none-any.whl → 0.1.165__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 codemie-test-harness might be problematic. Click here for more details.

Files changed (55) hide show
  1. codemie_test_harness/tests/__init__.py +2 -1
  2. codemie_test_harness/tests/assistant/datasource/test_confluence_datasource.py +2 -2
  3. codemie_test_harness/tests/assistant/datasource/test_jira_datasource.py +2 -2
  4. codemie_test_harness/tests/assistant/default_integrations/test_default_integrations_for_tool.py +11 -11
  5. codemie_test_harness/tests/assistant/default_integrations/test_default_integrations_for_tool_kit.py +11 -11
  6. codemie_test_harness/tests/assistant/default_integrations/test_default_integrations_for_tool_with_datasource.py +14 -14
  7. codemie_test_harness/tests/assistant/tools/ado/test_assistant_for_ado_test_plan_tools.py +3 -3
  8. codemie_test_harness/tests/assistant/tools/ado/test_assistant_for_ado_wiki_tools.py +3 -3
  9. codemie_test_harness/tests/assistant/tools/ado/test_assistant_for_ado_work_item_tools.py +3 -3
  10. codemie_test_harness/tests/assistant/tools/datamanagement/test_assistant_with_data_management_tools.py +3 -3
  11. codemie_test_harness/tests/assistant/tools/mcp/test_cli_mcp_server.py +2 -2
  12. codemie_test_harness/tests/assistant/tools/notification/test_assistant_notification_tools.py +3 -3
  13. codemie_test_harness/tests/assistant/tools/project_management/test_assistant_pm_tools.py +5 -5
  14. codemie_test_harness/tests/conftest.py +73 -45
  15. codemie_test_harness/tests/e2e/test_e2e.py +5 -5
  16. codemie_test_harness/tests/integrations/project/test_default_integrations.py +7 -7
  17. codemie_test_harness/tests/integrations/user/test_default_integrations.py +7 -7
  18. codemie_test_harness/tests/llm/assistants/test_lite_llm.py +3 -3
  19. codemie_test_harness/tests/search/test_search_datasource.py +2 -2
  20. codemie_test_harness/tests/search/test_search_integration.py +3 -3
  21. codemie_test_harness/tests/service/test_datasource_service.py +12 -12
  22. codemie_test_harness/tests/test_data/cloud_tools_test_data.py +5 -5
  23. codemie_test_harness/tests/test_data/codebase_tools_test_data.py +3 -3
  24. codemie_test_harness/tests/test_data/direct_tools/cloud_tools_test_data.py +5 -5
  25. codemie_test_harness/tests/test_data/direct_tools/file_management_tools_test_data.py +5 -1
  26. codemie_test_harness/tests/test_data/integrations_test_data.py +48 -48
  27. codemie_test_harness/tests/test_data/llm_test_data.py +1 -1
  28. codemie_test_harness/tests/test_data/notification_tools_test_data.py +2 -6
  29. codemie_test_harness/tests/test_data/report_portal_tools_test_data.py +4 -220
  30. codemie_test_harness/tests/test_data/vcs_tools_test_data.py +8 -5
  31. codemie_test_harness/tests/utils/aws_parameters_store.py +0 -560
  32. codemie_test_harness/tests/utils/base_utils.py +2 -2
  33. codemie_test_harness/tests/utils/client_factory.py +11 -9
  34. codemie_test_harness/tests/utils/credentials_manager.py +1358 -0
  35. codemie_test_harness/tests/utils/datasource_utils.py +7 -6
  36. codemie_test_harness/tests/utils/gitbud_utils.py +4 -4
  37. codemie_test_harness/tests/utils/notification_utils.py +6 -6
  38. codemie_test_harness/tests/workflow/assistant_tools/data_management/test_workflow_with_assistant_with_data_management_tools.py +3 -3
  39. codemie_test_harness/tests/workflow/assistant_tools/default_integrations/test_default_integrations_for_tool.py +11 -11
  40. codemie_test_harness/tests/workflow/assistant_tools/default_integrations/test_default_integrations_for_tool_kit.py +11 -11
  41. codemie_test_harness/tests/workflow/assistant_tools/default_integrations/test_default_integrations_for_tool_with_datasource.py +14 -14
  42. codemie_test_harness/tests/workflow/direct_tools_calling/default_integrations/test_default_integrations_for_tool.py +11 -11
  43. codemie_test_harness/tests/workflow/direct_tools_calling/default_integrations/test_default_integrations_for_tool_kit.py +11 -11
  44. codemie_test_harness/tests/workflow/direct_tools_calling/test_workflow_with_codebase_tools.py +7 -7
  45. codemie_test_harness/tests/workflow/direct_tools_calling/test_workflow_with_data_management_tools_elastic.py +4 -4
  46. codemie_test_harness/tests/workflow/direct_tools_calling/test_workflow_with_data_management_tools_sql.py +4 -4
  47. codemie_test_harness/tests/workflow/virtual_assistant_tools/codebase/test_workflow_with_codebase_tools.py +2 -2
  48. codemie_test_harness/tests/workflow/virtual_assistant_tools/data_management/test_workflow_with_data_management_tools.py +3 -3
  49. codemie_test_harness/tests/workflow/virtual_assistant_tools/default_integrations/test_default_integrations_for_tool.py +11 -11
  50. codemie_test_harness/tests/workflow/virtual_assistant_tools/default_integrations/test_default_integrations_for_tool_kit.py +11 -11
  51. codemie_test_harness/tests/workflow/virtual_assistant_tools/default_integrations/test_default_integrations_for_tool_with_datasource.py +14 -14
  52. {codemie_test_harness-0.1.163.dist-info → codemie_test_harness-0.1.165.dist-info}/METADATA +2 -2
  53. {codemie_test_harness-0.1.163.dist-info → codemie_test_harness-0.1.165.dist-info}/RECORD +55 -54
  54. {codemie_test_harness-0.1.163.dist-info → codemie_test_harness-0.1.165.dist-info}/WHEEL +0 -0
  55. {codemie_test_harness-0.1.163.dist-info → codemie_test_harness-0.1.165.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,1358 @@
1
+ """
2
+ Unified Credentials Manager with configuration-driven approach.
3
+ Supports .env variables first, then AWS Parameter Store with JSON path navigation.
4
+ """
5
+
6
+ import base64
7
+ import json
8
+ import os
9
+ import re
10
+ from typing import Optional, List, Dict, Any
11
+
12
+ from codemie_test_harness.tests.utils.aws_parameters_store import AwsParameterStore
13
+ from codemie_test_harness.tests.utils.env_resolver import EnvironmentResolver
14
+ from codemie_sdk.models.integration import CredentialValues
15
+
16
+ # Constants
17
+ INTEGRATIONS_PARAMETER_PATH = "/codemie/autotests/integrations/"
18
+
19
+
20
+ class CredentialsManager:
21
+ """
22
+ Unified credentials manager with configuration-driven approach.
23
+
24
+ Supports:
25
+ 1. .env variables (highest priority)
26
+ 2. AWS Parameter Store with JSON path navigation (fallback)
27
+ 3. Default values (final fallback)
28
+ """
29
+
30
+ AUTO_GENERATED = "AUTO_GENERATED"
31
+
32
+ # Configuration mapping: env_var -> AWS parameter details
33
+ CREDENTIAL_MAPPINGS = {
34
+ # === JIRA CREDENTIALS ===
35
+ "JIRA_URL": {
36
+ "env": "JIRA_URL",
37
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}jira",
38
+ "aws_path": "jira_server.url",
39
+ },
40
+ "JIRA_TOKEN": {
41
+ "env": "JIRA_TOKEN",
42
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}jira",
43
+ "aws_path": "jira_server.token",
44
+ },
45
+ "JIRA_JQL": {
46
+ "env": "JIRA_JQL",
47
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}jira",
48
+ "aws_path": "jira_server.jql",
49
+ },
50
+ "JIRA_CLOUD_URL": {
51
+ "env": "JIRA_CLOUD_URL",
52
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}jira",
53
+ "aws_path": "jira_cloud.url",
54
+ },
55
+ "JIRA_CLOUD_EMAIL": {
56
+ "env": "JIRA_CLOUD_EMAIL",
57
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}jira",
58
+ "aws_path": "jira_cloud.email",
59
+ },
60
+ "JIRA_CLOUD_TOKEN": {
61
+ "env": "JIRA_CLOUD_TOKEN",
62
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}jira",
63
+ "aws_path": "jira_cloud.token",
64
+ },
65
+ "JIRA_CLOUD_JQL": {
66
+ "env": "JIRA_CLOUD_JQL",
67
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}jira",
68
+ "aws_path": "jira_cloud.jql",
69
+ },
70
+ # === CONFLUENCE CREDENTIALS ===
71
+ "CONFLUENCE_URL": {
72
+ "env": "CONFLUENCE_URL",
73
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}confluence",
74
+ "aws_path": "confluence_server.url",
75
+ },
76
+ "CONFLUENCE_TOKEN": {
77
+ "env": "CONFLUENCE_TOKEN",
78
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}confluence",
79
+ "aws_path": "confluence_server.token",
80
+ },
81
+ "CONFLUENCE_CQL": {
82
+ "env": "CONFLUENCE_CQL",
83
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}confluence",
84
+ "aws_path": "confluence_server.cql",
85
+ },
86
+ "CONFLUENCE_CLOUD_URL": {
87
+ "env": "CONFLUENCE_CLOUD_URL",
88
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}confluence",
89
+ "aws_path": "confluence_cloud.url",
90
+ },
91
+ "CONFLUENCE_CLOUD_EMAIL": {
92
+ "env": "CONFLUENCE_CLOUD_EMAIL",
93
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}confluence",
94
+ "aws_path": "confluence_cloud.email",
95
+ },
96
+ "CONFLUENCE_CLOUD_TOKEN": {
97
+ "env": "CONFLUENCE_CLOUD_TOKEN",
98
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}confluence",
99
+ "aws_path": "confluence_cloud.token",
100
+ },
101
+ "CONFLUENCE_CLOUD_CQL": {
102
+ "env": "CONFLUENCE_CLOUD_CQL",
103
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}confluence",
104
+ "aws_path": "confluence_cloud.cql",
105
+ },
106
+ # === GITLAB CREDENTIALS ===
107
+ "GITLAB_URL": {
108
+ "env": "GITLAB_URL",
109
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}git",
110
+ "aws_path": "gitlab.url",
111
+ },
112
+ "GITLAB_TOKEN": {
113
+ "env": "GITLAB_TOKEN",
114
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}git",
115
+ "aws_path": "gitlab.token",
116
+ },
117
+ "GITLAB_PROJECT": {
118
+ "env": "GITLAB_PROJECT",
119
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}git",
120
+ "aws_path": "gitlab.project",
121
+ },
122
+ "GITLAB_PROJECT_ID": {
123
+ "env": "GITLAB_PROJECT_ID",
124
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}git",
125
+ "aws_path": "gitlab.project_id",
126
+ },
127
+ # === GITHUB CREDENTIALS ===
128
+ "GITHUB_URL": {
129
+ "env": "GITHUB_URL",
130
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}git",
131
+ "aws_path": "github.url",
132
+ },
133
+ "GITHUB_TOKEN": {
134
+ "env": "GITHUB_TOKEN",
135
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}git",
136
+ "aws_path": "github.token",
137
+ },
138
+ "GITHUB_PROJECT": {
139
+ "env": "GITHUB_PROJECT",
140
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}git",
141
+ "aws_path": "github.project",
142
+ },
143
+ # === AWS CREDENTIALS ===
144
+ "AWS_ACCESS_KEY_ID": {
145
+ "env": "AWS_ACCESS_KEY_ID",
146
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}aws",
147
+ "aws_path": "access_key_id",
148
+ },
149
+ "AWS_SECRET_ACCESS_KEY": {
150
+ "env": "AWS_SECRET_ACCESS_KEY",
151
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}aws",
152
+ "aws_path": "secret_access_key",
153
+ },
154
+ "AWS_REGION": {
155
+ "env": "AWS_REGION",
156
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}aws",
157
+ "aws_path": "region",
158
+ },
159
+ "AWS_SESSION_TOKEN": {
160
+ "env": "AWS_SESSION_TOKEN",
161
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}aws",
162
+ "aws_path": "session_token",
163
+ },
164
+ # === AZURE CREDENTIALS ===
165
+ "AZURE_CLIENT_ID": {
166
+ "env": "AZURE_CLIENT_ID",
167
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azure",
168
+ "aws_path": "client_id",
169
+ },
170
+ "AZURE_CLIENT_SECRET": {
171
+ "env": "AZURE_CLIENT_SECRET",
172
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azure",
173
+ "aws_path": "client_secret",
174
+ },
175
+ "AZURE_TENANT_ID": {
176
+ "env": "AZURE_TENANT_ID",
177
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azure",
178
+ "aws_path": "tenant_id",
179
+ },
180
+ "AZURE_SUBSCRIPTION_ID": {
181
+ "env": "AZURE_SUBSCRIPTION_ID",
182
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azure",
183
+ "aws_path": "subscription_id",
184
+ },
185
+ # === GCP CREDENTIALS ===
186
+ "GCP_PROJECT_ID": {
187
+ "env": "GCP_PROJECT_ID",
188
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}gcp",
189
+ "aws_path": "projectId",
190
+ },
191
+ "GCP_CLIENT_EMAIL": {
192
+ "env": "GCP_CLIENT_EMAIL",
193
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}gcp",
194
+ "aws_path": "clientEmail",
195
+ },
196
+ "GCP_PRIVATE_KEY": {
197
+ "env": "GCP_PRIVATE_KEY",
198
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}gcp",
199
+ "aws_path": "privateKey",
200
+ },
201
+ "GCP_SA_KEY_BASE64": {
202
+ "env": "GCP_SA_KEY_BASE64",
203
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}gcp",
204
+ "aws_path": "sa_key_in_base64",
205
+ },
206
+ # === AZURE DEVOPS CREDENTIALS ===
207
+ "AZURE_DEVOPS_URL": {
208
+ "env": "AZURE_DEVOPS_URL",
209
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azuredevops",
210
+ "aws_path": "url",
211
+ },
212
+ "AZURE_DEVOPS_TOKEN": {
213
+ "env": "AZURE_DEVOPS_TOKEN",
214
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azuredevops",
215
+ "aws_path": "personal_access_token",
216
+ },
217
+ "AZURE_DEVOPS_PROJECT_NAME": {
218
+ "env": "AZURE_DEVOPS_PROJECT_NAME",
219
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azuredevops",
220
+ "aws_path": "project_name",
221
+ },
222
+ "AZURE_DEVOPS_ORGANIZATION_NAME": {
223
+ "env": "AZURE_DEVOPS_ORGANIZATION_NAME",
224
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}azuredevops",
225
+ "aws_path": "organization_name",
226
+ },
227
+ # === SERVICENOW CREDENTIALS ===
228
+ "SERVICENOW_URL": {
229
+ "env": "SERVICENOW_URL",
230
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}service_now",
231
+ "aws_path": "url",
232
+ },
233
+ "SERVICENOW_TOKEN": {
234
+ "env": "SERVICENOW_TOKEN",
235
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}service_now",
236
+ "aws_path": "token",
237
+ },
238
+ # === KEYCLOAK CREDENTIALS ===
239
+ "KEYCLOAK_URL": {
240
+ "env": "KEYCLOAK_URL",
241
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}keycloak",
242
+ "aws_path": "url",
243
+ },
244
+ "KEYCLOAK_REALM": {
245
+ "env": "KEYCLOAK_REALM",
246
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}keycloak",
247
+ "aws_path": "realm",
248
+ },
249
+ "KEYCLOAK_CLIENT_ID": {
250
+ "env": "KEYCLOAK_CLIENT_ID",
251
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}keycloak",
252
+ "aws_path": "client_id",
253
+ },
254
+ "KEYCLOAK_CLIENT_SECRET": {
255
+ "env": "KEYCLOAK_CLIENT_SECRET",
256
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}keycloak",
257
+ "aws_path": "client_secret",
258
+ },
259
+ # === SONAR CREDENTIALS ===
260
+ "SONAR_URL": {
261
+ "env": "SONAR_URL",
262
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sonar",
263
+ "aws_path": "sonar_server.url",
264
+ },
265
+ "SONAR_TOKEN": {
266
+ "env": "SONAR_TOKEN",
267
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sonar",
268
+ "aws_path": "sonar_server.token",
269
+ },
270
+ "SONAR_PROJECT_KEY": {
271
+ "env": "SONAR_PROJECT_KEY",
272
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sonar",
273
+ "aws_path": "sonar_server.projectKey",
274
+ },
275
+ "SONAR_CLOUD_URL": {
276
+ "env": "SONAR_CLOUD_URL",
277
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sonar",
278
+ "aws_path": "sonar_cloud.url",
279
+ },
280
+ "SONAR_CLOUD_TOKEN": {
281
+ "env": "SONAR_CLOUD_TOKEN",
282
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sonar",
283
+ "aws_path": "sonar_cloud.token",
284
+ },
285
+ "SONAR_CLOUD_PROJECT_KEY": {
286
+ "env": "SONAR_CLOUD_PROJECT_KEY",
287
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sonar",
288
+ "aws_path": "sonar_cloud.projectKey",
289
+ },
290
+ # === EMAIL/GMAIL CREDENTIALS ===
291
+ "GMAIL_URL": {
292
+ "env": "GMAIL_URL",
293
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}email",
294
+ "aws_path": "email.url",
295
+ },
296
+ "SMTP_USERNAME": {
297
+ "env": "SMTP_USERNAME",
298
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}email",
299
+ "aws_path": "email.smtp_username",
300
+ },
301
+ "SMTP_PASSWORD": {
302
+ "env": "SMTP_PASSWORD",
303
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}email",
304
+ "aws_path": "email.smtp_password",
305
+ },
306
+ # === OAUTH CREDENTIALS ===
307
+ "OAUTH_URL": {
308
+ "env": "OAUTH_URL",
309
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}email",
310
+ "aws_path": "oauth.url",
311
+ },
312
+ "OAUTH_CLIENT_ID": {
313
+ "env": "OAUTH_CLIENT_ID",
314
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}email",
315
+ "aws_path": "oauth.client_id",
316
+ },
317
+ "OAUTH_CLIENT_SECRET": {
318
+ "env": "OAUTH_CLIENT_SECRET",
319
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}email",
320
+ "aws_path": "oauth.client_secret",
321
+ },
322
+ "OAUTH_REFRESH_TOKEN": {
323
+ "env": "OAUTH_REFRESH_TOKEN",
324
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}email",
325
+ "aws_path": "oauth.refresh_token",
326
+ },
327
+ # === TELEGRAM CREDENTIALS ===
328
+ "TELEGRAM_TOKEN": {
329
+ "env": "TELEGRAM_TOKEN",
330
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}telegram",
331
+ "aws_path": "token",
332
+ },
333
+ "TELEGRAM_CHAT_ID": {
334
+ "env": "TELEGRAM_CHAT_ID",
335
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}telegram",
336
+ "aws_path": "chat_id",
337
+ },
338
+ # === KUBERNETES CREDENTIALS ===
339
+ "KUBERNETES_URL": {
340
+ "env": "KUBERNETES_URL",
341
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}kubernetes",
342
+ "aws_path": "url",
343
+ },
344
+ "KUBERNETES_TOKEN": {
345
+ "env": "KUBERNETES_TOKEN",
346
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}kubernetes",
347
+ "aws_path": "bearerToken",
348
+ },
349
+ # === REPORT PORTAL CREDENTIALS ===
350
+ "REPORT_PORTAL_URL": {
351
+ "env": "REPORT_PORTAL_URL",
352
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}reportportal",
353
+ "aws_path": "url",
354
+ },
355
+ "REPORT_PORTAL_API_KEY": {
356
+ "env": "REPORT_PORTAL_API_KEY",
357
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}reportportal",
358
+ "aws_path": "api_key",
359
+ },
360
+ "REPORT_PORTAL_PROJECT": {
361
+ "env": "REPORT_PORTAL_PROJECT",
362
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}reportportal",
363
+ "aws_path": "project",
364
+ },
365
+ # === ELASTICSEARCH CREDENTIALS (Preview Environment) ===
366
+ "ELASTICSEARCH_URL": {
367
+ "env": "ELASTICSEARCH_URL",
368
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}elastic",
369
+ "aws_path": "elasticsearch_preview.url",
370
+ },
371
+ "ELASTICSEARCH_API_KEY_ID": {
372
+ "env": "ELASTICSEARCH_API_KEY_ID",
373
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}elastic",
374
+ "aws_path": "elasticsearch_preview.apiKeyId",
375
+ },
376
+ "ELASTICSEARCH_API_KEY": {
377
+ "env": "ELASTICSEARCH_API_KEY",
378
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}elastic",
379
+ "aws_path": "elasticsearch_preview.apiKey",
380
+ },
381
+ # === ELASTICSEARCH CREDENTIALS (Sandbox Environment) ===
382
+ "SANDBOX_ELASTICSEARCH_URL": {
383
+ "env": "ELASTICSEARCH_URL", # Same env var
384
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}elastic",
385
+ "aws_path": "elasticsearch_sandbox.url",
386
+ },
387
+ "SANDBOX_ELASTICSEARCH_API_KEY_ID": {
388
+ "env": "ELASTICSEARCH_API_KEY_ID", # Same env var
389
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}elastic",
390
+ "aws_path": "elasticsearch_sandbox.apiKeyId",
391
+ },
392
+ "SANDBOX_ELASTICSEARCH_API_KEY": {
393
+ "env": "ELASTICSEARCH_API_KEY", # Same env var
394
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}elastic",
395
+ "aws_path": "elasticsearch_sandbox.apiKey",
396
+ },
397
+ # === LITE LLM CREDENTIALS ===
398
+ "LITE_LLM_API_KEY": {
399
+ "env": "LITE_LLM_API_KEY",
400
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}litellm",
401
+ "aws_path": "api_key",
402
+ },
403
+ # === SQL CREDENTIALS (Environment-based) ===
404
+ # Preview MySQL
405
+ "PREVIEW_MYSQL_DIALECT": {
406
+ "env": "MYSQL_DIALECT",
407
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
408
+ "aws_path": "preview.mysql.dialect",
409
+ },
410
+ "PREVIEW_MYSQL_URL": {
411
+ "env": "MYSQL_URL",
412
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
413
+ "aws_path": "preview.mysql.url",
414
+ },
415
+ "PREVIEW_MYSQL_PORT": {
416
+ "env": "MYSQL_PORT",
417
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
418
+ "aws_path": "preview.mysql.port",
419
+ },
420
+ "PREVIEW_MYSQL_DATABASE_NAME": {
421
+ "env": "MYSQL_DATABASE_NAME",
422
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
423
+ "aws_path": "preview.mysql.database_name",
424
+ },
425
+ "PREVIEW_MYSQL_USERNAME": {
426
+ "env": "MYSQL_USERNAME",
427
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
428
+ "aws_path": "preview.mysql.username",
429
+ },
430
+ "PREVIEW_MYSQL_PASSWORD": {
431
+ "env": "MYSQL_PASSWORD",
432
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
433
+ "aws_path": "preview.mysql.password",
434
+ },
435
+ # Sandbox MySQL
436
+ "SANDBOX_MYSQL_DIALECT": {
437
+ "env": "MYSQL_DIALECT",
438
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
439
+ "aws_path": "sandbox.mysql.dialect",
440
+ },
441
+ "SANDBOX_MYSQL_URL": {
442
+ "env": "MYSQL_URL",
443
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
444
+ "aws_path": "sandbox.mysql.url",
445
+ },
446
+ "SANDBOX_MYSQL_PORT": {
447
+ "env": "MYSQL_PORT",
448
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
449
+ "aws_path": "sandbox.mysql.port",
450
+ },
451
+ "SANDBOX_MYSQL_DATABASE_NAME": {
452
+ "env": "MYSQL_DATABASE_NAME",
453
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
454
+ "aws_path": "sandbox.mysql.database_name",
455
+ },
456
+ "SANDBOX_MYSQL_USERNAME": {
457
+ "env": "MYSQL_USERNAME",
458
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
459
+ "aws_path": "sandbox.mysql.username",
460
+ },
461
+ "SANDBOX_MYSQL_PASSWORD": {
462
+ "env": "MYSQL_PASSWORD",
463
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
464
+ "aws_path": "sandbox.mysql.password",
465
+ },
466
+ # Preview PostgreSQL
467
+ "PREVIEW_POSTGRES_DIALECT": {
468
+ "env": "POSTGRES_DIALECT",
469
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
470
+ "aws_path": "preview.postgres.dialect",
471
+ },
472
+ "PREVIEW_POSTGRES_URL": {
473
+ "env": "POSTGRES_URL",
474
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
475
+ "aws_path": "preview.postgres.url",
476
+ },
477
+ "PREVIEW_POSTGRES_PORT": {
478
+ "env": "POSTGRES_PORT",
479
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
480
+ "aws_path": "preview.postgres.port",
481
+ },
482
+ "PREVIEW_POSTGRES_DATABASE_NAME": {
483
+ "env": "POSTGRES_DATABASE_NAME",
484
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
485
+ "aws_path": "preview.postgres.database_name",
486
+ },
487
+ "PREVIEW_POSTGRES_USERNAME": {
488
+ "env": "POSTGRES_USERNAME",
489
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
490
+ "aws_path": "preview.postgres.username",
491
+ },
492
+ "PREVIEW_POSTGRES_PASSWORD": {
493
+ "env": "POSTGRES_PASSWORD",
494
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
495
+ "aws_path": "preview.postgres.password",
496
+ },
497
+ # Sandbox PostgreSQL
498
+ "SANDBOX_POSTGRES_DIALECT": {
499
+ "env": "POSTGRES_DIALECT",
500
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
501
+ "aws_path": "sandbox.postgres.dialect",
502
+ },
503
+ "SANDBOX_POSTGRES_URL": {
504
+ "env": "POSTGRES_URL",
505
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
506
+ "aws_path": "sandbox.postgres.url",
507
+ },
508
+ "SANDBOX_POSTGRES_PORT": {
509
+ "env": "POSTGRES_PORT",
510
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
511
+ "aws_path": "sandbox.postgres.port",
512
+ },
513
+ "SANDBOX_POSTGRES_DATABASE_NAME": {
514
+ "env": "POSTGRES_DATABASE_NAME",
515
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
516
+ "aws_path": "sandbox.postgres.database_name",
517
+ },
518
+ "SANDBOX_POSTGRES_USERNAME": {
519
+ "env": "POSTGRES_USERNAME",
520
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
521
+ "aws_path": "sandbox.postgres.username",
522
+ },
523
+ "SANDBOX_POSTGRES_PASSWORD": {
524
+ "env": "POSTGRES_PASSWORD",
525
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
526
+ "aws_path": "sandbox.postgres.password",
527
+ },
528
+ # Sandbox MSSQL (only available in sandbox)
529
+ "SANDBOX_MSSQL_DIALECT": {
530
+ "env": "MSSQL_DIALECT",
531
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
532
+ "aws_path": "sandbox.mssql.dialect",
533
+ },
534
+ "SANDBOX_MSSQL_URL": {
535
+ "env": "MSSQL_URL",
536
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
537
+ "aws_path": "sandbox.mssql.url",
538
+ },
539
+ "SANDBOX_MSSQL_PORT": {
540
+ "env": "MSSQL_PORT",
541
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
542
+ "aws_path": "sandbox.mssql.port",
543
+ },
544
+ "SANDBOX_MSSQL_DATABASE_NAME": {
545
+ "env": "MSSQL_DATABASE_NAME",
546
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
547
+ "aws_path": "sandbox.mssql.database_name",
548
+ },
549
+ "SANDBOX_MSSQL_USERNAME": {
550
+ "env": "MSSQL_USERNAME",
551
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
552
+ "aws_path": "sandbox.mssql.username",
553
+ },
554
+ "SANDBOX_MSSQL_PASSWORD": {
555
+ "env": "MSSQL_PASSWORD",
556
+ "aws_param": f"{INTEGRATIONS_PARAMETER_PATH}sql",
557
+ "aws_path": "sandbox.mssql.password",
558
+ },
559
+ }
560
+
561
+ # Cache for AWS Parameter Store data to avoid repeated calls
562
+ _aws_cache: Dict[str, Dict[str, Any]] = {}
563
+
564
+ @staticmethod
565
+ def get_parameter(key: str, default: Optional[str] = "") -> Optional[str]:
566
+ """
567
+ Get parameter value using configuration-driven approach.
568
+
569
+ Priority:
570
+ 1. Environment variable (.env file)
571
+ 2. AWS Parameter Store (with JSON path navigation)
572
+ 3. Configuration mapping default value
573
+ 4. Provided default value
574
+
575
+ Args:
576
+ key: The parameter key (e.g., "JIRA_URL")
577
+ default: Default value if not found
578
+
579
+ Returns:
580
+ Parameter value or default
581
+ """
582
+ # 1. Try environment variable first (highest priority)
583
+ env_value = os.getenv(key)
584
+ if env_value is not None:
585
+ return env_value
586
+
587
+ # 2. Try AWS Parameter Store using configuration mapping
588
+ if key in CredentialsManager.CREDENTIAL_MAPPINGS:
589
+ config = CredentialsManager.CREDENTIAL_MAPPINGS[key]
590
+ aws_value = CredentialsManager._get_aws_parameter_with_path(
591
+ config["aws_param"], config["aws_path"]
592
+ )
593
+ if aws_value is not None:
594
+ return aws_value
595
+
596
+ # 3. Try configuration mapping default value
597
+ config_default = config.get("default", "")
598
+ if config_default is not None:
599
+ return config_default
600
+
601
+ return default
602
+
603
+ @staticmethod
604
+ def _get_aws_parameter_with_path(aws_param: str, json_path: str) -> Optional[str]:
605
+ """
606
+ Get value from AWS Parameter Store JSON using dot notation path.
607
+
608
+ Args:
609
+ aws_param: AWS Parameter Store parameter name (e.g., "/codemie/autotests/integrations/jira")
610
+ json_path: Dot notation path (e.g., "jira.url" or "jiracloud.token")
611
+
612
+ Returns:
613
+ Value at the specified path or None
614
+ """
615
+ try:
616
+ # Get AWS credentials from environment
617
+ aws_access_key = os.getenv("AWS_ACCESS_KEY", "")
618
+ aws_secret_key = os.getenv("AWS_SECRET_KEY", "")
619
+ aws_session_token = os.getenv("AWS_SESSION_TOKEN", "")
620
+
621
+ # Skip AWS Parameter Store if no credentials available
622
+ if not aws_access_key or not aws_secret_key:
623
+ return None
624
+
625
+ # Use cache to avoid repeated AWS calls for same parameter
626
+ if aws_param not in CredentialsManager._aws_cache:
627
+ aws_store = AwsParameterStore.get_instance(
628
+ aws_access_key, aws_secret_key, aws_session_token
629
+ )
630
+ raw_value = aws_store.get_parameter(aws_param)
631
+ if raw_value:
632
+ CredentialsManager._aws_cache[aws_param] = json.loads(raw_value)
633
+ else:
634
+ CredentialsManager._aws_cache[aws_param] = {}
635
+
636
+ # Navigate the JSON structure using dot notation
637
+ data = CredentialsManager._aws_cache[aws_param]
638
+ path_parts = json_path.split(".")
639
+
640
+ current = data
641
+ for part in path_parts:
642
+ if isinstance(current, dict) and part in current:
643
+ current = current[part]
644
+ else:
645
+ return None
646
+
647
+ return current
648
+
649
+ except Exception:
650
+ # Silently handle AWS errors (credentials not available, parameter doesn't exist, etc.)
651
+ return None
652
+
653
+ # === CREDENTIAL METHODS ===
654
+
655
+ @staticmethod
656
+ def jira_credentials() -> List[CredentialValues]:
657
+ """Create Jira Cloud credentials using configuration-driven approach."""
658
+ return [
659
+ CredentialValues(
660
+ key="url", value=CredentialsManager.get_parameter("JIRA_URL")
661
+ ),
662
+ CredentialValues(
663
+ key="token", value=CredentialsManager.get_parameter("JIRA_TOKEN")
664
+ ),
665
+ CredentialValues(key="username", value=""),
666
+ ]
667
+
668
+ @staticmethod
669
+ def jira_cloud_credentials() -> List[CredentialValues]:
670
+ """Create Jira Cloud credentials using configuration-driven approach."""
671
+ return [
672
+ CredentialValues(
673
+ key="url", value=CredentialsManager.get_parameter("JIRA_CLOUD_URL")
674
+ ),
675
+ CredentialValues(
676
+ key="username",
677
+ value=CredentialsManager.get_parameter("JIRA_CLOUD_EMAIL"),
678
+ ),
679
+ CredentialValues(
680
+ key="token", value=CredentialsManager.get_parameter("JIRA_CLOUD_TOKEN")
681
+ ),
682
+ CredentialValues(key="is_cloud", value=True),
683
+ ]
684
+
685
+ @staticmethod
686
+ def confluence_credentials() -> List[CredentialValues]:
687
+ """Create Confluence credentials using configuration-driven approach."""
688
+ return [
689
+ CredentialValues(
690
+ key="url", value=CredentialsManager.get_parameter("CONFLUENCE_URL")
691
+ ),
692
+ CredentialValues(key="username", value=""),
693
+ CredentialValues(
694
+ key="token", value=CredentialsManager.get_parameter("CONFLUENCE_TOKEN")
695
+ ),
696
+ ]
697
+
698
+ @staticmethod
699
+ def confluence_cloud_credentials() -> List[CredentialValues]:
700
+ """Create Confluence Cloud credentials using configuration-driven approach."""
701
+ return [
702
+ CredentialValues(
703
+ key="url",
704
+ value=CredentialsManager.get_parameter("CONFLUENCE_CLOUD_URL"),
705
+ ),
706
+ CredentialValues(
707
+ key="username",
708
+ value=CredentialsManager.get_parameter("CONFLUENCE_CLOUD_EMAIL"),
709
+ ),
710
+ CredentialValues(
711
+ key="token",
712
+ value=CredentialsManager.get_parameter("CONFLUENCE_CLOUD_TOKEN"),
713
+ ),
714
+ CredentialValues(key="is_cloud", value=True),
715
+ ]
716
+
717
+ @staticmethod
718
+ def gitlab_credentials() -> List[CredentialValues]:
719
+ """Create GitLab credentials using configuration-driven approach."""
720
+ return [
721
+ CredentialValues(
722
+ key="url", value=CredentialsManager.get_parameter("GITLAB_URL")
723
+ ),
724
+ CredentialValues(key="name", value=""),
725
+ CredentialValues(
726
+ key="token", value=CredentialsManager.get_parameter("GITLAB_TOKEN")
727
+ ),
728
+ ]
729
+
730
+ @staticmethod
731
+ def github_credentials() -> List[CredentialValues]:
732
+ """Create GitHub credentials using configuration-driven approach."""
733
+ return [
734
+ CredentialValues(
735
+ key="url", value=CredentialsManager.get_parameter("GITHUB_URL")
736
+ ),
737
+ CredentialValues(key="name", value=""),
738
+ CredentialValues(
739
+ key="token", value=CredentialsManager.get_parameter("GITHUB_TOKEN")
740
+ ),
741
+ ]
742
+
743
+ @staticmethod
744
+ def aws_credentials() -> List[CredentialValues]:
745
+ """Create AWS credentials using configuration-driven approach."""
746
+ return [
747
+ CredentialValues(
748
+ key="aws_access_key_id",
749
+ value=CredentialsManager.get_parameter("AWS_ACCESS_KEY_ID"),
750
+ ),
751
+ CredentialValues(
752
+ key="aws_secret_access_key",
753
+ value=CredentialsManager.get_parameter("AWS_SECRET_ACCESS_KEY"),
754
+ ),
755
+ CredentialValues(
756
+ key="aws_region", value=CredentialsManager.get_parameter("AWS_REGION")
757
+ ),
758
+ ]
759
+
760
+ @staticmethod
761
+ def azure_credentials() -> List[CredentialValues]:
762
+ """Create Azure credentials using configuration-driven approach."""
763
+ return [
764
+ CredentialValues(
765
+ key="azure_client_id",
766
+ value=CredentialsManager.get_parameter("AZURE_CLIENT_ID"),
767
+ ),
768
+ CredentialValues(
769
+ key="azure_client_secret",
770
+ value=CredentialsManager.get_parameter("AZURE_CLIENT_SECRET"),
771
+ ),
772
+ CredentialValues(
773
+ key="azure_tenant_id",
774
+ value=CredentialsManager.get_parameter("AZURE_TENANT_ID"),
775
+ ),
776
+ CredentialValues(
777
+ key="azure_subscription_id",
778
+ value=CredentialsManager.get_parameter("AZURE_SUBSCRIPTION_ID"),
779
+ ),
780
+ ]
781
+
782
+ @staticmethod
783
+ def gcp_credentials() -> List[CredentialValues]:
784
+ """Create GCP credentials using configuration-driven approach."""
785
+ sa_key_in_base64 = CredentialsManager.get_parameter("GCP_SA_KEY_BASE64")
786
+ gcp_api_key = base64.b64decode(sa_key_in_base64).decode()
787
+ return [
788
+ CredentialValues(
789
+ key="gcp_api_key",
790
+ value=gcp_api_key,
791
+ ),
792
+ ]
793
+
794
+ @staticmethod
795
+ def azure_devops_credentials() -> List[CredentialValues]:
796
+ """Create Azure DevOps credentials using configuration-driven approach."""
797
+ return [
798
+ CredentialValues(
799
+ key="url", value=CredentialsManager.get_parameter("AZURE_DEVOPS_URL")
800
+ ),
801
+ CredentialValues(
802
+ key="project",
803
+ value=CredentialsManager.get_parameter("AZURE_DEVOPS_PROJECT_NAME"),
804
+ ),
805
+ CredentialValues(
806
+ key="organization",
807
+ value=CredentialsManager.get_parameter(
808
+ "AZURE_DEVOPS_ORGANIZATION_NAME"
809
+ ),
810
+ ),
811
+ CredentialValues(
812
+ key="token",
813
+ value=CredentialsManager.get_parameter("AZURE_DEVOPS_TOKEN"),
814
+ ),
815
+ ]
816
+
817
+ @staticmethod
818
+ def servicenow_credentials() -> List[CredentialValues]:
819
+ """Create ServiceNow credentials using configuration-driven approach."""
820
+ return [
821
+ CredentialValues(
822
+ key="url", value=CredentialsManager.get_parameter("SERVICENOW_URL")
823
+ ),
824
+ CredentialValues(
825
+ key="api_key",
826
+ value=CredentialsManager.get_parameter("SERVICENOW_TOKEN"),
827
+ ),
828
+ ]
829
+
830
+ @staticmethod
831
+ def keycloak_credentials() -> List[CredentialValues]:
832
+ """Create Keycloak admin credentials using configuration-driven approach."""
833
+ return [
834
+ CredentialValues(
835
+ key="url", value=CredentialsManager.get_parameter("KEYCLOAK_URL")
836
+ ),
837
+ CredentialValues(
838
+ key="realm", value=CredentialsManager.get_parameter("KEYCLOAK_REALM")
839
+ ),
840
+ CredentialValues(
841
+ key="client_id",
842
+ value=CredentialsManager.get_parameter("KEYCLOAK_CLIENT_ID"),
843
+ ),
844
+ CredentialValues(
845
+ key="client_secret",
846
+ value=CredentialsManager.get_parameter("KEYCLOAK_CLIENT_SECRET"),
847
+ ),
848
+ ]
849
+
850
+ # === SPECIAL QUERY METHODS ===
851
+
852
+ @staticmethod
853
+ def jira_jql() -> str:
854
+ """Get Jira Server JQL using configuration-driven approach."""
855
+ return CredentialsManager.get_parameter("JIRA_JQL")
856
+
857
+ @staticmethod
858
+ def jira_cloud_jql() -> str:
859
+ """Get Jira Cloud JQL using configuration-driven approach."""
860
+ return CredentialsManager.get_parameter("JIRA_CLOUD_JQL")
861
+
862
+ @staticmethod
863
+ def confluence_cql() -> str:
864
+ """Get Confluence CQL using configuration-driven approach."""
865
+ return CredentialsManager.get_parameter("CONFLUENCE_CQL")
866
+
867
+ @staticmethod
868
+ def confluence_cloud_cql() -> str:
869
+ """Get Confluence Cloud CQL using configuration-driven approach."""
870
+ return CredentialsManager.get_parameter("CONFLUENCE_CLOUD_CQL")
871
+
872
+ @staticmethod
873
+ def sonar_credentials() -> List[CredentialValues]:
874
+ """Create SonarQube credentials using configuration-driven approach."""
875
+ return [
876
+ CredentialValues(
877
+ key="url", value=CredentialsManager.get_parameter("SONAR_URL")
878
+ ),
879
+ CredentialValues(
880
+ key="token", value=CredentialsManager.get_parameter("SONAR_TOKEN")
881
+ ),
882
+ CredentialValues(
883
+ key="sonar_project_name",
884
+ value=CredentialsManager.get_parameter("SONAR_PROJECT_KEY"),
885
+ ),
886
+ ]
887
+
888
+ @staticmethod
889
+ def sonar_cloud_credentials() -> List[CredentialValues]:
890
+ """Create SonarCloud credentials using configuration-driven approach."""
891
+ return [
892
+ CredentialValues(
893
+ key="url", value=CredentialsManager.get_parameter("SONAR_CLOUD_URL")
894
+ ),
895
+ CredentialValues(
896
+ key="token", value=CredentialsManager.get_parameter("SONAR_CLOUD_TOKEN")
897
+ ),
898
+ CredentialValues(
899
+ key="sonar_project_name",
900
+ value=CredentialsManager.get_parameter("SONAR_CLOUD_PROJECT_KEY"),
901
+ ),
902
+ ]
903
+
904
+ @staticmethod
905
+ def gmail_credentials() -> List[CredentialValues]:
906
+ """Create Gmail credentials using configuration-driven approach."""
907
+ return [
908
+ CredentialValues(
909
+ key="url", value=CredentialsManager.get_parameter("GMAIL_URL")
910
+ ),
911
+ CredentialValues(
912
+ key="smtp_username",
913
+ value=CredentialsManager.get_parameter("SMTP_USERNAME"),
914
+ ),
915
+ CredentialValues(
916
+ key="smtp_password",
917
+ value=CredentialsManager.get_parameter("SMTP_PASSWORD"),
918
+ ),
919
+ ]
920
+
921
+ @staticmethod
922
+ def oauth_credentials() -> List[CredentialValues]:
923
+ """Create OAuth credentials using configuration-driven approach."""
924
+ return [
925
+ CredentialValues(
926
+ key="url", value=CredentialsManager.get_parameter("OAUTH_URL")
927
+ ),
928
+ CredentialValues(
929
+ key="client_id",
930
+ value=CredentialsManager.get_parameter("OAUTH_CLIENT_ID"),
931
+ ),
932
+ CredentialValues(
933
+ key="client_secret",
934
+ value=CredentialsManager.get_parameter("OAUTH_CLIENT_SECRET"),
935
+ ),
936
+ CredentialValues(
937
+ key="refresh_token",
938
+ value=CredentialsManager.get_parameter("OAUTH_REFRESH_TOKEN"),
939
+ ),
940
+ ]
941
+
942
+ @staticmethod
943
+ def telegram_credentials() -> List[CredentialValues]:
944
+ """Create Telegram credentials using configuration-driven approach."""
945
+ return [
946
+ CredentialValues(
947
+ key="token", value=CredentialsManager.get_parameter("TELEGRAM_TOKEN")
948
+ ),
949
+ CredentialValues(
950
+ key="chat_id",
951
+ value=CredentialsManager.get_parameter("TELEGRAM_CHAT_ID"),
952
+ ),
953
+ ]
954
+
955
+ @staticmethod
956
+ def kubernetes_credentials() -> List[CredentialValues]:
957
+ """Create Kubernetes credentials using configuration-driven approach."""
958
+ return [
959
+ CredentialValues(key="url", value=CredentialsManager.AUTO_GENERATED),
960
+ CredentialValues(
961
+ key="kubernetes_url",
962
+ value=CredentialsManager.get_parameter("KUBERNETES_URL"),
963
+ ),
964
+ CredentialValues(
965
+ key="kubernetes_token",
966
+ value=CredentialsManager.get_parameter("KUBERNETES_TOKEN"),
967
+ ),
968
+ ]
969
+
970
+ @staticmethod
971
+ def report_portal_credentials() -> List[CredentialValues]:
972
+ """Create Report Portal credentials using configuration-driven approach."""
973
+ return [
974
+ CredentialValues(
975
+ key="url", value=CredentialsManager.get_parameter("REPORT_PORTAL_URL")
976
+ ),
977
+ CredentialValues(
978
+ key="project",
979
+ value=CredentialsManager.get_parameter("REPORT_PORTAL_PROJECT"),
980
+ ),
981
+ CredentialValues(
982
+ key="api_key",
983
+ value=CredentialsManager.get_parameter("REPORT_PORTAL_API_KEY"),
984
+ ),
985
+ ]
986
+
987
+ @staticmethod
988
+ def elasticsearch_credentials() -> List[CredentialValues]:
989
+ """Create Elasticsearch credentials using environment-aware configuration-driven approach.
990
+
991
+ Uses different JSON paths based on environment:
992
+ - Preview environment: elasticsearch.*
993
+ - Sandbox environments (azure, gcp, aws): sandbox.elasticsearch.*
994
+ """
995
+ # Check if we're in a sandbox environment
996
+ is_sandbox = EnvironmentResolver.is_sandbox()
997
+
998
+ if is_sandbox:
999
+ # For sandbox environments, use sandbox.elasticsearch.* paths
1000
+ url = CredentialsManager.get_parameter("SANDBOX_ELASTICSEARCH_URL")
1001
+ api_key_id = CredentialsManager.get_parameter(
1002
+ "SANDBOX_ELASTICSEARCH_API_KEY_ID"
1003
+ )
1004
+ api_key = CredentialsManager.get_parameter("SANDBOX_ELASTICSEARCH_API_KEY")
1005
+ else:
1006
+ # For preview environment, use elasticsearch.* paths
1007
+ url = CredentialsManager.get_parameter("ELASTICSEARCH_URL")
1008
+ api_key_id = CredentialsManager.get_parameter("ELASTICSEARCH_API_KEY_ID")
1009
+ api_key = CredentialsManager.get_parameter("ELASTICSEARCH_API_KEY")
1010
+
1011
+ return [
1012
+ CredentialValues(key="url", value=url),
1013
+ CredentialValues(key="elastic_api_key_id", value=api_key_id),
1014
+ CredentialValues(key="elastic_api_key", value=api_key),
1015
+ ]
1016
+
1017
+ @staticmethod
1018
+ def mcp_credentials() -> List[CredentialValues]:
1019
+ return [CredentialValues(key="ALLOWED_COMMANDS", value="ls,echo,mkdir")]
1020
+
1021
+ @staticmethod
1022
+ def file_system_credentials() -> List[CredentialValues]:
1023
+ """Create File System credentials using configuration-driven approach."""
1024
+ return [
1025
+ CredentialValues(key="url", value=CredentialsManager.AUTO_GENERATED),
1026
+ CredentialValues(key="root_directory", value="/"),
1027
+ ]
1028
+
1029
+ @staticmethod
1030
+ def lite_llm_credentials() -> List[CredentialValues]:
1031
+ """Create LiteLLM credentials using configuration-driven approach."""
1032
+ return [
1033
+ CredentialValues(
1034
+ key="api_key",
1035
+ value=CredentialsManager.get_parameter("LITE_LLM_API_KEY"),
1036
+ ),
1037
+ ]
1038
+
1039
+ @staticmethod
1040
+ def mysql_credentials() -> List[CredentialValues]:
1041
+ """Create MySQL credentials using environment-aware configuration-driven approach.
1042
+
1043
+ Uses different JSON paths based on environment:
1044
+ - Preview environment: preview.mysql.*
1045
+ - Sandbox environment: sandbox.mysql.*
1046
+ """
1047
+ # Check if we're in a sandbox environment
1048
+ is_sandbox = EnvironmentResolver.is_sandbox()
1049
+
1050
+ if is_sandbox:
1051
+ # For sandbox environments, use sandbox.mysql.* paths
1052
+ dialect = CredentialsManager.get_parameter("SANDBOX_MYSQL_DIALECT")
1053
+ url = CredentialsManager.get_parameter("SANDBOX_MYSQL_URL")
1054
+ port = CredentialsManager.get_parameter("SANDBOX_MYSQL_PORT")
1055
+ database_name = CredentialsManager.get_parameter(
1056
+ "SANDBOX_MYSQL_DATABASE_NAME"
1057
+ )
1058
+ username = CredentialsManager.get_parameter("SANDBOX_MYSQL_USERNAME")
1059
+ password = CredentialsManager.get_parameter("SANDBOX_MYSQL_PASSWORD")
1060
+ else:
1061
+ # For preview environment, use preview.mysql.* paths
1062
+ dialect = CredentialsManager.get_parameter("PREVIEW_MYSQL_DIALECT")
1063
+ url = CredentialsManager.get_parameter("PREVIEW_MYSQL_URL")
1064
+ port = CredentialsManager.get_parameter("PREVIEW_MYSQL_PORT")
1065
+ database_name = CredentialsManager.get_parameter(
1066
+ "PREVIEW_MYSQL_DATABASE_NAME"
1067
+ )
1068
+ username = CredentialsManager.get_parameter("PREVIEW_MYSQL_USERNAME")
1069
+ password = CredentialsManager.get_parameter("PREVIEW_MYSQL_PASSWORD")
1070
+
1071
+ return [
1072
+ CredentialValues(key="dialect", value=dialect),
1073
+ CredentialValues(key="url", value=url),
1074
+ CredentialValues(key="port", value=port),
1075
+ CredentialValues(key="database_name", value=database_name),
1076
+ CredentialValues(key="username", value=username),
1077
+ CredentialValues(key="password", value=password),
1078
+ ]
1079
+
1080
+ @staticmethod
1081
+ def postgres_credentials() -> List[CredentialValues]:
1082
+ """Create PostgreSQL credentials using environment-aware configuration-driven approach.
1083
+
1084
+ Uses different JSON paths based on environment:
1085
+ - Preview environment: preview.postgres.*
1086
+ - Sandbox environment: sandbox.postgres.*
1087
+ """
1088
+ # Check if we're in a sandbox environment
1089
+ is_sandbox = EnvironmentResolver.is_sandbox()
1090
+
1091
+ if is_sandbox:
1092
+ # For sandbox environments, use sandbox.postgres.* paths
1093
+ dialect = CredentialsManager.get_parameter("SANDBOX_POSTGRES_DIALECT")
1094
+ url = CredentialsManager.get_parameter("SANDBOX_POSTGRES_URL")
1095
+ port = CredentialsManager.get_parameter("SANDBOX_POSTGRES_PORT")
1096
+ database_name = CredentialsManager.get_parameter(
1097
+ "SANDBOX_POSTGRES_DATABASE_NAME"
1098
+ )
1099
+ username = CredentialsManager.get_parameter("SANDBOX_POSTGRES_USERNAME")
1100
+ password = CredentialsManager.get_parameter("SANDBOX_POSTGRES_PASSWORD")
1101
+ else:
1102
+ # For preview environment, use preview.postgres.* paths
1103
+ dialect = CredentialsManager.get_parameter("PREVIEW_POSTGRES_DIALECT")
1104
+ url = CredentialsManager.get_parameter("PREVIEW_POSTGRES_URL")
1105
+ port = CredentialsManager.get_parameter("PREVIEW_POSTGRES_PORT")
1106
+ database_name = CredentialsManager.get_parameter(
1107
+ "PREVIEW_POSTGRES_DATABASE_NAME"
1108
+ )
1109
+ username = CredentialsManager.get_parameter("PREVIEW_POSTGRES_USERNAME")
1110
+ password = CredentialsManager.get_parameter("PREVIEW_POSTGRES_PASSWORD")
1111
+
1112
+ return [
1113
+ CredentialValues(key="dialect", value=dialect),
1114
+ CredentialValues(key="url", value=url),
1115
+ CredentialValues(key="port", value=port),
1116
+ CredentialValues(key="database_name", value=database_name),
1117
+ CredentialValues(key="username", value=username),
1118
+ CredentialValues(key="password", value=password),
1119
+ ]
1120
+
1121
+ @staticmethod
1122
+ def mssql_credentials() -> List[CredentialValues]:
1123
+ """Create MSSQL credentials using configuration-driven approach.
1124
+
1125
+ MSSQL is only available in sandbox environment.
1126
+ """
1127
+ # MSSQL is only available in sandbox
1128
+ dialect = CredentialsManager.get_parameter("SANDBOX_MSSQL_DIALECT")
1129
+ url = CredentialsManager.get_parameter("SANDBOX_MSSQL_URL")
1130
+ port = CredentialsManager.get_parameter("SANDBOX_MSSQL_PORT")
1131
+ database_name = CredentialsManager.get_parameter("SANDBOX_MSSQL_DATABASE_NAME")
1132
+ username = CredentialsManager.get_parameter("SANDBOX_MSSQL_USERNAME")
1133
+ password = CredentialsManager.get_parameter("SANDBOX_MSSQL_PASSWORD")
1134
+
1135
+ return [
1136
+ CredentialValues(key="dialect", value=dialect),
1137
+ CredentialValues(key="url", value=url),
1138
+ CredentialValues(key="port", value=port),
1139
+ CredentialValues(key="database_name", value=database_name),
1140
+ CredentialValues(key="username", value=username),
1141
+ CredentialValues(key="password", value=password),
1142
+ ]
1143
+
1144
+ @staticmethod
1145
+ def sql_credentials(db_dialect: str) -> list[CredentialValues] | None:
1146
+ """Create SQL credentials using environment-aware configuration-driven approach.
1147
+
1148
+ Args:
1149
+ db_dialect: Database dialect ('mysql', 'postgres', 'mssql')
1150
+
1151
+ Returns:
1152
+ List of credential values for the specified database dialect
1153
+ """
1154
+ if db_dialect.lower() == "mysql":
1155
+ return CredentialsManager.mysql_credentials()
1156
+ elif db_dialect.lower() in ["postgres", "postgresql"]:
1157
+ return CredentialsManager.postgres_credentials()
1158
+ elif db_dialect.lower() in ["mssql", "sqlserver"]:
1159
+ return CredentialsManager.mssql_credentials()
1160
+
1161
+ @staticmethod
1162
+ def open_api_credentials(token: str) -> List[CredentialValues]:
1163
+ openapi_path = os.path.join(
1164
+ os.path.dirname(__file__), "../test_data/openapi.json"
1165
+ )
1166
+ with open(openapi_path, "r") as openapi_json_file:
1167
+ openapi_spec = json.load(openapi_json_file)
1168
+
1169
+ return [
1170
+ CredentialValues(key="url", value=CredentialsManager.AUTO_GENERATED),
1171
+ CredentialValues(key="openapi_api_key", value=f"Bearer {token}"),
1172
+ CredentialValues(
1173
+ key="openapi_spec",
1174
+ value=json.dumps(openapi_spec, indent=4).replace(
1175
+ "CODEMIE_API_DOMAIN", os.getenv("CODEMIE_API_DOMAIN")
1176
+ ),
1177
+ ),
1178
+ ]
1179
+
1180
+ @staticmethod
1181
+ def plugin_credentials(plugin_key) -> List[CredentialValues]:
1182
+ return [
1183
+ CredentialValues(key="url", value=CredentialsManager.AUTO_GENERATED),
1184
+ CredentialValues(key="plugin_key", value=plugin_key),
1185
+ ]
1186
+
1187
+ # === INVALID CREDENTIALS FOR TESTING ===
1188
+
1189
+ @staticmethod
1190
+ def invalid_jira_credentials() -> List[CredentialValues]:
1191
+ """Create invalid Jira credentials for testing."""
1192
+ credentials = CredentialsManager.jira_credentials()
1193
+ for cred in credentials:
1194
+ if cred.key == "token":
1195
+ cred.value = "wrong_token"
1196
+ return credentials
1197
+
1198
+ @staticmethod
1199
+ def invalid_gitlab_credentials() -> List[CredentialValues]:
1200
+ """Create invalid GitLab credentials for testing."""
1201
+ credentials = CredentialsManager.gitlab_credentials()
1202
+ for cred in credentials:
1203
+ if cred.key == "token":
1204
+ cred.value = "wrong_token"
1205
+ return credentials
1206
+
1207
+ @staticmethod
1208
+ def invalid_github_credentials() -> List[CredentialValues]:
1209
+ """Create invalid GitHub credentials for testing."""
1210
+ credentials = CredentialsManager.github_credentials()
1211
+ for cred in credentials:
1212
+ if cred.key == "token":
1213
+ cred.value = "wrong_token"
1214
+ return credentials
1215
+
1216
+ @staticmethod
1217
+ def invalid_confluence_credentials() -> List[CredentialValues]:
1218
+ """Create invalid Confluence credentials for testing."""
1219
+ credentials = CredentialsManager.confluence_credentials()
1220
+ for cred in credentials:
1221
+ if cred.key == "token":
1222
+ cred.value = "wrong_token"
1223
+ return credentials
1224
+
1225
+ @staticmethod
1226
+ def invalid_aws_credentials() -> List[CredentialValues]:
1227
+ """Create invalid AWS credentials for testing."""
1228
+ credentials = CredentialsManager.aws_credentials()
1229
+ for cred in credentials:
1230
+ if cred.key == "aws_secret_access_key":
1231
+ cred.value = re.sub(r"\d", "0", cred.value)
1232
+
1233
+ return credentials
1234
+
1235
+ @staticmethod
1236
+ def invalid_azure_credentials() -> List[CredentialValues]:
1237
+ """Create invalid Azure credentials for testing."""
1238
+ credentials = CredentialsManager.azure_credentials()
1239
+ for cred in credentials:
1240
+ if cred.key == "azure_client_secret":
1241
+ cred.value = "wrong_secret"
1242
+ return credentials
1243
+
1244
+ @staticmethod
1245
+ def invalid_gcp_credentials():
1246
+ credentials = CredentialsManager.gcp_credentials()
1247
+ for cred in credentials:
1248
+ if cred.key == "gcp_api_key":
1249
+ cred.value = re.sub(r"\d", "0", cred.value)
1250
+
1251
+ return credentials
1252
+
1253
+ @staticmethod
1254
+ def invalid_sonar_credentials() -> List[CredentialValues]:
1255
+ """Create invalid SonarQube credentials for testing."""
1256
+ credentials = CredentialsManager.sonar_credentials()
1257
+ for cred in credentials:
1258
+ if cred.key == "token":
1259
+ cred.value = "wrong_token"
1260
+ return credentials
1261
+
1262
+ @staticmethod
1263
+ def invalid_sonar_cloud_credentials() -> List[CredentialValues]:
1264
+ """Create invalid SonarCloud credentials for testing."""
1265
+ credentials = CredentialsManager.sonar_cloud_credentials()
1266
+ for cred in credentials:
1267
+ if cred.key == "token":
1268
+ cred.value = "wrong_token"
1269
+ return credentials
1270
+
1271
+ @staticmethod
1272
+ def invalid_gmail_credentials() -> List[CredentialValues]:
1273
+ """Create invalid Gmail credentials for testing."""
1274
+ credentials = CredentialsManager.gmail_credentials()
1275
+ for cred in credentials:
1276
+ if cred.key == "smtp_password":
1277
+ cred.value = "wrong_password"
1278
+ return credentials
1279
+
1280
+ @staticmethod
1281
+ def invalid_servicenow_credentials() -> List[CredentialValues]:
1282
+ """Create invalid ServiceNow credentials for testing."""
1283
+ credentials = CredentialsManager.servicenow_credentials()
1284
+ for cred in credentials:
1285
+ if cred.key == "api_key":
1286
+ cred.value = "wrong_token"
1287
+ return credentials
1288
+
1289
+ @staticmethod
1290
+ def invalid_kubernetes_credentials() -> List[CredentialValues]:
1291
+ """Create invalid Kubernetes credentials for testing."""
1292
+ credentials = CredentialsManager.kubernetes_credentials()
1293
+ for cred in credentials:
1294
+ if cred.key == "kubernetes_token":
1295
+ cred.value = "wrong_token"
1296
+ return credentials
1297
+
1298
+ @staticmethod
1299
+ def invalid_report_portal_credentials() -> List[CredentialValues]:
1300
+ """Create invalid Report Portal credentials for testing."""
1301
+ credentials = CredentialsManager.report_portal_credentials()
1302
+ for cred in credentials:
1303
+ if cred.key == "api_key":
1304
+ cred.value = "wrong_api_key"
1305
+ return credentials
1306
+
1307
+ @staticmethod
1308
+ def invalid_oauth_credentials() -> List[CredentialValues]:
1309
+ """Create invalid OAuth credentials for testing."""
1310
+ credentials = CredentialsManager.oauth_credentials()
1311
+ for cred in credentials:
1312
+ if cred.key == "client_secret":
1313
+ cred.value = "wrong_secret"
1314
+ return credentials
1315
+
1316
+ @staticmethod
1317
+ def invalid_keycloak_credentials() -> List[CredentialValues]:
1318
+ """Create invalid Keycloak credentials for testing."""
1319
+ credentials = CredentialsManager.keycloak_credentials()
1320
+ for cred in credentials:
1321
+ if cred.key == "client_secret":
1322
+ cred.value = "wrong_secret"
1323
+ return credentials
1324
+
1325
+ @staticmethod
1326
+ def invalid_mysql_credentials() -> List[CredentialValues]:
1327
+ """Create invalid MySQL credentials for testing."""
1328
+ credentials = CredentialsManager.mysql_credentials()
1329
+ for cred in credentials:
1330
+ if cred.key == "password":
1331
+ cred.value = "wrong_password"
1332
+ return credentials
1333
+
1334
+ @staticmethod
1335
+ def invalid_postgres_credentials() -> List[CredentialValues]:
1336
+ """Create invalid PostgreSQL credentials for testing."""
1337
+ credentials = CredentialsManager.postgres_credentials()
1338
+ for cred in credentials:
1339
+ if cred.key == "password":
1340
+ cred.value = "wrong_password"
1341
+ return credentials
1342
+
1343
+ @staticmethod
1344
+ def invalid_mssql_credentials() -> List[CredentialValues]:
1345
+ """Create invalid MSSQL credentials for testing."""
1346
+ credentials = CredentialsManager.mssql_credentials()
1347
+ for cred in credentials:
1348
+ if cred.key == "password":
1349
+ cred.value = "wrong_password"
1350
+ return credentials
1351
+
1352
+ @staticmethod
1353
+ def invalid_lite_llm_credentials() -> List[CredentialValues]:
1354
+ credentials = CredentialsManager.lite_llm_credentials()
1355
+ for cred in credentials:
1356
+ if cred.key == "api_key":
1357
+ cred.value = "wrong_key"
1358
+ return credentials