How to prepare, validate, and start a deployment using the XL Deploy REST API

Follow

Cath Tayag -

A deployment in XL Deploy may look like a single action when triggered by JenkinsBambooXL Release, or other plugins. However, preparing, validating, and executing a deployment is a sequence of individual steps that you may want to trigger from an integration point such as cloud management, provisioning, release management tools, and others. Here, we provide an example of walking through each of these steps with the XL Deploy REST API.

Before we get started, we highly recommend that you read this explanation of the deployment planning sequence, watch the _ Performing an initial deployment_ and _ Performing an update deployment_ videos, and carry out a few simple deployments via the XL Deploy UI yourself. This will give a much better understanding of the individual steps involved and how they related to the API calls we are going to use.

Here, we will describe the following sequence:

  • Preparing an initial deployment
  • Previewing the deployment plan before mapping
  • Mapping deployables to the target environment
  • Previewing the deployment plan after mapping
  • Validating the deployment
  • Creating a deployment task

Preparing an initial deployment

Our first step is to call GET /deployment/prepare/initial to retrieve a "deployment spec". For an initial deployment, the parameters we need to pass are the ID of the target environment and the ID of the deployment package we are trying to deploy.

INPUT:

curl -u<username>:<password> "http://<xl-deploy-server>:<xl-deploy-port>/deployit/deployment/prepare/initial/?environment=Environments/Dev/TEST&version=Applications/PetPortal/1.0"

OUTPUT:

<deployment id="deployment-be38a6b8-6743-40e7-bfcf-433083494097" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds/>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment>

