A php framework with docker to sync and connect to the ascio-api. Scalable, based on docker and kafka.
It makes make domain-management-processes easear like:
- Sync all data from ascio to the local databases in realtime.
- Auto-Queue blocking orders
- Scalable architecture
- Consume the poll-queue with multiple orders
- Provide one $domain->update functions. Change data, update, and all orders will be queued
- Auto unlock-relock
- REST-API: https://app.swaggerhub.com/apis/rendermani/Ascio-Framework/1.0.0-oas3
The only requirement is docker. It can be downloaded here: https://www.docker.com/
- Clone repository:
git clone https://github.com/rendermani/ascio-framework.git ascio-framework
cd ascio-framework
chmod u+x bin/init.sh
- Run
bin/init.sh <<github token>>
. The github-token can be used optionally to extend quotas (Could not authenticate against github.com). It can be obtained here: https://github.com/settings/tokens - Set missing passwords in the .env
- Enter the ascio-credentials in config/accounts/default.json
- Run
bin/up.sh
At the beginning the database is empty. As Ascio-messages are sent, when something changes, an initial sync must be done at the beginning. The sync-orders script syncs all orders and data that belongs to the orders, like Domains or SSL-Certificates.
- make sure the installation is complete, and default.json contains valid credentials and environment
- run
bin/sync-orders.sh
At the beginning there will be a Kafka exception in the logs. This will be gone as soon as Kafka has fully loaded. There is no dependancy on Kafka, because the Kafka could run somewhere else.
- run
bin/logs.sh
. Look for 401 Authentification failed - run
bin/php sandbox/create-order.php
- observe the logs for poll complete.
- check the database: http://localhost:8001/
- phpmyadmin: http://localhost:8001/
- REST-API: http://localhost:8000/
- Init framework, create tables, build:
bin/init.sh
- Initials sync orders:
bin/sync-orders.sh
- Start:
bin/up.sh
- Stop:
bin/down.sh
- Restart framework:
bin/restart-framework.sh
- View logs:
bin/logs.sh
- Docker shell:
docker exec -it ascio-framework-php bash
- Execute php:
docker exec ascio-framework-php php sandbox/my-example.php
Examples are in the sandbox directory. Here some examples:
First a register-order is created and a domain is registered. By setting $submitOptions->setQueue(false) the order is directly submitted. After that a expire-order is sent. But as the asynchronous register orders is still running, the expire order is queued in the database and started when the register is completed.
<?php
namespace ascio\lib;
use ascio\v2\TestLib;
use ascio\lib\SubmitOptions;
use SoapFault;
require(__DIR__."/../vendor/autoload.php");
// an alternative can be set here
Ascio::setConfig();
// get Test-Domain
$domain = TestLib::getDomain("testme-".uniqid().".com");
try {
$submitOptions = new SubmitOptions();
// direct submit if possible
$submitOptions->setQueue(false);
// register the domain
$order = $domain->register($submitOptions);
echo "Register: ". $domain->getDomainName()." Order: ".$order->getOrderId()." ".$order->db()->_id."\n";
// as register is running, the expire order will be auto-queued
$order = $domain->expire($submitOptions);
echo "Expire: ". $domain->getDomainName()." Order: ".$order->getOrderId()." ".$order->db()->_id."\n";
} catch (SoapFault $e) {
echo "error!";
echo $e->getMessage();
// view SOAP-Request
echo ascio::getClientV2()->__getLastRequest();
} catch (AscioException $e) {
// view Ascio-Errors and the result
echo $e->getMessage();
var_dump($e->getResult()->getCreateOrderResult());
}
Normally it's required to know the order-type when changing data. With the update method of the domain, it's possible to change any data and the order-type will be automatically selected. If multiple order-types are required, orders are queued like in the example above.
Some order-types can change 2 different objects. Like the owner-change can change the registrant and the admin-contact in one request. In this case, the update method only uses necessary objects.
<?php
namespace ascio\lib;
use ascio\v2\TestLib;
use SoapFault;
require(__DIR__."/../vendor/autoload.php");
// an alternative can be set here
Ascio::setConfig();
// get Test-Domain
$domain = TestLib::getDomain("testme-".uniqid().".com");
try {
// register the domain
$order = $domain->register();
echo "Register: ". $domain->getDomainName()." Order: ".$order->getOrderId()." ".$order->db()->_id."\n";
// change domain data
$domain->getAdminContact()->setFirstName("Manuel");
$domain->getRegistrant()->setAddress1("new adr. 123");
$domain->getNameServers()->createNameServer3()->setHostName("ns3.ascio.net");
// 3 orders are created: Registrant_Details_Update, Contact_Update and Nameserver_Update
$domain->update();
} catch (SoapFault $e) {
echo "error!";
echo $e->getMessage();
// view SOAP-Request
echo ascio::getClientV2()->__getLastRequest();
} catch (AscioException $e) {
// view Ascio-Errors and the result
echo $e->getMessage();
var_dump($e->getResult()->getCreateOrderResult());
}
All data is auto-stored in the database. If data should be stored manually, please use $object->produce()
to store data into all databases. This function should be use carefully, because data could get out of sync.
Database can be read from any database. Objects like domains have a serialize and deserialize data. Please use $object->deserialize()
to import data. And $object->serialize($data)
or $object->toJson()
to serialize.
Here an example of retrieving data from the database:
// get Domain by databaseId
$domain->db()->getById("myId");
// get Domain by ascio domain-handle
$domain->db()->getByHandle("DomainHandle");
// get Domain by domain-name
$domain->db()->getByName("myname.com");
// get Domain order by OrderId
$order->db()->getByOrderId();
// get Order by databaseId
$order->db()->getById("myId");
// get related tables: Domain, Registrant
$order->getDomain()->getRegistrant();
// custom lavarel-query
$domain->db()->where("Status","Active")->first();
// custom query
$domain->db()->raw("select * from domains where Status = 'Active'");
Database connectors listen on the Kafka-service and write data into the database. It's possible to include own connectors. Right now Redis and Couch are included as examples. This is the Redit-connector.
The process of creating connectors is:
- create the connector in the
docker/docker-compose.yml
. Duplicate the redis-connector, and change the script-name to your file - create the connector file
bin/down.sh
bin/up.sh
This is an example Redis connector which is in the services directory.
<?php
namespace ascio\lib;
require(__DIR__."/../vendor/autoload.php");
use Illuminate\Support\Str;
\Predis\Autoloader::register();
$client = new \Predis\Client([
'scheme' => 'tcp',
'host' => 'redis',
'port' => 6379,
]);
Consumer::object(function($payload) use($client) {
Ascio::setConfig($payload->Config);
$obj = $payload->object;
$client->set($obj->db()->_id,$obj->toJson());
echo $obj->getStatusSerializer()->console(LogLevel::Info,Str::ucfirst($payload->action));
});
Reads an Order from the API. When reading from the API, data is automatically synced to all databases.
<?php
use ascio\v2\Order;
require(__DIR__."/../vendor/autoload.php");
Ascio::setConfig();
$order = new Order();
$order->api()->getByOrderId("TEST561580");
Reads an Domain from the API. When reading from the API, data is automatically synced to all databases.
<?php
use ascio\v2\Domain;
require(__DIR__."/../vendor/autoload.php");
Ascio::setConfig();
$domain = new Domain();
$domain->api()->getByHandle("TEST1234");
Reads an Domain from the API. When reading from the API, data is automatically synced to all databases.
<?php
use ascio\v2\Domain;
require(__DIR__."/../vendor/autoload.php");
Ascio::setConfig();
$domain = new Domain();
$domain->api()->getByName("testmeee.com");
$order = new Order();
$order->db()->getByOrderId("TEST561580");
$order->api()->get();
$domain = new Domain();
$domain->db()->getByName("test.de");
$domain->api()->get();
Sometimes locks can prevent updates. This can be an issue when updating thousands of domains, and a few fail because they are locked. They would need to be unlocked and relocked again, after all operations are finished. The AutoUnlock makes this process easier
<?php
namespace ascio\lib;
use ascio\v2\Domain;
use ascio\v2\TestLib;
require(__DIR__."/../vendor/autoload.php");
Ascio::setConfig();
$domain = new Domain();
$domain->getByHandle("TESTME5D66885");
$wf = new Workflow($domain);
// if the orders of the workflow require and unlock it will be done before submitting the orders.
// After the orders are finished the relock will be restored if possible.
$wf->getSubmitOptions()->setAutoUnlock(true);
// add the expire order-object
$wf->addTask($domain->getOrderRequest()->expire());
// submit all orders
$wf->submit();
This example is the same like the example above, only that the declarative way is used. Instead of adding a $domain->getOrderRequest()->expire()
task, a $domain->getUpdateOrders()
task is added. There could be more changes like $domain->getRegistrant()->setName("Manuel L")
and an OwnerChange would be created. And the UpdateLock released if necessary.
<?php
namespace ascio\lib;
use ascio\v2\TestLib;
require(__DIR__."/../vendor/autoload.php");
Ascio::setConfig();
$domain = TestLib::getDomain("testme-".uniqid().".com");
// register domain
$domain->register();
// set AutoRenew
$domain->getAutoRenew()->set(false);
$wf = new Workflow($domain);
// if the orders of the workflow require and unlock it will be done before submitting the orders.
// After the orders are finished the relock will be restored if possible.
$wf->getSubmitOptions()->setAutoUnlock(true);
$wf->addTasks($domain->getUpdateOrders());
// submit workflow
$wf->submit();