SiD2
ServiceNow Employee
ServiceNow Employee

Hi Folks,

This article is to identify API calls a particular pattern makes during discovery. Though this is available in SNOW docs, but is not very specific or in detail.

This would be another additional way to check quickly running a script on the instance and you can see what all APIs used in a particular pattern.

Target Audience
Anyone using Discovery product using Patterns on their SNOW instance.

Overview
This script covers the APIs that are part of any Custom Operation involving a URL in pattern and doesn't have capability to fetch APIs run from EVAL Scripts or any other code blocks.


You can get the list of APIs for one particular pattern by giving the pattern sys id in the variable "args" in below script. You can get the sys id of the pattern quickly by right clicking on the pattern record and click "Copy sys_id".

Script Output also prints the Scope of the respective pattern which tells you whether it is part of family release or Store Release.

If Scope is Global it is a family release and if it is "Discovery and Service Mapping Patterns" it is indeed the Patterns store app name. If you have patterns from other store apps respective name gets displayed.

To run this script in your instance open "System Definition->Scripts-Background" in filter navigator and copy this script and click Run script.

Note: If the main pattern sys id is provided, it fetches the shared libraries and extension sections that are part of the pattern and lists APIs from all of them.


Ex: Below is the sample output for a pattern.

*** Script: *********************************************************************************************************
*** Script: -----------------------------------------------------------------------------------------------------
*** Script: Pattern: Azure - Storage Blobs(LP)   Scope: Discovery and Service Mapping Patterns
*** Script: -----------------------------------------------------------------------------------------------------
*** Script: Step: "Get the Storage Account details if no location"
			if {
				condition = is_empty {get_attr {"cmdb_ci_cloud_storage_account[1].location"}}
				on_true =URL:  = concat {
								"https://management."
								get_attr {"resource_url"}
								get_attr {"cmdb_ci_cloud_storage_account[1].object_id"}
								"?api-version=2019-06-01"
							}
						}
						Body:  = ""
						}
						
*** Script: Step: "Get Storage Account Keys"
		URL:  = concat {
							"https://management."
							get_attr {"resource_url"}
							get_attr {"cmdb_ci_cloud_storage_account[1].object_id"}
							"/listKeys?api-version=2019-04-01"
						}
					}
					Body:  = ""
					}
					
*** Script: Step: "Get Blobs - Add Response to Context"
		URL:  = concat {
							"https://"
							get_attr {"cmdb_ci_cloud_storage_account[1].name"}
							".blob.core."
							get_attr {"storage_api_suffix"}
							".net/"
							get_attr {"cmdb_ci_storage_container[1].name"}
							"?restype=container&comp=list"
						}
					}
					Body:  = ""
					}
					
*** Script: -----------------------------------------------------------------------------------------------------

*** Script: *********************************************************************************************************

 

Script:

gs.log('*********************************************************************************************************');
var args = '';
PatternParser(args, false);
ParsePatternExtensions(args);
gs.log('*********************************************************************************************************');


function ParsePatternExtensions(parPattern) {
    var gPatternExtRec = new GlideRecord('sa_pattern_extension');
    gPatternExtRec.addQuery('pattern', parPattern);
    gPatternExtRec.query();

    var totalExts = gPatternExtRec.getRowCount();
    if (totalExts != 0) {
        gs.log('Available Pattern Extensions are ' + totalExts);
        while (gPatternExtRec.next()) {
            var extSysID = gPatternExtRec.getValue('extension');
            PatternParser(extSysID, true);
        }
    }
}


function PatternParser(patternSysId, isLib) {
    var gPatternRec = new GlideRecord('sa_pattern');
    gPatternRec.addQuery('sys_id', patternSysId);
    if (isLib)
        gPatternRec.addQuery('ndl', 'CONTAINS', 'custom_operation').addOrCondition('ndl', 'CONTAINS', 'refid');
    gPatternRec.query();

    if (gPatternRec.getRowCount() != 0) {
        if (gPatternRec.next()) {
            gs.log('-----------------------------------------------------------------------------------------------------');
            var pattern_name = gPatternRec.getValue('name');
            var pattern_text = gPatternRec.getValue('ndl');
            var pattern_type = gPatternRec.getValue('cpattern_type');
            var sysscope_Ref = gPatternRec.sys_scope.getRefRecord();
            var sys_scope = sysscope_Ref.getValue('name');

            if (pattern_type != '2')
                gs.log('Pattern: ' + pattern_name + '   Scope: ' + sys_scope);
            else
                gs.log('Pattern[Shared Library]: ' + pattern_name + '   Scope: ' + sys_scope);
            gs.log('-----------------------------------------------------------------------------------------------------');

            var pattern_steps = pattern_text.split('step'); // Fetches all steps of pattern
            for (var index in pattern_steps) {
                if (pattern_steps[index].contains('custom_operation') && !pattern_steps[index].contains('source_column')) { // Steps that run custom operation is only of our interest and exclude Parse JSON Op
                    var attribs = pattern_steps[index].split('attribute');
                    var url = '';
                    var body = '';
                    for (var i in attribs) {
                        if (attribs[i].contains('url')) {
                            var idx1 = pattern_steps[index].indexOf('name = "') + 7;
                            var idx2 = pattern_steps[index].lastIndexOf('custom_operation') - 1;
                            var stepName = pattern_steps[index].substring(idx1, idx2);

                            url = attribs[i].split('value');
                        }

                        if (attribs[i].contains('body'))
                            body = attribs[i].split('value');

                        if (body) {
                            gs.log('Step: ' + stepName + 'URL: ' + url[1] + 'Body: ' + body[1]);
                            break;
                        }
                    }
                }
            }
            if (pattern_steps[index].contains('refid = ')) {
                var code_lines = pattern_steps[index].split('\n');
                for (var idx in code_lines) { // Making a recursive call to parse the shared library that came across in sequence.
                    if (code_lines[idx].contains('refid')) {
                        var index1 = code_lines[idx].indexOf('"') + 1;
                        var index2 = code_lines[idx].lastIndexOf('"');
                        libSysID = code_lines[idx].substring(index1, index2);
                        PatternParser(libSysID, true);
                    }
                }
            }
        }
        gs.log('-----------------------------------------------------------------------------------------------------\n');
    }
}
Comments
SiD2
ServiceNow Employee
ServiceNow Employee

You can check this advanced blog to list more no of operations that are run in a pattern.

Version history
Last update:
‎04-20-2022 05:31 AM
Updated by: