Using the Marker and Action Hook System - Learning OpenShift (2014)

Learning OpenShift (2014)

Chapter 11. Using the Marker and Action Hook System

In this chapter, we are going to learn how to use the marker and action hook systems that are part of OpenShift Online. Using the action hook system, we can customize the application by providing hooks that will be executed at defined points during the deployment life cycle. The marker system allows us to enable hot deployment, remote debugging, and the version of the Java SDK to be used to build and run applications.

An overview of the marker system

The marker system is provided as a convenient way for developers to notify the OpenShift platform that they want to change a particular behavior. In this chapter, we are going to look at the hot_deploy, enable_jpda, and disable_auto_scaling markers.

The hot_deploy marker

As you have noticed when deploying code to the OpenShift Online platform, the system performs several steps after a git push command is executed. The platform stops all running services on the remote gear, builds the code, deploys the code, and lastly, restarts all of the services. This is inconvenient and time consuming, especially for languages that are interpreted, such as PHP, where a restart of the application server is not required. In fact, even modern versions of Java application servers support hot deploying application code without requiring a full restart of the server.

In the following table, I have displayed the application runtime and depicted whether the hot deploy marker is available for use with the runtime:

Application runtime

Supports hot deploy

Tomcat/JBoss EWS

Yes

JBoss AS / EAP

Yes

PHP

Yes

Perl

Yes

Ruby

Yes

Python

Yes

Node.js

Yes

Jenkins

No

HAProxy

No

Zend Server (PHP)

Yes

DIY

No

JBoss-specific markers

OpenShift supports several markers that are specific to JBoss-based applications that will allow developers to control and manage some of the runtime features associated with their application. The available markers for the JBoss Application Server are as follows:

· enable_jpda: Setting this marker will enable the remote debugging of applications by enabling the Java Platform Debugger Architecture (JPDA) socket.

Note

If you are not familiar with JPDA, you can find more information at http://en.wikipedia.org/wiki/Java_Platform_Debugger_Architecture.

· skip_maven_build: Setting this marker will skip a Maven build when a new application's code is pushed to the remote gear.

· force_clean_build: This marker performs a full build using Maven, including clearing the Maven dependency cache and downloading all dependencies specified in the pom.xml file.

· hot_deploy: This marker will deploy the newly built .war or .ear files without restarting the application server.

· java7: This marker will enable Java 7 to run your application and application server. If this marker is not set, the base version of Java will be used, which is Java 6 at the time of writing this book.

Creating and using markers

In order to use a marker, you simply create a file with the given name in the .openshift/markers directory, which is located in the root directory of your application. In order to illustrate this, let's create a new Java-based application and enable some of the available markers.

The first thing we need to do is create a new application named markertest, and then specify that we want to use the JBoss EAP application server:

$ rhc app create markertest jbosseap

Once you enter the preceding command, you should see the following output on your screen, indicating that the operation was successful:

Using jbosseap-6 (JBoss Enterprise Application Platform 6) for 'jbosseap'

Application Options

-------------------

Domain: packt

Cartridges: jbosseap-6 (addtl. costs may apply)

Gear Size: default

Scaling: no

Creating application 'markertest' ... done

Waiting for your DNS name to be available ... done

Cloning into 'markertest'...

Your application 'markertest' is now available.

URL: http://markertest-packt.rhcloud.com/

SSH to: 538266264382ecae6000009c@markertest-packt.rhcloud.com

Git remote: ssh://538266264382ecae6000009c@markertest-packt.rhcloud.com/~/git/markertest.git/

Cloned to: /Users/gshipley/code/packt/markertest

Run 'rhc show-app markertest' for more details about your app.

Using the hot_deploy marker

Now that our application has been created, the first thing we want to do is enable hot deployment. In order to do this, we simply need to create an empty file named hot_deploy and place it in the .openshift/markers directory of our application. For this, you can enter the following commands:

$ cd markertest

