cwyodmodules 0.3.77__py3-none-any.whl → 0.3.79__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.
@@ -1,258 +1,423 @@
1
- """
2
- Azure Project Management Configuration Template
1
+ """Azure Project Management Configuration Template.
2
+
3
+ This module provides standardized configuration for Azure logging, identity management,
4
+ and Key Vault access across projects. It creates singleton instances that can be
5
+ imported and used throughout your application.
3
6
 
4
- This template provides standardized configuration for Azure logging and identity
5
- management across projects. It creates singleton instances of AzureLogger and
6
- AzureIdentity that can be imported and used throughout your application.
7
+ The configuration is driven by environment variables with sensible defaults, allowing
8
+ for flexible deployment across different environments (local development, staging,
9
+ production) without code changes.
10
+
11
+ Features:
12
+ - Automatic service detection (app vs function app)
13
+ - Configurable logging with Application Insights integration
14
+ - Azure identity management with token caching
15
+ - Key Vault integration for secrets, keys, and certificates
16
+ - Docker environment detection
17
+ - Local development environment setup
7
18
 
8
19
  Usage:
9
- from mgmt_config import logger, identity
20
+ Basic usage::
21
+
22
+ from mgmt_config import logger, identity
23
+
24
+ logger.info("Application started")
25
+ credential = identity.get_credential()
26
+
27
+ With Key Vault::
28
+
29
+ from mgmt_config import keyvault
30
+
31
+ if keyvault:
32
+ secret_value = keyvault.get_secret("my-secret")
33
+
34
+ Environment Variables:
35
+ Service Configuration:
36
+ REFLECTION_NAME: Service name for identification
37
+ REFLECTION_KIND: Service type (app, functionapp, etc.)
38
+ SERVICE_VERSION: Version of the service (default: "1.0.0")
39
+
40
+ Logging Configuration:
41
+ LOGGER_ENABLE_CONSOLE: Enable console logging (default: "true")
42
+ APPLICATIONINSIGHTS_CONNECTION_STRING: App Insights connection string
10
43
 
11
- logger.info("Application started")
12
- credential = identity.get_credential()
44
+ Identity Configuration:
45
+ IDENTITY_ENABLE_TOKEN_CACHE: Enable token caching (default: "true")
46
+ IDENTITY_ALLOW_UNENCRYPTED_STORAGE: Allow unencrypted token storage (default: "true")
47
+
48
+ Key Vault Configuration:
49
+ key_vault_uri: Primary Key Vault URL
50
+ head_key_vault_uri: Secondary Key Vault URL
51
+ KEYVAULT_ENABLE_SECRETS: Enable secrets client (default: "true")
52
+ KEYVAULT_ENABLE_KEYS: Enable keys client (default: "false")
53
+ KEYVAULT_ENABLE_CERTIFICATES: Enable certificates client (default: "false")
54
+
55
+ Examples:
56
+ Local Development:
57
+ Set REFLECTION_NAME and ensure .env file exists for local settings.
58
+
59
+ Azure Function App:
60
+ Set REFLECTION_KIND="functionapp" and REFLECTION_NAME to your function app name.
61
+
62
+ Web Application:
63
+ Set REFLECTION_KIND="app" (or leave default) and configure App Insights.
13
64
  """
14
65
 
15
66
  import os
16
- from typing import Optional, Dict, Any
17
- from azpaddypy.mgmt.logging import create_app_logger, create_function_logger
67
+ from typing import Any, Dict, Optional
68
+
18
69
  from azpaddypy.mgmt.identity import create_azure_identity
19
- from azpaddypy.resources.keyvault import create_azure_keyvault
20
70
  from azpaddypy.mgmt.local_env_manager import create_local_env_manager
71
+ from azpaddypy.mgmt.logging import create_app_logger, create_function_logger
72
+ from azpaddypy.resources.keyvault import create_azure_keyvault
21
73
 
22
- # Alias for import in other packages
23
74
 
24
75
  # =============================================================================
25
- # SERVICE CONFIGURATION
76
+ # DOCKER ENVIRONMENT DETECTION
26
77
  # =============================================================================
27
78
 
28
- # Service identity - customize these for your project
29
- REFLECTION_NAME = os.getenv("REFLECTION_NAME")
30
- REFLECTION_KIND = os.getenv("REFLECTION_KIND")
31
- SERVICE_NAME = REFLECTION_NAME or str(__name__)
32
- SERVICE_VERSION = os.getenv("SERVICE_VERSION", "1.0.0")
79
+ def is_running_in_docker() -> bool:
80
+ """Check if the current process is running inside a Docker container.
33
81
 
