Export all Update sets to XML - UI Action

restevao
Giga Expert

This code is still in an early access state, unclean but still works. Go ahead and update/improve.

Mainly designed for dev instances, not recommended for prod instances unless you can justify its need.

It works by using out of the box functionality for exporting an update set, just multiplies it for each update set.

 

WHAT

This exports all update sets in one go with the use of a UI Action

Currently it is possible to export all update sets, including ones that aren't in the 'completed' state. This can be adjusted in the code.

 

HOW

Client UI Action calls an ajax Script Include that does all the processing and returns values to be redirected in a URL

XML update sets are downloaded by multiple redirections to a page with the export update set URL.

 

 

FUTURE

It would be nice to have the Update Set download and save as the name of the update set and not the default id it is given. Currently the name is stored in the file — Some code for this is commented out, but still needs work - this may not be possible.

 

Also to have it only export updates sets that are selected in the update set list — code for this exists is commented out below but still needs some work.

 

SET UP

Names are note compulsory- feel free to adjust as you like, changes will have to be made in the code.

Create a UI Action and Script Include with the following

 

 

UI ACTION

Name: Export All Update Sets to XML

Table: Update Set [sys_update_set]

Order: 200

Active: TRUE

Show update: TRUE

Client: TRUE

List link: True

Onclick: AJAXCallUpdateXMLs()

Script:

 

functionAJAXCallUpdateXMLs()

{

                //maybe export selected list items in list view only

                /* var entries = g_list.getChecked().split(",");

                      if (!entries || entries.length == 0)

                      return;

                      alert(entries);

                                      */

/*       for (var i = 0 ; i < entries.length ; i++)

      {

      window.open("https://dev12053.service-now.com/export_update_set.do?sysparm_sys_id=" + entries[i] + "&sysparm_delete_when_done=false");    

      }*/

                            //ga.addParam('sysparm_entry_ids', entries.join(','));

                            // new GlideAjax object referencing name of AJAX script include

                      var ga = new GlideAjax("exportListUpdateSetXML");

                      // add name parameter to define which function we want to call

                      // method name in script include will be getFavorites

                      ga.addParam("sysparm_name", "getXMLs");

                     

                      // submit request to server, call ajaxResponse function with server response

     

                      ga.getXML(ajaxResponse);

                       

                      function ajaxResponse(serverResponse) {

                              // get result element and attributes

                       

                              var result = serverResponse.responseXML.getElementsByTagName("result");

                              var message = result[0].getAttribute("message");          

                              //check for message attribute and alert user

                              if(message)

                                      alert(message);

                       

                              //build output to display on client for testing

                              var output = "";

                       

                              // get favorite elements

                              var favorites = serverResponse.responseXML.getElementsByTagName("sysID");

                              for(var i = 0; i < favorites.length; i++)

                              {

                                      var name = favorites[i].getAttribute("name");

                                      var value = favorites[i].getAttribute("value");

                                      output += name + " = " + value + "\n";                     

                                      window.open("https://dev12053.service-now.com/export_update_set.do?sysparm_sys_id=" + value + "&sysparam_name=" + name +"&sysparm_delete_when_done=true");                                                               

                              }

                            alert(output);

                            return true;

              }

}

 

//downloadURI("https://dev12053.service-now.com/export_update_set.do?sysparm_sys_id=" + value + "&sysparam_name=" + name +"&sysparm_delete_when_done=true", name + ".xml");

                                      //pausecomp(1000);

/*

function downloadURI(uri, name) {

  var link = document.createElement("a");

  link.download = name;

  link.href = uri;

  document.body.appendChild(link);

  link.click();

  // Cleanup the DOM

  document.body.removeChild(link);

  delete link;

}*/

function pausecomp(ms) {

 

ms += new Date().getTime();

while (new Date() < ms){}

}

 

 

 

SCRIPT INCLUDE:

 

Name: exportListUpdateSetXML

API Name: global.exportListUpdateSetXML

Client callable: TRUE

Accessible from: All application Scopes

Active: TRUE

Script:

 