$ touch .openshift/markers/hot_deploy

Now that we have our hot deploy marker file created, we simply need to add it to our application repository and then push the changes to our remote gear as follows:

$ git add .

$ git commit -am "Adding hot_deploy marker"

$ git push

Now that we have hot deployment enabled, all future deployments will occur without having to restart the JBoss Application Server. Let's test this out by creating a new JSP file and deploying the changes. Create a new file called date.jsp and place it under the /src/main/webapp directory of your application. Once you have created this file, add the following line of code and save the changes:

<%= new java.util.Date() %>

Now, we need to add, commit, and push the changes to our remote OpenShift gear:

$ git add .

$ git commit -am "Adding test file"

$ git push

Once you push the new code to your gear, you should see the following output, which indicates that hot deployment has been enabled for your application:

remote: Not stopping cartridge jbosseap because hot deploy is enabled

The code will then be built and deployed. Once the code has been deployed, you will see the following message, indicating that the application server does not need to be started:

remote: Not starting cartridge jbosseap because hot deploy is enabled

Using the force_clean_build marker

Using the force_clean_build marker is similar to using the hot_deploy marker. You simply need to create an empty file in the .openshift/markers directory named force_clean_build, and when you push the code, the system will download all of the dependencies again. Run the following commands to create and use this marker:

$ touch .openshift/markers/force_clean_build

$ git add .

$ git commit -am "adding a marker to perform a clean build"

$ git push

Once you push the change to your remote OpenShift gear, you will notice that Maven downloads all the dependencies listed in the pom.xml file.

Note

Keep in mind that your application will continue to perform a clean build each time you push the new code until you remove the force_clean_build marker.

To remove the marker, you can simply remove the file from your repository and push the changes to your gear as follows:

$ git rm .openshift/markers/force_clean_build

$ git commit -am "removing clean build marker file"

$ git push

You will now see that your application is built using the Maven system. However, the existing dependencies that have been downloaded will be used.

An overview of the action hook system

The OpenShift Online platform provides a system that allows developers an entry point into the application build and deployment life cycle called action hooks. These action hooks reside in the application's home directory under the .openshift/action_hooks directory. One of the great things about action hooks is that they can be written in any language, with the only requirement being that they be executable by the gears' operating system. This opens up a whole world of possibilities in order to plug into the build and deploy life cycle of your application.

Note

Action hooks are scripts that can be written in virtually any programming language that is executable on the remote operating system, including Bash, Ruby, Python, Perl, and so on.

You might be wondering when you would want to use action hooks in your code. One of the common use cases for which I implement action hooks is clearing and rebuilding my application's database. This ensures that each time I deploy a new version of the application that I am developing, I start with a fresh set of data in the database.

Another example of when action hooks can be implemented is to alert the developer when their application server is stopped or restarted. Logging this information via an action hook will allow the developer to analyze how much time is spent during this part of the life cycle.

There are two groupings of action hooks in the OpenShift platform. The first grouping is called build action hooks and is performed after the developer issues a git push command. This grouping of action hooks allows the developer to plug directly into the build and deployment life cycle of their application.

The available action hooks for the build and deployment life cycle are as follows:

· pre_build: This action hook is executed directly before the application is built. For example, the pre_build action hook will be executed before Maven for Java-based projects.

· build: The build action hook is executed during the compilation, or build phase, of the application.

· deploy: This action hook is executed as part of the deploy process for an application.

· post_deploy: This action hook is executed directly after the application has completed the deploy phase of the life cycle.

The second grouping of action hooks allows the developer to have an entry point into the cartridge life cycle of an application. For example, a user can add an action hook that is executed every time the MySQL database is restarted in order to refresh the data in the database to its original state. The following action hooks are available in order to plug into the cartridge life cycle:

· Cartridge start control action:

o pre_start

o pre_start_{cartridgeName}

o post_start

o post_start_{cartridgeName}

· Cartridge stop control action:

o pre_stop

