Example node definition diff script for Chef: ConfigAutomationDiffBase

ChefNodeDefinitionDiff.prototype = Object. extendsObject (ConfigAutomationDiffBase , {
    initialize : function ( ) { } ,
 
	process : function (draftNodeDefId ) { var gr  = new GlideRecord ( 'chef_node_definition' ) ;
		gr. get (draftNodeDefId ) ; var nodeDefId  = '' + gr. peer. sys_id ; return this. getDiff (nodeDefId , draftNodeDefId ) ; } ,
 
	getDiff : function (nodeDefId , draftNodeDefId ) { var orgNodeData  = this._getNodeData (nodeDefId , 'chef_node_definition' ) ; var draftNodeData  = this._getNodeData (draftNodeDefId , 'chef_node_definition' ) ;
 
		 //Get the differences between node definition and draft node definition for the specific sys id. var diff  = this._getNodeComponentDiff (orgNodeData. nodeComponents , draftNodeData. nodeComponents ) ;
 
		 // Get the differences in attributes. 
		diff  += this._getAttributeDiffs (orgNodeData. nodeAttributes , draftNodeData. nodeAttributes ) ;
 
		 //Create messages var Name = gs. getMessage ( 'Name' ) ; var ChefManagementServer  = gs. getMessage ( 'Chef Management Server' ) ; var Environment  = gs. getMessage ( 'Environment' ) ; var ChangeChefNodeDefinition  = gs. getMessage ( 'Change Chef node definition' ) ; var ThisIs  = gs. getMessage ( 'This is a change generated by modifying Chef node definition.' ) ;
 
		 var nodeDiff  = { } ; var nodeDef  = orgNodeData. nodeObj ; var draftNodeDef  = draftNodeData. nodeObj ;
 
		nodeDiff. shortDescription = ChangeChefNodeDefinition ;
		nodeDiff. description = ThisIs  + "\n " ;
		nodeDiff. description += this._getDiff ( Name , nodeDef. name , draftNodeDef. name ) ;
		nodeDiff. description += this._getDiff (ChefManagementServer , nodeDef. chefManagementServer. name , draftNodeDef. chefManagementServer. name ) ;
		nodeDiff. description += this._getDiff (Environment , nodeDef. environment_name , draftNodeDef. environment_name ) + diff ;
 
		 return nodeDiff ; } ,
 
	_getNodeData : function (nodeDefId , tableName ) { var nodeData  = { } ; if ( !gs. nil (nodeDefId ) ) { var nodeObj  = this._getNodeInfo (nodeDefId , tableName ) ; if ( !gs. nil (nodeObj ) ) {
				nodeData. nodeObj = nodeObj ; }
 
			 // Get associated node definition classes and parameters
			nodeData. nodeComponents = this._getNodeComponents (nodeDefId ) ;
			nodeData. nodeAttributes = this._getNodeAttributes (nodeDefId ) ; }
 
		 return nodeData ; } ,
 
	 /**
	 */
	_getNodeInfo : function (sysId , tableName ) { var gr  = new GlideRecord (tableName ) ;
 
		 if (gr. get (sysId ) ) { var nodeObj  = { } ; // Common fields for Node definition
			nodeObj. sysId = sysId ;
			nodeObj. name = '' + gr. name ;
			nodeObj. chefManagementServer = { } ;
			nodeObj. chefManagementServer. sys_id = '' + gr. management_server ;
			nodeObj. chefManagementServer. name = '' + gr. management_server. name ;
 
			 // Unique fields... if (tableName. startsWith ( 'chef_node_definition' ) ) {
				nodeObj. inherits = '' + gr. inherits ;
				nodeObj. inheritsName = '' + gr. inherits. name ;
				nodeObj. environment_name = '' + gr. environment. name ; } return nodeObj ; } return null ; } ,
 
	 /*
	 * Retrieves the node class for the indicated node definition
	 */
	_getNodeComponents  : function (sysId ) { var gr  = new GlideRecord ( 'chef_map_node_to_object' ) ;
		gr. addQuery ( 'node_definition' , sysId ) ;
		gr. orderBy ( 'chef_object' ) ;
		gr. query ( ) ;
 
		 var nodeComponents  = [ ] ;
 
		 while (gr. next ( ) ) { var nodeComponentObj  = { } ;
			nodeComponentObj. sysId = '' + gr. sys_id ;
			nodeComponentObj. chefComponent = '' + gr. chef_object ;
			nodeComponentObj. chefComponentName = '' + gr. chef_object. name ;
			nodeComponentObj. nodeDefinition = '' + gr. node_definition ;
			nodeComponentObj. nodeDefinitionName = '' + gr. node_definition. name ;
			nodeComponentObj. type = '' + gr. type ;
			nodeComponentObj. chefObjectType = '' + gr. chef_object. sys_class_name. getDisplayValue ( ) ;
			nodeComponents. push (nodeComponentObj ) ; }
 
		 return nodeComponents ; } ,
 
	 /*
	 * Returns  difference if any for the passed field. 
	 */
	_getDiff : function (field , orig , draft ) { if (orig  != draft ) { return this._formatDiff (gs. getMessage ( "Modified {0} from {1} to {2}" , [field , orig , draft ] ) ) ; } return '' ; } ,
 
	 /*
	 * Retrieves the parameters for the indicated node definition
	 */
	_getNodeAttributes  : function (sysId ) { var nodeAttrs  = [ ] ; var gr  = new GlideRecord ( 'chef_node_def_attribute' ) ;
		gr. addQuery ( 'node_definition' , sysId ) ;
		gr. orderBy ( 'name' ) ;
		gr. query ( ) ; while (gr. next ( ) ) { var nodeAttrObj  = { } ;
			nodeAttrObj. name = (gs. nil (gr. chef_attribute. path ) ? '' : gr. chef_attribute. path + '.' ) + gr. chef_attribute. name ;
			nodeAttrObj. value = '' + gr. value ;
			nodeAttrObj. node_definition = '' + sysId ;
			nodeAttrs. push (nodeAttrObj ) ; } return nodeAttrs ; } ,
 
	 /**
	 * Returns the changes of node components beween node definitin and draft node definition.
	 * @param nodeComponents, draftNodeComponents
	 * @returns {String}
	 */
	_getNodeComponentDiff : function (nodeComponents , draftNodeComponents ) { var diff  = '' ; // Traverse thru the draft node components and find the differences. for ( var i  = 0 ; i  < draftNodeComponents. length ; i ++ ) { var draftNodeComponent  = draftNodeComponents [i ] ; //getting the original node definition. var nodeComponent  = this._findNodeComponent (nodeComponents , draftNodeComponent. chefComponent ) ;
			diff  += this._getComponentDiff (draftNodeComponent , nodeComponent ) ; }
 
		 // Traverse thru the node components and find the differences. for ( var i  = 0 ; i  < nodeComponents. length ; i ++ ) { var nodeComponent  = nodeComponents [i ] ; //getting the original node definition. var draftNodeComponent  = this._findNodeComponent (draftNodeComponents , nodeComponent. chefComponent ) ;
 
			diff  += this._getComponentDiff (draftNodeComponent , nodeComponent ) ; } return diff ; } ,
 
	 /**
	 * Find a specific class from the indicated collection of classes
	 */
	_findNodeComponent : function (nodeComponents , component ) { if ( !gs. nil (nodeComponents ) && !gs. nil (component ) ) { for ( var i = 0 ; i  < nodeComponents. length ; i ++ ) { var nodeComponent  = nodeComponents [i ] ; if (nodeComponent. chefComponent == component ) { return nodeComponent ; } } } return null ; } ,
 
	 /*
	 * Helper function for generating the chef node component differences.
	 */
	_getComponentDiff : function (draft , orig ) { if (gs. nil (orig ) ) { return this._formatDiff (gs. getMessage ( "Added {0} : {1}" , [draft. chefObjectType , draft. chefComponentName ] ) ) ; } else if (gs. nil (draft ) ) { return this._formatDiff (gs. getMessage ( "Deleted {0} : {1}" , [orig. chefObjectType , orig. chefComponentName ] ) ) ; } return '' ; } ,
 
	 /**
	 * Format diff string.
	 */
	_formatDiff : function (s ) { return "\n      " +s ; } ,
 
	 /**
	 * Returns the changes of attributes between node definition and draft node definition. 
	 * @param nodeDefRoot
	 * @returns {String}
	 */
	_getAttributeDiffs : function (nodeAttributes , draftNodeAttributes ) { var diff = '' ;
 
		 // See if any parameters were added or modified for ( var i  = 0 ; i  < draftNodeAttributes. length ; i ++ ) { var draftNodeAttr  = draftNodeAttributes [i ] ; var nodeAttr  = this._getNodeAttrByName (nodeAttributes , draftNodeAttr. name ) ;
			diff  += this._getNodeAttrDiff (draftNodeAttr , nodeAttr ) ; }
 
		 // See if any parameters were added or modified for ( var i  = 0 ; i  < nodeAttributes. length ; i ++ ) { var nodeAttr  = nodeAttributes [i ] ; var drartNodeAttr  = this._getNodeAttrByName (draftNodeAttributes , nodeAttr. name ) ;
			diff  += this._getNodeAttrDiff (drartNodeAttr , nodeAttr ) ; } return diff ; } ,
 
	 /**
	 * Find a specific attrbiute found by the passed name
	 */
	_getNodeAttrByName : function (attrs , name ) { if ( !gs. nil (attrs ) && !gs. nil ( name ) ) { for ( var i = 0 ; i  < attrs. length ; i ++ ) { var attr  = attrs [i ] ; if (attr. name == name ) { return attr ; } } } return null ; } ,
 
	 /*
	 * Helper function for generating the puppet node parameter differences.
	 */
	_getNodeAttrDiff : function (draft , orig ) { if (gs. nil (orig ) ) { return this._formatDiff (gs. getMessage ( "Added attribute : {0} with value {1}" , [draft. name , this._getAttrDisplayValue (draft ) ] ) ) ; } else if (gs. nil (draft ) ) { return this._formatDiff (gs. getMessage ( "Deleted attribute : {0} with value {1}" , [orig. name , this._getAttrDisplayValue (orig ) ] ) ) ; } else if (draft. value != orig. value ) { return this._formatDiff (gs. getMessage ( "Modified attribute : {0} from value {1} to {2}" , [draft. name , this._getAttrDisplayValue (orig ) , this._getAttrDisplayValue (draft ) ] ) ) ; } return '' ; } ,
 
	_getAttrDisplayValue : function (attr ) { return attr. value ; } ,
 
    type : 'ChefNodeDefinitionDiff' } ) ;