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/__init__.py +29 -0
- ic/cli.py +769 -0
- ic/commands/__init__.py +10 -0
- ic/commands/config.py +699 -0
- ic/compat/__init__.py +241 -0
- ic/compat/cli.py +289 -0
- ic/compat/common.py +243 -0
- ic/config/__init__.py +10 -0
- ic/config/cleanup.py +382 -0
- ic/config/docs_organizer.py +587 -0
- ic/config/external.py +456 -0
- ic/config/manager.py +898 -0
- ic/config/migration.py +628 -0
- ic/config/schema.py +595 -0
- ic/config/secrets.py +437 -0
- ic/config/security.py +462 -0
- ic/core/__init__.py +16 -0
- ic/core/logging.py +311 -0
- ic/core/mcp_manager.py +856 -0
- ic/core/session.py +392 -0
- ic/core/silence_logging.py +67 -0
- ic_code-1.0.0.dist-info/METADATA +354 -0
- ic_code-1.0.0.dist-info/RECORD +27 -0
- ic_code-1.0.0.dist-info/WHEEL +5 -0
- ic_code-1.0.0.dist-info/entry_points.txt +2 -0
- ic_code-1.0.0.dist-info/licenses/LICENSE +21 -0
- ic_code-1.0.0.dist-info/top_level.txt +1 -0
ic/compat/__init__.py
ADDED
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Backward compatibility layer for IC package.
|
|
3
|
+
|
|
4
|
+
This module provides compatibility shims for existing import paths and functionality
|
|
5
|
+
to ensure smooth migration from the old structure to the new src/ layout.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import warnings
|
|
9
|
+
from typing import Any, Dict, Optional
|
|
10
|
+
import os
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
# Import new modules
|
|
14
|
+
from ..config.manager import ConfigManager
|
|
15
|
+
from ..config.security import SecurityManager
|
|
16
|
+
from ..core.logging import ICLogger
|
|
17
|
+
from ..core.session import AWSSessionManager
|
|
18
|
+
from ..core.mcp_manager import MCPManager
|
|
19
|
+
|
|
20
|
+
# Global compatibility instances
|
|
21
|
+
_config_manager: Optional[ConfigManager] = None
|
|
22
|
+
_logger: Optional[ICLogger] = None
|
|
23
|
+
_aws_session_manager: Optional[AWSSessionManager] = None
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_config_manager() -> ConfigManager:
|
|
27
|
+
"""Get or create global ConfigManager instance."""
|
|
28
|
+
global _config_manager
|
|
29
|
+
if _config_manager is None:
|
|
30
|
+
security_manager = SecurityManager()
|
|
31
|
+
_config_manager = ConfigManager(security_manager=security_manager)
|
|
32
|
+
# Load configuration with .env fallback
|
|
33
|
+
_config_manager.load_config()
|
|
34
|
+
return _config_manager
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def get_logger() -> ICLogger:
|
|
38
|
+
"""Get or create global ICLogger instance."""
|
|
39
|
+
global _logger
|
|
40
|
+
if _logger is None:
|
|
41
|
+
config_manager = get_config_manager()
|
|
42
|
+
config = config_manager.get_config()
|
|
43
|
+
_logger = ICLogger(config)
|
|
44
|
+
return _logger
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def get_aws_session_manager() -> AWSSessionManager:
|
|
48
|
+
"""Get or create global AWSSessionManager instance."""
|
|
49
|
+
global _aws_session_manager
|
|
50
|
+
if _aws_session_manager is None:
|
|
51
|
+
config_manager = get_config_manager()
|
|
52
|
+
config = config_manager.get_config()
|
|
53
|
+
_aws_session_manager = AWSSessionManager(config)
|
|
54
|
+
return _aws_session_manager
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def warn_deprecated(old_path: str, new_path: str, version: str = "2.0.0") -> None:
|
|
58
|
+
"""Issue deprecation warning for old import paths."""
|
|
59
|
+
warnings.warn(
|
|
60
|
+
f"'{old_path}' is deprecated and will be removed in version {version}. "
|
|
61
|
+
f"Please use '{new_path}' instead.",
|
|
62
|
+
DeprecationWarning,
|
|
63
|
+
stacklevel=3
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class CompatibilityConfig:
|
|
68
|
+
"""
|
|
69
|
+
Compatibility wrapper for configuration access.
|
|
70
|
+
|
|
71
|
+
Provides backward compatibility for .env file access while encouraging
|
|
72
|
+
migration to the new YAML-based configuration system.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
def __init__(self):
|
|
76
|
+
self._config_manager = get_config_manager()
|
|
77
|
+
self._env_loaded = False
|
|
78
|
+
self._load_env_if_needed()
|
|
79
|
+
|
|
80
|
+
def _load_env_if_needed(self):
|
|
81
|
+
"""Load .env file if it exists and hasn't been loaded yet."""
|
|
82
|
+
if not self._env_loaded:
|
|
83
|
+
env_file = Path('.env')
|
|
84
|
+
if env_file.exists():
|
|
85
|
+
try:
|
|
86
|
+
from dotenv import load_dotenv
|
|
87
|
+
load_dotenv()
|
|
88
|
+
self._env_loaded = True
|
|
89
|
+
|
|
90
|
+
# Issue deprecation warning
|
|
91
|
+
warn_deprecated(
|
|
92
|
+
".env file usage",
|
|
93
|
+
"YAML configuration files (config.yaml)",
|
|
94
|
+
"2.0.0"
|
|
95
|
+
)
|
|
96
|
+
except ImportError:
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
def get(self, key: str, default: Any = None) -> Any:
|
|
100
|
+
"""
|
|
101
|
+
Get configuration value with .env fallback.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
key: Configuration key (supports dot notation)
|
|
105
|
+
default: Default value if key not found
|
|
106
|
+
|
|
107
|
+
Returns:
|
|
108
|
+
Configuration value
|
|
109
|
+
"""
|
|
110
|
+
# Try new config system first
|
|
111
|
+
value = self._config_manager.get_config_value(key, None)
|
|
112
|
+
if value is not None:
|
|
113
|
+
return value
|
|
114
|
+
|
|
115
|
+
# Fallback to environment variable
|
|
116
|
+
env_key = key.upper().replace('.', '_')
|
|
117
|
+
env_value = os.getenv(env_key)
|
|
118
|
+
if env_value is not None:
|
|
119
|
+
return env_value
|
|
120
|
+
|
|
121
|
+
# Legacy environment variable mappings
|
|
122
|
+
legacy_mappings = {
|
|
123
|
+
'aws.accounts': 'AWS_ACCOUNTS',
|
|
124
|
+
'aws.regions': 'AWS_REGIONS',
|
|
125
|
+
'aws.cross_account_role': 'AWS_CROSS_ACCOUNT_ROLE',
|
|
126
|
+
'azure.subscription_id': 'AZURE_SUBSCRIPTION_ID',
|
|
127
|
+
'azure.tenant_id': 'AZURE_TENANT_ID',
|
|
128
|
+
'azure.client_id': 'AZURE_CLIENT_ID',
|
|
129
|
+
'azure.client_secret': 'AZURE_CLIENT_SECRET',
|
|
130
|
+
'gcp.project_id': 'GCP_PROJECT_ID',
|
|
131
|
+
'gcp.service_account_key_path': 'GCP_SERVICE_ACCOUNT_KEY_PATH',
|
|
132
|
+
'cloudflare.email': 'CLOUDFLARE_EMAIL',
|
|
133
|
+
'cloudflare.api_token': 'CLOUDFLARE_API_TOKEN',
|
|
134
|
+
'slack.webhook_url': 'SLACK_WEBHOOK_URL',
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
legacy_env_key = legacy_mappings.get(key)
|
|
138
|
+
if legacy_env_key:
|
|
139
|
+
legacy_value = os.getenv(legacy_env_key)
|
|
140
|
+
if legacy_value is not None:
|
|
141
|
+
return legacy_value
|
|
142
|
+
|
|
143
|
+
return default
|
|
144
|
+
|
|
145
|
+
def get_all(self) -> Dict[str, Any]:
|
|
146
|
+
"""Get all configuration as dictionary."""
|
|
147
|
+
return self._config_manager.get_config()
|
|
148
|
+
|
|
149
|
+
def reload(self) -> None:
|
|
150
|
+
"""Reload configuration from all sources."""
|
|
151
|
+
self._config_manager.load_config()
|
|
152
|
+
self._env_loaded = False
|
|
153
|
+
self._load_env_if_needed()
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
# Global compatibility config instance
|
|
157
|
+
compat_config = CompatibilityConfig()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def get_env_value(key: str, default: Any = None) -> Any:
|
|
161
|
+
"""
|
|
162
|
+
Backward compatibility function for environment variable access.
|
|
163
|
+
|
|
164
|
+
Args:
|
|
165
|
+
key: Environment variable key
|
|
166
|
+
default: Default value if not found
|
|
167
|
+
|
|
168
|
+
Returns:
|
|
169
|
+
Environment variable value or default
|
|
170
|
+
"""
|
|
171
|
+
warn_deprecated(
|
|
172
|
+
f"get_env_value('{key}')",
|
|
173
|
+
f"compat_config.get('{key.lower().replace('_', '.')}')",
|
|
174
|
+
"2.0.0"
|
|
175
|
+
)
|
|
176
|
+
return os.getenv(key, default)
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
def load_dotenv_compat():
|
|
180
|
+
"""
|
|
181
|
+
Backward compatibility function for loading .env files.
|
|
182
|
+
"""
|
|
183
|
+
warn_deprecated(
|
|
184
|
+
"load_dotenv_compat()",
|
|
185
|
+
"ConfigManager.load_config() with YAML files",
|
|
186
|
+
"2.0.0"
|
|
187
|
+
)
|
|
188
|
+
try:
|
|
189
|
+
from dotenv import load_dotenv
|
|
190
|
+
load_dotenv()
|
|
191
|
+
except ImportError:
|
|
192
|
+
pass
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
# Compatibility aliases for common functions
|
|
196
|
+
def get_aws_accounts() -> list:
|
|
197
|
+
"""Get AWS accounts from configuration."""
|
|
198
|
+
accounts = compat_config.get('aws.accounts', [])
|
|
199
|
+
if isinstance(accounts, str):
|
|
200
|
+
return [acc.strip() for acc in accounts.split(',') if acc.strip()]
|
|
201
|
+
return accounts or []
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def get_aws_regions() -> list:
|
|
205
|
+
"""Get AWS regions from configuration."""
|
|
206
|
+
regions = compat_config.get('aws.regions', ['ap-northeast-2'])
|
|
207
|
+
if isinstance(regions, str):
|
|
208
|
+
return [reg.strip() for reg in regions.split(',') if reg.strip()]
|
|
209
|
+
return regions
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
def get_azure_subscription_id() -> Optional[str]:
|
|
213
|
+
"""Get Azure subscription ID from configuration."""
|
|
214
|
+
return compat_config.get('azure.subscription_id')
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
def get_gcp_project_id() -> Optional[str]:
|
|
218
|
+
"""Get GCP project ID from configuration."""
|
|
219
|
+
return compat_config.get('gcp.project_id')
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def get_slack_webhook_url() -> Optional[str]:
|
|
223
|
+
"""Get Slack webhook URL from configuration."""
|
|
224
|
+
return compat_config.get('slack.webhook_url')
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
# Export compatibility functions
|
|
228
|
+
__all__ = [
|
|
229
|
+
'get_config_manager',
|
|
230
|
+
'get_logger',
|
|
231
|
+
'get_aws_session_manager',
|
|
232
|
+
'compat_config',
|
|
233
|
+
'get_env_value',
|
|
234
|
+
'load_dotenv_compat',
|
|
235
|
+
'get_aws_accounts',
|
|
236
|
+
'get_aws_regions',
|
|
237
|
+
'get_azure_subscription_id',
|
|
238
|
+
'get_gcp_project_id',
|
|
239
|
+
'get_slack_webhook_url',
|
|
240
|
+
'warn_deprecated',
|
|
241
|
+
]
|
ic/compat/cli.py
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Backward compatibility layer for CLI functionality.
|
|
3
|
+
|
|
4
|
+
This module ensures that existing CLI commands continue to work while
|
|
5
|
+
providing migration path to new configuration system.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
import warnings
|
|
11
|
+
from typing import Any, Dict, Optional
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
|
|
14
|
+
# Import compatibility layer
|
|
15
|
+
from . import warn_deprecated, compat_config, get_logger
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def ensure_env_compatibility():
|
|
19
|
+
"""
|
|
20
|
+
Ensure environment variable compatibility for CLI commands.
|
|
21
|
+
|
|
22
|
+
This function checks for .env files and loads them if the new
|
|
23
|
+
configuration system hasn't been set up yet.
|
|
24
|
+
"""
|
|
25
|
+
# Check if new config exists
|
|
26
|
+
config_paths = [
|
|
27
|
+
Path("ic.yaml"),
|
|
28
|
+
Path(".ic/config.yaml"),
|
|
29
|
+
Path("config/config.yaml"),
|
|
30
|
+
Path.home() / ".ic" / "config.yaml",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
has_new_config = any(path.exists() for path in config_paths)
|
|
34
|
+
|
|
35
|
+
# If no new config exists, ensure .env is loaded
|
|
36
|
+
if not has_new_config:
|
|
37
|
+
env_file = Path('.env')
|
|
38
|
+
if env_file.exists():
|
|
39
|
+
try:
|
|
40
|
+
from dotenv import load_dotenv
|
|
41
|
+
load_dotenv()
|
|
42
|
+
|
|
43
|
+
# Issue one-time warning about migration
|
|
44
|
+
if not os.getenv('IC_MIGRATION_WARNING_SHOWN'):
|
|
45
|
+
logger = get_logger()
|
|
46
|
+
logger.log_info_file_only(
|
|
47
|
+
"Using .env file for configuration. "
|
|
48
|
+
"Consider migrating to YAML configuration with 'ic config migrate'"
|
|
49
|
+
)
|
|
50
|
+
os.environ['IC_MIGRATION_WARNING_SHOWN'] = '1'
|
|
51
|
+
|
|
52
|
+
except ImportError:
|
|
53
|
+
warnings.warn(
|
|
54
|
+
"python-dotenv not installed. .env file cannot be loaded. "
|
|
55
|
+
"Install with: pip install python-dotenv",
|
|
56
|
+
ImportWarning
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def wrap_command_function(original_func):
|
|
61
|
+
"""
|
|
62
|
+
Decorator to wrap existing command functions with compatibility layer.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
original_func: Original command function
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
Wrapped function with compatibility features
|
|
69
|
+
"""
|
|
70
|
+
def wrapper(args):
|
|
71
|
+
# Ensure environment compatibility
|
|
72
|
+
ensure_env_compatibility()
|
|
73
|
+
|
|
74
|
+
# Add compatibility attributes to args if needed
|
|
75
|
+
if not hasattr(args, '_ic_compat_wrapped'):
|
|
76
|
+
args._ic_compat_wrapped = True
|
|
77
|
+
|
|
78
|
+
# Add configuration access to args
|
|
79
|
+
args.config = compat_config
|
|
80
|
+
|
|
81
|
+
# Add logger access to args
|
|
82
|
+
args.logger = get_logger()
|
|
83
|
+
|
|
84
|
+
# Call original function
|
|
85
|
+
return original_func(args)
|
|
86
|
+
|
|
87
|
+
return wrapper
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_legacy_env_vars() -> Dict[str, str]:
|
|
91
|
+
"""
|
|
92
|
+
Get legacy environment variables that might be needed for compatibility.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
Dictionary of legacy environment variables
|
|
96
|
+
"""
|
|
97
|
+
legacy_vars = {}
|
|
98
|
+
|
|
99
|
+
# AWS legacy variables
|
|
100
|
+
aws_vars = [
|
|
101
|
+
'AWS_PROFILE', 'AWS_REGION', 'AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY',
|
|
102
|
+
'AWS_SESSION_TOKEN', 'AWS_ACCOUNTS', 'AWS_REGIONS', 'AWS_CROSS_ACCOUNT_ROLE'
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
# Azure legacy variables
|
|
106
|
+
azure_vars = [
|
|
107
|
+
'AZURE_SUBSCRIPTION_ID', 'AZURE_TENANT_ID', 'AZURE_CLIENT_ID',
|
|
108
|
+
'AZURE_CLIENT_SECRET', 'AZURE_SUBSCRIPTIONS', 'AZURE_LOCATIONS'
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
# GCP legacy variables
|
|
112
|
+
gcp_vars = [
|
|
113
|
+
'GCP_PROJECT_ID', 'GCP_PROJECTS', 'GCP_REGIONS', 'GCP_ZONES',
|
|
114
|
+
'GCP_SERVICE_ACCOUNT_KEY_PATH', 'GOOGLE_APPLICATION_CREDENTIALS'
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
# CloudFlare legacy variables
|
|
118
|
+
cf_vars = [
|
|
119
|
+
'CLOUDFLARE_EMAIL', 'CLOUDFLARE_API_TOKEN', 'CLOUDFLARE_ACCOUNTS', 'CLOUDFLARE_ZONES'
|
|
120
|
+
]
|
|
121
|
+
|
|
122
|
+
# Other legacy variables
|
|
123
|
+
other_vars = [
|
|
124
|
+
'SLACK_WEBHOOK_URL', 'SSH_CONFIG_FILE', 'SSH_KEY_DIR', 'OCI_CONFIG_PATH'
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
all_vars = aws_vars + azure_vars + gcp_vars + cf_vars + other_vars
|
|
128
|
+
|
|
129
|
+
for var in all_vars:
|
|
130
|
+
value = os.getenv(var)
|
|
131
|
+
if value:
|
|
132
|
+
legacy_vars[var] = value
|
|
133
|
+
|
|
134
|
+
return legacy_vars
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
def migrate_env_to_config_hint():
|
|
138
|
+
"""
|
|
139
|
+
Provide hint about migrating from .env to config files.
|
|
140
|
+
"""
|
|
141
|
+
env_file = Path('.env')
|
|
142
|
+
if env_file.exists():
|
|
143
|
+
config_paths = [
|
|
144
|
+
Path("ic.yaml"),
|
|
145
|
+
Path(".ic/config.yaml"),
|
|
146
|
+
Path("config/config.yaml"),
|
|
147
|
+
]
|
|
148
|
+
|
|
149
|
+
has_config = any(path.exists() for path in config_paths)
|
|
150
|
+
|
|
151
|
+
if not has_config:
|
|
152
|
+
logger = get_logger()
|
|
153
|
+
logger.log_info_file_only(
|
|
154
|
+
"💡 Tip: Migrate from .env to YAML configuration for better security and features. "
|
|
155
|
+
"Run 'ic config migrate' to get started."
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def check_deprecated_imports():
|
|
160
|
+
"""
|
|
161
|
+
Check for deprecated import patterns in the current execution.
|
|
162
|
+
"""
|
|
163
|
+
# This is called during CLI startup to check for deprecated usage
|
|
164
|
+
frame = sys._getframe(1)
|
|
165
|
+
|
|
166
|
+
# Check if we're being imported from old paths
|
|
167
|
+
if frame and frame.f_code:
|
|
168
|
+
filename = frame.f_code.co_filename
|
|
169
|
+
if 'common/log.py' in filename or 'common/gather_env.py' in filename:
|
|
170
|
+
warn_deprecated(
|
|
171
|
+
"importing from common.* modules",
|
|
172
|
+
"importing from ic.compat or using new configuration system",
|
|
173
|
+
"2.0.0"
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def setup_cli_compatibility():
|
|
178
|
+
"""
|
|
179
|
+
Set up CLI compatibility features.
|
|
180
|
+
|
|
181
|
+
This function should be called early in CLI initialization to ensure
|
|
182
|
+
backward compatibility features are available.
|
|
183
|
+
"""
|
|
184
|
+
# Ensure environment compatibility
|
|
185
|
+
ensure_env_compatibility()
|
|
186
|
+
|
|
187
|
+
# Check for deprecated imports
|
|
188
|
+
check_deprecated_imports()
|
|
189
|
+
|
|
190
|
+
# Provide migration hints
|
|
191
|
+
migrate_env_to_config_hint()
|
|
192
|
+
|
|
193
|
+
# Set up global compatibility state
|
|
194
|
+
if not hasattr(sys.modules[__name__], '_cli_compat_initialized'):
|
|
195
|
+
sys.modules[__name__]._cli_compat_initialized = True
|
|
196
|
+
|
|
197
|
+
# Log compatibility mode activation
|
|
198
|
+
logger = get_logger()
|
|
199
|
+
logger.log_info_file_only("CLI compatibility layer activated")
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def get_command_config(command_name: str) -> Dict[str, Any]:
|
|
203
|
+
"""
|
|
204
|
+
Get configuration for a specific command with backward compatibility.
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
command_name: Name of the command
|
|
208
|
+
|
|
209
|
+
Returns:
|
|
210
|
+
Configuration dictionary for the command
|
|
211
|
+
"""
|
|
212
|
+
# Get base configuration
|
|
213
|
+
config = compat_config.get_all()
|
|
214
|
+
|
|
215
|
+
# Add command-specific compatibility mappings
|
|
216
|
+
if command_name.startswith('aws'):
|
|
217
|
+
# Ensure AWS configuration is available
|
|
218
|
+
if not config.get('aws', {}).get('accounts'):
|
|
219
|
+
accounts_env = os.getenv('AWS_ACCOUNTS')
|
|
220
|
+
if accounts_env:
|
|
221
|
+
if 'aws' not in config:
|
|
222
|
+
config['aws'] = {}
|
|
223
|
+
config['aws']['accounts'] = [acc.strip() for acc in accounts_env.split(',')]
|
|
224
|
+
|
|
225
|
+
elif command_name.startswith('azure'):
|
|
226
|
+
# Ensure Azure configuration is available
|
|
227
|
+
if not config.get('azure', {}).get('subscription_id'):
|
|
228
|
+
sub_id = os.getenv('AZURE_SUBSCRIPTION_ID')
|
|
229
|
+
if sub_id:
|
|
230
|
+
if 'azure' not in config:
|
|
231
|
+
config['azure'] = {}
|
|
232
|
+
config['azure']['subscription_id'] = sub_id
|
|
233
|
+
|
|
234
|
+
elif command_name.startswith('gcp'):
|
|
235
|
+
# Ensure GCP configuration is available
|
|
236
|
+
if not config.get('gcp', {}).get('project_id'):
|
|
237
|
+
project_id = os.getenv('GCP_PROJECT_ID')
|
|
238
|
+
if project_id:
|
|
239
|
+
if 'gcp' not in config:
|
|
240
|
+
config['gcp'] = {}
|
|
241
|
+
config['gcp']['project_id'] = project_id
|
|
242
|
+
|
|
243
|
+
return config
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def handle_missing_config(service: str) -> None:
|
|
247
|
+
"""
|
|
248
|
+
Handle missing configuration for a service with helpful error messages.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
service: Name of the service (aws, azure, gcp, etc.)
|
|
252
|
+
"""
|
|
253
|
+
logger = get_logger()
|
|
254
|
+
|
|
255
|
+
error_messages = {
|
|
256
|
+
'aws': (
|
|
257
|
+
"AWS configuration not found. Please either:\n"
|
|
258
|
+
"1. Create a YAML config file with AWS settings, or\n"
|
|
259
|
+
"2. Set AWS_ACCOUNTS environment variable, or\n"
|
|
260
|
+
"3. Run 'ic config init' to set up configuration"
|
|
261
|
+
),
|
|
262
|
+
'azure': (
|
|
263
|
+
"Azure configuration not found. Please either:\n"
|
|
264
|
+
"1. Create a YAML config file with Azure settings, or\n"
|
|
265
|
+
"2. Set AZURE_SUBSCRIPTION_ID environment variable, or\n"
|
|
266
|
+
"3. Run 'ic config init' to set up configuration"
|
|
267
|
+
),
|
|
268
|
+
'gcp': (
|
|
269
|
+
"GCP configuration not found. Please either:\n"
|
|
270
|
+
"1. Create a YAML config file with GCP settings, or\n"
|
|
271
|
+
"2. Set GCP_PROJECT_ID environment variable, or\n"
|
|
272
|
+
"3. Run 'ic config init' to set up configuration"
|
|
273
|
+
),
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
message = error_messages.get(service, f"{service} configuration not found")
|
|
277
|
+
logger.log_error(message)
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
# Export compatibility functions
|
|
281
|
+
__all__ = [
|
|
282
|
+
'ensure_env_compatibility',
|
|
283
|
+
'wrap_command_function',
|
|
284
|
+
'get_legacy_env_vars',
|
|
285
|
+
'migrate_env_to_config_hint',
|
|
286
|
+
'setup_cli_compatibility',
|
|
287
|
+
'get_command_config',
|
|
288
|
+
'handle_missing_config',
|
|
289
|
+
]
|