ic-code 1.0.0__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.
ic/compat/common.py ADDED
@@ -0,0 +1,243 @@
1
+ """
2
+ Backward compatibility layer for common module imports.
3
+
4
+ This module provides compatibility shims for the common.* imports that are
5
+ used throughout the existing codebase.
6
+ """
7
+
8
+ import warnings
9
+ from typing import Any, Dict, Optional
10
+ import sys
11
+ from pathlib import Path
12
+
13
+ # Import the compatibility layer
14
+ from . import warn_deprecated, get_logger, compat_config
15
+
16
+ # Add root directory to path for legacy imports
17
+ root_path = Path(__file__).parent.parent.parent.parent
18
+ if str(root_path) not in sys.path:
19
+ sys.path.insert(0, str(root_path))
20
+
21
+
22
+ def log_error(message: str, **kwargs) -> None:
23
+ """
24
+ Backward compatibility function for log_error.
25
+
26
+ Args:
27
+ message: Error message to log
28
+ **kwargs: Additional keyword arguments (ignored for compatibility)
29
+ """
30
+ warn_deprecated(
31
+ "common.log.log_error",
32
+ "ICLogger.log_error or logger.error",
33
+ "2.0.0"
34
+ )
35
+ logger = get_logger()
36
+ logger.log_error(message)
37
+
38
+
39
+ def log_env_short(env_dict=None, **kwargs) -> None:
40
+ """
41
+ Backward compatibility function for log_env_short.
42
+
43
+ Args:
44
+ env_dict: Environment variables dictionary (optional)
45
+ **kwargs: Additional keyword arguments (ignored for compatibility)
46
+ """
47
+ warn_deprecated(
48
+ "common.log.log_env_short",
49
+ "ICLogger.log_info_file_only",
50
+ "2.0.0"
51
+ )
52
+ logger = get_logger()
53
+ if env_dict:
54
+ logger.log_info_file_only(f"Environment variables loaded: {len(env_dict)} variables")
55
+ else:
56
+ logger.log_info_file_only("Environment variables loaded")
57
+
58
+
59
+ def log_args_short(args: Any) -> None:
60
+ """
61
+ Backward compatibility function for log_args_short.
62
+
63
+ Args:
64
+ args: Arguments object to log
65
+ """
66
+ warn_deprecated(
67
+ "common.log.log_args_short",
68
+ "ICLogger.log_args",
69
+ "2.0.0"
70
+ )
71
+ logger = get_logger()
72
+ logger.log_args(args)
73
+
74
+
75
+ def gather_env_for_command(platform: str, service: str = None, command: str = None) -> Dict[str, Any]:
76
+ """
77
+ Backward compatibility function for gather_env_for_command.
78
+
79
+ Args:
80
+ platform: Platform name (aws, gcp, azure, etc.)
81
+ service: Service name (optional)
82
+ command: Command name (optional)
83
+
84
+ Returns:
85
+ Environment configuration dictionary
86
+ """
87
+ warn_deprecated(
88
+ "common.gather_env.gather_env_for_command",
89
+ "ConfigManager.get_config",
90
+ "2.0.0"
91
+ )
92
+
93
+ # Import the original function for backward compatibility
94
+ try:
95
+ from common.gather_env import gather_env_for_command as original_gather_env
96
+ return original_gather_env(platform, service, command)
97
+ except ImportError:
98
+ # Fallback to config manager
99
+ return compat_config.get_all()
100
+
101
+
102
+ # Legacy log module compatibility
103
+ class LogCompat:
104
+ """Compatibility class for common.log module."""
105
+
106
+ @staticmethod
107
+ def log_error(message: str, **kwargs) -> None:
108
+ """Log error message."""
109
+ log_error(message, **kwargs)
110
+
111
+ @staticmethod
112
+ def log_env_short(env_dict=None, **kwargs) -> None:
113
+ """Log environment variables."""
114
+ log_env_short(env_dict, **kwargs)
115
+
116
+ @staticmethod
117
+ def log_args_short(args: Any) -> None:
118
+ """Log command arguments."""
119
+ log_args_short(args)
120
+
121
+
122
+ # Legacy gather_env module compatibility
123
+ class GatherEnvCompat:
124
+ """Compatibility class for common.gather_env module."""
125
+
126
+ @staticmethod
127
+ def gather_env_for_command(platform: str, service: str = None, command: str = None) -> Dict[str, Any]:
128
+ """Gather environment for command."""
129
+ return gather_env_for_command(platform, service, command)
130
+
131
+
132
+ # Create module-like objects for backward compatibility
133
+ log_compat = LogCompat()
134
+ gather_env_compat = GatherEnvCompat()
135
+
136
+
137
+ # Utility functions for AWS session compatibility
138
+ def get_aws_session_compat(account_id: str, region: str = None):
139
+ """
140
+ Backward compatibility function for AWS session creation.
141
+
142
+ Args:
143
+ account_id: AWS account ID
144
+ region: AWS region
145
+
146
+ Returns:
147
+ AWS session object
148
+ """
149
+ warn_deprecated(
150
+ "manual AWS session creation",
151
+ "AWSSessionManager.create_session",
152
+ "2.0.0"
153
+ )
154
+ from . import get_aws_session_manager
155
+
156
+ session_manager = get_aws_session_manager()
157
+ if region is None:
158
+ region = compat_config.get('aws.regions', ['ap-northeast-2'])[0]
159
+
160
+ return session_manager.create_session(account_id, region)
161
+
162
+
163
+ def get_aws_profiles_compat():
164
+ """
165
+ Backward compatibility function for AWS profiles.
166
+
167
+ Returns:
168
+ Dictionary of AWS profiles
169
+ """
170
+ warn_deprecated(
171
+ "manual AWS profile parsing",
172
+ "AWSSessionManager.get_profiles",
173
+ "2.0.0"
174
+ )
175
+ from . import get_aws_session_manager
176
+
177
+ session_manager = get_aws_session_manager()
178
+ return session_manager.get_profiles()
179
+
180
+
181
+ # Azure compatibility functions
182
+ def get_azure_client_compat(service_type: str):
183
+ """
184
+ Backward compatibility function for Azure client creation.
185
+
186
+ Args:
187
+ service_type: Type of Azure service client
188
+
189
+ Returns:
190
+ Azure client object
191
+ """
192
+ warn_deprecated(
193
+ "manual Azure client creation",
194
+ "Azure service modules with new configuration",
195
+ "2.0.0"
196
+ )
197
+
198
+ # Import Azure utilities if available
199
+ try:
200
+ from common.azure_utils import get_azure_client
201
+ return get_azure_client(service_type)
202
+ except ImportError:
203
+ raise ImportError("Azure utilities not available. Please install azure dependencies.")
204
+
205
+
206
+ # GCP compatibility functions
207
+ def get_gcp_client_compat(service_type: str):
208
+ """
209
+ Backward compatibility function for GCP client creation.
210
+
211
+ Args:
212
+ service_type: Type of GCP service client
213
+
214
+ Returns:
215
+ GCP client object
216
+ """
217
+ warn_deprecated(
218
+ "manual GCP client creation",
219
+ "GCP service modules with new configuration",
220
+ "2.0.0"
221
+ )
222
+
223
+ # Import GCP utilities if available
224
+ try:
225
+ from common.gcp_utils import get_gcp_client
226
+ return get_gcp_client(service_type)
227
+ except ImportError:
228
+ raise ImportError("GCP utilities not available. Please install google-cloud dependencies.")
229
+
230
+
231
+ # Export compatibility functions
232
+ __all__ = [
233
+ 'log_error',
234
+ 'log_env_short',
235
+ 'log_args_short',
236
+ 'gather_env_for_command',
237
+ 'log_compat',
238
+ 'gather_env_compat',
239
+ 'get_aws_session_compat',
240
+ 'get_aws_profiles_compat',
241
+ 'get_azure_client_compat',
242
+ 'get_gcp_client_compat',
243
+ ]
ic/config/__init__.py ADDED
@@ -0,0 +1,10 @@
1
+ """
2
+ Configuration management module for IC.
3
+
4
+ This module provides configuration loading, validation, and security features.
5
+ """
6
+
7
+ from .manager import ConfigManager
8
+ from .security import SecurityManager
9
+
10
+ __all__ = ["ConfigManager", "SecurityManager"]
ic/config/cleanup.py ADDED
@@ -0,0 +1,382 @@
1
+ """
2
+ File cleanup and backup management module for IC.
3
+
4
+ This module provides functionality to organize and backup old files.
5
+ """
6
+
7
+ import os
8
+ import shutil
9
+ from datetime import datetime
10
+ from pathlib import Path
11
+ from typing import Dict, Any, List, Optional
12
+ import logging
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ class FileCleanupManager:
18
+ """
19
+ Manages file cleanup and backup operations.
20
+ """
21
+
22
+ def __init__(self):
23
+ """Initialize FileCleanupManager."""
24
+ self.backup_dir = Path("backup")
25
+ self.olds_dir = self.backup_dir / "olds"
26
+ self.cleanup_history: List[Dict[str, Any]] = []
27
+
28
+ def backup_old_files(self, file_patterns: Optional[List[str]] = None) -> bool:
29
+ """
30
+ Backup old files to backup/olds directory.
31
+
32
+ Args:
33
+ file_patterns: List of file patterns to backup (default: common old files)
34
+
35
+ Returns:
36
+ True if backup was successful
37
+ """
38
+ if file_patterns is None:
39
+ file_patterns = [
40
+ "*.env*",
41
+ "*.log",
42
+ "logs/",
43
+ "old_*",
44
+ "*.bak",
45
+ "*.backup",
46
+ "temp_*",
47
+ "tmp_*"
48
+ ]
49
+
50
+ try:
51
+ # Create backup directories
52
+ self.backup_dir.mkdir(exist_ok=True)
53
+ self.olds_dir.mkdir(exist_ok=True)
54
+
55
+ backed_up_files = []
56
+
57
+ for pattern in file_patterns:
58
+ files_found = self._find_files_by_pattern(pattern)
59
+
60
+ for file_path in files_found:
61
+ backup_path = self._backup_single_file(file_path)
62
+ if backup_path:
63
+ backed_up_files.append({
64
+ "original_path": str(file_path),
65
+ "backup_path": str(backup_path),
66
+ "file_type": self._get_file_type(file_path),
67
+ "size": file_path.stat().st_size if file_path.exists() else 0,
68
+ "timestamp": datetime.now().isoformat()
69
+ })
70
+
71
+ if backed_up_files:
72
+ self.cleanup_history.extend(backed_up_files)
73
+ logger.info(f"Backed up {len(backed_up_files)} files to {self.olds_dir}")
74
+ return True
75
+ else:
76
+ logger.info("No files found to backup")
77
+ return True
78
+
79
+ except Exception as e:
80
+ logger.error(f"Failed to backup old files: {e}")
81
+ return False
82
+
83
+ def _find_files_by_pattern(self, pattern: str) -> List[Path]:
84
+ """Find files matching a pattern."""
85
+ files = []
86
+
87
+ try:
88
+ if pattern.endswith('/'):
89
+ # Directory pattern
90
+ dir_name = pattern.rstrip('/')
91
+ dir_path = Path(dir_name)
92
+ if dir_path.exists() and dir_path.is_dir():
93
+ files.append(dir_path)
94
+ else:
95
+ # File pattern
96
+ files.extend(Path('.').glob(pattern))
97
+
98
+ except Exception as e:
99
+ logger.warning(f"Error finding files with pattern '{pattern}': {e}")
100
+
101
+ return files
102
+
103
+ def _backup_single_file(self, file_path: Path) -> Optional[Path]:
104
+ """Backup a single file or directory."""
105
+ if not file_path.exists():
106
+ return None
107
+
108
+ try:
109
+ # Generate backup name with timestamp
110
+ timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
111
+
112
+ if file_path.is_dir():
113
+ backup_name = f"{file_path.name}_{timestamp}"
114
+ backup_path = self.olds_dir / backup_name
115
+ shutil.copytree(file_path, backup_path)
116
+ # Remove original directory
117
+ shutil.rmtree(file_path)
118
+ else:
119
+ backup_name = f"{file_path.stem}_{timestamp}{file_path.suffix}"
120
+ backup_path = self.olds_dir / backup_name
121
+ shutil.copy2(file_path, backup_path)
122
+ # Remove original file
123
+ file_path.unlink()
124
+
125
+ logger.debug(f"Backed up {file_path} to {backup_path}")
126
+ return backup_path
127
+
128
+ except Exception as e:
129
+ logger.warning(f"Failed to backup {file_path}: {e}")
130
+ return None
131
+
132
+ def _get_file_type(self, file_path: Path) -> str:
133
+ """Determine file type for categorization."""
134
+ if file_path.is_dir():
135
+ return "directory"
136
+
137
+ suffix = file_path.suffix.lower()
138
+
139
+ if suffix in ['.env']:
140
+ return "environment_config"
141
+ elif suffix in ['.log']:
142
+ return "log_file"
143
+ elif suffix in ['.bak', '.backup']:
144
+ return "backup_file"
145
+ elif suffix in ['.py']:
146
+ return "python_file"
147
+ elif suffix in ['.yaml', '.yml']:
148
+ return "yaml_config"
149
+ elif suffix in ['.json']:
150
+ return "json_config"
151
+ elif suffix in ['.md']:
152
+ return "documentation"
153
+ else:
154
+ return "other"
155
+
156
+ def create_cleanup_history_document(self) -> bool:
157
+ """
158
+ Create a document recording all cleanup operations.
159
+
160
+ Returns:
161
+ True if document was created successfully
162
+ """
163
+ try:
164
+ history_content = self._generate_cleanup_history_content()
165
+
166
+ history_path = self.backup_dir / "file_cleanup_history.md"
167
+ with open(history_path, 'w', encoding='utf-8') as f:
168
+ f.write(history_content)
169
+
170
+ logger.info(f"Created cleanup history document at {history_path}")
171
+ return True
172
+
173
+ except Exception as e:
174
+ logger.error(f"Failed to create cleanup history document: {e}")
175
+ return False
176
+
177
+ def _generate_cleanup_history_content(self) -> str:
178
+ """Generate cleanup history document content."""
179
+ content = """# IC File Cleanup History
180
+
181
+ This document records all file cleanup and backup operations performed during the IC configuration migration.
182
+
183
+ ## Overview
184
+
185
+ During the migration from .env-based configuration to YAML-based configuration, various old files were identified and moved to the backup directory to keep the project clean while preserving important data.
186
+
187
+ ## Backup Structure
188
+
189
+ ```
190
+ backup/
191
+ ├── olds/ # Old files moved during cleanup
192
+ │ ├── .env_YYYYMMDD_HHMMSS # Original environment files
193
+ │ ├── logs_YYYYMMDD_HHMMSS/ # Old log directories
194
+ │ └── ... # Other backed up files
195
+ ├── file_cleanup_history.md # This document
196
+ └── migration_history.md # Configuration migration history
197
+ ```
198
+
199
+ ## File Categories
200
+
201
+ ### Environment Configuration Files
202
+ - `.env` files and variants
203
+ - Contains original environment variable configurations
204
+ - **Location**: Moved to `backup/olds/`
205
+ - **Purpose**: Preserve original configuration for rollback if needed
206
+
207
+ ### Log Files
208
+ - `*.log` files and `logs/` directories
209
+ - Contains historical application logs
210
+ - **Location**: Moved to `backup/olds/`
211
+ - **Purpose**: Archive old logs while implementing fixed log paths
212
+
213
+ ### Backup Files
214
+ - `*.bak`, `*.backup` files
215
+ - Previous backup files from other operations
216
+ - **Location**: Consolidated in `backup/olds/`
217
+ - **Purpose**: Centralize all backup files
218
+
219
+ ### Temporary Files
220
+ - `temp_*`, `tmp_*`, `old_*` files
221
+ - Temporary files from development or previous operations
222
+ - **Location**: Moved to `backup/olds/`
223
+ - **Purpose**: Clean up workspace while preserving potentially important data
224
+
225
+ ## Cleanup Operations
226
+
227
+ """
228
+
229
+ if self.cleanup_history:
230
+ # Group files by type
231
+ files_by_type = {}
232
+ for file_info in self.cleanup_history:
233
+ file_type = file_info['file_type']
234
+ if file_type not in files_by_type:
235
+ files_by_type[file_type] = []
236
+ files_by_type[file_type].append(file_info)
237
+
238
+ for file_type, files in files_by_type.items():
239
+ content += f"### {file_type.replace('_', ' ').title()}\n\n"
240
+
241
+ total_size = sum(f['size'] for f in files)
242
+ content += f"**Total Files**: {len(files)}\n"
243
+ content += f"**Total Size**: {self._format_size(total_size)}\n\n"
244
+
245
+ content += "| Original Path | Backup Path | Size | Timestamp |\n"
246
+ content += "|---------------|-------------|------|----------|\n"
247
+
248
+ for file_info in files:
249
+ content += f"| `{file_info['original_path']}` | `{file_info['backup_path']}` | {self._format_size(file_info['size'])} | {file_info['timestamp'][:19]} |\n"
250
+
251
+ content += "\n"
252
+ else:
253
+ content += "No cleanup operations recorded.\n\n"
254
+
255
+ content += """## File Roles and Purposes
256
+
257
+ ### Original .env Files
258
+ - **Role**: Primary configuration source for the old system
259
+ - **Contents**: Environment variables for all services (AWS, GCP, Azure, etc.)
260
+ - **Migration**: Values extracted and categorized into `config/default.yaml` and `config/secrets.yaml`
261
+ - **Backup Reason**: Preserve for rollback and reference
262
+
263
+ ### Log Files
264
+ - **Role**: Application runtime logs and debugging information
265
+ - **Contents**: Historical execution logs, error messages, debug information
266
+ - **Migration**: New fixed log path implemented at `~/.ic/logs/`
267
+ - **Backup Reason**: Archive historical data while implementing new logging system
268
+
269
+ ### Development Files
270
+ - **Role**: Temporary files created during development
271
+ - **Contents**: Test files, temporary configurations, development artifacts
272
+ - **Migration**: Not migrated, but preserved for reference
273
+ - **Backup Reason**: Clean workspace while preserving potentially useful development data
274
+
275
+ ## Recovery Instructions
276
+
277
+ ### Restoring Original .env Configuration
278
+ If you need to restore the original .env-based configuration:
279
+
280
+ 1. Copy the backed up .env file from `backup/olds/` to the project root
281
+ 2. Rename or remove the `config/` directory
282
+ 3. Restart the application
283
+
284
+ ### Accessing Historical Logs
285
+ Historical logs are preserved in `backup/olds/logs_*/` directories and can be accessed for debugging or audit purposes.
286
+
287
+ ### Recovering Specific Files
288
+ All backed up files maintain their original structure and can be restored by copying them back to their original locations.
289
+
290
+ ## Cleanup Benefits
291
+
292
+ 1. **Cleaner Workspace**: Removed clutter from the project root
293
+ 2. **Organized Structure**: All backups centralized in one location
294
+ 3. **Preserved Data**: No data loss - everything is backed up
295
+ 4. **Clear Migration Path**: Easy to identify what was changed
296
+ 5. **Rollback Capability**: Simple restoration process if needed
297
+
298
+ ## Maintenance
299
+
300
+ - Backup files are preserved indefinitely
301
+ - Consider periodic cleanup of very old backup files (>1 year)
302
+ - Monitor backup directory size if disk space becomes a concern
303
+ - Backup directory can be excluded from version control
304
+
305
+ """
306
+
307
+ return content
308
+
309
+ def _format_size(self, size_bytes: int) -> str:
310
+ """Format file size in human-readable format."""
311
+ if size_bytes == 0:
312
+ return "0 B"
313
+
314
+ for unit in ['B', 'KB', 'MB', 'GB']:
315
+ if size_bytes < 1024:
316
+ return f"{size_bytes:.1f} {unit}"
317
+ size_bytes /= 1024
318
+
319
+ return f"{size_bytes:.1f} TB"
320
+
321
+ def get_backup_summary(self) -> Dict[str, Any]:
322
+ """
323
+ Get summary of backup operations.
324
+
325
+ Returns:
326
+ Dictionary containing backup summary
327
+ """
328
+ if not self.cleanup_history:
329
+ return {"total_files": 0, "total_size": 0, "file_types": {}}
330
+
331
+ total_files = len(self.cleanup_history)
332
+ total_size = sum(f['size'] for f in self.cleanup_history)
333
+
334
+ file_types = {}
335
+ for file_info in self.cleanup_history:
336
+ file_type = file_info['file_type']
337
+ if file_type not in file_types:
338
+ file_types[file_type] = {"count": 0, "size": 0}
339
+ file_types[file_type]["count"] += 1
340
+ file_types[file_type]["size"] += file_info['size']
341
+
342
+ return {
343
+ "total_files": total_files,
344
+ "total_size": total_size,
345
+ "file_types": file_types,
346
+ "backup_location": str(self.olds_dir)
347
+ }
348
+
349
+ def validate_backups(self) -> Dict[str, List[str]]:
350
+ """
351
+ Validate that backed up files exist and are accessible.
352
+
353
+ Returns:
354
+ Dictionary of validation results
355
+ """
356
+ issues = {
357
+ "missing_backups": [],
358
+ "corrupted_backups": [],
359
+ "permission_issues": []
360
+ }
361
+
362
+ for file_info in self.cleanup_history:
363
+ backup_path = Path(file_info['backup_path'])
364
+
365
+ if not backup_path.exists():
366
+ issues["missing_backups"].append(file_info['backup_path'])
367
+ continue
368
+
369
+ try:
370
+ # Try to read a small portion to check if file is accessible
371
+ if backup_path.is_file():
372
+ with open(backup_path, 'rb') as f:
373
+ f.read(1024) # Read first 1KB
374
+ elif backup_path.is_dir():
375
+ list(backup_path.iterdir()) # List directory contents
376
+
377
+ except PermissionError:
378
+ issues["permission_issues"].append(file_info['backup_path'])
379
+ except Exception:
380
+ issues["corrupted_backups"].append(file_info['backup_path'])
381
+
382
+ return issues