public Boolean executeStep(AbstractBuild build, SkytapGlobalVariables globalVars) {

    JenkinsLogger.defaultLogMessage("----------------------------------------");
    JenkinsLogger.defaultLogMessage("Creating Environment from Template");
    JenkinsLogger.defaultLogMessage("----------------------------------------");

    if (preFlightSanityChecks() == false) {
      return false;
    }

    this.globalVars = globalVars;
    this.authCredentials = SkytapUtils.getAuthCredentials(build);

    String expTemplateFile = SkytapUtils.expandEnvVars(build, templateFile);
    String expConfigFile = SkytapUtils.expandEnvVars(build, configFile);
    String expConfigName = SkytapUtils.expandEnvVars(build, configName);

    // if user has provided just a filename with no path, default to
    // place it in their Jenkins workspace

    if (!expTemplateFile.equals("")) {
      expTemplateFile = SkytapUtils.convertFileNameToFullPath(build, expTemplateFile);
    }

    if (!expConfigFile.equals("")) {
      expConfigFile = SkytapUtils.convertFileNameToFullPath(build, expConfigFile);
    }

    JenkinsLogger.log("Template File: " + expTemplateFile);
    JenkinsLogger.log("Config File: " + expConfigFile);
    JenkinsLogger.log("Config Name: " + expConfigName);

    try {
      runtimeTemplateID = SkytapUtils.getRuntimeId(templateID, expTemplateFile);
    } catch (FileNotFoundException e1) {
      JenkinsLogger.error("Error obtaining template id: " + e1.getMessage());
      return false;
    }

    JenkinsLogger.log("Template ID:  " + runtimeTemplateID);

    // check busy state of template - if template doesn't become
    // available after configured wait time, fail build step
    if (checkIsTemplateAvailable(runtimeTemplateID) == false) {
      JenkinsLogger.error(
          "Template ID: "
              + runtimeTemplateID
              + " has not become available yet. Failing build step.");
      return false;
    }

    // build request url
    String requestURL = buildCreateConfigRequestURL(runtimeTemplateID);

    // create request for Skytap API
    HttpPost hp = SkytapUtils.buildHttpPostRequest(requestURL, this.authCredentials);

    // execute request
    String httpRespBody = "";

    try {
      httpRespBody = SkytapUtils.executeHttpRequest(hp);
    } catch (SkytapException e1) {
      JenkinsLogger.error("Skytap Exception: " + e1.getMessage());
      return false;
    }

    try {
      SkytapUtils.checkResponseForErrors(httpRespBody);
    } catch (SkytapException ex) {
      JenkinsLogger.error("Request returned an error: " + ex.getError());
      JenkinsLogger.error("Failing build step.");
      return false;
    }

    // get json object from the response
    JsonParser parser = new JsonParser();
    JsonElement je = parser.parse(httpRespBody);
    JsonObject jo = je.getAsJsonObject();

    // TODO: extract into separate method
    // if name was provided, update the created environment's name
    // using an http put request
    if (!expConfigName.equals("")) {

      String configId = jo.get("id").getAsString();

      // build request url
      String updateRequestURL = buildUpdateConfigNameRequestURL(configId, expConfigName);

      // create request for Skytap API
      HttpPut hput = SkytapUtils.buildHttpPutRequest(updateRequestURL, this.authCredentials);

      // execute request
      httpRespBody = "";

      try {
        httpRespBody = SkytapUtils.executeHttpRequest(hput);
      } catch (SkytapException ex) {
        JenkinsLogger.error("Request returned an error: " + ex.getError());
        JenkinsLogger.error("Failing build step.");
        return false;
      }

      try {
        SkytapUtils.checkResponseForErrors(httpRespBody);
      } catch (SkytapException ex) {
        JenkinsLogger.error("Request returned an error: " + ex.getError());
        JenkinsLogger.error("Failing build step.");
        return false;
      }

      // if the update succeeded, update the json object also
      je = parser.parse(httpRespBody);
      jo = je.getAsJsonObject();
    }

    // save json object to the environment file path
    // if user has provided just a filename with no path, default to
    // place it in their Jenkins workspace
    expConfigFile = SkytapUtils.convertFileNameToFullPath(build, expConfigFile);

    Writer output = null;
    File file = new File(expConfigFile);
    try {

      output = new BufferedWriter(new FileWriter(file));
      output.write(httpRespBody);
      output.close();
    } catch (IOException e) {

      JenkinsLogger.error("Skytap Plugin failed to save environment to file: " + expConfigFile);
      return false;
    }

    // Sleep for a a few seconds to make sure the Config is stable, then we
    // can exit
    try {
      Thread.sleep(10000);
    } catch (InterruptedException e) {
      JenkinsLogger.error("Error: " + e.getMessage());
    }

    JenkinsLogger.defaultLogMessage(
        "Environment successfully created and saved to file: " + expConfigFile);
    JenkinsLogger.defaultLogMessage("----------------------------------------");
    return true;
  }