feat(Deployment): Integrate Ansible deployment via PHP deployment pipeline

- Create AnsibleDeployStage using framework's Process module for secure command execution
- Integrate AnsibleDeployStage into DeploymentPipelineCommands for production deployments
- Add force_deploy flag support in Ansible playbook to override stale locks
- Use PHP deployment module as orchestrator (php console.php deploy:production)
- Fix ErrorAggregationInitializer to use Environment class instead of $_ENV superglobal

Architecture:
- BuildStage → AnsibleDeployStage → HealthCheckStage for production
- Process module provides timeout, error handling, and output capture
- Ansible playbook supports rollback via rollback-git-based.yml
- Zero-downtime deployments with health checks
This commit is contained in:
2025-10-26 14:08:07 +01:00
parent a90263d3be
commit 3b623e7afb
170 changed files with 19888 additions and 575 deletions

View File

@@ -0,0 +1,271 @@
<?php
declare(strict_types=1);
/**
* ML Adapter Integration Tests
*
* Tests all 3 ML adapters with ModelRegistry and ModelPerformanceMonitor:
* 1. QueueAnomalyModelAdapter
* 2. WafBehavioralModelAdapter
* 3. NPlusOneModelAdapter
*/
require_once __DIR__ . '/../../vendor/autoload.php';
use App\Framework\Queue\MachineLearning\QueueAnomalyModelAdapter;
use App\Framework\Queue\MachineLearning\JobAnomalyDetector;
use App\Framework\Queue\MachineLearning\ValueObjects\JobFeatures;
use App\Framework\Waf\MachineLearning\WafBehavioralModelAdapter;
use App\Framework\Waf\MachineLearning\BehaviorAnomalyDetector;
use App\Framework\Waf\MachineLearning\ValueObjects\BehaviorFeatures;
use App\Framework\Database\NPlusOneDetection\MachineLearning\NPlusOneModelAdapter;
use App\Framework\Database\NPlusOneDetection\MachineLearning\NPlusOneDetectionEngine;
use App\Framework\MachineLearning\ModelManagement\InMemoryModelRegistry;
use App\Framework\MachineLearning\ModelManagement\ModelPerformanceMonitor;
use App\Framework\MachineLearning\ModelManagement\InMemoryPerformanceStorage;
use App\Framework\MachineLearning\ModelManagement\NullAlertingService;
use App\Framework\Core\ValueObjects\Score;
echo "=== ML Adapter Integration Tests ===\n\n";
try {
// Initialize shared infrastructure
echo "1. Initializing Model Management Infrastructure...\n";
$registry = new InMemoryModelRegistry();
$storage = new InMemoryPerformanceStorage();
$alerting = new NullAlertingService();
$performanceMonitor = new ModelPerformanceMonitor($registry, $storage, $alerting);
echo " ✓ ModelRegistry created\n";
echo " ✓ PerformanceStorage created\n";
echo " ✓ ModelPerformanceMonitor created\n\n";
// ========================================================================
// Test 1: QueueAnomalyModelAdapter
// ========================================================================
echo "2. Testing QueueAnomalyModelAdapter...\n";
// Create detector and adapter
$queueDetector = new JobAnomalyDetector(
anomalyThreshold: new Score(0.4),
zScoreThreshold: 3.0,
iqrMultiplier: 1.5
);
$queueAdapter = new QueueAnomalyModelAdapter(
$registry,
$performanceMonitor,
$queueDetector
);
// Register model
echo " → Registering queue-anomaly model...\n";
$queueMetadata = $queueAdapter->registerCurrentModel();
echo " ✓ Model registered: {$queueMetadata->modelName} v{$queueMetadata->version->toString()}\n";
// Test with normal features
echo " → Testing with normal job features...\n";
$normalFeatures = new JobFeatures(
executionTimeVariance: 0.15,
memoryUsagePattern: 0.10,
retryFrequency: 0.0,
failureRate: 0.05,
queueDepthCorrelation: 0.10,
dependencyChainComplexity: 0.08,
payloadSizeAnomaly: 0.05,
executionTimingRegularity: 0.30
);
$normalResult = $queueAdapter->analyzeWithTracking($normalFeatures, groundTruth: false);
echo " ✓ Analysis: " . ($normalResult['is_anomalous'] ? "ANOMALOUS" : "NORMAL") . "\n";
echo " ✓ Score: " . sprintf("%.2f%%", $normalResult['anomaly_score'] * 100) . "\n";
echo " ✓ Tracking: {$normalResult['tracking']['prediction']} (ground truth: false)\n";
// Test with anomalous features
echo " → Testing with anomalous job features...\n";
$anomalousFeatures = new JobFeatures(
executionTimeVariance: 0.85,
memoryUsagePattern: 0.75,
retryFrequency: 0.85,
failureRate: 0.65,
queueDepthCorrelation: 0.50,
dependencyChainComplexity: 0.30,
payloadSizeAnomaly: 0.35,
executionTimingRegularity: 0.20
);
$anomalousResult = $queueAdapter->analyzeWithTracking($anomalousFeatures, groundTruth: true);
echo " ✓ Analysis: " . ($anomalousResult['is_anomalous'] ? "ANOMALOUS" : "NORMAL") . "\n";
echo " ✓ Score: " . sprintf("%.2f%%", $anomalousResult['anomaly_score'] * 100) . "\n";
echo " ✓ Tracking: {$anomalousResult['tracking']['prediction']} (ground truth: true)\n";
// Get performance metrics
echo " → Checking performance metrics...\n";
$queueMetrics = $queueAdapter->getCurrentPerformanceMetrics();
echo " ✓ Total predictions: {$queueMetrics['total_predictions']}\n";
echo " ✓ Accuracy: " . sprintf("%.2f%%", $queueMetrics['accuracy'] * 100) . "\n\n";
// ========================================================================
// Test 2: WafBehavioralModelAdapter
// ========================================================================
echo "3. Testing WafBehavioralModelAdapter...\n";
// Create detector and adapter
$wafDetector = new BehaviorAnomalyDetector(
anomalyThreshold: new Score(0.5),
zScoreThreshold: 2.5,
iqrMultiplier: 1.5
);
$wafAdapter = new WafBehavioralModelAdapter(
$registry,
$performanceMonitor,
$wafDetector
);
// Register model
echo " → Registering waf-behavioral model...\n";
$wafMetadata = $wafAdapter->registerCurrentModel();
echo " ✓ Model registered: {$wafMetadata->modelName} v{$wafMetadata->version->toString()}\n";
// Test with benign request
echo " → Testing with benign request features...\n";
$benignFeatures = new BehaviorFeatures(
requestFrequency: 0.2,
endpointDiversity: 2.5, // Moderate diversity
parameterEntropy: 3.0, // Normal entropy
userAgentConsistency: 0.9, // Consistent UA
geographicAnomaly: 0.1, // Same location
timePatternRegularity: 0.3, // Human-like timing
payloadSimilarity: 0.4, // Varied payloads
httpMethodDistribution: 0.6 // Mixed methods
);
$benignResult = $wafAdapter->analyzeWithTracking($benignFeatures, historicalBaseline: [], groundTruth: false);
echo " ✓ Analysis: " . ($benignResult['is_anomalous'] ? "MALICIOUS" : "BENIGN") . "\n";
echo " ✓ Score: " . sprintf("%.2f%%", $benignResult['anomaly_score'] * 100) . "\n";
echo " ✓ Tracking: {$benignResult['tracking']['prediction']} (ground truth: false)\n";
// Test with malicious request
echo " → Testing with malicious request features...\n";
$maliciousFeatures = new BehaviorFeatures(
requestFrequency: 20.0, // Very high frequency (>10/s)
endpointDiversity: 0.5, // Low diversity (scanning)
parameterEntropy: 7.0, // High entropy (probing)
userAgentConsistency: 0.1, // Inconsistent UA
geographicAnomaly: 0.85, // Suspicious location changes
timePatternRegularity: 0.95, // Automated timing
payloadSimilarity: 0.9, // Repetitive payloads
httpMethodDistribution: 0.2 // Limited methods
);
$maliciousResult = $wafAdapter->analyzeWithTracking($maliciousFeatures, historicalBaseline: [], groundTruth: true);
echo " ✓ Analysis: " . ($maliciousResult['is_anomalous'] ? "MALICIOUS" : "BENIGN") . "\n";
echo " ✓ Score: " . sprintf("%.2f%%", $maliciousResult['anomaly_score'] * 100) . "\n";
echo " ✓ Tracking: {$maliciousResult['tracking']['prediction']} (ground truth: true)\n";
// Get performance metrics
echo " → Checking performance metrics...\n";
$wafMetrics = $wafAdapter->getCurrentPerformanceMetrics();
echo " ✓ Total predictions: {$wafMetrics['total_predictions']}\n";
echo " ✓ Accuracy: " . sprintf("%.2f%%", $wafMetrics['accuracy'] * 100) . "\n\n";
// ========================================================================
// Test 3: NPlusOneModelAdapter
// ========================================================================
echo "4. Testing NPlusOneModelAdapter...\n";
echo " Requires QueryExecutionContext and full NPlusOneDetectionEngine\n";
echo " Skipping for now (database-dependent)\n\n";
// ========================================================================
// Model Registry Tests
// ========================================================================
echo "5. Testing ModelRegistry Integration...\n";
// List all registered models
echo " → Listing registered models...\n";
$modelNames = $registry->getAllModelNames();
echo " ✓ Total model types registered: " . count($modelNames) . "\n";
foreach ($modelNames as $modelName) {
$versions = $registry->getAll($modelName);
foreach ($versions as $metadata) {
echo " - {$metadata->modelName} v{$metadata->version->toString()}\n";
echo " Type: {$metadata->modelType->value}\n";
echo " Created: {$metadata->createdAt->format('Y-m-d H:i:s')}\n";
}
}
// Test model existence
echo " → Testing model existence checks...\n";
$queueExists = $registry->exists('queue-anomaly', \App\Framework\Core\ValueObjects\Version::fromString('1.0.0'));
$wafExists = $registry->exists('waf-behavioral', \App\Framework\Core\ValueObjects\Version::fromString('1.0.0'));
echo " ✓ queue-anomaly exists: " . ($queueExists ? "YES" : "NO") . "\n";
echo " ✓ waf-behavioral exists: " . ($wafExists ? "YES" : "NO") . "\n\n";
// ========================================================================
// Performance Monitor Tests
// ========================================================================
echo "6. Testing ModelPerformanceMonitor Integration...\n";
// Get metrics for each registered model
echo " → Getting metrics for all registered models...\n";
$allMetrics = [];
foreach ($modelNames as $modelName) {
$versions = $registry->getAll($modelName);
foreach ($versions as $metadata) {
$metrics = $performanceMonitor->getCurrentMetrics(
$metadata->modelName,
$metadata->version
);
$modelKey = "{$metadata->modelName}@{$metadata->version->toString()}";
$allMetrics[$modelKey] = $metrics;
}
}
echo " ✓ Models tracked: " . count($allMetrics) . "\n";
foreach ($allMetrics as $modelKey => $metrics) {
echo " - $modelKey:\n";
echo " Predictions: {$metrics['total_predictions']}\n";
echo " Accuracy: " . sprintf("%.2f%%", $metrics['accuracy'] * 100) . "\n";
if ($metrics['total_predictions'] > 0) {
echo " Avg Confidence: " . sprintf("%.2f%%", $metrics['average_confidence'] * 100) . "\n";
}
}
// Check for performance degradation
echo "\n → Checking for performance degradation...\n";
$queueDegradation = $queueAdapter->checkPerformanceDegradation(0.05);
$wafDegradation = $wafAdapter->checkPerformanceDegradation(0.05);
echo " ✓ queue-anomaly degraded: " . ($queueDegradation['has_degraded'] ? "YES" : "NO") . "\n";
echo " ✓ waf-behavioral degraded: " . ($wafDegradation['has_degraded'] ? "YES" : "NO") . "\n\n";
// ========================================================================
// Test Summary
// ========================================================================
echo "=== Test Summary ===\n";
echo "✓ QueueAnomalyModelAdapter: Working\n";
echo "✓ WafBehavioralModelAdapter: Working\n";
echo "✓ NPlusOneModelAdapter: Skipped (database-dependent)\n";
echo "✓ ModelRegistry: Working\n";
echo "✓ ModelPerformanceMonitor: Working\n";
echo "✓ Model registration: Working\n";
echo "✓ Performance tracking: Working\n";
echo "✓ Accuracy calculation: Working\n\n";
echo "Test Results:\n";
echo " - Queue Adapter: 2 predictions, " . sprintf("%.0f%%", $queueMetrics['accuracy'] * 100) . " accuracy\n";
echo " - WAF Adapter: 2 predictions, " . sprintf("%.0f%%", $wafMetrics['accuracy'] * 100) . " accuracy\n";
echo " - Total models registered: " . $registry->getTotalCount() . "\n";
echo " - Total predictions tracked: " . array_sum(array_column($allMetrics, 'total_predictions')) . "\n\n";
echo "=== ML Adapter Tests PASSED ===\n";
} catch (\Throwable $e) {
echo "\n!!! TEST FAILED !!!\n";
echo "Error: " . $e->getMessage() . "\n";
echo "File: " . $e->getFile() . ":" . $e->getLine() . "\n";
echo "\nStack trace:\n" . $e->getTraceAsString() . "\n";
exit(1);
}