Join the #BuildWithBuildAgent Challenge! Get recognized, earn exclusive swag, and inspire the ServiceNow Community with what you can build using Build Agent.  Join the Challenge.

Datasources with MID Server incorrect after clone

Dirk Hillmer
Tera Contributor

After clone from PROD to TEST the Mid Server configuration is incorrect. This is due to the differnt Sys_Id on the different environments. 

Instead of changing all MID Servers to the have the same Sys_ID on all environments is there a fix script that could be used?

 

1 ACCEPTED SOLUTION

Markus Kraus
Kilo Sage

Hello, so basically you can either follow ServiceNow Best Practice as described in the following KB Article: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0719301

 

Or you add a relatively complex Cleanup Script (System Clone > Cleanup Scripts):

/* global GlideRecord, gs, GlideUpdateSet */
/* global global */
/* eslint no-undef: "error" */
(function () {
	var dataSources = {}; // { 'application1': ['sys_id1', 'sys_id2'] }
	var dataSourceGr = new GlideRecord('sys_data_source');
	dataSourceGr.addNotNullQuery('mid_server'); // only update data sources that already had an mid server
	dataSourceGr.setLimit(100);
	dataSourceGr.query();
	while (dataSourceGr.next()) {
		var midServerGr = dataSourceGr.mid_server.getRefRecord();
		if (midServerGr.isValidRecord()) {
			// there is already a valid mid-server - we do not touch this record
			continue;
		}
		
		var appSysID = dataSourceGr.getValue('sys_scope');
		(dataSources[appSysID] || (dataSources[appSysID] = [])).push(dataSourceGr.getUniqueValue());
	}
	
	if (Object.keys(dataSources).length > 0) {
		// at least one data source needs to be updated
		
		var sccmMidServer = 'MY_MID_SERVER_SYS_ID';
		for (var appSysID in dataSources) {
			var updateSetGr = new GlideRecord('sys_update_set');
			updateSetGr.newRecord();
			updateSetGr.application = appSysID;
			updateSetGr.name = 'Data Source Fix';
			var usSysID = updateSetGr.insert();
			if (usSysID) {
				// use the newly created update set as "current update set"
				new GlideUpdateSet().set(usSysID);

				// all changes to the Data Source should be encapsulated within a special update set
				var dataSourceGr = new GlideRecord('sys_data_source');
				dataSourceGr.addQuery('sys_id', 'IN', dataSources[appSysID]);
				dataSourceGr.query();
				// now update the data sources
				// note: we do not use .updateMultiple because this sometimes runs async,
				// and we want to close the update set after update sources have been set
				while (dataSourceGr.next()) {
					dataSourceGr.mid_server = sccmMidServer;
					dataSourceGr.update();
				}

				updateSetGr = new GlideRecord('sys_update_set');
				if (updateSetGr.get(usSysID)) {
					updateSetGr.state = 'ignore';
					updateSetGr.update();
				} else {
					gs.error('Failed to find update set with SysID=' + usSysID);
				}
			} else {
				gs.error('Failed to create update set');
			}
			
			gs.info('Updated the following Data Sources: ' + dataSources[appSysID]);			
		}
	}
})();

View solution in original post

2 REPLIES 2

Markus Kraus
Kilo Sage

Hello, so basically you can either follow ServiceNow Best Practice as described in the following KB Article: https://support.servicenow.com/kb?id=kb_article_view&sysparm_article=KB0719301

 

Or you add a relatively complex Cleanup Script (System Clone > Cleanup Scripts):

/* global GlideRecord, gs, GlideUpdateSet */
/* global global */
/* eslint no-undef: "error" */
(function () {
	var dataSources = {}; // { 'application1': ['sys_id1', 'sys_id2'] }
	var dataSourceGr = new GlideRecord('sys_data_source');
	dataSourceGr.addNotNullQuery('mid_server'); // only update data sources that already had an mid server
	dataSourceGr.setLimit(100);
	dataSourceGr.query();
	while (dataSourceGr.next()) {
		var midServerGr = dataSourceGr.mid_server.getRefRecord();
		if (midServerGr.isValidRecord()) {
			// there is already a valid mid-server - we do not touch this record
			continue;
		}
		
		var appSysID = dataSourceGr.getValue('sys_scope');
		(dataSources[appSysID] || (dataSources[appSysID] = [])).push(dataSourceGr.getUniqueValue());
	}
	
	if (Object.keys(dataSources).length > 0) {
		// at least one data source needs to be updated
		
		var sccmMidServer = 'MY_MID_SERVER_SYS_ID';
		for (var appSysID in dataSources) {
			var updateSetGr = new GlideRecord('sys_update_set');
			updateSetGr.newRecord();
			updateSetGr.application = appSysID;
			updateSetGr.name = 'Data Source Fix';
			var usSysID = updateSetGr.insert();
			if (usSysID) {
				// use the newly created update set as "current update set"
				new GlideUpdateSet().set(usSysID);

				// all changes to the Data Source should be encapsulated within a special update set
				var dataSourceGr = new GlideRecord('sys_data_source');
				dataSourceGr.addQuery('sys_id', 'IN', dataSources[appSysID]);
				dataSourceGr.query();
				// now update the data sources
				// note: we do not use .updateMultiple because this sometimes runs async,
				// and we want to close the update set after update sources have been set
				while (dataSourceGr.next()) {
					dataSourceGr.mid_server = sccmMidServer;
					dataSourceGr.update();
				}

				updateSetGr = new GlideRecord('sys_update_set');
				if (updateSetGr.get(usSysID)) {
					updateSetGr.state = 'ignore';
					updateSetGr.update();
				} else {
					gs.error('Failed to find update set with SysID=' + usSysID);
				}
			} else {
				gs.error('Failed to create update set');
			}
			
			gs.info('Updated the following Data Sources: ' + dataSources[appSysID]);			
		}
	}
})();

Wow works like a charme!

Thanks