kailash 0.6.3__py3-none-any.whl → 0.6.5__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.
- kailash/__init__.py +3 -3
- kailash/api/custom_nodes_secure.py +3 -3
- kailash/api/gateway.py +1 -1
- kailash/api/studio.py +1 -1
- kailash/api/workflow_api.py +2 -2
- kailash/core/resilience/bulkhead.py +475 -0
- kailash/core/resilience/circuit_breaker.py +92 -10
- kailash/core/resilience/health_monitor.py +578 -0
- kailash/edge/discovery.py +86 -0
- kailash/mcp_server/__init__.py +309 -33
- kailash/mcp_server/advanced_features.py +1022 -0
- kailash/mcp_server/ai_registry_server.py +27 -2
- kailash/mcp_server/auth.py +789 -0
- kailash/mcp_server/client.py +645 -378
- kailash/mcp_server/discovery.py +1593 -0
- kailash/mcp_server/errors.py +673 -0
- kailash/mcp_server/oauth.py +1727 -0
- kailash/mcp_server/protocol.py +1126 -0
- kailash/mcp_server/registry_integration.py +587 -0
- kailash/mcp_server/server.py +1228 -96
- kailash/mcp_server/transports.py +1169 -0
- kailash/mcp_server/utils/__init__.py +6 -1
- kailash/mcp_server/utils/cache.py +250 -7
- kailash/middleware/auth/auth_manager.py +3 -3
- kailash/middleware/communication/api_gateway.py +1 -1
- kailash/middleware/communication/realtime.py +1 -1
- kailash/middleware/mcp/enhanced_server.py +1 -1
- kailash/nodes/__init__.py +2 -0
- kailash/nodes/admin/audit_log.py +6 -6
- kailash/nodes/admin/permission_check.py +8 -8
- kailash/nodes/admin/role_management.py +32 -28
- kailash/nodes/admin/schema.sql +6 -1
- kailash/nodes/admin/schema_manager.py +13 -13
- kailash/nodes/admin/security_event.py +15 -15
- kailash/nodes/admin/tenant_isolation.py +3 -3
- kailash/nodes/admin/transaction_utils.py +3 -3
- kailash/nodes/admin/user_management.py +21 -21
- kailash/nodes/ai/a2a.py +11 -11
- kailash/nodes/ai/ai_providers.py +9 -12
- kailash/nodes/ai/embedding_generator.py +13 -14
- kailash/nodes/ai/intelligent_agent_orchestrator.py +19 -19
- kailash/nodes/ai/iterative_llm_agent.py +2 -2
- kailash/nodes/ai/llm_agent.py +210 -33
- kailash/nodes/ai/self_organizing.py +2 -2
- kailash/nodes/alerts/discord.py +4 -4
- kailash/nodes/api/graphql.py +6 -6
- kailash/nodes/api/http.py +10 -10
- kailash/nodes/api/rate_limiting.py +4 -4
- kailash/nodes/api/rest.py +15 -15
- kailash/nodes/auth/mfa.py +3 -3
- kailash/nodes/auth/risk_assessment.py +2 -2
- kailash/nodes/auth/session_management.py +5 -5
- kailash/nodes/auth/sso.py +143 -0
- kailash/nodes/base.py +8 -2
- kailash/nodes/base_async.py +16 -2
- kailash/nodes/base_with_acl.py +2 -2
- kailash/nodes/cache/__init__.py +9 -0
- kailash/nodes/cache/cache.py +1172 -0
- kailash/nodes/cache/cache_invalidation.py +874 -0
- kailash/nodes/cache/redis_pool_manager.py +595 -0
- kailash/nodes/code/async_python.py +2 -1
- kailash/nodes/code/python.py +194 -30
- kailash/nodes/compliance/data_retention.py +6 -6
- kailash/nodes/compliance/gdpr.py +5 -5
- kailash/nodes/data/__init__.py +10 -0
- kailash/nodes/data/async_sql.py +1956 -129
- kailash/nodes/data/optimistic_locking.py +906 -0
- kailash/nodes/data/readers.py +8 -8
- kailash/nodes/data/redis.py +378 -0
- kailash/nodes/data/sql.py +314 -3
- kailash/nodes/data/streaming.py +21 -0
- kailash/nodes/enterprise/__init__.py +8 -0
- kailash/nodes/enterprise/audit_logger.py +285 -0
- kailash/nodes/enterprise/batch_processor.py +22 -3
- kailash/nodes/enterprise/data_lineage.py +1 -1
- kailash/nodes/enterprise/mcp_executor.py +205 -0
- kailash/nodes/enterprise/service_discovery.py +150 -0
- kailash/nodes/enterprise/tenant_assignment.py +108 -0
- kailash/nodes/logic/async_operations.py +2 -2
- kailash/nodes/logic/convergence.py +1 -1
- kailash/nodes/logic/operations.py +1 -1
- kailash/nodes/monitoring/__init__.py +11 -1
- kailash/nodes/monitoring/health_check.py +456 -0
- kailash/nodes/monitoring/log_processor.py +817 -0
- kailash/nodes/monitoring/metrics_collector.py +627 -0
- kailash/nodes/monitoring/performance_benchmark.py +137 -11
- kailash/nodes/rag/advanced.py +7 -7
- kailash/nodes/rag/agentic.py +49 -2
- kailash/nodes/rag/conversational.py +3 -3
- kailash/nodes/rag/evaluation.py +3 -3
- kailash/nodes/rag/federated.py +3 -3
- kailash/nodes/rag/graph.py +3 -3
- kailash/nodes/rag/multimodal.py +3 -3
- kailash/nodes/rag/optimized.py +5 -5
- kailash/nodes/rag/privacy.py +3 -3
- kailash/nodes/rag/query_processing.py +6 -6
- kailash/nodes/rag/realtime.py +1 -1
- kailash/nodes/rag/registry.py +1 -1
- kailash/nodes/rag/router.py +1 -1
- kailash/nodes/rag/similarity.py +7 -7
- kailash/nodes/rag/strategies.py +4 -4
- kailash/nodes/security/abac_evaluator.py +6 -6
- kailash/nodes/security/behavior_analysis.py +5 -5
- kailash/nodes/security/credential_manager.py +1 -1
- kailash/nodes/security/rotating_credentials.py +11 -11
- kailash/nodes/security/threat_detection.py +8 -8
- kailash/nodes/testing/credential_testing.py +2 -2
- kailash/nodes/transform/processors.py +5 -5
- kailash/runtime/local.py +163 -9
- kailash/runtime/parameter_injection.py +425 -0
- kailash/runtime/parameter_injector.py +657 -0
- kailash/runtime/testing.py +2 -2
- kailash/testing/fixtures.py +2 -2
- kailash/workflow/builder.py +99 -14
- kailash/workflow/builder_improvements.py +207 -0
- kailash/workflow/input_handling.py +170 -0
- {kailash-0.6.3.dist-info → kailash-0.6.5.dist-info}/METADATA +22 -9
- {kailash-0.6.3.dist-info → kailash-0.6.5.dist-info}/RECORD +122 -95
- {kailash-0.6.3.dist-info → kailash-0.6.5.dist-info}/WHEEL +0 -0
- {kailash-0.6.3.dist-info → kailash-0.6.5.dist-info}/entry_points.txt +0 -0
- {kailash-0.6.3.dist-info → kailash-0.6.5.dist-info}/licenses/LICENSE +0 -0
- {kailash-0.6.3.dist-info → kailash-0.6.5.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,425 @@
|
|
1
|
+
"""Parameter injection framework for enterprise nodes.
|
2
|
+
|
3
|
+
This module provides a framework for handling runtime parameter injection
|
4
|
+
in enterprise nodes that traditionally require initialization-time configuration.
|
5
|
+
It bridges the gap between static configuration and dynamic workflow parameters.
|
6
|
+
"""
|
7
|
+
|
8
|
+
import logging
|
9
|
+
from abc import ABC, abstractmethod
|
10
|
+
from typing import Any, Dict, Optional, Union
|
11
|
+
|
12
|
+
logger = logging.getLogger(__name__)
|
13
|
+
|
14
|
+
|
15
|
+
class ParameterInjectionMixin:
|
16
|
+
"""Mixin to add parameter injection capabilities to nodes.
|
17
|
+
|
18
|
+
This mixin allows nodes to defer configuration until runtime,
|
19
|
+
enabling workflow-level parameter injection for connection parameters.
|
20
|
+
"""
|
21
|
+
|
22
|
+
def __init__(self, *args, **kwargs):
|
23
|
+
"""Initialize with deferred configuration support."""
|
24
|
+
# Store original kwargs for deferred initialization
|
25
|
+
self._deferred_config = kwargs.copy()
|
26
|
+
self._is_initialized = False
|
27
|
+
self._runtime_config = {}
|
28
|
+
super().__init__(*args, **kwargs)
|
29
|
+
|
30
|
+
def set_runtime_parameters(self, **runtime_params: Any) -> None:
|
31
|
+
"""Set runtime parameters for deferred initialization.
|
32
|
+
|
33
|
+
Args:
|
34
|
+
**runtime_params: Runtime parameters to use for configuration
|
35
|
+
"""
|
36
|
+
self._runtime_config.update(runtime_params)
|
37
|
+
logger.debug(
|
38
|
+
f"Set runtime parameters for {self.__class__.__name__}: {list(runtime_params.keys())}"
|
39
|
+
)
|
40
|
+
|
41
|
+
def get_effective_config(self) -> Dict[str, Any]:
|
42
|
+
"""Get effective configuration combining init-time and runtime parameters.
|
43
|
+
|
44
|
+
Returns:
|
45
|
+
Combined configuration with runtime parameters taking precedence
|
46
|
+
"""
|
47
|
+
effective_config = self._deferred_config.copy()
|
48
|
+
effective_config.update(self._runtime_config)
|
49
|
+
return effective_config
|
50
|
+
|
51
|
+
def initialize_with_runtime_config(self) -> None:
|
52
|
+
"""Initialize the node with runtime configuration.
|
53
|
+
|
54
|
+
Should be called by subclasses when they need to set up connections
|
55
|
+
or other resources that depend on runtime parameters.
|
56
|
+
"""
|
57
|
+
if not self._is_initialized:
|
58
|
+
self._perform_initialization(self.get_effective_config())
|
59
|
+
self._is_initialized = True
|
60
|
+
|
61
|
+
@abstractmethod
|
62
|
+
def _perform_initialization(self, config: Dict[str, Any]) -> None:
|
63
|
+
"""Perform actual initialization with effective configuration.
|
64
|
+
|
65
|
+
Args:
|
66
|
+
config: Combined configuration to use for initialization
|
67
|
+
"""
|
68
|
+
pass
|
69
|
+
|
70
|
+
def validate_inputs(self, **kwargs) -> Dict[str, Any]:
|
71
|
+
"""Override to inject runtime parameters before validation."""
|
72
|
+
# Extract connection parameters from runtime inputs
|
73
|
+
connection_params = self._extract_connection_params(kwargs)
|
74
|
+
if connection_params:
|
75
|
+
self.set_runtime_parameters(**connection_params)
|
76
|
+
|
77
|
+
# Initialize if we have new runtime parameters
|
78
|
+
if connection_params and not self._is_initialized:
|
79
|
+
self.initialize_with_runtime_config()
|
80
|
+
|
81
|
+
return super().validate_inputs(**kwargs)
|
82
|
+
|
83
|
+
def _extract_connection_params(self, inputs: Dict[str, Any]) -> Dict[str, Any]:
|
84
|
+
"""Extract connection-related parameters from runtime inputs.
|
85
|
+
|
86
|
+
Args:
|
87
|
+
inputs: Runtime input parameters
|
88
|
+
|
89
|
+
Returns:
|
90
|
+
Dictionary of connection parameters
|
91
|
+
"""
|
92
|
+
# Define connection parameter patterns
|
93
|
+
connection_param_patterns = [
|
94
|
+
"host",
|
95
|
+
"port",
|
96
|
+
"database",
|
97
|
+
"user",
|
98
|
+
"password",
|
99
|
+
"connection_string",
|
100
|
+
"token_url",
|
101
|
+
"client_id",
|
102
|
+
"client_secret",
|
103
|
+
"auth_url",
|
104
|
+
"api_key",
|
105
|
+
"database_type",
|
106
|
+
"grant_type",
|
107
|
+
"scope",
|
108
|
+
"username",
|
109
|
+
]
|
110
|
+
|
111
|
+
connection_params = {}
|
112
|
+
for key, value in inputs.items():
|
113
|
+
if key in connection_param_patterns:
|
114
|
+
connection_params[key] = value
|
115
|
+
|
116
|
+
return connection_params
|
117
|
+
|
118
|
+
|
119
|
+
class ConfigurableOAuth2Node:
|
120
|
+
"""OAuth2Node with runtime parameter injection support.
|
121
|
+
|
122
|
+
This class extends OAuth2Node to support runtime configuration of
|
123
|
+
connection parameters through workflow parameter injection.
|
124
|
+
"""
|
125
|
+
|
126
|
+
def __init__(self, **kwargs):
|
127
|
+
"""Initialize with deferred OAuth configuration."""
|
128
|
+
from kailash.nodes.base import Node, NodeMetadata
|
129
|
+
|
130
|
+
# Store configuration
|
131
|
+
self._deferred_config = kwargs.copy()
|
132
|
+
self._runtime_config = {}
|
133
|
+
self._is_initialized = False
|
134
|
+
self._oauth_node = None
|
135
|
+
|
136
|
+
# Initialize metadata
|
137
|
+
if "metadata" not in kwargs:
|
138
|
+
kwargs["metadata"] = NodeMetadata(
|
139
|
+
id=kwargs.get("name", "configurable_oauth2").replace(" ", "_").lower(),
|
140
|
+
name=kwargs.get("name", "ConfigurableOAuth2Node"),
|
141
|
+
description="OAuth2 node with runtime parameter injection",
|
142
|
+
tags={"auth", "oauth2", "configurable"},
|
143
|
+
version="1.0.0",
|
144
|
+
)
|
145
|
+
|
146
|
+
# Store metadata for later use
|
147
|
+
self.metadata = kwargs["metadata"]
|
148
|
+
|
149
|
+
def _perform_initialization(self, config: Dict[str, Any]) -> None:
|
150
|
+
"""Initialize OAuth2Node with runtime configuration."""
|
151
|
+
from kailash.nodes.api.auth import OAuth2Node
|
152
|
+
|
153
|
+
# Filter out non-OAuth parameters
|
154
|
+
oauth_config = {}
|
155
|
+
oauth_params = [
|
156
|
+
"token_url",
|
157
|
+
"client_id",
|
158
|
+
"client_secret",
|
159
|
+
"grant_type",
|
160
|
+
"scope",
|
161
|
+
"username",
|
162
|
+
"password",
|
163
|
+
"refresh_token",
|
164
|
+
]
|
165
|
+
|
166
|
+
for param in oauth_params:
|
167
|
+
if param in config:
|
168
|
+
oauth_config[param] = config[param]
|
169
|
+
|
170
|
+
# Create the actual OAuth2Node
|
171
|
+
self._oauth_node = OAuth2Node(**oauth_config)
|
172
|
+
logger.info(
|
173
|
+
f"Initialized OAuth2Node with runtime config: {list(oauth_config.keys())}"
|
174
|
+
)
|
175
|
+
|
176
|
+
def get_parameters(self):
|
177
|
+
"""Get parameters from the underlying OAuth2Node or default set."""
|
178
|
+
if self._oauth_node:
|
179
|
+
return self._oauth_node.get_parameters()
|
180
|
+
else:
|
181
|
+
# Return default OAuth2 parameters for workflow building
|
182
|
+
from kailash.nodes.base import NodeParameter
|
183
|
+
|
184
|
+
return {
|
185
|
+
"token_url": NodeParameter(
|
186
|
+
name="token_url",
|
187
|
+
type=str,
|
188
|
+
required=True,
|
189
|
+
description="OAuth token endpoint URL",
|
190
|
+
),
|
191
|
+
"client_id": NodeParameter(
|
192
|
+
name="client_id",
|
193
|
+
type=str,
|
194
|
+
required=True,
|
195
|
+
description="OAuth client ID",
|
196
|
+
),
|
197
|
+
"client_secret": NodeParameter(
|
198
|
+
name="client_secret",
|
199
|
+
type=str,
|
200
|
+
required=False,
|
201
|
+
description="OAuth client secret",
|
202
|
+
),
|
203
|
+
"grant_type": NodeParameter(
|
204
|
+
name="grant_type",
|
205
|
+
type=str,
|
206
|
+
required=False,
|
207
|
+
default="client_credentials",
|
208
|
+
description="OAuth grant type",
|
209
|
+
),
|
210
|
+
}
|
211
|
+
|
212
|
+
def run(self, **kwargs):
|
213
|
+
"""Execute OAuth2 authentication with runtime configuration."""
|
214
|
+
# Ensure initialization with current parameters
|
215
|
+
if not self._is_initialized:
|
216
|
+
self.set_runtime_parameters(**kwargs)
|
217
|
+
self.initialize_with_runtime_config()
|
218
|
+
|
219
|
+
if not self._oauth_node:
|
220
|
+
raise RuntimeError(
|
221
|
+
"OAuth2Node not initialized - missing connection parameters"
|
222
|
+
)
|
223
|
+
|
224
|
+
# Delegate to the initialized OAuth2Node
|
225
|
+
return self._oauth_node.execute(**kwargs)
|
226
|
+
|
227
|
+
|
228
|
+
class ConfigurableAsyncSQLNode(ParameterInjectionMixin):
|
229
|
+
"""AsyncSQLDatabaseNode with runtime parameter injection support.
|
230
|
+
|
231
|
+
This class extends AsyncSQLDatabaseNode to support runtime configuration
|
232
|
+
of database connection parameters through workflow parameter injection.
|
233
|
+
"""
|
234
|
+
|
235
|
+
def __init__(self, **kwargs):
|
236
|
+
"""Initialize with deferred database configuration."""
|
237
|
+
from kailash.nodes.data.async_sql import AsyncSQLDatabaseNode
|
238
|
+
|
239
|
+
# Don't initialize AsyncSQLDatabaseNode yet - defer until runtime
|
240
|
+
self._sql_node = None
|
241
|
+
super().__init__(**kwargs)
|
242
|
+
|
243
|
+
def _perform_initialization(self, config: Dict[str, Any]) -> None:
|
244
|
+
"""Initialize AsyncSQLDatabaseNode with runtime configuration."""
|
245
|
+
from kailash.nodes.data.async_sql import AsyncSQLDatabaseNode
|
246
|
+
|
247
|
+
# Filter out non-SQL parameters
|
248
|
+
sql_config = {}
|
249
|
+
sql_params = [
|
250
|
+
"database_type",
|
251
|
+
"connection_string",
|
252
|
+
"host",
|
253
|
+
"port",
|
254
|
+
"database",
|
255
|
+
"user",
|
256
|
+
"password",
|
257
|
+
"pool_size",
|
258
|
+
"max_pool_size",
|
259
|
+
"timeout",
|
260
|
+
]
|
261
|
+
|
262
|
+
for param in sql_params:
|
263
|
+
if param in config:
|
264
|
+
sql_config[param] = config[param]
|
265
|
+
|
266
|
+
# Add any query parameters
|
267
|
+
if "query" in config:
|
268
|
+
sql_config["query"] = config["query"]
|
269
|
+
if "params" in config:
|
270
|
+
sql_config["params"] = config["params"]
|
271
|
+
if "fetch_mode" in config:
|
272
|
+
sql_config["fetch_mode"] = config["fetch_mode"]
|
273
|
+
|
274
|
+
# Create the actual AsyncSQLDatabaseNode
|
275
|
+
self._sql_node = AsyncSQLDatabaseNode(**sql_config)
|
276
|
+
logger.info(
|
277
|
+
f"Initialized AsyncSQLDatabaseNode with runtime config: {list(sql_config.keys())}"
|
278
|
+
)
|
279
|
+
|
280
|
+
def get_parameters(self):
|
281
|
+
"""Get parameters from the underlying AsyncSQLDatabaseNode or default set."""
|
282
|
+
if self._sql_node:
|
283
|
+
return self._sql_node.get_parameters()
|
284
|
+
else:
|
285
|
+
# Return default SQL parameters for workflow building
|
286
|
+
from kailash.nodes.base import NodeParameter
|
287
|
+
|
288
|
+
return {
|
289
|
+
"database_type": NodeParameter(
|
290
|
+
name="database_type",
|
291
|
+
type=str,
|
292
|
+
required=True,
|
293
|
+
default="postgresql",
|
294
|
+
description="Type of database",
|
295
|
+
),
|
296
|
+
"host": NodeParameter(
|
297
|
+
name="host", type=str, required=False, description="Database host"
|
298
|
+
),
|
299
|
+
"database": NodeParameter(
|
300
|
+
name="database",
|
301
|
+
type=str,
|
302
|
+
required=False,
|
303
|
+
description="Database name",
|
304
|
+
),
|
305
|
+
"user": NodeParameter(
|
306
|
+
name="user", type=str, required=False, description="Database user"
|
307
|
+
),
|
308
|
+
"password": NodeParameter(
|
309
|
+
name="password",
|
310
|
+
type=str,
|
311
|
+
required=False,
|
312
|
+
description="Database password",
|
313
|
+
),
|
314
|
+
"query": NodeParameter(
|
315
|
+
name="query",
|
316
|
+
type=str,
|
317
|
+
required=True,
|
318
|
+
description="SQL query to execute",
|
319
|
+
),
|
320
|
+
}
|
321
|
+
|
322
|
+
async def async_run(self, **kwargs):
|
323
|
+
"""Execute SQL query with runtime configuration."""
|
324
|
+
# Ensure initialization with current parameters
|
325
|
+
if not self._is_initialized:
|
326
|
+
self.set_runtime_parameters(**kwargs)
|
327
|
+
self.initialize_with_runtime_config()
|
328
|
+
|
329
|
+
if not self._sql_node:
|
330
|
+
raise RuntimeError(
|
331
|
+
"AsyncSQLDatabaseNode not initialized - missing connection parameters"
|
332
|
+
)
|
333
|
+
|
334
|
+
# Delegate to the initialized AsyncSQLDatabaseNode
|
335
|
+
return await self._sql_node.async_run(**kwargs)
|
336
|
+
|
337
|
+
def run(self, **kwargs):
|
338
|
+
"""Synchronous wrapper for async_run."""
|
339
|
+
import asyncio
|
340
|
+
|
341
|
+
return asyncio.run(self.async_run(**kwargs))
|
342
|
+
|
343
|
+
|
344
|
+
class EnterpriseNodeFactory:
|
345
|
+
"""Factory for creating enterprise nodes with parameter injection support."""
|
346
|
+
|
347
|
+
@staticmethod
|
348
|
+
def create_oauth2_node(**kwargs) -> ConfigurableOAuth2Node:
|
349
|
+
"""Create an OAuth2Node with runtime parameter injection support.
|
350
|
+
|
351
|
+
Args:
|
352
|
+
**kwargs: Initial configuration parameters
|
353
|
+
|
354
|
+
Returns:
|
355
|
+
ConfigurableOAuth2Node instance
|
356
|
+
"""
|
357
|
+
return ConfigurableOAuth2Node(**kwargs)
|
358
|
+
|
359
|
+
@staticmethod
|
360
|
+
def create_async_sql_node(**kwargs) -> ConfigurableAsyncSQLNode:
|
361
|
+
"""Create an AsyncSQLDatabaseNode with runtime parameter injection support.
|
362
|
+
|
363
|
+
Args:
|
364
|
+
**kwargs: Initial configuration parameters
|
365
|
+
|
366
|
+
Returns:
|
367
|
+
ConfigurableAsyncSQLNode instance
|
368
|
+
"""
|
369
|
+
return ConfigurableAsyncSQLNode(**kwargs)
|
370
|
+
|
371
|
+
@staticmethod
|
372
|
+
def wrap_enterprise_node(node_class, **kwargs):
|
373
|
+
"""Wrap any enterprise node class with parameter injection support.
|
374
|
+
|
375
|
+
Args:
|
376
|
+
node_class: The enterprise node class to wrap
|
377
|
+
**kwargs: Initial configuration parameters
|
378
|
+
|
379
|
+
Returns:
|
380
|
+
Wrapped node instance with parameter injection support
|
381
|
+
"""
|
382
|
+
|
383
|
+
# Create a dynamic wrapper class
|
384
|
+
class WrappedEnterpriseNode(ParameterInjectionMixin):
|
385
|
+
def __init__(self, **init_kwargs):
|
386
|
+
self._wrapped_node = None
|
387
|
+
self._node_class = node_class
|
388
|
+
super().__init__(**init_kwargs)
|
389
|
+
|
390
|
+
def _perform_initialization(self, config):
|
391
|
+
self._wrapped_node = self._node_class(**config)
|
392
|
+
|
393
|
+
def get_parameters(self):
|
394
|
+
if self._wrapped_node:
|
395
|
+
return self._wrapped_node.get_parameters()
|
396
|
+
else:
|
397
|
+
# Try to get parameters from class if possible
|
398
|
+
try:
|
399
|
+
temp_node = self._node_class()
|
400
|
+
return temp_node.get_parameters()
|
401
|
+
except:
|
402
|
+
return {}
|
403
|
+
|
404
|
+
def run(self, **run_kwargs):
|
405
|
+
if not self._is_initialized:
|
406
|
+
self.set_runtime_parameters(**run_kwargs)
|
407
|
+
self.initialize_with_runtime_config()
|
408
|
+
|
409
|
+
if not self._wrapped_node:
|
410
|
+
raise RuntimeError(f"{self._node_class.__name__} not initialized")
|
411
|
+
|
412
|
+
return self._wrapped_node.execute(**run_kwargs)
|
413
|
+
|
414
|
+
return WrappedEnterpriseNode(**kwargs)
|
415
|
+
|
416
|
+
|
417
|
+
# Convenience functions for workflow builders
|
418
|
+
def create_configurable_oauth2(**kwargs) -> ConfigurableOAuth2Node:
|
419
|
+
"""Convenience function to create a configurable OAuth2 node."""
|
420
|
+
return EnterpriseNodeFactory.create_oauth2_node(**kwargs)
|
421
|
+
|
422
|
+
|
423
|
+
def create_configurable_sql(**kwargs) -> ConfigurableAsyncSQLNode:
|
424
|
+
"""Convenience function to create a configurable SQL node."""
|
425
|
+
return EnterpriseNodeFactory.create_async_sql_node(**kwargs)
|