Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

ModelOp Center seamlessly integrates with existing ticketing systems, such as ServiceNow, to allow enterprises to orchestrate seamlessly change requests and incidents as part of the model life cycle.

Table of Contents

Table of Contents

Introduction

ModelOp Center provides the ability for a Model Life Cycle to create and manage tickets within an existing ServiceNow system. The ticket types supported include change requests and incidents created and managed using the Table or Import Set APIs. This guide details the steps to enable integration.

ServiceNow Integration Setup

Prerequisites

This guide is based on using the distribution moc-configuration for helm. If you do not have the distribution moc-configuration, please request download instructions here.

Before configuring, ServiceNow will need a service account created and configured. For an example of how to set up a service account see the instructions at https://community.servicenow.com/community?id=community_blog&sys_id=b4fca2a5dbd0dbc01dcaf3231f961900. This guide assumes that the service account uses the email "servicenow@modelop.com".

moc-

builder

configuration ServiceNow Configuration

The integration requires the ModelOp Center Gateway url and the url of the ServiceNow instance to be integrated.First, determine the external-ip of the Gateway. Set the Kubernetes context to the cluster and namespace that has ModelOp Center deployed. Run the following commandconfiguration properties for ServiceNow are located in application.yaml. Edit the following properties:

Code Block
languagebashyaml
kubectlmodelop:
get svc

The command will return an output like this:

Code Block
[johncarter@Johns-MacBook-Pro moc-builder (John@modelop-eks-test.us-east-2.eksctl.io:mocaasin)]$ kb get svc
NAME                TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)                                                 AGE
engine-1            ClusterIP      10.100.72.22     <none>                                                                    8003/TCP                                                23h
engine-2            ClusterIP      10.100.31.255    <none>                                                                    8003/TCP                                                23h
engine-test         ClusterIP      10.100.215.6     <none>                                                                    8003/TCP                                                23h
gateway             LoadBalancer   10.100.126.106   foo1.us-east-2.elb.amazonaws.com   8090:31166/TCP                                                                                 23h
jupyter             ClusterIP      10.100.242.107   <none>                                                                    8888/TCP                                                23h
kafka               ClusterIP      10.100.113.242   <none>                                                                    9092/TCP                                                23h
minio               ClusterIP      10.100.82.143    <none>                                                                    9000/TCP                                                23h
mlc-manager         LoadBalancer   10.100.145.82    foo3.us-east-2.elb.amazonaws.com    8085:31741/TCP                                                                                23h
model-manager       ClusterIP      10.100.205.30    <none>                                                                    8086/TCP,8088/TCP                                       23h
mongodb             ClusterIP      10.100.45.49     <none>                                                                    27017/TCP                                               23h
postgres            ClusterIP      10.100.77.22     <none>                                                                    5432/TCP                                                23h
registry            ClusterIP      10.100.138.128   <none>                                                                    8761/TCP                                                23h
reporting-service   ClusterIP      10.100.38.87     <none>                                                                    8091/TCP                                                23h

The important value is the external-ip and port corresponding to the ModelOp Center Gateway. In this example, it’s foo1.us-east-2.elb.amazonaws.com:8090.

NOTE: If the environment is using ingresses instead of load balancers, run kubectl get ing and obtain the address corresponding to the ingress that points to gateway. Do not append the port number to the end of the address. That is only required if you are using the external IP from a service of type LoadBalancer.

Next, open the application.yaml file within the moc-builder environment directory and navigate to the config.moc-services.gateway section. It will contain something like the following:

Code Block
languageyaml
    gateway:
      url: http://gateway:8090
      websocket-url: ws://gateway:8090
      external-url: http://localhost:8090
      response-timeout: 2m

Change the value of external-url to the location of gateway from above.

Here is an example of that section of application.yaml:

Code Block
languageyaml
    gateway:
      url: http://gateway:8090
      websocket-url: ws://gateway:8090
      external-url: foo1.us-east-2.elb.amazonaws.com:8090
      response-timeout: 2m

Find the config.moc-services.supporting-services.servicenow section. It will contain something like the following:

Code Block
languageyaml
    servicenow:
      username: demo
      password: modelop
      url: http://servicenow

Change the username to the username associated with the service account and the password to be the service account password. Update the url to be ServiceNow url. For this example we use https://dev.servicenow.com.

Here is an example:

Code Block
languageyaml
    servicenow:
      username: servicenow@modelop.com
      password: service account password goes here
      url: http://dev.servicenow.com