34
- def is_running_in_docker():
35
- """
36
- Checks if the current process is running inside a Docker container.
82
+ This function uses multiple detection methods to reliably identify
83
+ Docker environments across different container runtimes and orchestrators.
37
84
 
38
85
  Returns:
39
- bool: True if running in Docker, False otherwise.
86
+ True if running in Docker/container, False otherwise.
87
+
88
+ Detection Methods:
89
+ 1. Check for /.dockerenv file (standard Docker indicator)
90
+ 2. Check /proc/1/cgroup for container-specific entries
91
+ 3. Handles various container runtimes (Docker, Kubernetes, etc.)
40
92
  """
41
- # Method 1: Check for /.dockerenv file
93
+ # Method 1: Check for Docker environment file
42
94
  if os.path.exists('/.dockerenv'):
43
95
  return True
44
96
 
45
- # Method 2: Check cgroup for "docker"
97
+ # Method 2: Check process control groups for container indicators
46
98
  try:
47
- with open('/proc/1/cgroup', 'rt') as f:
99
+ with open('/proc/1/cgroup', 'rt', encoding='utf-8') as f:
48
100
  cgroup_content = f.read()
49
- if 'docker' in cgroup_content or 'kubepods' in cgroup_content:
50
- return True
51
- except FileNotFoundError:
52
- # /proc/1/cgroup does not exist, not a Linux-like environment
53
- pass
54
- except Exception:
55
- # Handle other potential exceptions, e.g., permissions
101
+ return any(indicator in cgroup_content
102
+ for indicator in ['docker', 'kubepods', 'containerd'])
103
+ except (FileNotFoundError, PermissionError, OSError):
104
+ # /proc filesystem not available or accessible (e.g., Windows, macOS)
56
105
  pass
57
106
 
58
107
  return False
59
108
 
60
- running_in_docker = is_running_in_docker()
61
- print("is_running_in_docker: " + str(running_in_docker))
62
109
 
110
+ RUNNING_IN_DOCKER = is_running_in_docker()
111
+ print(f"is_running_in_docker: {RUNNING_IN_DOCKER}")
63
112
 
64
113
  # =============================================================================
65
- # LOGGING CONFIGURATION
114
+ # LOCAL DEVELOPMENT CONFIGURATION
66
115
  # =============================================================================
67
116
 
68
- # Enable console output (useful for local development)
69
- LOGGER_ENABLE_CONSOLE = os.getenv("LOGGER_ENABLE_CONSOLE", "true").lower() == "true"
117
+ def _get_local_settings() -> Dict[str, str]:
118
+ """Get local development settings based on environment.
119
+
120
+ Returns:
121
+ Dictionary of local development settings appropriate for the environment.
122
+
123
+ Note:
124
+ Docker environments get Azure service principal settings,
125
+ while local environments get Azure Storage Emulator settings.
126
+ """
127
+ if RUNNING_IN_DOCKER:
128
+ return {
129
+ "AZURE_CLIENT_ID": "aa73da4a-2888-4cb7-896e-5d51125f11f0",
130
+ "AZURE_TENANT_ID": "e5590d5d-336c-4cf5-b0ac-b79a598ec797",
131
+ "AZURE_CLIENT_SECRET": "IQ08Q~4uCfc4B~p2F95D2737GzYvvrtIjursFbCf"
132
+ }
133
+ else:
134
+ return {
135
+ "AzureWebJobsStorage": "UseDevelopmentStorage=true",
136
+ "AzureWebJobsDashboard": "UseDevelopmentStorage=true",
137
+ "input_queue_connection__queueServiceUri": "UseDevelopmentStorage=true",
138
+ "AzureWebJobsStorage__accountName": "UseDevelopmentStorage=true",
139
+ "AzureWebJobsStorage__blobServiceUri": "UseDevelopmentStorage=true",
140
+ "AZURE_CLIENT_ID": "aa73da4a-2888-4cb7-896e-5d51125f11f0",
141
+ "AZURE_TENANT_ID": "e5590d5d-336c-4cf5-b0ac-b79a598ec797",
142
+ "AZURE_CLIENT_SECRET": "IQ08Q~4uCfc4B~p2F95D2737GzYvvrtIjursFbCf"
143
+ }
144
+
145
+ # Initialize local environment manager
146
+ local_env_manager = create_local_env_manager(
147
+ file_path=".env",
148
+ settings=_get_local_settings(),
149
+ override_json=True,
150
+ override_dotenv=True,
151
+ override_settings=True,
152
+ )
70
153
 
