- Delete .aitbc.yaml.example CLI configuration template - Delete .lycheeignore link checker exclusion rules - Delete .nvmrc Node.js version specification - Add advanced search panel with filters for address, amount range, transaction type, time range, and validator - Add analytics dashboard with transaction volume, active addresses, and block time metrics - Add Chart.js integration
404 lines
13 KiB
Python
404 lines
13 KiB
Python
"""
|
|
Test for production deployment and scaling system
|
|
"""
|
|
|
|
import asyncio
|
|
import pytest
|
|
from datetime import datetime, timedelta
|
|
from pathlib import Path
|
|
from aitbc_cli.core.deployment import (
|
|
ProductionDeployment, DeploymentConfig, DeploymentMetrics,
|
|
ScalingEvent, ScalingPolicy, DeploymentStatus
|
|
)
|
|
|
|
def test_deployment_creation():
|
|
"""Test deployment system creation"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
assert deployment.config_path == Path("/tmp/test_aitbc")
|
|
assert deployment.deployments == {}
|
|
assert deployment.metrics == {}
|
|
assert deployment.scaling_events == []
|
|
assert deployment.health_checks == {}
|
|
|
|
# Check directories were created
|
|
assert deployment.deployment_dir.exists()
|
|
assert deployment.config_dir.exists()
|
|
assert deployment.logs_dir.exists()
|
|
assert deployment.backups_dir.exists()
|
|
|
|
async def test_create_deployment_config():
|
|
"""Test deployment configuration creation"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Create deployment
|
|
deployment_id = await deployment.create_deployment(
|
|
name="test-deployment",
|
|
environment="production",
|
|
region="us-west-1",
|
|
instance_type="t3.medium",
|
|
min_instances=1,
|
|
max_instances=10,
|
|
desired_instances=2,
|
|
port=8080,
|
|
domain="test.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": "aitbc"}
|
|
)
|
|
|
|
assert deployment_id is not None
|
|
assert deployment_id in deployment.deployments
|
|
|
|
config = deployment.deployments[deployment_id]
|
|
assert config.name == "test-deployment"
|
|
assert config.environment == "production"
|
|
assert config.min_instances == 1
|
|
assert config.max_instances == 10
|
|
assert config.desired_instances == 2
|
|
assert config.scaling_policy == ScalingPolicy.AUTO
|
|
assert config.port == 8080
|
|
assert config.domain == "test.aitbc.dev"
|
|
|
|
async def test_deployment_application():
|
|
"""Test application deployment"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Create deployment first
|
|
deployment_id = await deployment.create_deployment(
|
|
name="test-app",
|
|
environment="staging",
|
|
region="us-east-1",
|
|
instance_type="t3.small",
|
|
min_instances=1,
|
|
max_instances=5,
|
|
desired_instances=2,
|
|
port=3000,
|
|
domain="staging.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": "aitbc_staging"}
|
|
)
|
|
|
|
# Mock the infrastructure deployment (skip actual system calls)
|
|
original_deploy_infra = deployment._deploy_infrastructure
|
|
async def mock_deploy_infra(dep_config):
|
|
print(f"Mock infrastructure deployment for {dep_config.name}")
|
|
return True
|
|
|
|
deployment._deploy_infrastructure = mock_deploy_infra
|
|
|
|
# Deploy application
|
|
success = await deployment.deploy_application(deployment_id)
|
|
|
|
assert success
|
|
assert deployment_id in deployment.health_checks
|
|
assert deployment.health_checks[deployment_id] == True
|
|
assert deployment_id in deployment.metrics
|
|
|
|
# Restore original method
|
|
deployment._deploy_infrastructure = original_deploy_infra
|
|
|
|
async def test_manual_scaling():
|
|
"""Test manual scaling"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Create deployment
|
|
deployment_id = await deployment.create_deployment(
|
|
name="scale-test",
|
|
environment="production",
|
|
region="us-west-2",
|
|
instance_type="t3.medium",
|
|
min_instances=1,
|
|
max_instances=10,
|
|
desired_instances=2,
|
|
port=8080,
|
|
domain="scale.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": "aitbc"}
|
|
)
|
|
|
|
# Mock infrastructure deployment
|
|
original_deploy_infra = deployment._deploy_infrastructure
|
|
async def mock_deploy_infra(dep_config):
|
|
return True
|
|
deployment._deploy_infrastructure = mock_deploy_infra
|
|
|
|
# Deploy first
|
|
await deployment.deploy_application(deployment_id)
|
|
|
|
# Scale up
|
|
success = await deployment.scale_deployment(deployment_id, 5, "manual scaling test")
|
|
|
|
assert success
|
|
|
|
# Check deployment was updated
|
|
config = deployment.deployments[deployment_id]
|
|
assert config.desired_instances == 5
|
|
|
|
# Check scaling event was created
|
|
scaling_events = [e for e in deployment.scaling_events if e.deployment_id == deployment_id]
|
|
assert len(scaling_events) > 0
|
|
|
|
latest_event = scaling_events[-1]
|
|
assert latest_event.old_instances == 2
|
|
assert latest_event.new_instances == 5
|
|
assert latest_event.success == True
|
|
assert latest_event.trigger_reason == "manual scaling test"
|
|
|
|
# Restore original method
|
|
deployment._deploy_infrastructure = original_deploy_infra
|
|
|
|
async def test_auto_scaling():
|
|
"""Test automatic scaling"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Create deployment
|
|
deployment_id = await deployment.create_deployment(
|
|
name="auto-scale-test",
|
|
environment="production",
|
|
region="us-east-1",
|
|
instance_type="t3.medium",
|
|
min_instances=1,
|
|
max_instances=10,
|
|
desired_instances=2,
|
|
port=8080,
|
|
domain="autoscale.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": "aitbc"}
|
|
)
|
|
|
|
# Mock infrastructure deployment
|
|
original_deploy_infra = deployment._deploy_infrastructure
|
|
async def mock_deploy_infra(dep_config):
|
|
return True
|
|
deployment._deploy_infrastructure = mock_deploy_infra
|
|
|
|
# Deploy first
|
|
await deployment.deploy_application(deployment_id)
|
|
|
|
# Set metrics to trigger scale up (high CPU)
|
|
metrics = deployment.metrics[deployment_id]
|
|
metrics.cpu_usage = 85.0 # Above threshold
|
|
metrics.memory_usage = 40.0
|
|
metrics.error_rate = 1.0
|
|
metrics.response_time = 500.0
|
|
|
|
# Trigger auto-scaling
|
|
success = await deployment.auto_scale_deployment(deployment_id)
|
|
|
|
assert success
|
|
|
|
# Check deployment was scaled up
|
|
config = deployment.deployments[deployment_id]
|
|
assert config.desired_instances == 3 # Should have scaled up by 1
|
|
|
|
# Set metrics to trigger scale down
|
|
metrics.cpu_usage = 15.0 # Below threshold
|
|
metrics.memory_usage = 25.0
|
|
|
|
# Trigger auto-scaling again
|
|
success = await deployment.auto_scale_deployment(deployment_id)
|
|
|
|
assert success
|
|
|
|
# Check deployment was scaled down
|
|
config = deployment.deployments[deployment_id]
|
|
assert config.desired_instances == 2 # Should have scaled down by 1
|
|
|
|
# Restore original method
|
|
deployment._deploy_infrastructure = original_deploy_infra
|
|
|
|
async def test_deployment_status():
|
|
"""Test deployment status retrieval"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Create and deploy
|
|
deployment_id = await deployment.create_deployment(
|
|
name="status-test",
|
|
environment="production",
|
|
region="us-west-1",
|
|
instance_type="t3.medium",
|
|
min_instances=1,
|
|
max_instances=5,
|
|
desired_instances=2,
|
|
port=8080,
|
|
domain="status.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": "aitbc"}
|
|
)
|
|
|
|
# Mock infrastructure deployment
|
|
original_deploy_infra = deployment._deploy_infrastructure
|
|
async def mock_deploy_infra(dep_config):
|
|
return True
|
|
deployment._deploy_infrastructure = mock_deploy_infra
|
|
|
|
await deployment.deploy_application(deployment_id)
|
|
|
|
# Get status
|
|
status = await deployment.get_deployment_status(deployment_id)
|
|
|
|
assert status is not None
|
|
assert "deployment" in status
|
|
assert "metrics" in status
|
|
assert "health_status" in status
|
|
assert "recent_scaling_events" in status
|
|
assert "uptime_percentage" in status
|
|
|
|
# Check deployment info
|
|
deployment_info = status["deployment"]
|
|
assert deployment_info["name"] == "status-test"
|
|
assert deployment_info["environment"] == "production"
|
|
assert deployment_info["desired_instances"] == 2
|
|
|
|
# Check health status
|
|
assert status["health_status"] == True
|
|
|
|
# Check metrics
|
|
metrics = status["metrics"]
|
|
assert metrics["deployment_id"] == deployment_id
|
|
assert metrics["cpu_usage"] >= 0
|
|
assert metrics["memory_usage"] >= 0
|
|
|
|
# Restore original method
|
|
deployment._deploy_infrastructure = original_deploy_infra
|
|
|
|
async def test_cluster_overview():
|
|
"""Test cluster overview"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Mock infrastructure deployment
|
|
original_deploy_infra = deployment._deploy_infrastructure
|
|
async def mock_deploy_infra(dep_config):
|
|
return True
|
|
deployment._deploy_infrastructure = mock_deploy_infra
|
|
|
|
# Create multiple deployments
|
|
deployment_ids = []
|
|
for i in range(3):
|
|
deployment_id = await deployment.create_deployment(
|
|
name=f"cluster-test-{i+1}",
|
|
environment="production" if i % 2 == 0 else "staging",
|
|
region="us-west-1",
|
|
instance_type="t3.medium",
|
|
min_instances=1,
|
|
max_instances=5,
|
|
desired_instances=2,
|
|
port=8080 + i,
|
|
domain=f"test{i+1}.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": f"aitbc_{i+1}"}
|
|
)
|
|
|
|
await deployment.deploy_application(deployment_id)
|
|
deployment_ids.append(deployment_id)
|
|
|
|
# Get cluster overview
|
|
overview = await deployment.get_cluster_overview()
|
|
|
|
assert overview is not None
|
|
assert "total_deployments" in overview
|
|
assert "running_deployments" in overview
|
|
assert "total_instances" in overview
|
|
assert "aggregate_metrics" in overview
|
|
assert "recent_scaling_events" in overview
|
|
assert "successful_scaling_rate" in overview
|
|
assert "health_check_coverage" in overview
|
|
|
|
# Check overview data
|
|
assert overview["total_deployments"] == 3
|
|
assert overview["running_deployments"] == 3
|
|
assert overview["total_instances"] == 6 # 2 instances per deployment
|
|
assert overview["health_check_coverage"] == 1.0 # 100% coverage
|
|
|
|
# Restore original method
|
|
deployment._deploy_infrastructure = original_deploy_infra
|
|
|
|
def test_scaling_thresholds():
|
|
"""Test scaling threshold configuration"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Check default thresholds
|
|
assert deployment.scaling_thresholds['cpu_high'] == 80.0
|
|
assert deployment.scaling_thresholds['cpu_low'] == 20.0
|
|
assert deployment.scaling_thresholds['memory_high'] == 85.0
|
|
assert deployment.scaling_thresholds['memory_low'] == 30.0
|
|
assert deployment.scaling_thresholds['error_rate_high'] == 5.0
|
|
assert deployment.scaling_thresholds['response_time_high'] == 2000.0
|
|
assert deployment.scaling_thresholds['min_uptime'] == 99.0
|
|
|
|
async def test_deployment_config_validation():
|
|
"""Test deployment configuration validation"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Test valid configuration
|
|
deployment_id = await deployment.create_deployment(
|
|
name="valid-config",
|
|
environment="production",
|
|
region="us-west-1",
|
|
instance_type="t3.medium",
|
|
min_instances=1,
|
|
max_instances=10,
|
|
desired_instances=5,
|
|
port=8080,
|
|
domain="valid.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": "aitbc"}
|
|
)
|
|
|
|
assert deployment_id is not None
|
|
|
|
config = deployment.deployments[deployment_id]
|
|
assert config.min_instances <= config.desired_instances <= config.max_instances
|
|
|
|
async def test_metrics_initialization():
|
|
"""Test metrics initialization"""
|
|
deployment = ProductionDeployment("/tmp/test_aitbc")
|
|
|
|
# Create deployment
|
|
deployment_id = await deployment.create_deployment(
|
|
name="metrics-test",
|
|
environment="production",
|
|
region="us-west-1",
|
|
instance_type="t3.medium",
|
|
min_instances=1,
|
|
max_instances=5,
|
|
desired_instances=2,
|
|
port=8080,
|
|
domain="metrics.aitbc.dev",
|
|
database_config={"host": "localhost", "port": 5432, "name": "aitbc"}
|
|
)
|
|
|
|
# Mock infrastructure deployment
|
|
original_deploy_infra = deployment._deploy_infrastructure
|
|
async def mock_deploy_infra(dep_config):
|
|
return True
|
|
deployment._deploy_infrastructure = mock_deploy_infra
|
|
|
|
# Deploy to initialize metrics
|
|
await deployment.deploy_application(deployment_id)
|
|
|
|
# Check metrics were initialized
|
|
metrics = deployment.metrics[deployment_id]
|
|
assert metrics.deployment_id == deployment_id
|
|
assert metrics.cpu_usage >= 0
|
|
assert metrics.memory_usage >= 0
|
|
assert metrics.disk_usage >= 0
|
|
assert metrics.request_count >= 0
|
|
assert metrics.error_rate >= 0
|
|
assert metrics.response_time >= 0
|
|
assert metrics.uptime_percentage >= 0
|
|
assert metrics.active_instances >= 1
|
|
|
|
# Restore original method
|
|
deployment._deploy_infrastructure = original_deploy_infra
|
|
|
|
if __name__ == "__main__":
|
|
# Run basic tests
|
|
test_deployment_creation()
|
|
test_scaling_thresholds()
|
|
|
|
# Run async tests
|
|
asyncio.run(test_create_deployment_config())
|
|
asyncio.run(test_deployment_application())
|
|
asyncio.run(test_manual_scaling())
|
|
asyncio.run(test_auto_scaling())
|
|
asyncio.run(test_deployment_status())
|
|
asyncio.run(test_cluster_overview())
|
|
asyncio.run(test_deployment_config_validation())
|
|
asyncio.run(test_metrics_initialization())
|
|
|
|
print("✅ All deployment tests passed!")
|