Automate the installation of a product with bash scripts

The problem

I was given the repetitive task to make an archive and install the content on a machine every 3 weeks. This archive contained sql files and shell scripts. A shell script would install the product and create a database.

The procedure was entirely manual and repetitive. I decided steps by steps to automate all the procedure with maven and ant plugin. With Jenkins I launched the procedure daily ,thus I could detect problems early.
I have been using mavento create the archive. Then I used maven plugin “maven-antrun-plugin” to install automatically the archive on a distant server.

Generate the archive

Content of the pom.xml

First of all I had to generate an archive with maven-assembly plugin. This following plugin will call the file assembly.xml to generate an archive of type zip.


<plugin>
<inherited>false</inherited>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptors>
<descriptor>src/main/assembly.xml</descriptor>
</descriptors>
</configuration>
</plugin>

Content of the assembly.xml

This is the headline of the assembly. The variable ${name} is defined in the properties file of the  pom.

<assembly>
<id>${name}</id>
<formats>
<format>dir</format>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>

The filesets will add files from the local code in the archive. I can as well exclude all files of type txt for example if I don’t want them in the archive.

<fileSets>
        <fileSet>
            <directory>${basedir}/src/main/resources</directory>
            <outputDirectory>/</outputDirectory>
            <lineEnding>unix</lineEnding>
            <fileMode>755</fileMode>
            <directoryMode>755</directoryMode>
            <excludes>
                <exclude>**/*.txt</exclude>
            </excludes>
        </fileSet>
    </fileSets>

Below I select the module child1 in the tree of my modules. Then I retrieve the content of the directory src/main in the module child1. I include all text files of types war,properties, etc…

More information on moduleSets :

http://maven.apache.org/plugins/maven-assembly-plugin/advanced-module-set-topics.html

<moduleSets>
<moduleSet>
<includes>
<include>org.lib:child1</include>
</includes>
<sources>
<fileSets>
<fileSet>
<directory>src/main</directory>
<outputDirectory>/</outputDirectory>
<fileMode>755</fileMode>
<lineEnding>keep</lineEnding>
<directoryMode>755</directoryMode>
<includes>
<include>**/*.war</include>
<include>**/*.properties</include>
<include>**/*.jar</include>
<include>**/*.dump</include>
</includes>
</fileSet>
<moduleSet>
<moduleSets>

Then I want to retrieve some dependencies of the pom into my archive file :

<dependencySets>
<dependencySet>
<outputFileNameMapping>
myapp.war
</outputFileNameMapping>
<outputDirectory>/web</outputDirectory>
<includes>
<include>org.lib:web</include>
</includes>
</dependencySet>

That’s it : I have created a basic archive.

Install the archive in some distant server

Content of the pom.xml

In order to install the archive in some distant server I used the plugin maven-antrun-plugin

<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-antrun-plugin</artifactId>
                <inherited>false</inherited>
                <dependencies>
                    <dependency>
                        <groupId>org.apache.ant</groupId>
                        <artifactId>ant-jsch</artifactId>
                        <version>1.7.0</version>
                    </dependency>
                    <dependency>
                        <groupId>com.jcraft</groupId>
                        <artifactId>jsch</artifactId>
                        <version>0.1.51</version>
                    </dependency>
                    <dependency>
                        <groupId>ant-contrib</groupId>
                        <artifactId>ant-contrib</artifactId>
                        <version>1.0b3</version>
                        <scope>compile</scope>
                        <exclusions>
                            <exclusion>
                                <groupId>ant</groupId>
                                <artifactId>ant</artifactId>
                             </exclusion>
                        </exclusions>
                    </dependency>
                </dependencies>
                <executions>
                    <execution>
                        <id>install</id>
                        <phase>install</phase>
                        <goals>
                            <goal>run</goal>
                        </goals>
                        <configuration>
                            <tasks>
                                <property name="compile_classpath" refid="maven.compile.classpath"/>
                                <property name="runtime_classpath" refid="maven.runtime.classpath"/>
                                <property name="test_classpath" refid="maven.test.classpath"/>
                                <property name="plugin_classpath" refid="maven.plugin.classpath"/>
                                <property name="remote_host" value="${remoteHost}"/>
                                                               <property name="remote.dir" value="${remote.dir}"/>
                                <property name="remote.login" value="${remote.login}"/>
                                <property name="remote.pwd" value="${remote.pwd}"/>
                                 
                                <ant antfile="${antdir}">
                                    <target name="deploy"/>
                                </ant>
                            </tasks>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <properties>
                <remote.login>login</remote.login>
                <remote.pwd>pass</remote.pwd>
                <remoteHost>blaha.org.2015.com</remoteHost>
                <remote.dir>/remote/dir</remote.dir>
                <antdir>src/main/resources/ant/build.xml</antdir>
            </properties></pre>
<pre>

The plugin maven will call the build.xml. All variables set in <tasks> are sent to the build.xml file.

build.xml:

The default target of the build.xml is in the  header.Here I have defined some properties and load some constants from the file build.properties.

<?xml version="1.0" encoding="UTF-8"?>
<project name="Build" basedir="." default="deploy">

<property name="baseDirectory" location="./target" />

<property name="myworkspace" location="${baseDirectory}" />
<property file="${baseDirectory}/build.properties" />

Here is defined the target deploy .If remote.dir is not defined I can take the value /remote/dir by default.

<target name="deploy">
      <if>
          <equals arg1="${remote.dir}" arg2="" />
          <then>
              <property name="remote_dir" value="/remote/dir" />
          </then>
          <else>
        <property name="remote_dir" value="${remote.dir}" />
          </else>
      </if>

Another ant file is called. It is useful when we want to factor some ant code.

<ant antfile="src/main/resources/ant/build_common.xml" target="deploy"/>

Copy the zip file(scp) generated from the current directory to the distant server remote_host at the remote_dir folder

 <scp todir="${remote_login}:${remote_pwd}@${remote_host}:${remote_dir}/" file="${baseDirectory}/${archive}.zip" trust="true" />

Execute a command unzip on the remote server  with sshexec.

    <sshexec host="${remote_host}" username="${remote_login}" password="${remote_pwd}" command="cd ${remote_dir};unzip -o ${remote_dir}/colis/${name.archive.full}.zip;" trust="true" />

Execution of bash script which will install the product, create the database, etc…

  <sshexec host="${remote_host}" username="${remote_login}" password="${remote_pwd}" command="cd ${remote_dir};${remote_dir}/install.sh" trust="true" />

After the installation I need to import a dump on the distant server. As you can see i defined the variables before calling the script.

  <sshexec host="${remote_host}" username="${remote_login}" password="${remote_pwd}" command="export ORACLE_HOME=${oracle_home};export ORACLE_SID=${oracle_sid};${oracle_home}/bin/imp login/pass file=/mydir/mydump.dump tables=* commit=y ignore=y" trust="true" />

Conclusion

From spending two to four days in manual installing every three weeks, I spend only half days now doing this process.

Furthermore I had also to manually install and test a patch at each delivery. This patch is now created and installed automatically. I have done it in the same pom so it was a bit tricky. Maybe i will explain in another post.

Advertisements

One thought on “Automate the installation of a product with bash scripts”

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s