Application Packaging Standard

Last updated 18-Mar-2019

Endpoint Host

Note

The examples in this section are applicable to endpoint hosts using the APS PHP runtime.

Package Location

By default, you can find the application backend scripts and application instance configuration in a subfolder of the Apache document root. In the following example, the application endpoint subfolder is basic1p:

# ls -al /var/www/html/basic1p/
total 32
drwxr-xr-x 4 apache apache 4096 Mar 16 17:15 .
drwxr-xr-x 8 root   root   4096 Mar 17 17:53 ..
-rwxr-xr-x 1 apache apache 1131 Feb 12 18:53 clouds.php
drwxr-xr-x 2 apache apache 4096 Mar 16 17:15 config
-rwxr-xr-x 1 apache apache 1612 Feb 12 18:53 contexts.php
-rwxr-xr-x 1 apache apache  372 Mar 16 17:15 .htaccess
drwxr-xr-x 3 apache apache 4096 Mar 16 17:17 typeCache
-rwxr-xr-x 1 apache apache 2152 Feb 12 18:53 vpses.php

The config/ folder in the above list contains SSL certificates and keys for the APS application instances, as shown in the following listing:

# ls -al /var/www/html/basic1p/config/
total 28
drwxr-xr-x 2 apache apache 4096 Mar 16 17:15 .
drwxr-xr-x 4 apache apache 4096 Mar 16 17:15 ..
-rw------- 1 apache apache 4223 Mar 16 17:15 3641e96b-4ab4-4c00-8a45-b6f9d2a61fd0
-rw------- 1 apache apache 1196 Mar 16 17:15 3641e96b-4ab4-4c00-8a45-b6f9d2a61fd0.apsc.pem
-rw------- 1 apache apache 2818 Mar 16 17:15 3641e96b-4ab4-4c00-8a45-b6f9d2a61fd0.pem
-rw-r--r-- 1 apache apache   31 Mar 16 17:15 .htaccess

Development Mode

While testing and debugging a PHP script, you should define the APS_DEVELOPMENT_MODE global constant in it:

if (!defined('APS_DEVELOPMENT_MODE')) define ('APS_DEVELOPMENT_MODE', 'on');

require_once("aps/2/runtime.php");

Defining this global constant in your PHP script enables:

  • The APS PHP framework to record traced calls of this script in the Apache error_log file.
  • The use of debug and trace log levels.

In the following example with the global constant defined, a user saves an edited resource (VPS), and the error_log file records the following trace:

Note

For brevity, the example omits most strings and the suffixes with date and time, and adds some inline comments using the “//” suffix:

DEBUG Incoming Application API request: PUT user/vpses/1645e72d-6d90-488e-8e94-089bf7c00ddf
DEBUG Request:
{
   "aps":
   {
      "type": "http://aps-standard.org/samples/suwizard1p/vps/1.1",
      "id": "1645e72d-6d90-488e-8e94-089bf7c00ddf",
      ...
   },
   ...// Full JSON representation of the resource with the updated property
   "hardware":
   {
      "CPU":
      {
         "number": 4 // Request to set the new value
      },
      ...
   }
}

DEBUG TypeLibrary: Found class "http://aps-standard.org/samples/suwizard1p/vps/1.1" in local type cache.
TRACE #Request to APS controller [apsc-request-56e7b60a4f40f]:
GET https://10.28.110.145:6308/aps/2.2/resources/1645e72d-6d90-488e-8e94-089bf7c00ddf
APS-Controller-URI: https://10.28.110.145:6308/
APS-Request-ID: a5d3c74f-2b4b-4516-a2bb-6ff76238f548
Content-type: application/json
..............................

TRACE #Response from APS controller [apsc-request-56e7b60a4f40f]:
HTTP/1.1 200 OK
..............................
Content-Type: application/json

