System XML

The system xml describes a set of components and how they will be deployed. Each <system> block is made up of one or more <agent> blocks. Each <agent> block represents a single computer that will run one or more components. The <agent> block has everything it requires to manage the deployment and execution. The attributes of the agent element are the id attribute - used to identify an agent uniquely - and an optional os attribute that allows you to specify which operating system you wish the Agent to be running on.

An <agent> element has one or more <group> blocks. A <group> is a logical separation of components. For example, one may wish to create a <group> for the web processing, and another for the database server. This would allow us to easily and quickly change a future test run, by moving the database group from one agent to another without the need to change any other variables or configurations.

The <component> elements indicate which component xml files will be used in the deployment. The 'base' attribute indicates the name of the component xml file to load. The <property> elements in the body of the <component> element allow you to pass in variables that will be available at the component execution time and allow you to override properties that have been defaulted in the component xml in question (more on that later).

Finally, the <script> element can be used to provide a block of Ant tasks that will be ran when the given 'state' is executed.

This flexibile model allows us to easily build blocks of components and move them around to further our tests or to benchmark the best configuration/combination for a given environment.

Let us consider the example <agent> block below that sets up a webserver (apache + php) and a database server (mysql) but places them on the same machine. The php application needs to know where the database server resides, but it won't know this until everything is deployed. BlackBadger utilises late-binding to tie in all the components using a hierarchy of variable addressing. We address the database address by using the variable ${group.databaseserver.mysql_ipaddress}. This addresses the mysql_ipaddress variable inside the databaseserver group. With this addressing mechanism, the actual location of the databaseserver group is not important at this stage, except to note there is indeed a relationship.

<?xml version="1.0" encoding="UTF-8"?>
<system name="AMP example">

  <agent id="dbweb">
    <property name="webroot">/home/docroot/</property>
    <property name="tmp">/tmp/</property>

    <group id="webserver">
      <comp base="apache_currentstack" id="apache">
        <property name="webroot">${agent.this.webroot}</property>
      </comp>
      <comp base="php_currentstack" id="php">
        <property name="mysql_ipaddress">${mysql.ipaddress}</property>
        <property name="mysql_port">${mysql.port}</property>
      </comp>
      <script id="docroot_setup" state="deploy">
        <get src="${system.system_repository}testcases/sample_amp_docroot.zip" 
                dest="${agent.this.tmp}sample_amp_docroot.zip"/>
        <unzip src="${agent.this.tmp}sample_amp_docroot.zip" dest="${agent.this.webroot}"/>
      </script>
    </group>
	
    <group id="databaseserver">
      <comp base="mysql_currentstack" id="mysql">
        <property name="ipaddress">${agent.this.ipaddress}</property>
        <property name="port">3306</property>
      </comp>
      <script id="database_setup" state="deploy">
        <get src="${system.system_repository}testcases/sample_amp_sql.zip" 
                dest="${agent.this.tmp}sample_amp_sql.zip"/>
        <unzip src="${agent.this.tmp}sample_amp_sql.zip" dest="${agent.this.tmp}"/>
        <sql driver="org.database.jdbcDriver" url="jdbc:${mysql.ipaddress}:${mysql.port}" 
             userid="sa" password="pass" src="${agent.this.tmp}sample_amp_sql.sql"/>
      </script>
    </group>

  </agent>
</system>

This example, now shows the database server running on a separate machine, but all other configuration setups remain the same. This allows us now to benchmark and test the components laid across two machines instead of all being executed on a single machine.

<?xml version="1.0" encoding="UTF-8"?>
<system name="AMP example">
  <agent id="web">
    <property name="webroot">/home/docroot/</property>
    <property name="tmp">/tmp/</property>

    <group id="webserver">
      <comp base="apache_currentstack" id="apache">
        <var name="webroot">${agent.this.webroot}</property>
      </comp>
      <comp base="php_currentstack" id="php">
        <property name="mysql_ipaddress">${mysql.ipaddress}</property>
        <property name="mysql_port">${mysql.port}</property>
      </comp>
      <script id="docroot_setup">
        <get src="${system.system_repository}testcases/sample_amp_docroot.zip" 
                dest="${agent.this.tmp}sample_amp_docroot.zip"/>
        <unzip src="${agent.this.tmp}sample_amp_docroot.zip" dest="${agent.this.webroot}"/>
      </script>
    </group>
  </agent>

  <agent id="db">

    <property name="tmp">/tmp/</property>

    <group id="databaseserver">
      <comp base="mysql_currentstack" id="mysql">
        <property name="mysql_ipaddress">${agent.this.ipaddress}</property>
        <property name="mysql_port">3306</property>
      </comp>
      <script id="database_setup">
        <get src="${system.system_repository}testcases/sample_amp_sql.zip" 
                dest="${agent.this.tmp}sample_amp_sql.zip"/>
        <unzip src="${agent.this.tmp}sample_amp_sql.zip" dest="${agent.this.tmp}"/>
        <sql driver="org.database.jdbcDriver" url="jdbc:${mysql.ipaddress}:${mysql.port}" 
             userid="sa" password="pass" src="${agent.this.tmp}sample_amp_sql.sql"/>
      </script>
    </group>

  </agent>
</system>