1. Home
  2. Docs
  3. User Manual
  4. Changesets
  5. Iterator and Evaluator Scripts

Iterator and Evaluator Scripts

Iterator Script

The iterator script determines the number of times (iterations) an action will be run.

Evaluator Script

The evaluator script is called for each iteration of the Action and it is intended to be used to alter the changeset variables for each iteration. Changes to the changeset variables persist beyond this action.

The ability to perform Genesys configuration automation becomes more challenging when you consider the scaling differences between production and non-production environments. Here we will discuss how to address the horizontal and vertical scale of Genesys components with the use of InProd Changesets.

While your Genesys application architecture and configuration options should all be in alignment with your environments, it is common that there will be scaling differences between them.

Most Genesys lab environments do not have all of the High Availability (HA) components installed, as they are often not needed during the development phase. But, a higher testing environment usually has full HA. Pre Production environments could then be a multi-site HA deployment.

So, how do you deploy in a consistent manner to multiple environments that have different scaling requirements?

Scaling differences between Genesys environments

When promoting a change in the environment, there are a number of factors that need to be considered for a successful deployment, scaling differences should be up the top.

With the use of Changesets, InProd is able to take a single change and promote it between environments without being modified. The Changeset can cater to environmental differences and detect issues before performing any changes. Now, within the 1.13 release, InProd is also able to meet the different scaling requirements of each environment.

To achieve this, we introduced two new concepts, the first of which is the iterator. Each action within a Changeset can be configured to be iterated or repeated a different number of times for each targeted environment.

Iterator value per application/environment

In the above example, the backup application would be iterated 0 times (skipped) within the Dev environment, which means it will not be installed and an iterator value of 2 would be used for PreProd to support deployment for Site 1 & Site 2. The iterator allows the user to determine how many instances of an object there should be for the given environment. Here we are using an Application object as an example, but any Genesys configuration object could be used.

The second concept introduced is the evaluator, which is focused on modifying the Changeset variables on each iteration of the action. Consider the Primary application, you need to modify its name each for each instance. For PreProd the backup application will also need to be set differently for each instance.  These are just two examples of parameters that need to be modified between each iteration within the same environment.

With the introduction of the iterator and evaluator, InProd Changesets are now able to cater for extreme edge case situations such as the scaling differences discussed here. A single InProd Changeset can be used to deploy and maintain CX features within multiple Genesys environments.

