Download attachments and page content from Confluence

For a project there is a need to move all the attachments in Confluence, including the page content, in a remote repository.

Confluence offers different API and the XML-RPC API can be still used. The API do not allow to download all the attachments in once but only page by page therefore the need for this python script which:

  1. Creates a folder for each page which includes
    1. the html export of the page
    2. all the attachments of the page
  2. Once all the pages are saved, it moves all the folders in the same hierarchical structure of the space

You can find the code my GitHub repository:

https://github.com/EmidioStani/confluence_attachments

Main inspiration came from: https://answers.atlassian.com/questions/114490/how-to-get-all-attachments-under-a-space-via-rest-api

Confluence Jmeter performance script

Recently for a project we needed to measure the performance of an instance of Confluence for a certain number of concurrent users.

Fortunately Atlassian releases a procedure to measure the performance using  Jmeter here. The latest script version we used is 4.2.2 which has been released on 27th of August with Confluence 4.3.1

The script needs some fixes:

  • it doesn’t save the session on the Remote API and then operations like Create Personal Space and Grant View on Personal Space fail to connect because of the rpc token
  • the labels used as tags in Confluence are not the same (we used demonstration and sales)
  • the Browsse User Status operation has an incomplete Response Assertion
  • When deleting  the space, operation that can take some time,  the script doesn’t wait in a loop so it can’t remove some users and also when deleting a space Confluence doesn’t go back to the Dashboard but instead stays on the page

Further I improved the script giving the possibility:

  • to create users from Crowd, using a new command line parameter -Jenable.sso=true, which is false by default
  • to use https in case Confluence is setup with https instead of http, using a new command like parameter -Jconfluence.protocol=https, which is http by default

Therefore, after you download the script (with the resources) , just remember to adapt the Crowd configuration (parameter -Jcrowd.host) and that the operation Create User from Crowd expect to have Crowd under the same ip address of Confluence (you can of course change it).

Selenium wiki formatter (textile e altri)

Di recente avevo necessità di copiare dei test case creati con Selenium IDE su Redmine, si potrebbe allegarli ma l’intenzione è quella di mostrali come una tabella.

Ho cosi’ consultato velocemente la pagina su come creare un custom format.

Da li’, a meno di eccezioni (quali l’escape della pipe | ) ho creato questo semplice script da aggiungere nel menu opzioni di Selenium IDE nel tab formats (inserite Wiki nel campo wiki format name e sovrascrivete con il seguente contenuto):

var wiki = {
confluence:{
  start_table: "",
  end_table: "",
  header: "||Command||Target||Value||\n",
  header_row:"||#",
  start_row: "| ",
  end_row: " |\n",
  separator: " | ",
},
dokuwiki:{
  start_table: "",
  end_table: "",
  header: "^ Command ^ Target ^ Value ^\n",
  header_row:"^ # ",
  start_row: "| ",
  end_row: " |\n",
  separator: " | ",
},
mediawiki:{
  start_table: "{|border=\"1\" \n",
  end_table: "|}",
  header: "!Command\n!Target\n!Value\n",
  header_row:"!#\n",
  start_row: "|-\n|",
  end_row: "\n",
  separator: "\n|",
},
moinmoin:{
  start_table: "",
  end_table: "",
  header: "||\'\'\'Command\'\'\'||\'\'\'Target\'\'\'||\'\'\'Value\'\'\'||\n",
  header_row:"||\'\'\'#\'\'\'",
  start_row: "||",
  end_row: "||\n",
  separator: "||",
},
textile:{
  start_table: "",
  end_table: "",
  header: "|_. Command|_. Target|_. Value|\n",
  header_row:"|_. #",
  start_row: "|",
  end_row: "|\n",
  separator: "|",
},
trac:{
  start_table: "",
  end_table: "",
  header: "||= Command =||=  Target =||=  Value =||\n",
  header_row:"||= # =",
  start_row: "||",
  end_row: "||\n",
  separator: "||",
},
twiki:{
  start_table: "",
  end_table: "",
  header: "|  *Command*  |  *Target*  |  *Value*  |\n",
  header_row:"| *#*",
  start_row: "|  ",
  end_row: "  |\n",
  separator: "  |  ",
},
xwiki:{
  start_table: "",
  end_table: "",
  header: "|=Command|=Target|=Value\n",
  header_row:"|=#",
  start_row: "|",
  end_row: "\n",
  separator: "|",
}
};

function formatCommands(commands) {
  var result = '';
  var start_table =  wiki[options['wiki']]["start_table"];
  var end_table =  wiki[options['wiki']]["end_table"];
  var header = wiki[options['wiki']]["header"];
  var header_row = wiki[options['wiki']]["header_row"];
  var start_row = wiki[options['wiki']]["start_row"];
  var end_row = wiki[options['wiki']]["end_row"];
  var sep = wiki[options['wiki']]["separator"];
  var row_num = '';
  for (var i = 0; i < commands.length; i++) {
    var command = commands[i];
    if('true' == options.row)
            row_num= i+sep;
    if (command.type == 'command') {
      result += start_row + row_num+ command.command + sep + command.target + sep + command.value + end_row;
    }
  }
    if('true' == options.row)
         header = header_row+header;
    result = start_table + header + result + end_table;
  return result;
}

function parse(testCase, source) {
  var doc = source;
  var commands = [];
  var start_row = wiki[options['wiki']]["start_row"];
  var sep = wiki[options['wiki']]["separator"];
  while (doc.length > 0) {
    var line = /(.*)(\r\n|[\r\n])?/.exec(doc);
    var line2 = line[1].slice(start_row.length);
    var array = line2.split(sep);
    if (array.length >= 3) {
      var command = new Command();
      command.command = array[0];
      command.target = array[1];
      command.value = array[2];
      commands.push(command);
    }
    doc = doc.substr(line[0].length);
  }
  testCase.setCommands(commands);
}

function format(testCase, name) {
  return formatCommands(testCase.commands);
}

options = {wiki: 'confluence', row:"false"};

configForm = '<description>Choose a wiki syntax:</description>' + '<menulist id="options_wiki">'
+ 	'<menuitem label="Confluence" value="confluence"/>' +
+ 	'<menuitem label="DokuWiki" value="dokuwiki"/>' +
	'<menuitem label="MediaWiki" value="mediawiki"/>' +
	'<menuitem label="MoinMoin" value="moinmoin"/>' + '<menuitem label="Textile" value="textile"/>' + '<menuitem label="Trac" value="trac"/>' + '<menuitem label="Twiki" value="twiki"/>' + '<menuitem label="Xwiki" value="xwiki"/>' + '</menupopup>' + '</menulist>'+ '<separator class="groove"/>' + '<checkbox id="options_row" label="Row number"/>';

Dal menu delle opzioni, vedete che confluence  è impostato di default (potete abilitare anche i numeri di riga tramite la checkbox) e potete scegliere tra Confluence, DokuWiki, MediaWiki, MoinMoin, Textile (Redmine), Trac, Twiki e Xwiki.

Una volta salvato, andate in Options -> Format e scegliete Wiki, cliccate poi sul tab Source e vedete il test case nel formato wiki da voi scelto, potete poi copiare e incollare nel vostro wiki preferito.