{
   "aps":
   {
      "type": "http://aps-standard.org/samples/suwizard1p/vps/1.1",
      "id": "1645e72d-6d90-488e-8e94-089bf7c00ddf",
      ...
   },
   ...// Full JSON representation of the current resource properties
   "hardware":
   {
      "CPU":
      {
         "number": 2 // This is the current value
      },
      ...
   }
}
...

DEBUG TypeLibrary: Found registered class "http://aps-standard.org/samples/suwizard1p/vps/1.1".
DEBUG Result:
{
    "aps": {
        "type": "http://aps-standard.org/samples/suwizard1p/vps/1.1",
        "id": "1645e72d-6d90-488e-8e94-089bf7c00ddf",
      ...// Full JSON representation of the updated resource
   },
   ...
   "hardware":
   {
      "CPU":
      {
         "number": 4 // The property updated to the required value
      },
      ...
   }
}

The log shows the following traced steps:

  1. The vpses service of the application receives a PUT request from the APSC to update the specified VPS.
  2. The service calls the APSC for the current VPS properties using the GET request. The application needs to know all the other properties in order not to change them in its response.
  3. The service returns the updated VPS representation to the APSC to confirm the update.

Logs

You can use the following Apache (HTTPD) logs to identify and analyze error and information records.

  • ssl_access_log - provides data about REST requests sent to the APS application endpoints.

    [root@endpoint ~]# tail -f /var/log/httpd/ssl_access_log
    10.28.99.128 - - [30/Jan/2015:11:34:10 +0300] "POST /async/vpses HTTP/1.1" 202 466
    10.28.99.128 - - [30/Jan/2015:11:34:11 +0300] "POST /async/vpses HTTP/1.1" 202 466
    
  • error_log - stores the log messages that application scripts send using the log methods.

    [root@endpoint ~]# tail -fn0 /var/log/httpd/error_log
    
    [2013/12/02 09:25:35] DEBUG TypeLibrary: Can't found class 'http://aps-standard.org/types/core/resource/1.0',
        loading from /usr/share/aps/php/aps/2/types/org/standard/aps/types/core/resource/Resource.php
    [2013/12/02 09:25:35] DEBUG Incoming Application API request: POST package/users
    [Mon Dec 02 13:25:35 2013] [error] [client 10.10.2.224] PHP Fatal error:  Class 'Logger' not found
        in /var/www/html/package/users.php on line 88
    

    In the development mode, the error log contains traced calls in the most detailed format.

APS PHP Logger

The APS PHP runtime provides the APSLoggerRegistry class that you can use to record some data in the error_log file. To mark those records with specific log levels, use their respective functions: fatal, error, info, debug, and trace, for example:

public function provision() {
   $logger = \APS\LoggerRegistry::get();
   ...
   $logger->error("This is a log message of the error level");
   $logger->debug("This is a log message of the debug level");
   ...
}

The debug and trace levels are only available in APS development mode.

If you need to send an array or object to the log, you should first convert it to a string:

$msg = print_r(<object or array>, true);
$logger->info("This is an object: ".$msg);

REST Requests in Command Line

The command line interface (CLI) allows you to send REST requests directly from any host that can communicate with the management node or endpoint host.

From Account to APS Controller

To send a REST request to the APSC on behalf of an account, you need to add the account token to the request. The steps to do so are as follows.

Note