The deployment spec that is returned (it's actually called a Deployment object) describes the components of our deployment package that we want deployed to target containers.

We're preparing an initial deployment here, which we can only do if there is no version of the application currently deployed to the target environment. That's also why we get a "blank" deployment spec, with an empty set of deployed items.

If there already is a version of the application running in the target environment, we need to call /deployment/prepare/update instead, passing the ID of the DeployedApplication representing the current version of the application running in the environment instead of the environment ID.

The deployment spec returned in that case will not be "blank", but will contain <deployeds> describing the state of the currently deployed application version.

Whether we start with an initial or update deployment, the subsequent steps are the same: we need to store the deployment spec returned by the server, modify it to describe how we want the new application version to be deployed, and ask XL Deploy to prepare a deployment plan to make our desired state actually happen.

First, though, we will see the deployment plan that the XL Deploy server calculates based on our current deployment spec.

Previewing the deployment plan before mapping

We can call POST /deployment/preview to ask XL Deploy to calculate a deployment plan based on our current deployment spec and return the steps that would be executed. Here, we assume that we've stored the deployment spec returned by the previous call in /tmp/deployment-spec.xml.

> INPUT:

curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/deployit/deployment/preview -d@/tmp/deployment-spec.xml

*Content of /tmp/deployment-spec.xml:

*

<deployment id="deployment-c90ec677-0be2-49bf-906f-650766740c36" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds/>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment>

>OUTPUT:

> <preview id="deployment-c90ec677-0be2-49bf-906f-650766740c36">

  <steps>

    <step failures="0" state="PENDING">

      <description>Logging release authorization for deployment of 'Applications/PetPortal/1.0'</description>

      <log></log>

      <metadata>

        <order>9</order>

        <previewAvailable>false</previewAvailable>

      </metadata>

    </step>

  </steps>

</preview>

The returned object is a TaskPreview, which is very similar to a TaskWithSteps object. Unsurprisingly, there's nothing really going on in this deployment plan, apart from the standard auditing step that ensures all release conditions that have been met are added to the task log. That's because our deployment spec is still "blank"; we're not asking XL Deploy to deploy any of the application components to the containers in our target environments.

That's what we'll do next, by asking XL Deploy to automatically map our deployables to the target containers.

Mapping deployables to the target environment

We'll call POST /deployment/prepare/deployeds to update our deployment spec by automatically mapping our deployables to the target containers in our environment.

INPUT:

curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/deployit/deployment/prepare/deployeds -d@/tmp/deployment-spec.xml

Content of /tmp/deployment-spec.xml:

<deployment id="deployment-c90ec677-0be2-49bf-906f-650766740c36" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds/>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment>

OUTPUT:

<deployment id="deployment-c90ec677-0be2-49bf-906f-650766740c36" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds>

    <sql.ExecutedSqlScripts id="Infrastructure/Dev/Database-1/MySql/sql">

      <deployable ref="Applications/PetPortal/1.0/sql"/>

      <container ref="Infrastructure/Dev/Database-1/MySql"/>

      <placeholders/>

    </sql.ExecutedSqlScripts>

    <jbossas.EarModule id="Infrastructure/Dev/Appserver-1/JBoss/PetClinic-ear">

      <deployable ref="Applications/PetPortal/1.0/PetClinic-ear"/>

      <container ref="Infrastructure/Dev/Appserver-1/JBoss"/>

      <placeholders/>

    </jbossas.EarModule>

  </deployeds>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment> 

That's more like it! The server has automatically mapped the SQL scripts in the deployment package to the MySQL client, and the EAR file to the JBoss server, to create two deployed items. It has also replaced placeholders in the deployable items with the specific values defined for this environment in dictionaries. You can use tags for more fine-grained controlover the automated mapping process, by the way.

The call we made, which is equivalent to the "auto-map all" button in the UI, is not the only way to generate the deployed items for our deployment spec. You can also simply specify the desired deployeds directly in the XML, or use of the the /deployment/generate calls provided by the DeploymentService, which are equivalent to mapping individual deployables via the UI.

In general, though, it's recommend best practice to use tags in your packages and environments so that this call just "does the right thing". This will make it very easy to use XL Deploy from other tools as part of your delivery pipeline.

Now that we are actually asking XL Deploy to create two new deployed items, let's see what the calculated deployment plan looks like.

Previewing the deployment plan after mapping

We'll assume we've saved the updated deployment spec returned from the previous call back to /tmp/deployment-spec.xml. We can then call POST /deployment/preview again to preview the deployment plan generated by XL Deploy for our updated spec:

INPUT:

curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/deployit/deployment/preview -d@/tmp/deployment-spec.xml

Content of /tmp/deployment-spec.xml:

<deployment id="deployment-c90ec677-0be2-49bf-906f-650766740c36" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds>

    <sql.ExecutedSqlScripts id="Infrastructure/Dev/Database-1/MySql/sql">

      <deployable ref="Applications/PetPortal/1.0/sql"/>

      <container ref="Infrastructure/Dev/Database-1/MySql"/>

      <placeholders/>

    </sql.ExecutedSqlScripts>

    <jbossas.EarModule id="Infrastructure/Dev/Appserver-1/JBoss/PetClinic-ear">

      <deployable ref="Applications/PetPortal/1.0/PetClinic-ear"/>

      <container ref="Infrastructure/Dev/Appserver-1/JBoss"/>

      <placeholders/>

    </jbossas.EarModule>

  </deployeds>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment>

OUTPUT:

<preview id="deployment-c90ec677-0be2-49bf-906f-650766740c36">

  <steps>

    <step failures="0" state="PENDING">

      <description>Logging release authorization for deployment of 'Applications/PetPortal/1.0'</description>

      <log></log>

      <metadata>

        <order>9</order>

        <previewAvailable>false</previewAvailable>

      </metadata>

    </step>

    <step failures="0" state="PENDING">

      <description>Stop JBoss</description>

      <log></log>

      <metadata>

        <order>10</order>

        <previewAvailable>true</previewAvailable>

      </metadata>

    </step>

    <step failures="0" state="PENDING">

      <description>Deploy PetClinic-ear on JBoss</description>

      <log></log>

      <metadata>

        <order>50</order>

        <deployed\_0>Infrastructure/Dev/Appserver-1/JBoss/PetClinic-ear</deployed\_0>

        <previewAvailable>false</previewAvailable>

      </metadata>

    </step>

    <step failures="0" state="PENDING">

      <description>Run 1-create-table.sql on MySql</description>

      <log></log>

      <metadata>

        <order>50</order>

        <deployed\_0>Infrastructure/Dev/Database-1/MySql/sql</deployed\_0>

        <previewAvailable>true</previewAvailable>

      </metadata>

    </step>

    <step failures="0" state="PENDING">

      <description>Start JBoss</description>

      <log></log>

      <metadata>

        <order>90</order>

        <previewAvailable>true</previewAvailable>

      </metadata>

    </step>

  </steps>

</preview>  

This time, we have some "real" deployment steps to stop the JBoss server, deploy the EAR file, run the database update scripts, and restart the server. These steps have been contributed by the Database plugin and JBoss plugin, respectively. See here for a more detailed description on how plugins interact to contribute steps to the overall deployment plan.

Since XL Deploy has successfully been able to generate a deployment plan based on our current deployment spec, we can reasonably assume that the spec is actually valid. We can also check that explicitly however and, if our current spec does not happen to be valid, get the server to return any validation errors.

Validating the deployment

We can pass our deployment spec to POST /deployment/validate to validate the deployment spec:

INPUT:

curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/deployit/deployment/validate -d@/tmp/deployment-spec.xml

Content of /tmp/deployment-spec.xml:

<deployment id="deployment-c90ec677-0be2-49bf-906f-650766740c36" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds>

    <sql.ExecutedSqlScripts id="Infrastructure/Dev/Database-1/MySql/sql">

      <deployable ref="Applications/PetPortal/1.0/sql"/>

      <container ref="Infrastructure/Dev/Database-1/MySql"/>

      <placeholders/>

    </sql.ExecutedSqlScripts>

    <jbossas.EarModule id="Infrastructure/Dev/Appserver-1/JBoss/PetClinic-ear">

      <deployable ref="Applications/PetPortal/1.0/PetClinic-ear"/>

      <container ref="Infrastructure/Dev/Appserver-1/JBoss"/>

      <placeholders/>

    </jbossas.EarModule>

  </deployeds>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment>

OUTPUT:

<deployment id="deployment-c90ec677-0be2-49bf-906f-650766740c36" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds>

    <sql.ExecutedSqlScripts id="Infrastructure/Dev/Database-1/MySql/sql">

      <deployable ref="Applications/PetPortal/1.0/sql"/>

      <container ref="Infrastructure/Dev/Database-1/MySql"/>

      <placeholders/>

    </sql.ExecutedSqlScripts>

    <jbossas.EarModule id="Infrastructure/Dev/Appserver-1/JBoss/PetClinic-ear">

      <deployable ref="Applications/PetPortal/1.0/PetClinic-ear"/>

      <container ref="Infrastructure/Dev/Appserver-1/JBoss"/>

      <placeholders/>

    </jbossas.EarModule>

  </deployeds>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment>

As described here, validation errors are indicated by a <validation-messages> block nested within the CI with errors. There are no validation errors in our case, as we anticipated.

Finally, then, we can ask XL Deploy to convert our validated deployment spec into a task that can be executed.

Creating a deployment task

We can submit our deployment spec to the server using POST /deployment/ to create a deployment task that we can run:

INPUT:

curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/deployit/deployment/ -d@/tmp/deployment-spec.xml

Content of /tmp/deployment-spec.xml:

<deployment id="deployment-c90ec677-0be2-49bf-906f-650766740c36" type="INITIAL">

  <application>

    <udm.DeployedApplication id="Environments/Dev/TEST/PetPortal">

      <version ref="Applications/PetPortal/1.0"/>

      <environment ref="Environments/Dev/TEST"/>

      <deployeds/>

      <orchestrator/>

      <optimizePlan>true</optimizePlan>

    </udm.DeployedApplication>

  </application>

  <deployeds>

    <sql.ExecutedSqlScripts id="Infrastructure/Dev/Database-1/MySql/sql">

      <deployable ref="Applications/PetPortal/1.0/sql"/>

      <container ref="Infrastructure/Dev/Database-1/MySql"/>

      <placeholders/>

    </sql.ExecutedSqlScripts>

    <jbossas.EarModule id="Infrastructure/Dev/Appserver-1/JBoss/PetClinic-ear">

      <deployable ref="Applications/PetPortal/1.0/PetClinic-ear"/>

      <container ref="Infrastructure/Dev/Appserver-1/JBoss"/>

      <placeholders/>

    </jbossas.EarModule>

  </deployeds>

  <deployables>

    <ci ref="Applications/PetPortal/1.0/PetClinic-ear" type="jee.Ear"/>

    <ci ref="Applications/PetPortal/1.0/sql" type="sql.SqlScripts"/>

  </deployables>

  <containers>

    <ci ref="Infrastructure/Dev/Appserver-1/JBoss" type="jbossas.ServerV5"/>

    <ci ref="Infrastructure/Dev/Database-1/MySql" type="sql.MySqlClient"/>

  </containers>

</deployment>

OUTPUT:

bd4aef1c-3a85-4d1a-a839-03ae619d01df

The task ID returned by the server can be used to start and inspect the deployment task using the TaskService. See this article for an example of starting a task using the REST API.

Have more questions? Submit a request