71
- # Application Insights connection string (optional, will use environment variable if not set)
72
- LOGGER_CONNECTION_STRING = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING")
154
+ # =============================================================================
155
+ # SERVICE CONFIGURATION
156
+ # =============================================================================
157
+
158
+ def _get_service_configuration() -> tuple[str, str, str]:
159
+ """Get service configuration from environment variables.
160
+
161
+ Returns:
162
+ A tuple containing (service_name, service_version, service_kind).
163
+
164
+ Note:
165
+ REFLECTION_KIND has commas replaced with hyphens for compatibility.
166
+ """
167
+ reflection_name = os.getenv("REFLECTION_NAME")
168
+ reflection_kind = os.getenv("REFLECTION_KIND", "").replace(",", "-")
169
+ service_name = reflection_name or str(__name__)
170
+ service_version = os.getenv("SERVICE_VERSION", "1.0.0")
171
+
172
+ return service_name, service_version, reflection_kind
73
173
 
74
- # Local development settings
75
- if running_in_docker:
76
- LOCAL_SETTINGS = {
77
- "AZURE_CLIENT_ID": "aa73da4a-2888-4cb7-896e-5d51125f11f0",
78
- "AZURE_TENANT_ID": "e5590d5d-336c-4cf5-b0ac-b79a598ec797",
79
- "AZURE_CLIENT_SECRET": "IQ08Q~4uCfc4B~p2F95D2737GzYvvrtIjursFbCf"
80
- }
81
- else:
82
- LOCAL_SETTINGS = {
83
- "AzureWebJobsStorage": "UseDevelopmentStorage=true",
84
- "AzureWebJobsDashboard": "UseDevelopmentStorage=true",
85
- "input_queue_connection__queueServiceUri": "UseDevelopmentStorage=true",
86
- "AzureWebJobsStorage__accountName": "UseDevelopmentStorage=true",
87
- "AzureWebJobsStorage__blobServiceUri": "UseDevelopmentStorage=true",
88
- }
89
174
 
90
- # Configure which Azure SDK components to instrument
91
- LOGGER_INSTRUMENTATION_OPTIONS = {
92
- "azure_sdk": {"enabled": True},
93
- "django": {"enabled": False},
94
- "fastapi": {"enabled": False},
95
- "flask": {"enabled": True},
96
- "psycopg2": {"enabled": True},
97
- "requests": {"enabled": True},
98
- "urllib": {"enabled": True},
99
- "urllib3": {"enabled": True},
100
- }
175
+ SERVICE_NAME, SERVICE_VERSION, REFLECTION_KIND = _get_service_configuration()
101
176
 
102
177
  # =============================================================================
103
- # IDENTITY CONFIGURATION
178
+ # LOGGING CONFIGURATION
104
179
  # =============================================================================
105
180
 
106
- # Token caching settings
107
- IDENTITY_ENABLE_TOKEN_CACHE = os.getenv("IDENTITY_ENABLE_TOKEN_CACHE", "true").lower() == "true"
108
- IDENTITY_ALLOW_UNENCRYPTED_STORAGE = os.getenv("IDENTITY_ALLOW_UNENCRYPTED_STORAGE", "true").lower() == "true"
181
+ def _get_logging_configuration() -> tuple[bool, Optional[str], Dict[str, Dict[str, bool]]]:
182
+ """Get logging configuration from environment variables.
183
+
184
+ Returns:
185
+ A tuple containing (console_enabled, connection_string, instrumentation_options).
186
+ """
187
+ console_enabled = os.getenv("LOGGER_ENABLE_CONSOLE", "true").lower() == "true"
188
+ connection_string = os.getenv("APPLICATIONINSIGHTS_CONNECTION_STRING")
189
+ log_level = os.getenv("LOGGER_LOG_LEVEL", "INFO")
190
+ enable_console_logging = os.getenv("LOGGER_ENABLE_CONSOLE", "true").lower() == "true"
191
+
192
+ instrumentation_options = {
193
+ "azure_sdk": {"enabled": True},
194
+ "django": {"enabled": False},
195
+ "fastapi": {"enabled": False},
196
+ "flask": {"enabled": True},
197
+ "psycopg2": {"enabled": True},
198
+ "requests": {"enabled": True},
199
+ "urllib": {"enabled": True},
200
+ "urllib3": {"enabled": True},
201
+ }
202
+
203
+ return console_enabled, connection_string, instrumentation_options, log_level
109
204
 