varexportListUpdateSetXML = Class.create();

  1. exportListUpdateSetXML.prototype = Object.extendsObject(AbstractAjaxProcessor, {

 

      getXMLs : function() {   

                              var result = this.newItem("result");

                              result.setAttribute("message", "returning");

             

                              //var index = 0;

                              var updateSet = new GlideRecord('sys_update_set');

                              //updateSet.addQuery('state','complete');                       // adjust here to select completed updates only

                              updateSet.query();

                              //gs.log("count us = " + updateSet.getRowCount());

                              while(updateSet.next())

                              {

                                              var retrievedUpdateSet = new GlideRecord('sys_remote_update_set');

                                              retrievedUpdateSet.initialize();

                                             

                                              retrievedUpdateSet.description = updateSet.description;

                                              retrievedUpdateSet.name = updateSet.name;

                                              retrievedUpdateSet.release_date = updateSet.release_date;

                                              retrievedUpdateSet.remote_sys_id = updateSet.sys_id;

                                              retrievedUpdateSet.application = updateSet.application;

                                                                                    

                                              var scopeGr = new GlideRecord('sys_scope');

 

                                              scopeGr.get(updateSet.application);

                                              if (scopeGr.isValid()) {

                                                      retrievedUpdateSet.application_name = scopeGr.name;

                                                      retrievedUpdateSet.application_scope = scopeGr.scope;

                                                      retrievedUpdateSet.application_version = scopeGr.version;

                                              }                                     

                                              retrievedUpdateSet.state = "loaded";                                   

                                              var sysid = retrievedUpdateSet.insert();                              

                                              var update = new GlideRecord('sys_update_xml');

                                              update.addQuery('update_set', updateSet.sys_id);

                                              update.query();

                                             

                                              while(update.next()) {

                                                    update.remote_update_set = retrievedUpdateSet.sys_id;

                                                    update.update_set = '';

                                                    update.insert();

                                              }

                                              //gs.log("Export # = " + index++);                                      

                                              this._addValue(updateSet.name, sysid);

                                              //gs.log("https://dev12053.service-now.com/export_update_set.do?sysparm_sys_id=" + sysid + "&sysparm_delete_when_done=true");

                                              //action.setRedirectURL("export_update_set.do?sysparm_sys_id=" + sysid + "&sysparm_delete_when_done=true");

                                              //redirect("export_update_set.do?sysparm_sys_id=" + sysid + "&sysparm_delete_when_done=true");      

                              }        

              // all items are returned to the client through the inherited methods of AbstractAjaxProcessor

      },

      _addValue : function(name, value) {

              var sysID = this.newItem("sysID");

              sysID.setAttribute("name", name);

              sysID.setAttribute("value", value);

             

      },

 

type: 'exportListUpdateSetXML'

});

 

you should end up with a button like this

 

Untitled.png

 

 

Please feel free to add any improvements and re-post

19 REPLIES 19

christianmehrin
Tera Contributor

A way to set filename is to update script include ExportWithRelatedLists.



        getFileName: function(){


                  var grName = '';



                  if (this.parent_table == 'sys_remote_update_set') {


                            var gr = new GlideRecord(this.parent_table);


                            gr.get(this.sys_id);



                            if (gr.name && !gr.name.isNil()) {


                                      grName = '_' + gr.name;


                            }


                  }



                  return (this.parent_table + grName + '_' + this.sys_id + '.xml');


      },



Take care you will not receive updates of ExportWithRelatedLists without checking "Replace on upgrade" on latest relevant customer update (or deleting customer updates).


Good Stuff,


But also by changing that script include you are also changing the out-of-box functionality. Maybe there is a way to do it that is external to the original script files


Yes, that would be possible as well.



Override ExportWithRelatedLists



SCRIPT INCLUDE:



Name: ExportWithRelatedListsMine


Client callable: FALSE


Accessible from: All application Scopes


Active: TRUE


Script:



function ExportWithRelatedListsMine(table, sysid) {


  var fileName = null;


  ExportWithRelatedLists.call(this, table, sysid);


}




ExportWithRelatedListsMine.prototype = new ExportWithRelatedLists();


ExportWithRelatedListsMine.prototype.constructor = ExportWithRelatedListsMine;




ExportWithRelatedListsMine.prototype.getFileName = function() {


        if (this.fileName != null) {


            return this.fileName;


        }


        var grName = '';


        // if (this.parent_table == 'sys_remote_update_set') {


          var gr = new GlideRecord(this.parent_table);


          gr.get(this.sys_id);



          if (gr.name && !gr.name.isNil()) {


          grName = '_' + gr.name;


          }


        // }



        return (this.parent_table + grName + '_' + this.sys_id + '.xml');


};



ExportWithRelatedListsMine.prototype.setFileName = function(fileName) {


        this.fileName =   fileName


};