For brevity, an ellipsis (…) shows abbreviated example code.

  1. Get the account token from the management node by executing the following command from the platform XML API (account ID in the system is 4 in this example):

    curl -d @get-accnt-token.xml http://<management-node>:8440
    

    The get-accnt-token.xml file used in the above command contains the XML request:

    <?xml version='1.0'?>
    <methodCall>
       <methodName>pem.APS.getAccountToken</methodName>
       <params>
          <param>
             <value>
                <struct>
                   <member>
                      <name>account_id</name>
                      <value>
                         <i4>4</i4>
                      </value>
                   </member>
                   <member>
                      <name>subscription_id</name>
                      <value>
                         <i4>0</i4>
                      </value>
                   </member>
                </struct>
             </value>
          </param>
       </params>
    </methodCall>
    
  2. Using the account token, run the desired REST request. For example, to get a list of the resources owned by the customer, send:

    # curl -k -X GET -H 'APS-Token:JEFFUy0xMjgtR0NNJ...` \
       https://<management-node>:6308/aps/2/resources/
    

    To create a resource, send a POST request similar to:

    # curl -k -X POST -d @v-102.json -H 'APS-Token:JEFFU...` \
       -H 'APS-Subscription-ID:f7fbf93f-...' \
       https://<management-node>:6308/aps/2/resources/
    

    The v-102.json file contains the JSON representation of the required resource.

    To update the created resource (for example, to change its state property), send a PUT request similar to:

    # curl -k -X PUT -d'{"aps":{"id":"38146701-..."},"state":"Running"}' \
       -H 'APS-Token:JEFFU...` \
       https://<management-node>:6308/aps/2/resources/38146701-...
    

From Application to APS Controller

To send a REST request on behalf of your application instance to the APSC, you need to send the application SSL certificate that the APS controller trusts. The certificate is contained in the <endpoint>/config/<instance-id>.pem file, where:

  • <endpoint> is the root folder of the APS application endpoint
  • <instance-id> is the APS ID assigned to the APS application instance

If you are on the endpoint host, use the following syntax to send a GET request:

# cd <endpoint>/config
# curl -k -X GET -E ./`ls | grep  '^[a-z0-9-]\{36\}\.pem$'` https://<management-node>:6308/aps/2/resources/

As explained in the From Account to APS Controller section, you can also send PUT and POST requests.

Direct Request to PHP Script

You can verify a PHP script by sending a test REST request directly to it. For example, to trace provisioning of a VPS by the vpses.php script, use the following command:

# php vpses.php < request.txt

The input data in the request.txt file may look as follows (many lines are omitted for brevity):

PUT /user/vpses/545838c3-d2e3-46f6-ac65-4e7ed54f5ba4 HTTP/1.1
APS-Instance-Id:57e6af16-1e81-4bd9-91dc-d8b6b452e61c

{
   "aps":
   {
      "type": "http://aps-standard.org/samples/suwizard1p/vps/1.1",
      "id": "1645e72d-6d90-488e-8e94-089bf7c00ddf",
   ...
   },
   ... // Full JSON representation of the resource
   "hardware": { "CPU": { "number": 3 } },
   ...
}

Since an APS application endpoint can serve many application instances, the request must contain the APS-Instance-Id header. You can find the needed value in the config/ subfolder in the APS application endpoint folder. For example:

# ls -l config/
total 16
-rw------- 1 apache apache 4225 Mar  4 12:06 57e6af16-1e81-4bd9-91dc-d8b6b452e61c
-rw------- 1 apache apache 1196 Mar  4 12:06 57e6af16-1e81-4bd9-91dc-d8b6b452e61c.apsc.pem
-rw------- 1 apache apache 2818 Mar  4 12:06 57e6af16-1e81-4bd9-91dc-d8b6b452e61c.pem

Restoration of Application Instance

An application instance cannot function if its SSL certificate is lost or damaged. The gen_appcert.py script generates a new SSL certificate and keys for an application instance. The script requires the instance ID as the input argument that you can find using the following steps:

  1. In the provider control panel, go to Services > Applications > APS Instances.

  2. Identify the instance of the application and note the ID shown in the first column.

  3. Establish an SSH connection to the management node and access the database. In the following example, the application instance ID is 15:

    # psql -h `hostname` -U plesk
    plesk=> select uuid from aps_application_instances where app_instance_id=15;
                     uuid
    --------------------------------------
     83fb36d2-1adb-453a-a0b4-db998ea1946c
    (1 row)
    

To restore the application instance with the same UUID, use the gen_appcert.py script. The following example uses the UUID found in the previous step:

# python gen_appcert.py 83fb36d2-1adb-453a-a0b4-db998ea1946c