110
- # Custom credential options (None means use defaults)
111
- IDENTITY_CUSTOM_CREDENTIAL_OPTIONS: Optional[Dict[str, Any]] = None
112
205
 
113
- # Connection string for identity logging (uses same as logger by default)
114
- IDENTITY_CONNECTION_STRING = LOGGER_CONNECTION_STRING
206
+ LOGGER_ENABLE_CONSOLE, LOGGER_CONNECTION_STRING, LOGGER_INSTRUMENTATION_OPTIONS, LOGGER_LOG_LEVEL = _get_logging_configuration()
115
207
 
116
208
  # =============================================================================
117
- # KEYVAULT CONFIGURATION
209
+ # IDENTITY CONFIGURATION
118
210
  # =============================================================================
119
211
 
120
- # Enable specific Key Vault client types
121
- KEYVAULT_ENABLE_SECRETS = os.getenv("KEYVAULT_ENABLE_SECRETS", "true").lower() == "true"
122
- KEYVAULT_ENABLE_KEYS = os.getenv("KEYVAULT_ENABLE_KEYS", "false").lower() == "true"
123
- KEYVAULT_ENABLE_CERTIFICATES = os.getenv("KEYVAULT_ENABLE_CERTIFICATES", "false").lower() == "true"
212
+ def _get_identity_configuration() -> tuple[bool, bool, Optional[Dict[str, Any]], Optional[str]]:
213
+ """Get identity configuration from environment variables.
214
+
215
+ Returns:
216
+ A tuple containing (token_cache_enabled, unencrypted_storage_allowed,
217
+ custom_options, connection_string).
218
+ """
219
+ token_cache_enabled = os.getenv("IDENTITY_ENABLE_TOKEN_CACHE", "true").lower() == "true"
220
+ unencrypted_storage_allowed = os.getenv("IDENTITY_ALLOW_UNENCRYPTED_STORAGE", "true").lower() == "true"
221
+ custom_options = None # Reserved for future custom credential configuration
222
+ connection_string = LOGGER_CONNECTION_STRING # Share with logger by default
223
+
224
+ return token_cache_enabled, unencrypted_storage_allowed, custom_options, connection_string
124
225
 
125
- # Connection string for keyvault logging (uses same as logger by default)
126
- KEYVAULT_CONNECTION_STRING = LOGGER_CONNECTION_STRING
226
+
227
+ (IDENTITY_ENABLE_TOKEN_CACHE,
228
+ IDENTITY_ALLOW_UNENCRYPTED_STORAGE,
229
+ IDENTITY_CUSTOM_CREDENTIAL_OPTIONS,
230
+ IDENTITY_CONNECTION_STRING) = _get_identity_configuration()
127
231
 
128
232
  # =============================================================================
129
- # INITIALIZE SERVICES
233
+ # KEY VAULT CONFIGURATION
130
234
  # =============================================================================
131
235
 
132
- # Create logger instance
133
- if "functionapp" in os.getenv("REFLECTION_KIND", "app"):
134
- logger = create_function_logger(
135
- function_app_name=REFLECTION_NAME,
136
- function_name=REFLECTION_KIND,
137
- service_version=SERVICE_VERSION,
138
- connection_string=LOGGER_CONNECTION_STRING,
139
- instrumentation_options=LOGGER_INSTRUMENTATION_OPTIONS,
140
- )
141
- logger.info("Function logger: " + str(REFLECTION_KIND) + " " + str(REFLECTION_NAME) + " initialized")
142
- else:
143
- logger = create_app_logger(
144
- service_name=SERVICE_NAME,
145
- service_version=SERVICE_VERSION,
146
- connection_string=LOGGER_CONNECTION_STRING,
147
- enable_console_logging=LOGGER_ENABLE_CONSOLE,
148
- instrumentation_options=LOGGER_INSTRUMENTATION_OPTIONS,
149
- )
150
- logger.info("App logger: " + str(REFLECTION_KIND) + " " + str(REFLECTION_NAME) + " initialized")
236
+ def _get_keyvault_configuration() -> tuple[Optional[str], Optional[str], bool, bool, bool, Optional[str]]:
237
+ """Get Key Vault configuration from environment variables.
238
+
239
+ Returns:
240
+ A tuple containing (vault_url, head_vault_url, secrets_enabled,
241
+ keys_enabled, certificates_enabled, connection_string).
242
+ """
243
+ vault_url = os.getenv("key_vault_uri")
244
+ head_vault_url = os.getenv("head_key_vault_uri")
245
+ secrets_enabled = os.getenv("KEYVAULT_ENABLE_SECRETS", "true").lower() == "true"
246
+ keys_enabled = os.getenv("KEYVAULT_ENABLE_KEYS", "false").lower() == "true"
247
+ certificates_enabled = os.getenv("KEYVAULT_ENABLE_CERTIFICATES", "false").lower() == "true"
248
+ connection_string = LOGGER_CONNECTION_STRING # Share with logger by default
249
+
250
+ return vault_url, head_vault_url, secrets_enabled, keys_enabled, certificates_enabled, connection_string
151
251
 
152
- # Create local development settings instance
153
- local_env_manager = create_local_env_manager(
154
- file_path=".env",
155
- settings=LOCAL_SETTINGS,
156
- logger=logger,
157
- override_json=True,
158
- override_dotenv=True,
159
- override_settings=True,
160
- )
161
252
 
162
- # Create identity instance with shared logger
163
- identity = create_azure_identity(
164
- service_name=SERVICE_NAME,
165
- service_version=SERVICE_VERSION,
166
- enable_token_cache=IDENTITY_ENABLE_TOKEN_CACHE,
167
- allow_unencrypted_storage=IDENTITY_ALLOW_UNENCRYPTED_STORAGE,
168
- custom_credential_options=IDENTITY_CUSTOM_CREDENTIAL_OPTIONS,
169
- connection_string=IDENTITY_CONNECTION_STRING,
170
- logger=logger,
171
- )
253
+ (KEYVAULT_URL,
254
+ HEAD_KEYVAULT_URL,
255
+ KEYVAULT_ENABLE_SECRETS,
256
+ KEYVAULT_ENABLE_KEYS,
257
+ KEYVAULT_ENABLE_CERTIFICATES,
258
+ KEYVAULT_CONNECTION_STRING) = _get_keyvault_configuration()
259
+
260
+ # =============================================================================
261
+ # SERVICE INITIALIZATION
262
+ # =============================================================================
263
+
264
+ def _create_logger():
265
+ """Create and configure the appropriate logger instance.
266
+
267
+ Returns:
268
+ Configured AzureLogger instance (either app or function logger).
269
+
270
+ Note:
271
+ Logger type is determined by REFLECTION_KIND environment variable.
272
+ Function apps get specialized function loggers with additional context.
273
+ """
274
+ if "functionapp" in REFLECTION_KIND:
275
+ logger_instance = create_function_logger(
276
+ function_app_name=SERVICE_NAME,
277
+ function_name=REFLECTION_KIND,
278
+ service_version=SERVICE_VERSION,
279
+ connection_string=LOGGER_CONNECTION_STRING,
280
+ log_level=LOGGER_LOG_LEVEL,
281
+ instrumentation_options=LOGGER_INSTRUMENTATION_OPTIONS,
282
+ )
283
+ logger_instance.info(
284
+ f"Function logger initialized: {REFLECTION_KIND} {SERVICE_NAME}",
285
+ extra={"logger_type": "function", "function_name": REFLECTION_KIND}
286
+ )
287
+ else:
288
+ logger_instance = create_app_logger(
289
+ service_name=SERVICE_NAME,
290
+ service_version=SERVICE_VERSION,
291
+ connection_string=LOGGER_CONNECTION_STRING,
292
+ log_level=LOGGER_LOG_LEVEL,
293
+ enable_console_logging=LOGGER_ENABLE_CONSOLE,
294
+ instrumentation_options=LOGGER_INSTRUMENTATION_OPTIONS,
295
+ )
296
+ logger_instance.info(
297
+ f"App logger initialized: {REFLECTION_KIND} {SERVICE_NAME}",
298
+ extra={"logger_type": "app", "service_kind": REFLECTION_KIND}
299
+ )
300
+
301
+ return logger_instance
172
302
 
