This example shows how REST API requests can be used within a ServiceNow Workflow to populate the ServiceNow Service Catalog with catalog items published in the Buttonwood Broker.
The following related articles provide further details in configuring associated processes:
- Automate REST API Reference
- ServiceNow - Example - How to Create REST API Requests
- ServiceNow - Example - Deploy Automate Catalog Items from ServiceNow
Note: This is an example only. Please consult with your organisation's ServiceNow administrators to correctly gather and store the required variables and keys to ensure the process confirms to the organisation's business processes and policies.
Prerequisites
- This example has been tested against the following versions of ServiceNow:
- Jakarta through to Quebec
- This example has been tested against the following instance types of ServiceNow:
- Hosted
- Hosted developer clone
- Developer (this is a free service which can be requested via http://developer.servicenow.com)
- Access to the ServiceNow Workflow Editor module is required (may require additional licensing)
- The following REST API messages have been created as per article ServiceNow - Example - How to Create REST API Requests
Name Method Endpoint POST Content Get Cost Centres GET https://<automate_fqdn_or_ip>/api/v1/costCentre N/A Get Catalog Items GET https://<automate_fqdn_or_ip>/api/v1/catalogItem N/A Get Blueprint Information GET https://<automate_fqdn_or_ip>/api/v1/catalogItem/${catalogItemID} N/A
Information Required
The following information will be required for this example.
- API Token for the user to allow ServiceNow to communicate with the Broker API service
- sys_id value of the ServiceNow Service Catalog which the items will be populated within
- sys_id value of the ServiceNow Service Catalog Category which the items will be populated within
- workflow value of the ServiceNow Workflow to initiate when this catalog item is ordered - please refer to the article ServiceNow - Example - Deploy Broker Catalog Items from ServiceNow for further information on this workflow
Creating the Workflow
- Log in to ServiceNow as an administrative user
- Navigate to Workflow > Workflow Editor
A new tab will open to the Workflow Editor - Click the New Workflow button
- Enter the following details for the workflow
- Name: Name of the workflow
- Table: The ServiceNow table context for this workflow - Global [global]
- Description: Description of this workflow
- Click Submit
- A basic workflow canvas is populated with Begin and End activities
- Using the activity selector, navigate to Core Activities > Utilities
Locate the Run Script activity - Drag and drop the Run Script activity onto the workflow canvas
The activity editor will automatically open - Paste the following script into the script editor
// Start logging workflow.info("Script Get Broker Blueprints and Create Catalog Items starting..."); // Configure variables var userName = gs.getUserName(); var userDisplayName = gs.getUserDisplayName(); var apiToken = 'OWY1ZTE1NWUtNWM2MC00YWFiLTg2YTEtZGNiYmZmOGE5OGM1'; // Broker Account Authorisation Token var scSysId = 'e0d08b13c3330100c8b837659bba8fb4'; // sys_id of Service Catalog var catSysId = '109f0438c6112276003ae8ac13e7009d'; // sys_id of ServiceNow Service Catalog Category var wfSysId = '920c60de4f903300e4b8eb118110c7b3'; // sys_id of ServiceNow Workflow to initiate when ordering this item var sNowRestMessage = 'Buttonwood Cloud Broker'; // Name of the REST Message created in the Service Now instance which communicates with a Buttonwood Broker var sNowRestMethodGetCostCentres = 'Get Cost Centres'; // Name of the HTTP Method for GET /costCentre API call var sNowRestMethodGetCatalogItems = 'Get Catalog Items'; // Name of the HTTP Method for the GET /catalogItem API call var SNowRestMethodGetBlueprintInfo = 'Get Blueprint Information'; // Name of the HTTP Method of the GET /catalogItem API call workflow.info("User Name: " + userName); workflow.info("Display Name: " + userDisplayName); workflow.info("API Token: " + apiToken); // Get list of cost centres from Buttonwood Broker workflow.info("Getting list of Cost Centres from Broker"); try { var r1 = new sn_ws.RESTMessageV2(sNowRestMessage, sNowRestMethodGetCostCentres); r1.setStringParameterNoEscape('BearerApiToken', apiToken); var response1 = r1.execute(); var responseBody1 = response1.getBody(); var httpStatus1 = response1.getStatusCode(); } catch(ex) { var message = ex.getMessage(); } workflow.info("REST API HTTP Status: " + httpStatus1); workflow.info("REST API Response: " + responseBody1); // Process JSON Response var parser1 = new JSONParser(); var parsed1 = parser1.parse(responseBody1); // Write the data into a scratchpad variable for the next script to use. var availableCostCentres = parsed1.costCentres; // Get list of available blueprints from Buttonwood Broker workflow.info("Getting list of Blueprints from Broker"); try { var r2 = new sn_ws.RESTMessageV2(sNowRestMessage, sNowRestMethodGetCatalogItems); r2.setStringParameterNoEscape('BearerApiToken', apiToken); var response2 = r2.execute(); var responseBody2 = response2.getBody(); var httpStatus2 = response2.getStatusCode(); } catch(ex) { var message = ex.getMessage(); } workflow.info("REST API HTTP Status: " + httpStatus2); workflow.info("REST API Response: " + responseBody2); // Process JSON Response parser2 = new JSONParser(); parsed2 = parser2.parse(responseBody2); // Write the data into a scratchpad variable for the next script to use. var availableBlueprints = parsed2.catalogItems; // Process the blueprints and create catalog items workflow.info("Creating catalog items in Service Now"); for(var count1 in availableBlueprints) { workflow.info("Blueprint Name: " + availableBlueprints[count1].blueprintName + ", ID: " + availableBlueprints[count1].id + ", Daily Cost: " + availableBlueprints[count1].averageDailyCostBudgetCurrency + ", Currency: " + availableBlueprints[count1].budgetCurrencyCode + ", Provider: " + availableBlueprints[count1].providerCode + ", Region: " + availableBlueprints[count1].regionCode); // Check ServiceNow Catalog if item already exists var sc = new GlideRecord('sc_cat_item'); sc.addActiveQuery(); sc.addQuery('name', availableBlueprints[count1].blueprintName); sc.addQuery('sc_catalogs', scSysId); sc.setLimit(100); sc.query(); // If there are 0 items, create one if (sc.getRowCount() == 0){ workflow.info('Creating item ' + availableBlueprints[count1].blueprintName); // Getting detailed information from Broker try { var r3 = new sn_ws.RESTMessageV2(sNowRestMessage, sNowRestMethodGetBluePrintInfo); r3.setStringParameterNoEscape('catalogItemID', availableBlueprints[count1].id); r3.setStringParameterNoEscape('BearerApiToken', apiToken); var response3 = r3.execute(); var responseBody3 = response3.getBody(); var httpStatus3 = response3.getStatusCode(); } catch(ex) { var message = ex.getMessage(); } workflow.info("REST API HTTP Status: " + httpStatus3); workflow.info("REST API Response: " + responseBody3); // Process JSON Response parser3 = new JSONParser(); parsed3 = parser3.parse(responseBody3); // Write the data into a variable. var blueprintInfo = parsed3.catalogItem; // Create Catalogue Item var cat_item = new GlideRecord('sc_cat_item'); cat_item.newRecord(); // Creates a new item on the table, assigns a sys_id, and populates the default values cat_item.name = (availableBlueprints[count1].blueprintName); cat_item.sc_catalogs = (scSysId); cat_item.active = ('true'); cat_item.no_quantity = ('true'); cat_item.no_cart = ('true'); cat_item.omit_price = ('true'); cat_item.setValue('workflow', wfSysId); // _DeployBlueprint workflow cat_item.category = (catSysId); cat_item.description = ('Deploy blueprint <strong>>' + availableBlueprints[count1].blueprintName + '</strong>> from the Buttonwood Broker<br> \ Buttonwood Catalog Item ID: ' + availableBlueprints[count1].id + '<br> \ Environment: ' + blueprintInfo.environment); cat_item.insert(); // Create Catalogue Variable Items // Create standard Buttonwood Broker variables createCatVariable('catalogItemId',cat_item.getValue('sys_id'),'Catalog Item ID',(availableBlueprints[count1].id).toString(),6,'true','','','true','100',''); createCatVariable('leaseEndDate',cat_item.getValue('sys_id'),'Lease End Date','',6,'true','YYYY-MM-DD','Enter the terminating date for your deployment in YYYY-MM-DD format','true','200',''); createCatVariable('deploymentName',cat_item.getValue('sys_id'),'Deployment Name','',6,'true',userDisplayName + 's ' + availableBlueprints[count1].blueprintName + ' deployment','Enter a name for your deployment','true','300',''); createCatVariable('deploymentDescription',cat_item.getValue('sys_id'),'Deployment Description','',2,'false','Description (Optional)','Enter a description for your deployment if you want to','true','400',''); createCatVariable('costCentreName',cat_item.getValue('sys_id'),'Cost Centre Name',availableCostCentres[0].name,5,'true','','Enter the Buttonwood Cloud Broker cost centre for your deploymnet','true','500',availableCostCentres); // Create additional blueprint specific variables if (blueprintInfo.deployTimeParameters) { for(var count2 in blueprintInfo.deployTimeParameters) { // Check what the parameter type is and convert it to ServiceNow's numbering system. var parameterType = 6; var additionalQuestionItems = ''; switch(blueprintInfo.deployTimeParameters[count2].type) { case 'Boolean': parameterType = 1; break; case 'Password': parameterType = 25; break; case 'Select': parameterType = 5; break; case 'String': parameterType = 6; break; default: parameterType = 6; } // If there are options it must be a select field if (blueprintInfo.deployTimeParameters[count2].options) { parameterType = 5; additionalQuestionItems = blueprintInfo.deployTimeParameters[count2].options; } createCatVariable(blueprintInfo.deployTimeParameters[count2].name,cat_item.getValue('sys_id'),blueprintInfo.deployTimeParameters[count2].helpText,blueprintInfo.deployTimeParameters[count2].defaultValue,parameterType,blueprintInfo.deployTimeParameters[count2].mandatory,'','','true',600,additionalQuestionItems); } } } // If there is 1 or more items, edit them if (sc.getRowCount() >= 1){ workflow.info('Editing item ' + availableBlueprints[count1].blueprintName); // Update the description of the next catalog item if (sc.next()){ sc.setValue('description','<p>Deploy blueprint <strong><em>' + availableBlueprints[count1].blueprintName + '</em></strong> from the Buttonwood Broker</p> \ <p>Buttonwood Catalog Item ID: ' + availableBlueprints[count1].id + '</p>'); sc.setValue('workflow', wfSysId); cat_item.setValue('price','AUD;' + availableBlueprints[count1].averageDailyCostBudgetCurrency); sc.update(); } } } // End logging workflow.info("Script Get Broker Blueprints and Create Catalog Items ending..."); // Functions function createCatVariable(name,cat_item,question_text,default_value,type,mandatory,exampleText,tooltipText,visible,order,questionItems) { var var_item = new GlideRecord('item_option_new'); var_item.newRecord(); // Creates a new item on the table, assigns a sys_id, and populates the default values var_item.name = (name.replace(/\s/g, '')); var_item.active = ('true'); var_item.setValue('cat_item',cat_item); var_item.setValue('question_text',question_text); var_item.setValue('sys_name',name.replace(/\s/g, '')); var_item.setValue('default_value',default_value); var_item.setValue('type',type); // 1 = Yes/No, 2 = Multi line text, 3 = Multiple choice, 5 = Select Box, 6 = Single line text, 25 = Masked var_item.setValue('mandatory',mandatory); var_item.setValue('example_text',exampleText); var_item.setValue('tooltip',tooltipText); var_item.setValue('visible_bundle',visible); var_item.setValue('visible_guide',visible); var_item.setValue('visible_standalone',visible); var_item.setValue('visible_summary',visible); var_item.setValue('order',order); var_item.insert(); // Create question choices if applicable if ((type == 3) || (type == 5)) { for(var count3 in questionItems) { var question_item = new GlideRecord('question_choice'); question_item.newRecord(); // Creates a new item on the table, assigns a sys_id, and populates the default values question_item.name = (questionItems[count3].name); question_item.active = ('true'); question_item.setValue('text',questionItems[count3].name); question_item.setValue('value',questionItems[count3].name); question_item.setValue('question',var_item.getValue('sys_id')); question_item.setValue('order',(count3 + 1) * 100); question_item.insert(); } } var_item.update(); }
- Ensure that the following variables are edited to reflect the environment
- apiToken: API Token for the user to allow ServiceNow to communicate with the Broker API service
- scSysId: sys_id of the ServiceNow Service Catalog which the items will be populated within
- catSysId: sys_id of the ServiceNow Service Catalog Category which the items will be populated within
- wfSysId: sys_id of the ServiceNow Workflow to initiate when this catalog item is ordered
- Utilise the activity connectors to insert the Run Script activity into the workflow between Begin and End activities
- The workflow can now be published
Running the Workflow
- Log in to ServiceNow as an administrative user
- Navigate to Workflow > Workflow Editor
A new tab will open to the Workflow Editor - Select the workflow to run
This example uses the example workflow BW - Populate Service Catalog - From the actions toolbar, click the Start button
- From the Start Workflow window, click Start
- The execution result is displayed
Any failures will be highlighted in red
Checking Workflow Logs
- Log in to ServiceNow as an administrative user
- Navigate to Workflow > All Contexts
- The workflow task should appear towards the top of the list when sorted by Started
- Click on the Started time for the relevant record
Note: Clicking on other values instead of the time will open the generic record for those values rather than the context record for the time that the task ran - The Workflow Log tab displays a log of the request as well as any logged outputs from the associated workflow script