Name

global.MIDDeploymentRequest

Description

This class contains utility functions for working with MID Deployment Requests.

Script

var MIDDeploymentRequest = Class.create();

MIDDeploymentRequest.DEFAULT_MAX_MID_QUANTITY_PER_REQUEST = 10;

/**
* Determine the maximum number of mid servers that are allowed to create per request
*/
MIDDeploymentRequest.maxMidQuantity = function() {
  return parseInt(gs.getProperty('mid.deployment.max_mid_quantity', MIDDeploymentRequest.DEFAULT_MAX_MID_QUANTITY_PER_REQUEST)) ||
      MIDDeploymentRequest.DEFAULT_MAX_MID_QUANTITY_PER_REQUEST;
};

/**
* Retrieve profile parameters
*
* @param {string} tableName The name of a profile config table, i.e. mid_profile_wrapper_config and mid_profile_config
* @param {string} profileID The sys_id of a MID Server profile record
* @returns {array} array of config parameters associated with a profile from the given table
*/
MIDDeploymentRequest.getProfileParams = function(tableName, profileID) {
  if (JSUtil.nil(tableName) || (tableName != 'mid_profile_wrapper_config' && tableName != 'mid_profile_config'))
      throw new Error(gs.getMessage('Table {0} is not a valid profile config table', tableName));

  var result = [];
  var gr = new GlideRecord(tableName);
  gr.addQuery("profile", profileID);
  gr.query();
  while (gr.next()) {
      var param = {};
      param["name"] = gr.getValue("name");
      param["value"] = gr.getValue("value");
      result.push(param);
  }
  return result;
};

/**
* Retrieve the profile data.
*
* @param {string} profileID The sys_id of a MID Server profile record
* @returns {object} an object that holds the given profile's data
*/
MIDDeploymentRequest.getProfile = function(profileID) {
  var gr = new GlideRecord('mid_server_profile');
  if (!gr.get(profileID))
      throw new Error(gs.getMessage("The MID Server profile with ID {0} does not exist!", profileID));

  var wrapperParams = MIDDeploymentRequest.getProfileParams("mid_profile_wrapper_config", profileID);

  var configParams = MIDDeploymentRequest.getProfileParams("mid_profile_config", profileID);
  // add the mid_profile_id config param
  var param = {};
  param["name"] = "mid_profile_id";
  param["value"] = profileID;
  configParams.push(param);

  var profile = {};
  profile["profile_id"] = profileID;
  profile["config"] = configParams;
  profile["wrapper_config"] = wrapperParams;
  return profile;
};

/**
* Retrieve the agent application name with the given ID
*
* @param {string} applicationID The sys_id of a MID Server application record
* @returns {string} The agent application name with the given ID
*/
MIDDeploymentRequest.findMIDApplication = function(applicationID) {
  var gr = new GlideRecord("ecc_agent_application");
  if (!gr.get(applicationID))
      throw new Error(gs.getMessage("The agent application with ID {0} does not exist!", applicationID));

  return gr.getValue("name");
};

/**
* Retrieve the agent capabilities from a comma separated list of capability IDs
*
* @param {string} capabilityIDs a comma separated list of agent capability IDs
* @returns {array} An array of agent capabilities with the given IDs
*/
MIDDeploymentRequest.findMIDCapabilities = function(capabilityIDs) {
  var result = [];
  if (JSUtil.nil(capabilityIDs) || capabilityIDs.trim().length == 0)
      return result;

  var capArr = capabilityIDs.split(',');
  var gr = new GlideRecord("ecc_agent_capability");
  for (var i = 0; i < capArr.length; i++) {
      if (!gr.get(capArr[i])) {
          gs.logWarning(gs.getMessage("Could not find MID Server capability with ID {0}", capArr[i]), this.MID_SERVER_MANAGEMENT);
          continue;
      }
      var cap = {};
      cap["capability"] = gr.getValue('capability');
      cap["value"] = gr.getValue('value');
      result.push(cap);
  }
  return result;
};

/**
* Convert a comma separated list to an array
*/
MIDDeploymentRequest.toArray = function(commaSeparatedList) {
  if (commaSeparatedList == null || commaSeparatedList.trim().length == 0)
      return [];

  return commaSeparatedList.split(',').map(
      function(item) {
          return item.trim();
      }
  );
};

/**
* Convert a string to a JSON object
*/
MIDDeploymentRequest.toJSON = function(text) {
  try {
      return JSON.parse(text);
  } catch (error) {
      throw new Error(gs.getMessage("The text {0} is a not valid JSON string! Error: {1}", [text, error]));
  }
};