Next, run the moc-builder compose and deploy commands to bring up the instance of ModelOp Center integrated with ServiceNow.
center-url: # this should be the external name of MOC; this url will be the base for urls from servicenow back to moc center entities
  service-now-url: # this should be the external name of ServiceNow
  service-now-user:
  service-now-password:

As an example, this properties might look as follows:

Code Block
languageyaml
modelop:
  moc-center-url: foo1.us-east-2.elb.amazonaws.com:8090
  service-now-url: https://foo.servicenow.com
  service-now-user: servicenow@modelop.com
  service-now-password: servicenowpass

where foo1.us-east-2.elb.amazonaws.com:8090 is the external URL to the gateway, https://foo.servicenow.com is the ServiceNow URL, servicenow@modelop.com is the user name, and servicenowpass is the password.

Next, ensure the configuration is active in the fleet.

  • If using sscs backed by git, commit the changes and refresh the actuator or restart mlc-manager

  • If using a configmap, run helm upgrade, restart sccs, and refresh the actuator or restart mlc-manager

Security

As mentioned in Prerequisites we recommend using a service account for the ServiceNow integration. Limit the access rights of the service account to just those needed for the integration and only use the service account for the integration. The security advantages to using a service account are explained here.

The integration uses Basic Authentication to authenticate REST calls to ServiceNow. The credentials can be set up using Kubernetes secrets, as in the configuration example above, or using Vault.

ServiceNow Ticket Customization

The integration provides a variety of parameters to allow customization of ServiceNow ticket creation and lifecycle management within a Model Life Cycle. Some of these parameters are discussed in more detail below.

Ticket Creation

SERVICENOW_API - The API to use when creating tickets (table or import). The integration supports both the Table API and the Import Set API for ticket creation.

SERVICENOW_TABLE_NAME - The table to create new tickets in. This is the path parameter of the API being used. This is usually change_request, incident, or the name of an Import Set.

SERVICENOW_CUSTOM_FIELDS- A JSON string containing any custom fields to send with the creation request. By default the implementation will provide data for a few fields and this parameter allows setting as many fields as needed. The custom fields can also be used to override the value traditionally sent for that field. One exception to the override functionality is the description field. If the description field is overridden, the custom override value will be used as a notification message within the description and the default description template will still be used to ensure that links back to the appropriate entity are included in the description. If a uuid or u_uuid field is required per request, including retries, then set the field to empty string and the integration will generate a random UUID to use for each request.

Ticket Updates

SERVICENOW_UPDATES - A JSON string specifying additional updates to make to the ticket after creation. Some workflows require additional automated updates to the ticket after creation. This field includes the required information to make those updates. UUID generation works here the same as for SERVICENOW_CUSTOM_FIELDS. If a field needs to use the value from the current state of the ticket include that field in the payload and set the value to empty string. The integration will replace the value with the value of the field in the ticket. The structure of the JSON is shown below:

Code Block
languagejson
[
  {
    "serviceNowApi" : "(table|import)",
    "serviceNowTableName" : "tableName",
    "serviceNowCustomFields" : {
      "field1":"value1",
      "replacement": "",
       ...
  }
  ...
]

Ticket Lifecycle

SERVICENOW_EXIT_STATUS_FIELD - The field on the ticket to watch for an exit state. The Model Life Cycle waits until this field reaches a desired SERVICENOW_EXIT_STATUS. By default the integration watches the state field. The display_value of the field is watched.

SERVICENOW_EXIT_STATUS - A string listing out the exit statuses for the ticket. When the SERVICENOW_EXIT_STATUS_FIELD reaches one of the exit statuses in this parameter the Model Life Cycle will stop watching the ticket and proceed.

SERVICENOW_EXIT_CONDITIONS - A string listing out statuses and exit conditions that must be met for each status to be realized. Some workflows require considering multiple fields to determine if the ticket has met its exit status. This field uses a CSV-like format to list out conditions. Specifically,

Code Block
Status1,ConditionType1,Condition1
Status2,ConditionType2,Condition2
…

where commas are used as a separator. Commas are permitted in the condition. A new line indicates the beginning of a new condition. Both juel and spel conditions are supported.

As an example, a workflow may require watching the state field to reach canceled or for the approval field to reach approved or rejected. The conditions for such a workflow could look like the following.

Code Block
languagetext
Canceled,juel,\${ticket.state.display_value.equalsIgnoreCase('canceled')}
Rejected,juel,\${ticket.approval.display_value.equalsIgnoreCase('rejected')}
Approved,juel,\${ticket.approval.display_value.equalsIgnoreCase('approved')}

The conditions are evaluated in the order they are listed. The ticket variable is provided for expression evaluation by the integration and represents the current state of the ticket. The \$ is escaped in the example above so that Camunda itself will not attempt to evaluate the juel conditions. When a condition is satisfied the TICKET_STATUS variable will be set to the matching status for further use in the Model Life Cycle.

Only one of SERVICENOW_EXIT_CONDITIONS and SERVICENOW_EXIT_STATUS will be used when determining if a ticket has reached exit status with the following priority order:

  1. Local SERVICENOW_EXIT_CONDITIONS variable

  2. Local SERVICENOW_EXIT_STATUS variable

  3. SERVICENOW_EXIT_CONDITIONS variable

  4. SERVICENOW_EXIT_STATUS variable

In cases 2 and 4 SERVICENOW_EXIT_STATUS can be set to null to indicate that there should be no wait after creation and update. If SERVICENOW_EXIT_CONDITIONS is used then SERVICENOW_EXIT_STATUS_FIELD has no effect.

UPDATE_STORED_MODEL_FIELDS - A map used to update values in the stored model from fields in the ServiceNow ticket. As an example, a mapping from u_model_risk to modelMetaData.modelRisk would update modelRisk to the value of the ServiceNow u_model_risk field.

UPDATE_DEPLOYABLE_MODEL_FIELDS - A map used to update values in the deployable model from fields in the ServiceNow ticket. This works the same way as UPDATE_STORED_MODEL_FIELDS but targets a deployable model instead of the stored model.

Raising/Managing Change Requests

To use a change request within a Model Life Cycle a notification must be created and stored and then the ticket created and the lifecycle managed. Examples of how to use the different notifications are provided in mlc-building-blocks. A simple example is shown below.

The Simple Notification requires the following parameters.

NOTIFICATION_MESSAGE - A message to include in the notification. This message will appear on the ModelOp dashboard. It will also appear as part of the short_description and in some cases description of the ServiceNow ticket unless those fields are overridden using SERVICENOW_CUSTOM_FIELDS.

NOTIFICATION_SEVERITY - The severity of the notification (INFO, WARN, ERROR, etc.). This will be reflected in the ModelOp dashboard notification.

SERVICENOW_API - The API to use for creating the ServiceNow ticket (table or import).

SERVICENOW_TABLE_NAME - The ServiceNow table to create the ticket in. If using the Table API this will be change_request. If using the Import Set API this will be the name of the import set.

Supplying these parameters correctly will result in a dashboard notification and a ServiceNow ticket being created. After ticket creation, however, the Model Life Cycle will continue on and not wait for any specific status of the ticket. In some cases this is desirable but often waiting for a specific status is the desired behavior. The SERVICENOW_EXIT_STATUS variable can be used to set the the status to wait for. For example, if set to “Closed,Canceled” then the Model Life Cycle will wait until the ticket’s state.display_value has reached either the closed or canceled status before continuing. The final status will be set in the TICKET_STATUS variable which the Model Life Cycle can use to determine different paths of execution. See ServiceNow Ticket Customization for more parameters for customizing ticket creation, updates, and lifecycle management.

In order to keep Model Life Cycles visually simple the three steps of this sub-process can be combined into a single activity as show below. For this example, all above parameters are moved to the external task (the final step, which could also be renamed) and the first two steps can be removed. An additional parameter of NOTIFICATION_TYPE must be set to PROCESS_NOTIFICATION to indicate the type of notification to create. The create and store steps will be executed as part of the external task. When specifying a NOTIFICATION_TYPE be sure to provide all needed parameters for that notification type.

Raising/Managing Incidents

Raising and managing an incident is nearly identical to Raising/Managing Change Requests. Ensure that SERVICENOW_TABLE_NAME is set to either incident (if using the Table API) or the name of the appropriate import set. That’s it! An incident will be created instead of a change request. Update any other parameters as needed to manage creation, updates, and lifecycle.

MLC Example Usages

The ServiceNow integration is present in two locations in the RunAssociatedModelMetricsServiceNow Model Life Cycle. Some examples are:

  • If performing an associated model run fails a ServiceNow ticket is created detailing the error

  • If tests fails a ServiceNow ticket is created detailing the failure

Each created notification appears on the Notification dashboard. Notifications also appear on context specific pages (E.g., Model Review Notifications will appear on the snapshot page). The display includes a link to the ticket and displays the ticket’s current status. The status is synced back periodically while waiting on the ticket’s exit status. An example is shown below.

Related Articles