o pre_stop_{cartridgeName}

o post_stop

o post_stop_{cartridgeName}

· Cartridge reload control action:

o pre_reload

o pre_reload_{cartridgeName}

o post_reload

o post_reload_{cartridgeName}

· Cartridge restart control action:

o pre_restart

o pre_restart_{cartridgeName}

o post_restart

o post_restart_{cartridgeName}

· Cartridge tidy control action:

o pre_tidy

o pre_tidy_{cartridgeName}

o post_tidy

o post_tidy_{cartridgeName}

Creating and using action hooks

Now that we have a good understanding of what action hooks are useful for, and the available ones that we can use, let's see how they work by integrating them into an application. Create an application called action using the PHP-5.4 runtime with the following command:

$ rhc app create action php-5.4

Once the application has been created and the source code has been cloned to your local computer, switch to the .openshift directory of your application with the help of the following command:

$ cd action/.openshift

Once you are in the directory, list all of the contents with the help of the following command:

$ ls -l

You should see the following output:

drwxr-xr-x 3 gshipley staff 102 May 26 10:04 action_hooks

drwxr-xr-x 8 gshipley staff 272 May 26 10:04 cron

drwxr-xr-x 3 gshipley staff 102 May 26 10:04 markers

-rw-r--r-- 1 gshipley staff 0 May 26 10:04 pear.txt

As you can see in the preceding output, we have an action_hooks directory. This is where all the scripts that you create should be located. Switch to the action_hooks directory with the following command:

$ cd action_hooks

Inside of this directory, you will notice a README.md file that ships as part of the application template. This file will provide documentation on the available action hooks by providing a link to the official OpenShift Online user guide.

Creating the deploy action hook

As an example of creating an action hook, we are going to create a simple hook that will echo a message every time the application is deployed. In order to do this, create a new file in the action/.openshift/action_hooks directory named deploy with the following contents:

#!/bin/bash

echo " ***** Starting the deploy action hook ***** "

Once you have saved this file, you need to modify the script so that it is executable. For this, we can use the chmod command:

$ chmod +x deploy

To verify that the script is now executable, enter the following command:

$ ./deploy

You should see the following output:

***** Starting the deploy action hook *****

Now that we have our deploy action hook created, we need to add, commit, and push the file to our remote gear. For this, run the following commands:

$ git add deploy

$ git commit -am "adding deploy action_hook"

$ git push

Pay close attention to the output that is displayed on your screen while the git push command is being executed. As part of the push process, the application code is deployed and all associated action hooks are executed, including the one we just added. The output from the command is as follows:

Counting objects: 8, done.

Delta compression using up to 8 threads.

Compressing objects: 100% (5/5), done.

Writing objects: 100% (5/5), 577 bytes | 0 bytes/s, done.

Total 5 (delta 0), reused 0 (delta 0)

remote: Stopping PHP 5.4 cartridge (Apache+mod_php)

remote: Waiting for stop to finish

remote: Waiting for stop to finish

remote: Building git ref 'master', commit 58c7b6b

remote: Checking .openshift/pear.txt for PEAR dependency...

remote: Preparing build for deployment

remote: Deployment id is 7491a262

remote: Activating deployment

remote: ***** Starting the deploy action hook *****

remote: Starting PHP 5.4 cartridge (Apache+mod_php)

remote: Application directory "/" selected as DocumentRoot

remote: -------------------------

remote: Git Post-Receive Result: success

remote: Activation status: success

remote: Deployment completed with status: success

To ssh://538373ac4382ec3af10001a1@action-packt.rhcloud.com/~/git/action.git/

dcaf5db..58c7b6b master -> master

If you notice, the output includes the following line, indicating that our deploy script is being executed as part of the life cycle:

remote: ***** Starting the deploy action hook *****

Now that we know that our deploy action hook is being executed, we can begin to do more interesting things such as adding a database and refreshing the contents each time the application is deployed. To start, let's embed a MySQL database into our application:

$ rhc cartridge add mysql-5.5 -a action

Once the database has been added to the application, create a new file named schema.sql in the root directory of the action application. Insert the following lines of code into the file and save the changes:

DROP TABLE IF EXISTS `users`;

CREATE TABLE `users` (

`user_id` int(11) NOT NULL AUTO_INCREMENT,

`username` varchar(200) DEFAULT NULL,

PRIMARY KEY (`user_id`)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;

LOCK TABLES `users` WRITE;

INSERT INTO `users` VALUES (1,'gshipley');

UNLOCK TABLES;

Ensure that this file is located in the root directory of the action application. The code in the schema.sql file is SQL commands that perform the following SQL operations:

· Drop the users table if it exists

· Create a table named users and define the columns for the table

· Insert a row into the users table

Now that we have a DDL file that will delete and create the schema, we want to modify our deploy action hook to perform the SQL commands during the deployment phase. To do this, open the .openshift/action_hooks/deploy file and enter the following lines of code, replacing what is already there:

#!/bin/bash

echo " ***** REFRESHING THE DATABASE ***** "

/usr/bin/mysql -u "$OPENSHIFT_MYSQL_DB_USERNAME" --password="$OPENSHIFT_MYSQL_DB_PASSWORD" --host="$OPENSHIFT_MYSQL_DB_HOST" $OPENSHIFT_APP_NAME < $OPENSHIFT_REPO_DIR/schema.sql

echo " ***** REFRESH COMPLETE ***** "

Let's examine each line of the deploy script in detail to ensure that we fully understand it:

· #!/bin/bash: This line simply defines that the information contained in the file is a script for the Bash Linux shell.

· echo " ***** REFRESHING THE DATABASE ***** ": This line informs the user that we are going to refresh the database. This is what is printed on the terminal when the action hook is being executed.

· /usr/bin/mysql -u "$OPENSHIFT_MYSQL_DB_USERNAME" --password="$OPENSHIFT_MYSQL_DB_PASSWORD" --host="$OPENSHIFT_MYSQL_DB_HOST" $OPENSHIFT_APP_NAME < $OPENSHIFT_REPO_DIR/schema.sql: This is where we connect to the MySQL database and run the SQL commands that we defined in our schema.sql file. This line is further broken down as follows:

o /usr/bin/mysql: This is the path of the mysql executable on the remote OpenShift gear.

o -u "$OPENSHIFT_MYSQL_DB_USERNAME": This specifies the username that will be used to authenticate to the database. Note that instead of hardcoding the username, we are using the environment variable for our application to ensure that this script is portable across deployments.

o --password="$OPENSHIFT_MYSQL_DB_PASSWORD": This is the password for the user that we are authenticating with. Again, we are using the environment variable instead of hardcoding the password.

o --host="$OPENSHIFT_MYSQL_DB_HOST": When connecting to MySQL, we need to specify the host that we are connecting to. Remember that in OpenShift Online, a MySQL database has its own internal private IP address and does not use 127.0.0.1. For this reason, we have to specify the location of the server.

o $OPENSHIFT_APP_NAME: We specify the application name by itself in order to alert MySQL of the database we want to connect to. Since a default database is created based on the name of the application, using the $OPENSHIFT_APP_NAME environment will provide the database with the correct information.

o < $OPENSHIFT_REPO_DIR/schema.sql: This is the last section of the command and will simply redirect the contents of the schema.sql file into the database. When this happens, the SQL commands inside of the file are executed against the database.

Testing the deploy action hook

Now that our schema file and action hook have been created, it's time to test them out. Add all the new files to your repository, and then commit and push them to your application as follows:

$ git add .

$ git commit -am "Adding deploy action hook to refresh database"

$ git push

During the deployment, you will notice the following section of output that is presented on the terminal screen:

remote: Preparing build for deployment

remote: Deployment id is cc259719

remote: Activating deployment

remote: Starting MySQL 5.5 cartridge

remote: ***** REFRESHING THE DATABASE *****

remote: ***** REFRESH COMPLETE *****

This indicates that the refresh was successful. Let's test this out by logging in to our remote gear and looking at the contents of the MySQL database. First, we need to SSH in with the following command:

$ rhc app ssh action

Once you have been authenticated to the remote server, you will be presented with a terminal prompt. To connect to MySQL, simply enter the following command:

$ mysql

Note

When running the mysql command while connected to the remote gear, the OpenShift platform will automatically authenticate you to the database without having to provide any credentials.

From the MySQL shell, enter the following commands:

mysql> use action;

mysql> select * from users;

You should see the following output:

+---------+----------+

| user_id | username |

+---------+----------+

| 1 | gshipley |

+---------+----------+

1 row in set (0.00 sec)

Insert an additional row into the database with the following command:

mysql> insert into users values (null, 'reader');

Verify that the new user was added by running the select statement again. Now that we have a new user created in the database, let's make a change to the code and deploy the application again. Create a new file called hello.php in the root directory of the application and add the following code:

<?php

echo "Learning how the deploy action_hook works"

Once you have saved the file, add, commit, and push the changes to your remote gear:

$ git add hello.php

$ git commit -am "adding new file"

$ git push

During the deployment phase of the life cycle, you will see the following lines in the remote server:

remote: Stopping MySQL 5.5 cartridge

remote: Stopping PHP 5.4 cartridge (Apache+mod_php)

remote: Waiting for stop to finish

remote: Waiting for stop to finish

remote: Building git ref 'master', commit 1211b7a

remote: Checking .openshift/pear.txt for PEAR dependency...

remote: Preparing build for deployment

remote: Deployment id is a2ed0fcf

remote: Activating deployment

remote: Starting MySQL 5.5 cartridge

remote: ***** REFRESHING THE DATABASE *****

remote: ***** REFRESH COMPLETE *****

remote: Starting PHP 5.4 cartridge (Apache+mod_php)

remote: Application directory "/" selected as DocumentRoot

remote: -------------------------

remote: Git Post-Receive Result: success

remote: Activation status: success

remote: Deployment completed with status: success

You will notice that the database was refreshed, as indicated by the following two lines of output:

remote: ***** REFRESHING THE DATABASE *****

remote: ***** REFRESH COMPLETE *****

To verify that the database was indeed refreshed, SSH to your application and execute the mysql command again:

$ rhc app ssh action

$ mysql

From the MySQL shell, enter the following commands:

mysql> use action;

mysql> select * from users;

You should see the following output:

+---------+----------+

| user_id | username |

+---------+----------+

| 1 | gshipley |

+---------+----------+

1 row in set (0.00 sec)

Pretty awesome, huh? From now on, every time we deploy a new change to our application, we can be assured that we are starting with a fresh set of data in the databases.

What would be even better is if we could refresh our database with a simple reload command:

$ rhc cartridge reload mysql-5.1

Good news, you can do this by creating an action hook named post_reload_{cartridgeName}. For example, you can copy the deploy action hook to a new file with the following command:

$ mv .openshift/action_hooks/deploy .openshift/action_hooks/post_reload_mysql-5.1

After you add the new file and push your changes, the script will get executed every time you issue a reload command to the MySQL cartridge.

Summary

In this chapter, we learned about the marker and action hook functionality that is provided as part of the OpenShift Online platform. We started by creating marker files in order to enable hot deployment, and then created a marker to force a clean build of our application code. After this, we learned how to use the marker system, examined the action hook system, and learned how to create a deploy action hook that refreshes the contents of the database after each new deployment. The action hook system is a powerful feature that will allow you to customize the workflow of your application by providing an entry point into the OpenShift system.

In the next chapter, we are going to learn about application scaling and how automatic and manual scaling works. We will also learn how to customize the scaling algorithm in order to allow us to scale based on metrics that are provided by the developer.