runbooks 1.0.3__py3-none-any.whl → 1.1.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.
- runbooks/__init__.py +10 -5
- runbooks/__init__.py.backup +134 -0
- runbooks/__init___optimized.py +110 -0
- runbooks/cloudops/base.py +56 -3
- runbooks/cloudops/cost_optimizer.py +496 -42
- runbooks/common/aws_pricing.py +236 -80
- runbooks/common/business_logic.py +485 -0
- runbooks/common/cli_decorators.py +219 -0
- runbooks/common/error_handling.py +424 -0
- runbooks/common/lazy_loader.py +186 -0
- runbooks/common/module_cli_base.py +378 -0
- runbooks/common/performance_monitoring.py +512 -0
- runbooks/common/profile_utils.py +133 -6
- runbooks/enterprise/logging.py +30 -2
- runbooks/enterprise/validation.py +177 -0
- runbooks/finops/README.md +311 -236
- runbooks/finops/aws_client.py +1 -1
- runbooks/finops/business_case_config.py +723 -19
- runbooks/finops/cli.py +136 -0
- runbooks/finops/commvault_ec2_analysis.py +25 -9
- runbooks/finops/config.py +272 -0
- runbooks/finops/dashboard_runner.py +136 -23
- runbooks/finops/ebs_cost_optimizer.py +39 -40
- runbooks/finops/enhanced_trend_visualization.py +7 -2
- runbooks/finops/enterprise_wrappers.py +45 -18
- runbooks/finops/finops_dashboard.py +50 -25
- runbooks/finops/finops_scenarios.py +22 -7
- runbooks/finops/helpers.py +115 -2
- runbooks/finops/multi_dashboard.py +7 -5
- runbooks/finops/optimizer.py +97 -6
- runbooks/finops/scenario_cli_integration.py +247 -0
- runbooks/finops/scenarios.py +12 -1
- runbooks/finops/unlimited_scenarios.py +393 -0
- runbooks/finops/validation_framework.py +19 -7
- runbooks/finops/workspaces_analyzer.py +1 -5
- runbooks/inventory/mcp_inventory_validator.py +2 -1
- runbooks/main.py +132 -94
- runbooks/main_final.py +358 -0
- runbooks/main_minimal.py +84 -0
- runbooks/main_optimized.py +493 -0
- runbooks/main_ultra_minimal.py +47 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/METADATA +1 -1
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/RECORD +47 -31
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/WHEEL +0 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/entry_points.txt +0 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {runbooks-1.0.3.dist-info → runbooks-1.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,493 @@
|
|
1
|
+
"""
|
2
|
+
PERFORMANCE OPTIMIZED CloudOps Runbooks - Enterprise CLI Interface
|
3
|
+
|
4
|
+
## Performance Optimizations Applied
|
5
|
+
|
6
|
+
### 1. Lazy Loading Architecture
|
7
|
+
- Defer AWS session initialization until needed
|
8
|
+
- Defer MCP validator loading until actual validation
|
9
|
+
- Defer pricing API calls until cost analysis operations
|
10
|
+
- Keep basic CLI operations (--help, --version) lightning fast
|
11
|
+
|
12
|
+
### 2. Startup Experience Optimization
|
13
|
+
- Move enterprise validation to on-demand loading
|
14
|
+
- Eliminate pricing API failures during basic operations
|
15
|
+
- Clean up warning pollution for simple commands
|
16
|
+
- Progressive disclosure of enterprise features
|
17
|
+
|
18
|
+
### 3. Import Optimization
|
19
|
+
- Critical imports only at module level
|
20
|
+
- Expensive imports deferred using lazy_loader
|
21
|
+
- Basic CLI functionality remains fast
|
22
|
+
|
23
|
+
## Performance Targets:
|
24
|
+
- Basic CLI operations < 0.5s
|
25
|
+
- Zero warnings for --help, --version
|
26
|
+
- Clean startup without overhead
|
27
|
+
"""
|
28
|
+
|
29
|
+
import sys
|
30
|
+
from datetime import datetime
|
31
|
+
from pathlib import Path
|
32
|
+
from typing import Optional
|
33
|
+
import os
|
34
|
+
|
35
|
+
import click
|
36
|
+
from loguru import logger
|
37
|
+
|
38
|
+
# Import lazy loading architecture FIRST
|
39
|
+
from runbooks.common.lazy_loader import (
|
40
|
+
lazy_rich_console,
|
41
|
+
lazy_aws_session,
|
42
|
+
lazy_mcp_validator,
|
43
|
+
lazy_performance_monitor,
|
44
|
+
lazy_pricing_api,
|
45
|
+
lazy_inventory_collector,
|
46
|
+
fast_startup_mode,
|
47
|
+
defer_expensive_imports,
|
48
|
+
requires_aws,
|
49
|
+
requires_mcp
|
50
|
+
)
|
51
|
+
|
52
|
+
# Enable deferred imports for startup optimization
|
53
|
+
defer_expensive_imports()
|
54
|
+
|
55
|
+
# Fast Rich console loading
|
56
|
+
try:
|
57
|
+
from rich.console import Console
|
58
|
+
from rich.table import Table
|
59
|
+
from rich.markup import escape
|
60
|
+
_HAS_RICH = True
|
61
|
+
except ImportError:
|
62
|
+
_HAS_RICH = False
|
63
|
+
# Fallback console implementation
|
64
|
+
class Console:
|
65
|
+
def print(self, *args, **kwargs):
|
66
|
+
output = " ".join(str(arg) for arg in args)
|
67
|
+
print(output)
|
68
|
+
|
69
|
+
# Basic imports only - no heavy AWS/MCP initialization
|
70
|
+
from runbooks import __version__
|
71
|
+
|
72
|
+
# Lazy imports for performance-critical operations
|
73
|
+
def get_assessment_runner():
|
74
|
+
"""Lazy load CFAT assessment runner."""
|
75
|
+
from runbooks.cfat.runner import AssessmentRunner
|
76
|
+
return AssessmentRunner
|
77
|
+
|
78
|
+
def get_profile_utils():
|
79
|
+
"""Lazy load profile utilities."""
|
80
|
+
from runbooks.common.profile_utils import (
|
81
|
+
create_management_session,
|
82
|
+
create_operational_session,
|
83
|
+
get_profile_for_operation,
|
84
|
+
)
|
85
|
+
return {
|
86
|
+
'create_management_session': create_management_session,
|
87
|
+
'create_operational_session': create_operational_session,
|
88
|
+
'get_profile_for_operation': get_profile_for_operation,
|
89
|
+
}
|
90
|
+
|
91
|
+
def get_rich_utils():
|
92
|
+
"""Lazy load Rich utilities."""
|
93
|
+
from runbooks.common.rich_utils import (
|
94
|
+
console, create_table, print_banner, print_header, print_status
|
95
|
+
)
|
96
|
+
return {
|
97
|
+
'console': console,
|
98
|
+
'create_table': create_table,
|
99
|
+
'print_banner': print_banner,
|
100
|
+
'print_header': print_header,
|
101
|
+
'print_status': print_status,
|
102
|
+
}
|
103
|
+
|
104
|
+
def get_config_utils():
|
105
|
+
"""Lazy load configuration utilities."""
|
106
|
+
from runbooks.config import load_config, save_config
|
107
|
+
return {'load_config': load_config, 'save_config': save_config}
|
108
|
+
|
109
|
+
def get_logging_utils():
|
110
|
+
"""Lazy load logging utilities."""
|
111
|
+
from runbooks.utils import setup_logging, setup_enhanced_logging
|
112
|
+
return {'setup_logging': setup_logging, 'setup_enhanced_logging': setup_enhanced_logging}
|
113
|
+
|
114
|
+
def get_business_case_utils():
|
115
|
+
"""Lazy load business case utilities."""
|
116
|
+
from runbooks.finops.business_case_config import get_business_case_config, format_business_achievement
|
117
|
+
return {
|
118
|
+
'get_business_case_config': get_business_case_config,
|
119
|
+
'format_business_achievement': format_business_achievement
|
120
|
+
}
|
121
|
+
|
122
|
+
# Global console for basic operations
|
123
|
+
console = Console()
|
124
|
+
|
125
|
+
# ============================================================================
|
126
|
+
# CLI ARGUMENT FIXES - Handle Profile Tuples and Export Format Issues
|
127
|
+
# ============================================================================
|
128
|
+
|
129
|
+
def normalize_profile_parameter(profile_param):
|
130
|
+
"""
|
131
|
+
Normalize profile parameter from Click multiple=True tuple to string.
|
132
|
+
|
133
|
+
Args:
|
134
|
+
profile_param: Profile parameter from Click (could be tuple, list, or string)
|
135
|
+
|
136
|
+
Returns:
|
137
|
+
str: Single profile name for AWS operations
|
138
|
+
"""
|
139
|
+
if profile_param is None:
|
140
|
+
return None
|
141
|
+
|
142
|
+
# Handle tuple/list from Click multiple=True
|
143
|
+
if isinstance(profile_param, (tuple, list)):
|
144
|
+
# Take the first profile if multiple provided
|
145
|
+
return profile_param[0] if len(profile_param) > 0 else None
|
146
|
+
|
147
|
+
# Handle string directly
|
148
|
+
return profile_param
|
149
|
+
|
150
|
+
# Performance monitoring decorator
|
151
|
+
def track_performance(operation_name: str):
|
152
|
+
"""Decorator to track CLI operation performance."""
|
153
|
+
def decorator(func):
|
154
|
+
def wrapper(*args, **kwargs):
|
155
|
+
if fast_startup_mode():
|
156
|
+
# Skip performance tracking for fast operations
|
157
|
+
return func(*args, **kwargs)
|
158
|
+
|
159
|
+
start_time = datetime.now()
|
160
|
+
try:
|
161
|
+
result = func(*args, **kwargs)
|
162
|
+
end_time = datetime.now()
|
163
|
+
duration = (end_time - start_time).total_seconds()
|
164
|
+
|
165
|
+
# Only log if operation takes >0.1s to avoid spam
|
166
|
+
if duration > 0.1:
|
167
|
+
logger.debug(f"Operation '{operation_name}' completed in {duration:.3f}s")
|
168
|
+
|
169
|
+
return result
|
170
|
+
except Exception as e:
|
171
|
+
end_time = datetime.now()
|
172
|
+
duration = (end_time - start_time).total_seconds()
|
173
|
+
logger.error(f"Operation '{operation_name}' failed after {duration:.3f}s: {e}")
|
174
|
+
raise
|
175
|
+
return wrapper
|
176
|
+
return decorator
|
177
|
+
|
178
|
+
# ============================================================================
|
179
|
+
# CLI MAIN ENTRY POINT - OPTIMIZED FOR PERFORMANCE
|
180
|
+
# ============================================================================
|
181
|
+
|
182
|
+
@click.group()
|
183
|
+
@click.version_option(version=__version__, prog_name="runbooks")
|
184
|
+
@click.option('--debug', is_flag=True, help='Enable debug logging')
|
185
|
+
@click.option('--profile', help='AWS profile to use')
|
186
|
+
@click.pass_context
|
187
|
+
def cli(ctx: click.Context, debug: bool, profile: str):
|
188
|
+
"""
|
189
|
+
CloudOps Runbooks - Enterprise AWS Automation Platform
|
190
|
+
|
191
|
+
Fast, enterprise-grade automation for CloudOps, DevOps, and SRE teams.
|
192
|
+
|
193
|
+
Performance optimized for sub-second response times.
|
194
|
+
"""
|
195
|
+
# Fast context setup
|
196
|
+
ctx.ensure_object(dict)
|
197
|
+
ctx.obj['profile'] = profile
|
198
|
+
ctx.obj['debug'] = debug
|
199
|
+
|
200
|
+
# Only setup logging if not a fast operation
|
201
|
+
if not fast_startup_mode() and debug:
|
202
|
+
setup_logging = get_logging_utils()['setup_logging']
|
203
|
+
setup_logging(debug=debug)
|
204
|
+
|
205
|
+
@cli.command()
|
206
|
+
@track_performance("version")
|
207
|
+
def version():
|
208
|
+
"""Show version information (fast operation)."""
|
209
|
+
console.print(f"CloudOps Runbooks v{__version__}")
|
210
|
+
console.print("Enterprise AWS Automation Platform")
|
211
|
+
|
212
|
+
@cli.command()
|
213
|
+
@track_performance("status")
|
214
|
+
def status():
|
215
|
+
"""Show system status (fast operation)."""
|
216
|
+
console.print("🚀 CloudOps Runbooks Status")
|
217
|
+
console.print(f"Version: {__version__}")
|
218
|
+
console.print("Status: Ready")
|
219
|
+
|
220
|
+
# Only check AWS if explicitly requested (not for basic status)
|
221
|
+
import sys
|
222
|
+
if '--aws' in sys.argv:
|
223
|
+
check_aws_status()
|
224
|
+
|
225
|
+
def check_aws_status():
|
226
|
+
"""Check AWS connectivity (lazy loaded)."""
|
227
|
+
try:
|
228
|
+
session = lazy_aws_session()
|
229
|
+
console.print("AWS: Connected")
|
230
|
+
except Exception as e:
|
231
|
+
console.print(f"AWS: Error - {e}")
|
232
|
+
|
233
|
+
# ============================================================================
|
234
|
+
# FINOPS COMMANDS - WITH LAZY LOADING
|
235
|
+
# ============================================================================
|
236
|
+
|
237
|
+
@cli.group()
|
238
|
+
def finops():
|
239
|
+
"""Financial Operations and Cost Analysis"""
|
240
|
+
pass
|
241
|
+
|
242
|
+
@finops.command()
|
243
|
+
@click.option('--profile', help='AWS profile to use')
|
244
|
+
@click.option('--export', type=click.Choice(['csv', 'json', 'html', 'pdf']), help='Export format')
|
245
|
+
@click.option('--output-file', type=click.Path(), help='Output file path')
|
246
|
+
@click.option('--mcp-validation', is_flag=True, help='Enable MCP validation')
|
247
|
+
@track_performance("finops_dashboard")
|
248
|
+
@requires_aws
|
249
|
+
def dashboard(profile: str, export: str, output_file: str, mcp_validation: bool):
|
250
|
+
"""Run FinOps cost analysis dashboard (lazy loaded)."""
|
251
|
+
# Lazy load FinOps components only when needed
|
252
|
+
from runbooks.finops.dashboard_runner import run_dashboard
|
253
|
+
|
254
|
+
profile_utils = get_profile_utils()
|
255
|
+
rich_utils = get_rich_utils()
|
256
|
+
|
257
|
+
# Normalize profile parameter
|
258
|
+
normalized_profile = normalize_profile_parameter(profile)
|
259
|
+
|
260
|
+
console.print("🚀 Starting FinOps Dashboard Analysis...")
|
261
|
+
|
262
|
+
# Optional MCP validation
|
263
|
+
if mcp_validation:
|
264
|
+
validator = lazy_mcp_validator()
|
265
|
+
console.print("📊 MCP validation enabled")
|
266
|
+
|
267
|
+
# Run dashboard with lazy-loaded components
|
268
|
+
try:
|
269
|
+
result = run_dashboard(
|
270
|
+
profile=normalized_profile,
|
271
|
+
export_format=export,
|
272
|
+
output_file=output_file
|
273
|
+
)
|
274
|
+
console.print("✅ FinOps analysis completed successfully")
|
275
|
+
return result
|
276
|
+
except Exception as e:
|
277
|
+
console.print(f"❌ FinOps analysis failed: {e}")
|
278
|
+
raise
|
279
|
+
|
280
|
+
# ============================================================================
|
281
|
+
# INVENTORY COMMANDS - WITH LAZY LOADING
|
282
|
+
# ============================================================================
|
283
|
+
|
284
|
+
@cli.group()
|
285
|
+
def inventory():
|
286
|
+
"""Resource Discovery and Inventory Management"""
|
287
|
+
pass
|
288
|
+
|
289
|
+
@inventory.command()
|
290
|
+
@click.option('--profile', help='AWS profile to use')
|
291
|
+
@click.option('--regions', multiple=True, help='AWS regions to scan')
|
292
|
+
@click.option('--services', multiple=True, help='AWS services to include')
|
293
|
+
@click.option('--export', type=click.Choice(['csv', 'json', 'yaml']), help='Export format')
|
294
|
+
@track_performance("inventory_collect")
|
295
|
+
@requires_aws
|
296
|
+
def collect(profile: str, regions: tuple, services: tuple, export: str):
|
297
|
+
"""Collect comprehensive inventory across AWS accounts (lazy loaded)."""
|
298
|
+
# Lazy load inventory collector only when needed
|
299
|
+
InventoryCollector = lazy_inventory_collector()
|
300
|
+
|
301
|
+
profile_utils = get_profile_utils()
|
302
|
+
|
303
|
+
# Normalize profile parameter
|
304
|
+
normalized_profile = normalize_profile_parameter(profile)
|
305
|
+
|
306
|
+
console.print("🔍 Starting inventory collection...")
|
307
|
+
|
308
|
+
# Create collector with lazy-loaded session
|
309
|
+
session = lazy_aws_session()
|
310
|
+
collector = InventoryCollector(session=session)
|
311
|
+
|
312
|
+
try:
|
313
|
+
result = collector.collect_all(
|
314
|
+
profile=normalized_profile,
|
315
|
+
regions=list(regions) if regions else None,
|
316
|
+
services=list(services) if services else None,
|
317
|
+
export_format=export
|
318
|
+
)
|
319
|
+
console.print("✅ Inventory collection completed successfully")
|
320
|
+
return result
|
321
|
+
except Exception as e:
|
322
|
+
console.print(f"❌ Inventory collection failed: {e}")
|
323
|
+
raise
|
324
|
+
|
325
|
+
# ============================================================================
|
326
|
+
# SECURITY COMMANDS - WITH LAZY LOADING
|
327
|
+
# ============================================================================
|
328
|
+
|
329
|
+
@cli.group()
|
330
|
+
def security():
|
331
|
+
"""Security Assessment and Compliance"""
|
332
|
+
pass
|
333
|
+
|
334
|
+
@security.command()
|
335
|
+
@click.option('--profile', help='AWS profile to use')
|
336
|
+
@click.option('--frameworks', multiple=True, help='Compliance frameworks to check')
|
337
|
+
@click.option('--export', type=click.Choice(['csv', 'json', 'html']), help='Export format')
|
338
|
+
@track_performance("security_assess")
|
339
|
+
@requires_aws
|
340
|
+
def assess(profile: str, frameworks: tuple, export: str):
|
341
|
+
"""Run security baseline assessment (lazy loaded)."""
|
342
|
+
# Lazy load security components only when needed
|
343
|
+
from runbooks.security.security_baseline_tester import SecurityBaselineTester
|
344
|
+
|
345
|
+
profile_utils = get_profile_utils()
|
346
|
+
|
347
|
+
# Normalize profile parameter
|
348
|
+
normalized_profile = normalize_profile_parameter(profile)
|
349
|
+
|
350
|
+
console.print("🔒 Starting security assessment...")
|
351
|
+
|
352
|
+
# Create tester with lazy-loaded session
|
353
|
+
session = lazy_aws_session()
|
354
|
+
tester = SecurityBaselineTester(session=session)
|
355
|
+
|
356
|
+
try:
|
357
|
+
result = tester.run_assessment(
|
358
|
+
profile=normalized_profile,
|
359
|
+
frameworks=list(frameworks) if frameworks else None,
|
360
|
+
export_format=export
|
361
|
+
)
|
362
|
+
console.print("✅ Security assessment completed successfully")
|
363
|
+
return result
|
364
|
+
except Exception as e:
|
365
|
+
console.print(f"❌ Security assessment failed: {e}")
|
366
|
+
raise
|
367
|
+
|
368
|
+
# ============================================================================
|
369
|
+
# OPERATE COMMANDS - WITH LAZY LOADING
|
370
|
+
# ============================================================================
|
371
|
+
|
372
|
+
@cli.group()
|
373
|
+
def operate():
|
374
|
+
"""AWS Resource Operations and Automation"""
|
375
|
+
pass
|
376
|
+
|
377
|
+
@operate.command()
|
378
|
+
@click.option('--profile', help='AWS profile to use')
|
379
|
+
@click.option('--dry-run', is_flag=True, default=True, help='Dry run mode (default: enabled)')
|
380
|
+
@track_performance("operate_ec2")
|
381
|
+
@requires_aws
|
382
|
+
def ec2(profile: str, dry_run: bool):
|
383
|
+
"""EC2 resource operations (lazy loaded)."""
|
384
|
+
# Lazy load EC2 operations only when needed
|
385
|
+
from runbooks.operate.ec2_operations import EC2Operations
|
386
|
+
|
387
|
+
# Normalize profile parameter
|
388
|
+
normalized_profile = normalize_profile_parameter(profile)
|
389
|
+
|
390
|
+
console.print("⚡ Starting EC2 operations...")
|
391
|
+
|
392
|
+
if dry_run:
|
393
|
+
console.print("🔒 Running in dry-run mode (no changes will be made)")
|
394
|
+
|
395
|
+
# Create operations with lazy-loaded session
|
396
|
+
session = lazy_aws_session()
|
397
|
+
ec2_ops = EC2Operations(session=session)
|
398
|
+
|
399
|
+
try:
|
400
|
+
result = ec2_ops.list_instances(
|
401
|
+
profile=normalized_profile,
|
402
|
+
dry_run=dry_run
|
403
|
+
)
|
404
|
+
console.print("✅ EC2 operations completed successfully")
|
405
|
+
return result
|
406
|
+
except Exception as e:
|
407
|
+
console.print(f"❌ EC2 operations failed: {e}")
|
408
|
+
raise
|
409
|
+
|
410
|
+
# ============================================================================
|
411
|
+
# CFAT COMMANDS - WITH LAZY LOADING
|
412
|
+
# ============================================================================
|
413
|
+
|
414
|
+
@cli.group()
|
415
|
+
def cfat():
|
416
|
+
"""Cloud Foundations Assessment Tool"""
|
417
|
+
pass
|
418
|
+
|
419
|
+
@cfat.command()
|
420
|
+
@click.option('--profile', help='AWS profile to use')
|
421
|
+
@click.option('--output-file', type=click.Path(), help='Assessment report output file')
|
422
|
+
@track_performance("cfat_assess")
|
423
|
+
@requires_aws
|
424
|
+
def assess(profile: str, output_file: str):
|
425
|
+
"""Run Cloud Foundations Assessment (lazy loaded)."""
|
426
|
+
# Lazy load CFAT components only when needed
|
427
|
+
AssessmentRunner = get_assessment_runner()
|
428
|
+
|
429
|
+
# Normalize profile parameter
|
430
|
+
normalized_profile = normalize_profile_parameter(profile)
|
431
|
+
|
432
|
+
console.print("🏛️ Starting Cloud Foundations Assessment...")
|
433
|
+
|
434
|
+
# Create runner with lazy-loaded session
|
435
|
+
session = lazy_aws_session()
|
436
|
+
runner = AssessmentRunner(session=session)
|
437
|
+
|
438
|
+
try:
|
439
|
+
result = runner.run_assessment(
|
440
|
+
profile=normalized_profile,
|
441
|
+
output_file=output_file
|
442
|
+
)
|
443
|
+
console.print("✅ CFAT assessment completed successfully")
|
444
|
+
return result
|
445
|
+
except Exception as e:
|
446
|
+
console.print(f"❌ CFAT assessment failed: {e}")
|
447
|
+
raise
|
448
|
+
|
449
|
+
# ============================================================================
|
450
|
+
# PERFORMANCE DIAGNOSTICS
|
451
|
+
# ============================================================================
|
452
|
+
|
453
|
+
@cli.command()
|
454
|
+
@track_performance("perf_test")
|
455
|
+
def perf():
|
456
|
+
"""Performance diagnostics and benchmarking."""
|
457
|
+
start_time = datetime.now()
|
458
|
+
|
459
|
+
console.print("🚀 Performance Diagnostics")
|
460
|
+
console.print(f"Startup Time: {(datetime.now() - start_time).total_seconds():.3f}s")
|
461
|
+
|
462
|
+
# Test lazy loading performance
|
463
|
+
console.print("\n📊 Component Loading Times:")
|
464
|
+
|
465
|
+
# Test Rich loading
|
466
|
+
rich_start = datetime.now()
|
467
|
+
lazy_rich_console()
|
468
|
+
rich_time = (datetime.now() - rich_start).total_seconds()
|
469
|
+
console.print(f"Rich Console: {rich_time:.3f}s")
|
470
|
+
|
471
|
+
# Test AWS session (only if credentials available)
|
472
|
+
try:
|
473
|
+
aws_start = datetime.now()
|
474
|
+
lazy_aws_session()
|
475
|
+
aws_time = (datetime.now() - aws_start).total_seconds()
|
476
|
+
console.print(f"AWS Session: {aws_time:.3f}s")
|
477
|
+
except Exception:
|
478
|
+
console.print("AWS Session: Not available (no credentials)")
|
479
|
+
|
480
|
+
# Test MCP validator
|
481
|
+
try:
|
482
|
+
mcp_start = datetime.now()
|
483
|
+
lazy_mcp_validator()
|
484
|
+
mcp_time = (datetime.now() - mcp_start).total_seconds()
|
485
|
+
console.print(f"MCP Validator: {mcp_time:.3f}s")
|
486
|
+
except Exception:
|
487
|
+
console.print("MCP Validator: Not available")
|
488
|
+
|
489
|
+
total_time = (datetime.now() - start_time).total_seconds()
|
490
|
+
console.print(f"\n⏱️ Total Diagnostic Time: {total_time:.3f}s")
|
491
|
+
|
492
|
+
if __name__ == "__main__":
|
493
|
+
cli()
|
@@ -0,0 +1,47 @@
|
|
1
|
+
"""
|
2
|
+
ULTRA MINIMAL CloudOps Runbooks CLI - Performance Baseline Test
|
3
|
+
|
4
|
+
This version avoids ALL runbooks imports to isolate the performance issue.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import sys
|
8
|
+
import click
|
9
|
+
from datetime import datetime
|
10
|
+
|
11
|
+
# Hard-code version to avoid import chain
|
12
|
+
__version__ = "1.0.0"
|
13
|
+
|
14
|
+
@click.group()
|
15
|
+
@click.version_option(version=__version__, prog_name="runbooks")
|
16
|
+
@click.pass_context
|
17
|
+
def cli(ctx: click.Context):
|
18
|
+
"""
|
19
|
+
CloudOps Runbooks - Ultra Minimal Test Version
|
20
|
+
|
21
|
+
Testing CLI performance without any runbooks imports.
|
22
|
+
"""
|
23
|
+
ctx.ensure_object(dict)
|
24
|
+
|
25
|
+
@cli.command()
|
26
|
+
def version():
|
27
|
+
"""Show version information."""
|
28
|
+
print(f"CloudOps Runbooks v{__version__}")
|
29
|
+
|
30
|
+
@cli.command()
|
31
|
+
def status():
|
32
|
+
"""Show basic status."""
|
33
|
+
print("🚀 CloudOps Runbooks Status")
|
34
|
+
print(f"Version: {__version__}")
|
35
|
+
print("Status: Ready")
|
36
|
+
|
37
|
+
@cli.command()
|
38
|
+
def perf():
|
39
|
+
"""Test CLI performance baseline."""
|
40
|
+
start_time = datetime.now()
|
41
|
+
print("🚀 Performance Test")
|
42
|
+
end_time = datetime.now()
|
43
|
+
duration = (end_time - start_time).total_seconds()
|
44
|
+
print(f"Command execution: {duration:.3f}s")
|
45
|
+
|
46
|
+
if __name__ == "__main__":
|
47
|
+
cli()
|