173
- # Azure Key Vault URL (required for Key Vault operations)
174
- KEYVAULT_URL = os.getenv("key_vault_uri")
175
- HEAD_KEYVAULT_URL = os.getenv("head_key_vault_uri")
176
303
 
177
- # Create keyvault instance with shared logger and identity (if URL is configured)
178
- keyvault = None
179
- if KEYVAULT_URL:
180
- keyvault = create_azure_keyvault(
181
- vault_url=KEYVAULT_URL,
182
- azure_identity=identity,
304
+ def _create_identity_manager(logger_instance):
305
+ """Create and configure the Azure identity manager.
306
+
307
+ Args:
308
+ logger_instance: Shared logger instance for identity operations.
309
+
310
+ Returns:
311
+ Configured AzureIdentity instance.
312
+ """
313
+ return create_azure_identity(
183
314
  service_name=SERVICE_NAME,
184
315
  service_version=SERVICE_VERSION,
185
- logger=logger,
186
- connection_string=KEYVAULT_CONNECTION_STRING,
187
- enable_secrets=KEYVAULT_ENABLE_SECRETS,
188
- enable_keys=KEYVAULT_ENABLE_KEYS,
189
- enable_certificates=KEYVAULT_ENABLE_CERTIFICATES,
316
+ enable_token_cache=IDENTITY_ENABLE_TOKEN_CACHE,
317
+ allow_unencrypted_storage=IDENTITY_ALLOW_UNENCRYPTED_STORAGE,
318
+ custom_credential_options=IDENTITY_CUSTOM_CREDENTIAL_OPTIONS,
319
+ connection_string=IDENTITY_CONNECTION_STRING,
320
+ logger=logger_instance,
190
321
  )
191
322
 
192
- head_keyvault = None
193
- if HEAD_KEYVAULT_URL:
194
- head_keyvault = create_azure_keyvault(
195
- vault_url=HEAD_KEYVAULT_URL,
196
- azure_identity=identity,
323
+
324
+ def _create_keyvault_client(vault_url: str, identity_instance, logger_instance):
325
+ """Create a Key Vault client for the specified vault.
326
+
327
+ Args:
328
+ vault_url: Azure Key Vault URL.
329
+ identity_instance: Shared identity manager.
330
+ logger_instance: Shared logger instance.
331
+
332
+ Returns:
333
+ Configured AzureKeyVault instance or None if creation fails.
334
+ """
335
+ if not vault_url:
336
+ return None
337
+
338
+ return create_azure_keyvault(
339
+ vault_url=vault_url,
340
+ azure_identity=identity_instance,
197
341
  service_name=SERVICE_NAME,
198
342
  service_version=SERVICE_VERSION,
199
- logger=logger,
343
+ logger=logger_instance,
200
344
  connection_string=KEYVAULT_CONNECTION_STRING,
201
345
  enable_secrets=KEYVAULT_ENABLE_SECRETS,
202
346
  enable_keys=KEYVAULT_ENABLE_KEYS,
203
347
  enable_certificates=KEYVAULT_ENABLE_CERTIFICATES,
204
348
  )
205
349
 
206
- # =============================================================================
207
- # VALIDATION & STARTUP
208
- # =============================================================================
209
350
 
210
- # Validate critical configuration
211
- if SERVICE_NAME == __name__:
212
- logger.warning(
213
- "SERVICE_NAME is not configured. Please set SERVICE_NAME environment variable or update this template.",
214
- extra={"configuration_issue": "service_name_not_set"}
215
- )
351
+ # Initialize core services
352
+ logger = _create_logger()
353
+ identity = _create_identity_manager(logger)
216
354
 
217
- if not LOGGER_CONNECTION_STRING:
218
- logger.info(
219
- "No Application Insights connection string configured. Telemetry will be disabled.",
220
- extra={"telemetry_status": "disabled"}
221
- )
355
+ # Initialize Key Vault clients (if URLs are configured)
356
+ keyvault = _create_keyvault_client(KEYVAULT_URL, identity, logger)
357
+ head_keyvault = _create_keyvault_client(HEAD_KEYVAULT_URL, identity, logger)
222
358
 
223
- if not KEYVAULT_URL:
224
- logger.info(
225
- "No Key Vault URL configured. Key Vault operations will be disabled.",
226
- extra={"keyvault_status": "disabled"}
227
- )
359
+ # =============================================================================
360
+ # CONFIGURATION VALIDATION & STARTUP LOGGING
361
+ # =============================================================================
228
362
 
229
- if not HEAD_KEYVAULT_URL:
363
+ def _validate_and_log_configuration():
364
+ """Validate configuration and log startup information.
365
+
366
+ This function performs validation checks and logs important configuration
367
+ status information for debugging and monitoring purposes.
368
+ """
369
+ # Validate critical configuration
370
+ if SERVICE_NAME == __name__:
371
+ logger.warning(
372
+ "SERVICE_NAME is using module name. Consider setting REFLECTION_NAME environment variable.",
373
+ extra={"configuration_issue": "service_name_not_set", "current_name": SERVICE_NAME}
374
+ )
375
+
376
+ # Log telemetry status
377
+ if not LOGGER_CONNECTION_STRING:
378
+ logger.info(
379
+ "No Application Insights connection string configured. Telemetry will be disabled.",
380
+ extra={"telemetry_status": "disabled"}
381
+ )
382
+
383
+ # Log Key Vault status
384
+ if not KEYVAULT_URL:
385
+ logger.info(
386
+ "No Key Vault URL configured. Key Vault operations will be disabled.",
387
+ extra={"keyvault_status": "disabled"}
388
+ )
389
+
390
+ if not HEAD_KEYVAULT_URL:
391
+ logger.info(
392
+ "No Head Key Vault URL configured. Head Key Vault operations will be disabled.",
393
+ extra={"head_keyvault_status": "disabled"}
394
+ )
395
+
396
+ # Log successful initialization with comprehensive metadata
230
397
  logger.info(
231
- "No Head Key Vault URL configured. Head Key Vault operations will be disabled.",
232
- extra={"head_keyvault_status": "disabled"}
398
+ f"Management configuration initialized for service '{SERVICE_NAME}' v{SERVICE_VERSION}",
399
+ extra={
400
+ "service_name": SERVICE_NAME,
401
+ "service_version": SERVICE_VERSION,
402
+ "console_logging": LOGGER_ENABLE_CONSOLE,
403
+ "token_cache_enabled": IDENTITY_ENABLE_TOKEN_CACHE,
404
+ "telemetry_enabled": bool(LOGGER_CONNECTION_STRING),
405
+ "keyvault_enabled": bool(KEYVAULT_URL),
406
+ "head_keyvault_enabled": bool(HEAD_KEYVAULT_URL),
407
+ "keyvault_secrets_enabled": KEYVAULT_ENABLE_SECRETS if KEYVAULT_URL else False,
408
+ "keyvault_keys_enabled": KEYVAULT_ENABLE_KEYS if KEYVAULT_URL else False,
409
+ "keyvault_certificates_enabled": KEYVAULT_ENABLE_CERTIFICATES if KEYVAULT_URL else False,
410
+ "running_in_docker": RUNNING_IN_DOCKER,
411
+ }
233
412
  )
234
413
 
235
- # Log successful initialization
236
- logger.info(
237
- f"Management configuration initialized for service '{SERVICE_NAME}' v{SERVICE_VERSION}",
238
- extra={
239
- "service_name": SERVICE_NAME,
240
- "service_version": SERVICE_VERSION,
241
- "console_logging": LOGGER_ENABLE_CONSOLE,
242
- "token_cache_enabled": IDENTITY_ENABLE_TOKEN_CACHE,
243
- "telemetry_enabled": bool(LOGGER_CONNECTION_STRING),
244
- "keyvault_enabled": bool(KEYVAULT_URL),
245
- "head_keyvault_enabled": bool(HEAD_KEYVAULT_URL),
246
- "keyvault_secrets_enabled": KEYVAULT_ENABLE_SECRETS if KEYVAULT_URL else False,
247
- "keyvault_keys_enabled": KEYVAULT_ENABLE_KEYS if KEYVAULT_URL else False,
248
- "keyvault_certificates_enabled": KEYVAULT_ENABLE_CERTIFICATES if KEYVAULT_URL else False,
249
- "running_in_docker": running_in_docker,
250
- }
251
- )
414
+
415
+ # Perform validation and startup logging
416
+ _validate_and_log_configuration()
252
417
 
253
418
  # =============================================================================
254
- # EXPORTS
419
+ # MODULE EXPORTS
255
420
  # =============================================================================
256
421
 
257
- # Export logger, identity, and keyvault for use in applications
422
+ # Export primary service instances for application use
258
423
  __all__ = ["logger", "local_env_manager", "identity", "keyvault", "head_keyvault"]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cwyodmodules
3
- Version: 0.3.77
3
+ Version: 0.3.79
4
4
  Summary: Add your description here
5
5
  Author-email: Patrik <patrikhartl@gmail.com>
6
6
  Classifier: Operating System :: OS Independent
@@ -40,7 +40,7 @@ Requires-Dist: azure-search-documents==11.6.0b4
40
40
  Requires-Dist: semantic-kernel==1.3.0
41
41
  Requires-Dist: pydantic==2.7.4
42
42
  Requires-Dist: pandas>=2.2.3
43
- Requires-Dist: azpaddypy>=0.5.5
43
+ Requires-Dist: azpaddypy>=0.5.7
44
44
  Dynamic: license-file
45
45
 
46
46
  # paddypy
@@ -1,5 +1,5 @@
1
1
  cwyodmodules/__init__.py,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
2
- cwyodmodules/mgmt_config.py,sha256=5dzqIQDWv9X4Rk0UYlaPxMGyXHcw38LnanFxxfAEFn4,10185
2
+ cwyodmodules/mgmt_config.py,sha256=8QtOFn_2xmuuUuJhVXHd1Q488Yh3Fe58AesLBxa0Cfg,17257
3
3
  cwyodmodules/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
4
  cwyodmodules/api/chat_history.py,sha256=bVXFmhTHIfEiHv_nBrfizO-cQRHhKgrdcZ07OD1b0Tw,20683
5
5
  cwyodmodules/batch/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -109,8 +109,8 @@ cwyodmodules/graphrag/query/generate.py,sha256=BZiB6iw7PkIovw-CyYFogMHnDxK0Qu_4u
109
109
  cwyodmodules/graphrag/query/graph_search.py,sha256=95h3ecSWx4864XgKABtG0fh3Nk8HkqJVzoCrO8daJ-Y,7724
110
110
  cwyodmodules/graphrag/query/types.py,sha256=1Iq1dp4I4a56_cuFjOZ0NTgd0A2_MpVFznp_czgt6cI,617
111
111
  cwyodmodules/graphrag/query/vector_search.py,sha256=9Gwu9LPjtoAYUU8WKqCvbCHAIg3dpk71reoYd1scLnQ,1807
112
- cwyodmodules-0.3.77.dist-info/licenses/LICENSE,sha256=UqBDTipijsSW2ZSOXyTZnMsXmLoEHTgNEM0tL4g-Sso,1150
113
- cwyodmodules-0.3.77.dist-info/METADATA,sha256=01PMVtALsE7-N-Jaa8jL-cslSVzkwtWgYO5K2K8VTio,2002
114
- cwyodmodules-0.3.77.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
115
- cwyodmodules-0.3.77.dist-info/top_level.txt,sha256=99RENLbkdRX-qpJvsxZ5AfmTL5s6shSaKOWYpz1vwzg,13
116
- cwyodmodules-0.3.77.dist-info/RECORD,,
112
+ cwyodmodules-0.3.79.dist-info/licenses/LICENSE,sha256=UqBDTipijsSW2ZSOXyTZnMsXmLoEHTgNEM0tL4g-Sso,1150
113
+ cwyodmodules-0.3.79.dist-info/METADATA,sha256=SARhrWy5eFC3Hi1Ov9pOtEREJoiXwCTqZH-GP9XLgfM,2002
114
+ cwyodmodules-0.3.79.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
115
+ cwyodmodules-0.3.79.dist-info/top_level.txt,sha256=99RENLbkdRX-qpJvsxZ5AfmTL5s6shSaKOWYpz1vwzg,13
116
+ cwyodmodules-0.3.79.dist-info/RECORD,,