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:
271
tests/debug/test-ml-adapters.php
Normal file
271
tests/debug/test-ml-adapters.php
Normal 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);
|
||||
}
|
||||
Reference in New Issue
Block a user