application-manager-tools/am-driver
Symfony bundle + framework-agnostic PHP library to connect managed apps to Application Manager: orchestration commands, consumption webhooks, and instance operational state push. Includes OpenAPI 3.1 spec + Swagger UI, plus integration guides.
Install the Package
composer require application-manager-tools/am-driver
Configure Symfony Bundle (if using Symfony):
config/bundles.php:
ApplicationManagerTools\AmDriver\Bridge\Symfony\AmDriverBundle::class => ['all' => true],
.env.local (e.g., AM_DRIVER_AM_BASE_URL, AM_DRIVER_SOURCE=captain-learning).config/packages/am_driver.yaml:
am_driver:
route_prefix: am
consumption_webhook_token: '%env(AM_DRIVER_CONSUMPTION_WEBHOOK_TOKEN)%'
orchestration_command_token: '%env(AM_DRIVER_ORCHESTRATION_COMMAND_TOKEN)%'
Import Routes
Add to config/routes/am_driver.yaml:
am_driver:
resource: '@AmDriverBundle/Resources/config/routes.yaml'
Implement a Handler
Create a CreateInstanceHandler for orchestration commands:
use ApplicationManagerTools\AmDriver\Core\Contract\CreateInstanceHandlerInterface;
use ApplicationManagerTools\AmDriver\Core\Dto\OrchestrationCommand;
final class MyCreateInstanceHandler implements CreateInstanceHandlerInterface {
public function handle(OrchestrationCommand $command): void {
// Logic to create tenant/instance (e.g., provision DB, storage)
}
}
Tag it in services.yaml:
services:
App\Handler\MyCreateInstanceHandler:
tags: ['am_driver.create_instance_handler']
Test Locally Start the receptacle server:
vendor/bin/am-driver serve --port=8099 --token-command=dev-command-token
Simulate an orchestration command:
vendor/bin/am-driver orchestration:simulate create --token=dev-command-token
CREATE_INSTANCECREATE_INSTANCE command to your /am/orchestration/commands endpoint.CreateInstanceHandler receives the OrchestrationCommand DTO with:
tenantId: Unique identifier for the tenant.integrationInstanceId: (New in v0.0.16) Unique identifier for the integration instance (useful for multi-tenancy or multi-instance setups).parameters: Custom payload (e.g., {"storage_gb": 10, "region": "eu-west-1"})./am/orchestration/commands/callbacks with the result (success/failure).
integrationInstanceId in the callback response for better traceability.integrationInstanceId fields).src/Core/Contract/ for handler interfaces (e.g., CreateInstanceHandlerInterface).src/Core/Dto/ for data transfer objects (e.g., OrchestrationCommand now includes integrationInstanceId).src/Bridge/Symfony/ for Symfony-specific wiring.vendor/bin/am-driver serve for local testing.orchestration:simulate (ensure integrationInstanceId is included in test payloads).CreateInstanceHandlerInterface, StopInstanceHandlerInterface, etc.am_driver.{command}_handler (e.g., am_driver.create_instance_handler).// Handle START_INSTANCE with custom logic, now using integrationInstanceId
final class MyStartInstanceHandler implements StartInstanceHandlerInterface {
public function handle(OrchestrationCommand $command): void {
$this->tenantService->startTenant(
tenantId: $command->tenantId,
integrationInstanceId: $command->integrationInstanceId // New field
);
$this->logger->info(
"Started tenant {$command->tenantId} (instance: {$command->integrationInstanceId})"
);
}
}
integrationInstanceId).ConsumptionWebhookReceiver to process inbound consumption events.
/am/consumption/webhook with a consumption_webhook_token.tenantId, resourceKey, value, integrationInstanceId).use ApplicationManagerTools\AmDriver\Core\Contract\ConsumptionWebhookReceiverInterface;
final class MyConsumptionWebhookReceiver implements ConsumptionWebhookReceiverInterface {
public function receive(
string $tenantId,
string $resourceKey,
float $value,
?string $integrationInstanceId = null // New optional field
): void {
$this->consumptionStore->record(
tenantId: $tenantId,
integrationInstanceId: $integrationInstanceId,
resourceKey: $resourceKey,
value: $value
);
}
}
OperationalStatePublisher to push state updates to AM.
$publisher->pushOperationalState($tenantId, $state, $integrationInstanceId).RUNNING, STOPPED, FAILED.$publisher = $container->get('am_driver.operational_state_publisher');
$publisher->pushOperationalState(
tenantId: $tenantId,
state: 'STOPPED',
integrationInstanceId: $integrationInstanceId // New optional field
);
ConsumptionPublisher to push resource usage to AM.
$publisher->pushResourceConsumption($tenantId, 'storage_gb', 5.2, $integrationInstanceId).$publisher = $container->get('am_driver.consumption_publisher');
$publisher->pushResourceConsumption(
tenantId: $tenantId,
resourceKey: 'proof_storage_mo',
value: 12.5,
integrationInstanceId: $integrationInstanceId // New optional field
);
am_driver.orchestration_command_processoram_driver.operational_state_publisheram_driver.consumption_publisher/am/orchestration/commands). Customize with route_prefix in config.security.yaml:
access_control:
- { path: ^/am/, roles: PUBLIC_ACCESS }
$client = new AmApiClient($amBaseUrl, $orchestrationCommandToken);
$processor = new OrchestrationCommandProcessor(
$client,
new CreateInstanceHandler(),
new StopInstanceHandler()
);
$processor->process($command);
AmDriverReceptacle to expose endpoints:
$receptacle = new AmDriverReceptacle(
new CreateInstanceHandler(),
new ConsumptionWebhookReceiver()
);
$server = new SwooleHttpServer($receptacle);
$server->start();
integrationInstanceId:
vendor/bin/am-driver orchestration:simulate create \
--token=dev-command-token \
--integration-instance-id=test-instance-123
http://localhost:18098 (default port) for updated fields.How can I help you explore Laravel packages today?