define



PROCESSOR:



Name: ExportAsRemoteUpdateSet


Type: Script


Active: TRUE


Path: export_as_remote_update_set



var sysidLocal = g_request.getParameter('sysparm_sys_id');


var fileName = g_request.getParameter('sysparam_file_name');




var grUpdateSet = new GlideRecord('sys_update_set');  


if (grUpdateSet.get(sysidLocal)) {


  var grRetrievedUpdateSet = new GlideRecord('sys_remote_update_set');  


  grRetrievedUpdateSet.initialize();  


  grRetrievedUpdateSet.description = grUpdateSet.description;  


  grRetrievedUpdateSet.name = grUpdateSet.name;  


  grRetrievedUpdateSet.release_date = grUpdateSet.release_date;  


  grRetrievedUpdateSet.remote_sys_id = grUpdateSet.sys_id;  


  grRetrievedUpdateSet.application = grUpdateSet.application;  



  var grScope = new GlideRecord('sys_scope');


  grScope.get(grUpdateSet.application);  


  if (grScope.isValid()) {  


  grRetrievedUpdateSet.application_name = grScope.name;  


  grRetrievedUpdateSet.application_scope = grScope.scope;  


  grRetrievedUpdateSet.application_version = grScope.version;  


  }



  grRetrievedUpdateSet.state = "loaded";  


      var sysidRetrieved;



  if (sysidRetrieved = grRetrievedUpdateSet.insert()) {


  var grUpdateXML = new GlideRecord('sys_update_xml');  


  grUpdateXML.addQuery('update_set', sysidLocal);  


  grUpdateXML.query();  


   


  while(grUpdateXML.next()) {  


      grUpdateXML.remote_update_set = sysidRetrieved;  


      grUpdateXML.update_set = '';  


      grUpdateXML.insert();  


  }



  var exporter = new ExportWithRelatedListsMine('sys_remote_update_set', sysidRetrieved);


  if (fileName) {


      exporter.setFileName(fileName);


  }


  exporter.addRelatedList('sys_update_xml', 'remote_update_set');


  exporter.exportRecords(g_response);



  grUpdateXML = new GlideRecord('sys_update_xml');


  grUpdateXML.addQuery('remote_update_set', sysidRetrieved);


  grUpdateXML.query();


  grUpdateXML.deleteMultiple();


  grRetrievedUpdateSet = new GlideRecord('sys_remote_update_set');  


  grRetrievedUpdateSet.get(sysidRetrieved);


  grRetrievedUpdateSet.deleteRecord();


  }


}



link to this URL from



UI ACTION



Name: Export As Remote Update Set


Table: Update Set [sys_update_set]


Domain: global


Active: TRUE


Show update: TRUE


Form link: TRUE



Script:



action.setRedirectURL("export_as_remote_update_set.do?sysparm_sys_id=" + current.sys_id + "&sysparam_file_name=" + current.name);




You could use this URL with your UI Action to trigger multiple downloads or combine them in one file by using ExportWithRelatedLists.addQuerySet().



Or have a look to ExportWithRelatedLists.exportRecords() to create a new method for your needs:



var exporter = new ExportWithRelatedLists('sys_remote_update_set', sysidRemoteUpdateSet);


exporter.setHeaders(g_response);


var outputStream = g_response.getOutputStream();


exporter.hd = exporter.beginExport(outputStream);


exporter.exportRecord(grRetrievedUpdateSet);




var grUpdateXML = new GlideRecord('sys_update_xml');  


grUpdateXML.addQuery('update_set', sysidLocal);  


grUpdateXML.query();  


   


while(grUpdateXML.next()) {  


      grUpdateXML.remote_update_set = sysidRetrieved;  


      grUpdateXML.update_set = '';  


      grUpdateXML.sys_id = null;


      exporter.exportRecord(grUpdateXML);


}



grRetrievedUpdateSet = new GlideRecord('sys_remote_update_set');  


grRetrievedUpdateSet.get(sysidRetrieved);


grRetrievedUpdateSet.deleteRecord();



exporter.endExport(outputStream);




FYI: When using GlideRecordXMLSerializer(used by ExportWithRelatedLists.exportRecord), it looks as you don't need to insert record before serializing. Sysid will be empty but will be created when loading update set on target instance. If you don't need to reference you may skip. E.g. sys_remote_update sets needs to be inserted, but not sys_update_xml.


good idea with the processor script. I've never used one of those before.