DevOps Classroom Series – 19/Aug/2020

Jinja2 Templates

  • Manipulating configuration files is a tedious & error prone task, whenever we need to automate deployments we need to modify configuration files of various servers, so to make this modifications simple ansible use Jinja2 as its templating engine.
  • Jinja2 is a designer-friendly templating language for Python.
  • Refer Here for official documentations.
  • Basic syntax for Jinja2 is {{ <expression> }} . <expression> could be a variable or variable with filters
  • Jinja2 supports lots of filters for formatting data.
  • So first lets solve the problem of tomcat configuration file with jinja2.
  • Lets create a file called tomcat.conf.j2 with the following content
# System-wide configuration file for tomcat services
# This will be loaded by systemd as an environment file,
# so please keep the syntax. For shell expansion support
# place your custom files as /etc/tomcat/conf.d/*.conf
#
# There are 2 "classes" of startup behavior in this package.
# The old one, the default service named tomcat.service.
# The new named instances are called tomcat@instance.service.
#
# Use this file to change default values for all services.
# Change the service specific ones to affect only one service.
# For tomcat.service it's /etc/sysconfig/tomcat, for
# tomcat@instance it's /etc/sysconfig/tomcat@instance.

# This variable is used to figure out if config is loaded or not.
TOMCAT_CFG_LOADED="1"

# In new-style instances, if CATALINA_BASE isn't specified, it will
# be constructed by joining TOMCATS_BASE and NAME.
TOMCATS_BASE="/var/lib/tomcats/"

# Where your java installation lives
JAVA_HOME="/usr/lib/jvm/jre"

# Where your tomcat installation lives
CATALINA_HOME="/usr/share/tomcat"

# System-wide tmp
CATALINA_TMPDIR="/var/cache/tomcat/temp"

# You can pass some parameters to java here if you wish to
#JAVA_OPTS="-Xminf0.1 -Xmaxf0.3"
JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Djava.awt.headless=true -Xmx{{ xmx_size }} -XX:MaxPermSize={{ MaxPermSize }} -XX:+UseConcMarkSweepGC"

# Use JAVA_OPTS to set java.library.path for libtcnative.so
#JAVA_OPTS="-Djava.library.path=/usr/lib"

# You can change your tomcat locale here
#LANG="en_US"

# Run tomcat under the Java Security Manager
SECURITY_MANAGER="false"

# SHUTDOWN_WAIT has been deprecated. To change the shutdown wait time, set
# TimeoutStopSec in tomcat.service.

# If you wish to further customize your tomcat environment,
# put your own definitions here
# (i.e. LD_LIBRARY_PATH for some jdbc drivers)

Preview

  • To copy this template lets use template module Refer Here
  • The playbook with template looks as shown below
---
- hosts: appserver
  become: yes
  vars:
    tomcat_package_name: tomcat
    tomcat_additional_packages:
      - tomcat-webapps 
      - tomcat-admin-webapps
    tomcat_conf_location: "/usr/share/tomcat/conf/tomcat.conf"
    xmx_size: 512m
    MaxPermSize: 256m
  pre_tasks:
    - name: update ubuntu packages
      apt:
        update_cache: yes
      when: ansible_os_family == "Debian"
  tasks:
    - name: install tomcat
      package:
        name: "{{ tomcat_package_name }}"
        state: present
      notify:
        - enable and restart tomcat
    - name: install additional packages
      package:
        name: "{{ item }}"
        state: present
      loop: "{{ tomcat_additional_packages }}"
      notify:
        - enable and restart tomcat
    - name: copy tomcat configuration
      template:
        src: tomcat.conf.j2
        dest: /usr/share/tomcat/conf/tomcat.conf
      notify:
        - enable and restart tomcat
  handlers:
    - name: enable and restart tomcat
      service:
        name: "{{ tomcat_package_name }}"
        enabled: yes
        state: restarted
      
  • Execute playbook Preview
  • Lets login into the machine & look at configuration file
  • Now there is one last step to create a configuration file tomcat-users.xml, so lets create a tomcat-users.xml.j2 file
<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
    <user username="{{ username }}" password="{{ password }}" roles="{{ roles }}"/>
</tomcat-users>
  • The playbook will be as shown below
---
- hosts: appserver
  become: yes
  vars:
    tomcat_package_name: tomcat
    tomcat_additional_packages:
      - tomcat-webapps 
      - tomcat-admin-webapps
    tomcat_conf_location: "/usr/share/tomcat/conf/tomcat.conf"
    xmx_size: 512m
    MaxPermSize: 256m
    username: admin
    password: password
    roles: "manager-gui,admin-gui"
  pre_tasks:
    - name: update ubuntu packages
      apt:
        update_cache: yes
      when: ansible_os_family == "Debian"
  tasks:
    - name: install tomcat
      package:
        name: "{{ tomcat_package_name }}"
        state: present
      notify:
        - enable and restart tomcat
    - name: install additional packages
      package:
        name: "{{ item }}"
        state: present
      loop: "{{ tomcat_additional_packages }}"
      notify:
        - enable and restart tomcat
    - name: copy tomcat configuration
      template:
        src: tomcat.conf.j2
        dest: /usr/share/tomcat/conf/tomcat.conf
      notify:
        - enable and restart tomcat
    - name: copy tomcat users xml
      template:
        src: tomcat-users.xml.j2
        dest: /usr/share/tomcat/conf/tomcat-users.xml
      notify:
        - enable and restart tomcat
  handlers:
    - name: enable and restart tomcat
      service:
        name: "{{ tomcat_package_name }}"
        enabled: yes
        state: restarted
      
  • Now execute the playbook Preview

Next steps

  • You have asked to automate the deployment for which no module is present in ansible you have only manual linux steps. Then what has to be done?
  • Many organizations might already have developed lot of ansible playbooks why do i need to write playbook from scratch can’t i reuse existing ones?
  • How to write ansible playbook in a way that it is reusable?

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About learningthoughtsadmin