MIDDeploymentRequest.prototype = {

  MID_SERVER_MANAGEMENT: 'MID Server Management',

  initialize: function(requestID) {
      var gr = new GlideRecord('mid_server_deployment');
      if (!gr.get(requestID))
          throw new Error(gs.getMessage('The deployment request with ID {0} does not exist!', requestID));

      this.requestID = '' + requestID;
      this.realTableName = '' + gr.sys_class_name; // convert to string

      gr = new GlideRecord(this.realTableName);
      gr.get(this.requestID);
      this.requestGR = gr;
      this.maxMidQuantity = MIDDeploymentRequest.maxMidQuantity();
  },

  duplicate: function(duplicatedNameSuffix, numberOfMids) {
      this.requestGR.name = this.requestGR.name + duplicatedNameSuffix;
      if (JSUtil.notNil(numberOfMids) && !isNaN(numberOfMids))
          this.requestGR.mid_quantity = numberOfMids;
      this.requestGR.number = '';
      this.requestGR.state = 'new';
      this.requestGR.processed_at = null;
      this.requestGR.results = '';
      return this.requestGR.insert();
  },

  findDeploymentMIDServer: function() {
      var midSelectMethod = this.requestGR.getValue('mid_select_method');
      var deploymentMIDServerID;
      var midSelector;
      switch (midSelectMethod) {
          case 'auto_select':
              var application = MIDDeploymentRequest.findMIDApplication(this.requestGR.getValue('mid_application'));
              var capabilities = this.requestGR.getValue('mid_capabilities');
              var capabilityList = MIDDeploymentRequest.findMIDCapabilities(capabilities);
              midSelector = new SNC.MidSelector();
              try {
                  deploymentMIDServerID = midSelector.selectAnyDegradedOrBetterMidServer(application, null, capabilityList);
              } catch (e) {
                  throw new Error(gs.getMessage("Could not find a suitable MID Server with application {0} and capabilities {1}. Error: {2}", [application, JSON.stringify(capabilityList), e]));
              }
              break;

          case 'specific_cluster':
              var midClusterID = this.requestGR.getValue('mid_cluster');
              midSelector = new SNC.MidSelector();
              try {
                  deploymentMIDServerID = midSelector.selectAnyDegradedOrBetterMidServerFromClusterEx(this.MID_SERVER_MANAGEMENT, midClusterID);
              } catch (e) {
                  throw new Error(gs.getMessage("Could not find a suitable MID Server from the cluster with ID {0}. Error: {1}", [midClusterID, e]));
              }
              break;

          case 'specific_mid_server':
              deploymentMIDServerID = this.requestGR.getValue('mid_server');
              break;

          default:
              throw new Error(gs.getMessage("Unknown MID selection Method {0}", midSelectMethod));
      }

      var agentCache = new SNC.ECCAgentCache();
      var agentGR = agentCache.getBySysId(deploymentMIDServerID);
      if (agentGR == null)
          throw new Error(gs.getMessage("Could not find a deployment MID Server with ID {0}", deploymentMIDServerID));

      return agentGR.getValue('name');
  },

  generateMIDServerNames: function() {
      var auto_generate = JSUtil.getBooleanValue(this.requestGR, 'auto_generate_mid_names');
      if (auto_generate) {
          var quantity = this.requestGR.getValue('mid_quantity');
          if (quantity <= 0)
              throw new Error(gs.getMessage("The MID server quantity {0} must be a positive number", quantity));

          if (quantity > this.maxMidQuantity)
              throw new Error(gs.getMessage("The MID server quantity {0} is greater than the maximum number {1} of MID Servers allowed per request", [quantity, this.maxMidQuantity]));

          var prefix = this.requestGR.getValue('mid_server_name_prefix');
          var midServerNames = '';
          var numMgr = new NumberManager('ecc_agent');
          for (var i = 0; i < quantity; i++) {
              var midName = numMgr.getNextObjNumberPadded();
              if (i > 0)
                  midServerNames += ",";
              midServerNames += midName.replace('MID_', prefix);
          }
          this.requestGR.setValue('mid_server_names', midServerNames);
          this.requestGR.update();
          return midServerNames;
      }
      return this.requestGR.getValue('mid_server_names');
  },

  validateMIDServerNames: function(midNameList) {
      if (JSUtil.nil(midNameList) || midNameList.length == 0)
          throw new Error(gs.getMessage("The list of new MID server names is empty"));

      // check for duplicate MID Server name
      var duplicates = [];
      var agentCache = new SNC.ECCAgentCache();
      for (var i = 0; i < midNameList.length; i++) {
          var agentGR = agentCache.getByName(midNameList[i]);
          if (agentGR)
              duplicates.push(midNameList[i]);
      }

      if (duplicates.length > 0)
          throw new Error(gs.getMessage("The MID server names {0} are already in use!", duplicates.join()));
  },

  isStatefulSet: function() {
  	return JSUtil.getBooleanValue(this.requestGR,"ss_choice");
  },

  getK8sDeploymentRequest: function() {
      if (this.realTableName != 'mid_k8s_deployment')
          throw new Error(gs.getMessage("The deployment type {0} is not supported!", this.realTableName));

      var k8sDeploymentLabel = MIDDeploymentRequest.toJSON(this.requestGR.getValue("k8s_deployment_label"));
      var profileID = this.requestGR.getValue("profile");
      var profile = MIDDeploymentRequest.getProfile(profileID);

      var midServerNames = this.generateMIDServerNames();
      var midNameList = MIDDeploymentRequest.toArray(midServerNames);
      this.validateMIDServerNames(midNameList);

      var deployRequest = {};
      deployRequest["deployment_request_id"] = this.requestID;
      deployRequest["name"] = this.requestGR.getValue('name');
      deployRequest["type"] = this.realTableName;
      deployRequest["profile"] = profile;

      deployRequest["container_image_repository"] = this.requestGR.getValue("container_image_repository");
      deployRequest["container_image_tag"] = this.requestGR.getValue("container_image_tag");

      deployRequest["cpu_request"] = this.requestGR.getValue("cpu_request");
      deployRequest["memory_request"] = this.requestGR.getValue("memory_request");
      deployRequest["cpu_limit"] = this.requestGR.getValue("cpu_limit");
      deployRequest["memory_limit"] = this.requestGR.getValue("memory_limit");

      deployRequest["post_start_command"] = this.requestGR.getValue("post_start_command");
      deployRequest["pre_stop_command"] = this.requestGR.getValue("pre_stop_command");
      deployRequest["termination_grace_time"] = this.requestGR.getValue("termination_grace_time");

      deployRequest["k8s_namespace"] = this.requestGR.getValue("k8s_namespace");
      deployRequest["k8s_service_account"] = this.requestGR.getValue("k8s_service_account");
      deployRequest["k8s_deployment_label"] = k8sDeploymentLabel;

      deployRequest["mid_secrets_name"] = this.requestGR.getValue("mid_secrets_name");
      deployRequest["mid_secrets_file_path"] = this.requestGR.getValue("mid_secrets_file_path");

      deployRequest["mid_mutual_auth_pem_secrets_name"] = this.requestGR.getValue("mid_mutual_auth_pem_secrets_name");
      deployRequest["mid_mutual_auth_pem_file_path"] = this.requestGR.getValue("mid_mutual_auth_pem_file_path");

      deployRequest["mid_server_names"] = midNameList;
      return deployRequest;
  },

  createK8sProbe: function() {
      if (this.realTableName != 'mid_k8s_deployment')
          throw new Error(gs.getMessage("The deployment type {0} is not supported!", this.realTableName));

      if (this.isStatefulSet())
          throw new Error(gs.getMessage("StatefulSet is only supported via exported YAML file!"));

      var deploymentMIDServer = this.findDeploymentMIDServer();
      var deployRequest = this.getK8sDeploymentRequest();

      var probe = new SncProbe();
      probe.setName(deployRequest['name']);
      probe.setTopic("KubernetesOperationProbe");
      probe.setSource('');
      probe.addParameter("enc_input_payload", "false");
      probe.addParameter("skip_sensor", "true");
      probe.addParameter("deployment_request_id", this.requestID);

      var jsonStr = JSON.stringify(deployRequest);
      var deployRequestBase64 = GlideStringUtil().base64Encode(jsonStr);
      probe.addEncryptedParameter("deployment_request", deployRequestBase64);
      var eccOutputSysId = probe.create(deploymentMIDServer);
      if (JSUtil.nil(eccOutputSysId))
          throw new Error(gs.getMessage("Failed to create KubernetesOperationProbe to the deployment MID server {0}", deploymentMIDServer));
      var result = {};
      result["eccOutputSysId"] = eccOutputSysId;
      result["deploymentRequest"] = deployRequest;
      return result;
  },

  type: 'MIDDeploymentRequest'
};

Sys ID

49460fe753463010347cddeeff7b12b3

Offical Documentation

Official Docs: