Reckoning DevOps’ role in the enterprise value stream
DevOps
If you’re a software or digital solutions company, you may use DevOps ...
Read MoreThis post is from the XebiaLabs blog and has not been updated since the original publish date.
A deployment in XL Deploy may look like a single action when triggered by Jenkins, Bamboo, XL 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:INPUT: curl -u<username>:<password> "http://<xl-deploy-server>:<xl-deploy-port>/XL Deploy/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.
INPUT: curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/XL Deploy/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.
INPUT: curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/XL Deploy/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 control over 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.
INPUT: curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/XL Deploy/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.
INPUT: curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/XL Deploy/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>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.
INPUT: curl -u<username>:<password> -X POST -H "content-type:application/xml" http://<xl-deploy-server>:<xl-deploy-port>/XL Deploy/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-03ae619d01dfThe 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.