Skip to main content
DevOps icon showing cogs

This post is from the XebiaLabs blog and has not been updated since the original publish date.

Last Updated Dec 11, 2014 — DevOps Expert

Deploying with Dojo and JavaScript

DevOps

Using XL Deploy's REST API, you can embed a deployment process into a web application.  JavaScript with Dojo provides a nice medium for this.   See www.dojotoolkit.org for more information on Dojo.

The logic flow is exactly the same whether working from the GUI, the command line, or JavaScript.  First determine whether your deployment is an intial deployment or an update deployment. and make the appropriate REST API call to obtain a deployment spec.  Next, pass the spec to the prepare-deployed, validate-deployment and deploy steps.  The first two of these will make updates to the spec to be passed along to subsequent steps, and the final result is a task in a pending state.  Make a call to start the task, and your deployment is off and running. Here is this logic expressed in a JavaScript function that drives the process:
function xldDriver(env, app, ver, depApp) {
  error = false;
  deploymentType = checkDeploymentExists(env, app);
  deploymentSpec = null;
  taskId="";
  if (deploymentType == "update") {
    deploymentSpec = prepareUpdate(ver, depApp);
  } else if (deploymentType == "initial") {
    deploymentSpec = prepareInitial(env, ver);
  } else {
    error = true;
    dojo.publish("xhrError", [{message: "Application or Environment not found", type: "error", duration: 2000}]);
  }
  if (!error) {
    deploymentSpec = prepareDeployeds(deploymentSpec);
  }
  if (!error) {
    deploymentSpec = validateDeployment(deploymentSpec);
  }
  if (!error) {
    taskId = deploy(deploymentSpec);
  }
  if (!error && taskId.length > 0) {
    startTask(taskId);
  }
}
Each call is made from a subfunction, so let's look at those in sequence. The first one, checkDeploymentExists(), determines whether the deployment should be initial or update.  It uses the Dojo xhrGet method and passes the required parameters in a JavaScript object.
function checkDeploymentExists(environment, application) {
  deploymentType = "notfound";
  dojo.xhrGet({
    url: "http://localhost:4516/XL Deploy/deployment/exists",
    user: "admin",
    password: "admin",
    headers: { "Content-Type": "application/xml"},
    content: {
      environment: environment,
      application: application
    },
    sync: true,
    //timeout: 10000,
    handleAs: "xml",
    load: function(result, ioargs) {
      if (result.getElementsByTagName("boolean")[0].childNodes[0].nodeValue == "true") {
        deploymentType = "update";
      } else {
        deploymentType = "initial";
      }
      dojo.publish("xldStatus", [{message: deploymentType + " HTTP status code " + ioargs.xhr.status,
        type: "message", duration: 2000}]);
      },
    error: commonError
  });
  return deploymentType;
}
Url, user, password and headers are the standard HTML parameters you would expect.  The items under content are appended to the url as a query string.  You have a choice between sync (wait until the query returns before continuing), and timeout (run asynchronously but fail if the given number of milliseconds elapses without a return). The remaining parameters refer to how to handle what comes back:  handleAs refers to the format of the returned data, load is a callback function for a good result, and error is the "errback" for a bad one.  In this case, the latter will be commonError -- we'll handle all error conditions with the same logic to make the code a little simpler. When we get a good result, we parse the XML for the value between the <boolean>...</boolean> tags, and expect either true or false.  Otherwise we return not-found and exit out of the driver. The next two functions are similar, differing in the REST API calls used and the parameters passed to them:
function prepareInitial(environment, version) {
  deploymentSpec = "";
  dojo.xhrGet({
    url: "http://localhost:4516/XL Deploy/deployment/prepare/initial",
    user: "admin",
    password: "admin",
    headers: { "Content-Type": "application/xml"},
    content: {
      environment: environment,
      version: version
    },
    sync: true,
    //timeout: 10000,
    handleAs: "xml",
    load: function(result, ioargs) {
      deploymentSpec = result;
      dojo.publish("xldStatus", [{message: "InitDeplSpec HTTP status code " + ioargs.xhr.status, type: "message", duration: 2000}]);
    },
    error: commonError
  });
  return deploymentSpec;
}
function prepareUpdate(version, deployedApplication) {
  deploymentSpec = "";
  dojo.xhrGet({
    url: "http://localhost:4516/XL Deploy/deployment/prepare/update",
    user: "admin",
    password: "admin",
    headers: { "Content-Type": "application/xml"},
    content: {
      version: version,
      deployedApplication: deployedApplication
    },
    sync: true,
    //timeout: 10000,
    handleAs: "xml",
    load: function(result, ioargs) {
      deploymentSpec = result;
      dojo.publish("xldStatus", [{message: "UpdtDeplSpec HTTP status code " + ioargs.xhr.status, type: "message", duration: 2000}]);
    },
    error: commonError
  });
  return deploymentSpec;
}
They both use xhrGet calls similar to the one for checkDeploymentExists(), and both return the entire XML object obtained, which is the deployment spec in XML format.  In this example, they get their parameters from input fields using dojo.byId. The next two functions for prepareDeployeds and validDeployment() are similar to each other as well.  They both use xhrPost to make a Post request.  The deployment spec already obtained is passed in as the value of the postData item after being serialized to a string by a handy method of the XMLSerializer object.  Both return a deployment spec, potentially with new data added since we started.
function prepareDeployeds(deploymentSpec) {
  dojo.xhrPost({
    url: "http://localhost:4516/XL Deploy/deployment/prepare/deployeds",
    user: "admin",
    password: "admin",
    headers: { "Content-Type": "application/xml"},
    sync: true,
    postData: (new XMLSerializer()).serializeToString(deploymentSpec),
    //timeout: 10000,
    handleAs: "xml",
    load: function(result, ioargs) {
      deploymentSpec = result;
      dojo.publish("xldStatus", [{message: "PrepareDeployeds HTTP status code " + ioargs.xhr.status, type: "message", duration: 2000}]);
      },
    error: commonError
  });
  return deploymentSpec;
}
function validateDeployment(deploymentSpec) {
  dojo.xhrPost({
    url: "http://localhost:4516/XL Deploy/deployment/validate",
    user: "admin",
    password: "admin",
    headers: { "Content-Type": "application/xml"},
    sync: true,
    postData: (new XMLSerializer()).serializeToString(deploymentSpec),
    //timeout: 10000,
    handleAs: "xml",
    load: function(result, ioargs) {
      deploymentSpec = result;
      dojo.publish("xldStatus", [{message: "ValidateDeployeds HTTP status code " + ioargs.xhr.status, type: "message", duration: 2000}]);
      },
    error: commonError
  });
  return deploymentSpec;
}
Finally, we pass the deployment spec to the deploy function, which creates a task in pending status and returns its id to us as text.  Note the handeAs item reflects this format in this xhrPost call.
function deploy(deploymentSpec) {
  taskId = "";
  dojo.xhrPost({
    url: "http://localhost:4516/XL Deploy/deployment",
    user: "admin",
    password: "admin",
    headers: { "Content-Type": "application/xml"},
    sync: true,
    postData: (new XMLSerializer()).serializeToString(deploymentSpec),
    //timeout: 10000,
    handleAs: "text",
    load: function(result, ioargs) {
      taskId = result;
      dojo.publish("xldStatus", [{message: "Deploy HTTP status code " + ioargs.xhr.status, type: "message", duration: 2000}]);
      },
    error: commonError
  });
  return taskId;
}
We can start the task with this function, whose xhrPost call embeds the taskId in the url and omits the postData item:
function startTask(taskId) {
  dojo.xhrPost({
  url: "http://localhost:4516/XL Deploy/task/" + taskId + "/start",
  user: "admin",
  password: "admin",
  headers: { "Content-Type": "application/xml"},
  sync: true,
  handleAs: "xml",
  load: function(result, ioargs) {
    dojo.publish("xldStatus", [{message: "StartTask HTTP status code " + ioargs.xhr.status, type: "message", duration: 2000}]);
    },
  error: commonError
  });
}
Finally, the common error function is
// Global error variable accessed by multiple functions
error = false;
function commonError(text, ioargs) {
 error = true;
 dojo.publish("xhrError", [{message: "HTTP status code " + ioargs.xhr.status, type: "error", duration: 2000}]);
 return text;
}
And this is a good time to mention that throughout the process, we've passed HTTP status messages to two Dojo Toaster objects for display, under the names xldStatus and xhrError.  If you've found this article useful, please comment.  And let us know what other creative and interesting things you are doing with Dojo, JavaScript and XL Deploy!

More from the Blog

View more
Ascension Launch Banner
Apr 26, 2022

Get ready for peak performance with Digital.ai’s newest AI-Powered DevOps Platform Ascension Release

DevOps
Today, Digital.ai is excited to announce our latest AI-Powered DevOps ...
Read More
Jan 24, 2022

Digital.ai Value Stream Delivery for SAFe®: The key to amazing business outcomes

DevOps
The Scaled Agile Framework (SAFe) is the world’s leading framework for ...
Read More
Dec 09, 2021

How SaaS and cloud-based solutions helped the U.S. Department of Veterans Affairs achieve digital transformation

DevOps
Modernizing legacy systems was an ongoing goal for the U.S. Department ...
Read More
Nov 29, 2021

Increase velocity and reduce risk with AI and machine learning

DevOps
Artificial Intelligence (AI) and machine learning (ML) have proven use ...
Read More
Contact Us