The iteration and evaluator are both Javascript expressions that are resolved at run time. Full details are available within the following KB article Scripting with Javascript V8 compiler
(https://help.inprod.io/a/solutions/articles/43000539677)

Working Example

The below section is a working example of a changeset that will deploy a Message Server application into three different environments as described above. This Changeset assumes that your environment has 3 environments with the Ids of 1,2 and 3.

Scripting with Javascript V8 compiler

Some Changeset components support the ability to write Javascript code to drive complex conditional logic that could not be achieved with the use of Changeset Variables. With the use of javascript, Changesets are able to cater to any level of complexity that you may encounter.

InProd uses the same Javascript V8 engine that is used within the Chrome browser to execute the script. This provides access to the latest Javascript features. No external libraries or system resources can be accessed by the Javascript VM.

The Iterator script is called once for each Action within a Changeset and can result in the Action being performed multiple times (iterated). The Evaluator script is called for each iteration of the Action and can be used to alter the results greatly between the Actions.

The Generic API has a Script parameter, which allows for returned data from API calls to be applied to Changeset Variables.

Available Variables

A number of variables will be made available to the Javascript VM that can be used within conditional logic. Any updates to these values will not be retained.

Iterator Script

Determines how many times the Changeset action will be run (iterated). A result of zero indicates that the action will be skipped. The following system variables will be available within the Javascript environment.

  • inprod_environment = Environment Id
  • inprod_objectType = Object type the action is performing a change on
  • inprod_action = Object containing the Changeset Action data
  • All defined Changeset variables including Global Variables

Iterator Script Example

Iterator script example that returns a different number of iterations for each environment. Here environment 1 returns a value of 0 which means the action will be skipped.

JavaScript

(() => {
     if(inprod_environment == 1) {
          return 0
     } else if(inprod_environment == 2) {
          return 1
     } else if(inprod_environment == 3) {
          return 2
     }
})()

Evaluator Script

The Javascript code can modify the Changeset variables with each iteration of the action. These modifications will be applied to the remaining actions. The following system variables are available within the Javascript environment.

  • inprod_environment = Environment Id
  • inprod_objectType = Object type the action is performing a change on
  • inprod_action = Object containing the Changeset Action data
  • All defined Changeset variables including Global Variables
  • inprod_iteration = The current iternation number, starting at 1.

The return value should be a regular dictionary Object of the Changeset Variables to be updated. Only return the values that should be updated. ES6 Arrow functions can be used, such as (() => { ..code.. })() Note that the function is also be called with the code.

Evaluator Script Example

Evaluator script example returns a variable named ‘backup’ that is being used within the Backup parameter of the Application objects query value. The script will return an empty value for environment 1, meaning the application will not have a backup application configured.

JavaScript

(() => {
     if(inprod_environment == 1) {
          return {'backup': '', 'site':''}
     } else if(inprod_iteration == 1) {
          return {'backup': 'name=MS_Backup', 'site':'_site1'}
     } else if(inprod_iteration == 2) {
          return {'backup': 'name=MS_Backup_site2', 'site':'_site2'}
     }
})()

Evaluator Script ES5 Functions

Within the Evaluator scripting, the default is JavaScript ES6 but this can be disabled which defaults to ES5. A limited number of internal InProd function calls can be exposed with ES5 which greatly expands the functionality of what can be done within a Changeset. The following functions are available

setChangesetProperty(property_name, property_data) This function call allows the JavaScript code to update any Changeset parameter directly within the script. This is designed to meet complex edge cases where some Genesys parameters, such as annex and options, are not easily set via a Changeset variable. Some parameters will require special formatting, for clarification check the bow log file.

  • Skills are a list of dictionaries in the following format {'skillDbid': {'lookup_method':'query', 'value': skillName}, 'level': 9}
  • Any reference objects such as folder or host will use {'lookup_method': 'query', 'value': folderPath}
  • Annex and Options are complex and the default code within the Evaluator Script of a Change Sync object should be referenced as an example

getGenFolderPath(folderDbid) Returns the full path for any folder object, this is in path notation that can be used within a query.

getObject(environment_id, model_name, query_str, return_single=False) – Get any object within InProd. Environment Id can be seen on the Admin page. The query string format is the same that is used within a standard Changeset Action query. The optional argument return_single is used to indicate if you are expecting a single match or a list of results. The data returned is a JSON string and needs to be converted into an object

// For Environment 1, we are looking for a Skill, with the query based on the name of the skill which is determined by the variable ‘skill’
var skillObjStr = getObject(1,’GenSkill’,’name=’.concat(skill));
// The result is a string, conver this to an object
var skillObj = JSON.parse(skillObjStr);
var skillDbid = skillObj[‘dbid’]

logError(message) – Generates a Changeset validation error with a custom message. This is useful to catch error conditions or sometimes used as a debug tool to display a JavaScript output.

logMsg(message) – Generates a log message that can only be seen within the Bow log file.

The following sample code demonstrates how some of these functions can be used. This is taken from a Create Person action that has an Iterator Script value set to 8, meaning the same action will run 8 times. Each time the action runs the JavaScript variable inprod_iteration is incremented which changes the outcome.

function addSkill(skill, level) {

  // The Genesys Skill name is supplied by 'skill' and the level of the is within 'level'
  return {skillDbid: {lookup_method: 'query', value: 'name='.concat(skill)}, level: level }
}

function foo() {
  // A list of user names that will be created
  let userNamelist = ['James', 'John', 'Jim', 'Jeff', 'Jill', 'Jeremy', 'Jake', 'Jack'];
  // Give the user name based off the list
  setChangesetProperty('userName', userNamelist[inprod_iteration-1]);

  // employeeId will be update with the iteration number
  setChangesetProperty('employeeId', inprod_iteration);

  // A list of skills that can be assigned within this example
  let skill_list = ['skill_One', 'skill_Two', 'skill_Three', 'skill_Four'];
  // Generate a random number to assign the skill
  let randomNumber = Math.floor(Math.random()*skill_list.length);
  logMsg('randomNumber = '.concat(randomNumber)); // create a log message
  let skill = [];
  if (randomNumber == 1) {skill.push(addSkill(skill_list[0], randomNumber))}
  if (randomNumber == 2) {skill.push(addSkill(skill_list[1], randomNumber))}
  if (randomNumber == 3) {skill.push(addSkill(skill_list[2], randomNumber))}
  if (randomNumber == 4) {skill.push(addSkill(skill_list[3], randomNumber)); skill.push(addSkill(skill_list[2], randomNumber))}
  setChangesetProperty('skills', skill);

  return {}; // In this case we are not updating any Changeset variables.
}

foo();

Generic API Script

  • inprod_environment = Environment Id
  • response_data = String data returned from API call

Generic API Script Example

Full example of Generic API Script that returns the token used to login to the InProd API

JavaScript

(() => {
     response_data = JSON.parse(response_data);
     var token = response_data['tokens']['auth'];
     return {"token": "Token " + token}
})()

How can we help?