You are here

Ansible Basics by Example. Configure and Deploy an Application

Following on other ansible posts, just to get the hang of things and have some more examples, here we are going to use ansible to deploy and test and application.

This is only and example app, nothing serious or usefull, just to get a little bit of practice, The application analyzes OS support bundles for hardware/soft errors, the bundles are read from a /dir in the host, and it outputs the analysis via a web page on a docker container running and http server.

The ansible role nickel_tool job is to configure the host, download pkgs, enable all needed services to upload the bundles, pull the docker latest docker image, and finally configures the wrapper scripts that monitors the FS to check if there are new bundles.

The ansible check_allworks, is use to check all the configuration from the previous role is working without problems.

In this post we are just going to take a walk along the nickel_tool role:


[liquid@liquid-ibm:nickel-tool-ansible/roles]$ tree .                                                                                                                                    (12-16 12:39)
.
├── check_allworks
│   ├── tasks
│   │   └── main.yml
│   └── vars
│       └── main.yml
└── nickel_tool
    ├── defaults
    │   └── main.yml
    ├── handlers
    │   ├── debian.yml
    │   ├── main.yml
    │   └── redhat.yml
    ├── tasks
    │   ├── debian.yml
    │   ├── main.yml
    │   └── redhat.yml
    ├── templates
    │   ├── docker-storage-setup.j2
    │   ├── smb.j2
    │   └── vsftpd.j2
    └── vars
        └── main.yml

Like allways we have our role dir setup, to get the dir layout setup for you, you can use the ansible-galaxy command:

$ ansible-galaxy init nickel_tool

Just to explain the tree:

└── nickel_tool
    ├── defaults        ----------> in defaults folder we have all the default vars the user can change, easy to override, no passwds in these vars
    │   └── main.yml
    ├── handlers        ----------> handlers for our 2 types of servers
    │   ├── debian.yml
    │   ├── main.yml
    │   └── redhat.yml
    ├── tasks        ----> I divided the 2 types of os families(redhat/debian)
    │   ├── debian.yml  --> debian tasks file, there should be a common file for both for shared tasks, in this case they are duplicated bad!
    │   ├── main.yml  ---> includes the debian and redhat yaml files with a when conditional statement gathered by facts
    │   └── redhat.yml --> redhat tasks file, there should be a common file for both for shared tasks, in this case they are duplicated bad!
    ├── templates
    │   ├── docker-storage-setup.j2   --> template to configure the the lvm driver for docker in redhat based systems
    │   ├── smb.j2                    --> configure the samba service
    │   └── vsftpd.j2 		      --> configure the vsftpd service
    └── vars
        └── main.yml       ---> this vars file is encrypted using ansible vault, it contains passwords for gitlab,users,etc.


Ok, so lets take a look at the defaults var main.yml file:

[liquid@liquid-ibm:nickel-tool-ansible/roles]$ cat nickel_tool/defaults/main.yml                                                                                                         (12-16 14:12)
---
#Docker storage options(only for redhat based systems):
#Warning!!: if docker_storage is enabled and there is a current installation using loopback it will delete it!!!
docker_storage: false
# If docker_storage: true, you have to give it a disk to use for lvm (only for redhat based systems)
disk_name: '/dev/vdb'
#And a VG name to use (only for redhat based systems)
vg_name: dockervg
##tmpfs options, nickel_tool work dir gives better performance using tmpfs:
use_tmpfs_workdir: true
## if tmpfs_workdir: true please select a size for the FS:
tmpfs_size: 2048m
###Create Work dirs:
docker_work_nickel: /docker-work-nickel-files
docker_input_nickel: /docker-input-nickel-files
docker_history_nickel: /docker-history-nickel-files
##Public IP to access the nickel-tool output via web
public_ip_nickel: 192.168.121
## Start port that will mapped on the host to access the container web service
start_port_nickel: 6565
## Purging logs and stoped docker containers
## When log files are oldar than N days remove them
purge_log_days_nickel: 5
## Remove docker containers older than N days
purge_containers_days_nickel: 5
##Configure services to upload nickels
samba_nickel: true
ftp_nickel: true

now let's check the tasks the main yaml file:

[liquid@liquid-ibm:nickel-tool-ansible/roles]$ cat nickel_tool/tasks/main.yml                                                                                                            (12-16 14:12)
---
###As we explained we use the when sentence to include one file or the other
- name: Include Redhat Based distributions install
  include: redhat.yml
  when: ansible_os_family == "RedHat" 
- name: Include Debian Based distributions install
  include: debian.yml
  when: ansible_os_family == "Debian"

On the redhat tasks we have quite a lot of things, this really should be divided in different yaml files for cleaner reading
In the next post I will show you how to clean it up and segregate:

[liquid@liquid-ibm:nickel-tool-ansible/roles]$ cat nickel_tool/tasks/redhat.yml                                                                                                          (12-16 14:17)
---

####First we add yum epel and docker repos

- name: Add repository epel
  yum_repository:
    name: epel
    description: EPEL YUM repo
    baseurl: http://download.fedoraproject.org/pub/epel/$releasever/$basearch/
    gpgcheck: no
  when: ansible_distribution == "CentOS"

- name: Add repository docker
  yum_repository:
    name: Docker
    description: docker yUM repo
    baseurl: https://yum.dockerproject.org/repo/main/centos/$releasever/
    gpgcheck: no
  when: ansible_distribution == "CentOS"


#################### We create a user for the application

- name: Create the nickel tool user in the OS
  user:
    name: nickel
    comment: "nickel user for nickel tool"
    group: adm
    shell: /bin/bash
    home: "{{ docker_input_nickel }}"


############## The password is part of the vars vault encrypted dir

- name: Create a passwd fro the nickel user
  shell: echo "{{ nickel_user_pass }}" | passwd nickel --stdin

###### Create the work dirs, this variables are defaults

- name: Create dirs to work on
  file: path={{ item }} state=directory owner=nickel group=adm setype=svirt_sandbox_file_t
  with_items:
     - "{{ docker_work_nickel }}"
     - "{{ docker_input_nickel }}"
     - "{{ docker_history_nickel }}"

#### mount the work dir as tmpfs filesystem using if use_tmpfs_workdir variable is enabled in defaults

- name: Mount tempfs if option selected
  mount: name={{ docker_work_nickel }}  src=tmpfs fstype=tmpfs state=mounted opts=size={{ tmpfs_size }}
  when: use_tmpfs_workdir == true

#### Modify the selinux type on the fs after mounting, so docker can have access to it

- name: Change file setype for work dir to use svirt_sandbox_file_t
  file: path={{ docker_work_nickel }} setype=svirt_sandbox_file_t


####### Install rpms needed by software

- name: Install Software for Nickel-Tool
  yum: name={{ item }} state=latest  update_cache=yes
  with_items:
   - python-pip
   - git
   - net-tools
   - psmisc
   - zip
   - unzip
   - samba
   - vsftpd


### because of a bug on the version docker-selinux on the version found in centos 7.2 we use dockers rpms
### Only when we we are installing in centos 7

- name: Install docker for Nickel-Tool
  yum: name={{ item }} state=latest
  with_items:
   - docker-engine
  when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"

### If not in centos 7 use the centos docker rpms

- name: Install docker for Nickel-Tool
  yum: name={{ item }} state=latest  
  with_items:
   - docker
  when: ansible_distribution != "CentOS"

### Downloading docker-py from pip to get latest version, also hit a bug on the current centos rpm version
- name: Pip install docker-py
  pip: name=docker-py


- name: Get updated files from git repository
  git: repo=https://{{ gitlabuser }}:{{ gitlabpassword }}@gitlab.com/liquidsmail/nickel_tool.git dest=/usr/local/bin/nickel force=yes
  register: git_deploy
  until: git_deploy|succeeded


### Replace configuration parameters on the wrapper scripts to use our variables from the default vars file
- name: replace wrapper scripts with input dirs
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^INPUTDIR=.*' line=INPUTDIR={{ docker_input_nickel }}

- name: replace wrapper scripts with work dirs
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^WORKDIR=.*' line=WORKDIR={{ docker_work_nickel }}

- name: replace wrapper scripts public IP
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^IPPUBSUB=.*' line=IPPUBSUB={{ public_ip_nickel }}

- name: replace wrapper scripts with days to purge logs
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^PURGELOGDAYS=.*' line=PURGELOGDAYS={{ purge_log_days_nickel }}

- name: replace wrapper scripts with days to purge containers
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^PURGERUNINGDOCKERS=.*' line=PURGERUNINGDOCKERS={{ purge_containers_days_nickel }}

- name: replace wrapper scripts with ports to use for web access
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^STARTPORT=.*' line=STARTPORT={{ start_port_nickel }}

### when we enable in the defaults the samba service via the samba_nickel variable in defaults
### we use a template and restart the samba smbd nmbd with the handler:

- name: Configure CIFS server
  template: src=smb.j2 dest=/etc/samba/smb.conf validate='testparm -s %s'
  notify:
  - Restart Samba
  when: samba_nickel == true

### Enable samba on boot
- name: Start and enable Samba
  service: name={{ item }} state=started enabled=yes
  with_items:
  - smb
  - nmb
  when: samba_nickel == true

### IF iptables is configured, we have to add the rules for samba to work

- name: Check if iptables is configured 
  shell: systemctl -t service | grep -i iptables
### we ignore if the shell command fails we only whant to grab the variable
  ignore_errors: yes   
### we register the output of the command in the iptables_status variable
  register: iptables_status

## we evaluate the return code in a when conditional using the iptables_status variable we registered in the previous task
## if it returned 0(iptables enabled) and samba service variable is on, lets insert iptable rules
- name: Add tcp iptables rules for samba
  iptables:
    chain: INPUT
    action: insert
    ctstate: ESTABLISHED,RELATED
    jump: ACCEPT
    protocol: TCP
    destination_port: 4056
    state: present
  when: iptables_status.rc == 0 and samba_nickel == true

- name: Add udp iptables rules for samba
  iptables:
    chain: INPUT
    action: insert
    ctstate: ESTABLISHED,RELATED
    jump: ACCEPT
    protocol: UDP
    destination_port: 5570
    state: present
  when: iptables_status.rc == 0 and samba_nickel == true

- name: Add tcp iptables rules for ftp data
  iptables:
    chain: INPUT
    action: insert
    ctstate: ESTABLISHED,RELATED
    jump: ACCEPT
    protocol: TCP
    destination_port: "20:21"
    state: present
  when: iptables_status.rc == 0 and ftp_nickel == true

- name: Add tcp iptables rules for ftp passive
  iptables:
    chain: INPUT
    action: insert
    ctstate: ESTABLISHED,RELATED
    jump: ACCEPT
    protocol: TCP
    destination_port: 10090:10100
    state: present
  when: iptables_status.rc == 0 and ftp_nickel == true


### The core iptables module, doesn't save state, so we have to do a iptables-save

- name: Save iptables
  shell: "iptables-save > /etc/sysconfig/iptables"
  when: iptables_status.rc == 0 and samba_nickel == true

### Here we configure the FTP service
   
- name: start and enable Vsftp
  service: name=vsftpd state=started enabled=yes
  when: ftp_nickel == true

- name: Configure ftp server
  template: src=vsftpd.j2 dest=/etc/vsftpd/vsftpd.conf
  notify:
  - Restart Vsftp
  when: ftp_nickel == true

## There is no core module to create a samba user at the moment
## so we use a shell command with encypted variables sambaname and sambapassword

- name: Create nickel Samba user
  shell: >
    (pdbedit -L | grep {{ sambaname }} 2>&1 > /dev/null) 
    || (echo {{ sambapassword }}; echo {{ sambapassword }}) 
    | smbpasswd -s -a {{ sambaname }}
  when: samba_nickel == true

#### Configure a couple of sebool selinux parameters to get them working

- name: Set seboolean for selinux so ftp and cifs works
  seboolean:
    name: "{{ item }}"
    state: yes
    persistent: yes
  with_items:
   - ftpd_full_access
   - samba_export_all_rw
  when: samba_nickel == true or ftp_nickel == true

#### Here we are going to configure the storage driver to use lvm when: docker_storage variable is set to true
### first we use the shell to check if storage is allready configure, we store the info using register in stor_driver var

- name: Check if the storage driver is allready configured
  shell: grep storage-driver /etc/sysconfig/docker-storage
  ignore_errors: yes
  register: stor_driver
  when: docker_storage == true

### If the storage driver is not configured, we stop the daemon

- name: Stop the docker daemon
  service: name=docker state=stopped
  when: docker_storage == true and stor_driver.rc > 0 

## and clean all the docker config

- name: Delete docker dir
  file:
    path: /var/lib/docker
    state: absent
  when: docker_storage == true and stor_driver.rc > 0

#### We apply our vars to the config file(disk to use, vg name)

- name: Apply variables to Docker storage config
  template: src=docker-storage-setup.j2 dest=/usr/lib/docker-storage-setup/docker-storage-setup
  when: docker_storage == true and stor_driver.rc > 0
### here the handler runs the docker-storage-setup command to set it up 
  notify:
  - Apply conf

####finally we start docjer again
- name: Start the docker daemon
  service: name=docker state=started enabled=yes

#### Now that we have the software and the services configured, let's get our wrapper scripts
#### We log into gitlab with variables in the vault encrypted vars file
- name: Log into gitlab
  docker_login:
    registry: registry.gitlab.com
    username: "{{ gitlabuser }}"
    password: "{{ gitlabpassword }}"
    reauthorize: yes

### We also pull the latest nickel_tool app image
- name: Pull image
  docker_image:
    state: present
    name:  registry.gitlab.com/liquidsmail/nickel_tool
    tag: latest

### We add the wrapper script to cron, so it will run every minute to check if there are new bundles in the app fs

- name: Add the check nickel wrapper to cron
  cron:
    name: "Add the check nickel wrapper to cron"
    job: "/usr/local/bin/nickel/check-files.sh"
    user: root

### This is the of the tasks file for redhat based systems.


these are the template files with the variables, nothing new here:

[liquid@liquid-ibm:nickel_tool_git/nickel-tool-ansible]$ cat roles/nickel_tool/templates/docker-storage-setup.j2 | grep -vE '(^#|^$)'                                                    (12-16 14:52)
STORAGE_DRIVER=devicemapper
DEVS={{ disk_name }} 
VG={{ vg_name }}
DATA_SIZE=40%FREE
MIN_DATA_SIZE=2G
CHUNK_SIZE=512K
GROWPART=false
AUTO_EXTEND_POOL=yes
POOL_AUTOEXTEND_THRESHOLD=60
POOL_AUTOEXTEND_PERCENT=20
DEVICE_WAIT_TIMEOUT=60
WIPE_SIGNATURES=false

[liquid@liquid-ibm:nickel_tool_git/nickel-tool-ansible]$ cat roles/nickel_tool/templates/smb.j2 | grep -vE '(^#|^$)'                                                                     (12-16 14:52)
[global]
   workgroup = WORKGROUP
   server string = %h server (Samba, Ubuntu)
   dns proxy = no
   log file = /var/log/samba/log.%m
   max log size = 1000
   syslog = 0
   panic action = /usr/share/samba/panic-action %d
   server role = standalone server
   passdb backend = tdbsam
   obey pam restrictions = yes
   unix password sync = yes
   passwd program = /usr/bin/passwd %u
   passwd chat = *Entersnews*spassword:* %nn *Retypesnews*spassword:* %nn *passwordsupdatedssuccessfully* .
   pam password change = yes
   map to guest = bad user
   usershare allow guests = yes
[CheckNickel]
   comment = Check-Nickel Tool Share
   browseable = yes
   path = {{ docker_input_nickel }}
   printable = no
   guest ok = no
   read only = no
   create mask = 0770
   write list = root, nickel

[liquid@liquid-ibm:nickel_tool_git/nickel-tool-ansible]$ cat roles/nickel_tool/templates/vsftpd.j2 | grep -vE '(^#|^$)'                                                                  (12-16 14:53)
listen=YES
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
dirmessage_enable=YES
use_localtime=YES
xferlog_enable=YES
connect_from_port_20=YES
ascii_download_enable=YES
pam_service_name=vsftpd
rsa_cert_file=/etc/ssl/certs/ssl-cert-snakeoil.pem
rsa_private_key_file=/etc/ssl/private/ssl-cert-snakeoil.key
pasv_enable=Yes
pasv_max_port=10100
pasv_min_port=10090


Here are the handler filesi,nothing speciall here:

[liquid@liquid-ibm:roles/nickel_tool]$ cat handlers/main.yml                                                                                                                             (12-16 14:55)
---
- name: Include Redhat Based distributions install
  include: redhat.yml
  when: ansible_os_family == "RedHat" 
- name: Include Debian Based distributions install
  include: debian.yml
  when: ansible_os_family == "Debian"
[liquid@liquid-ibm:roles/nickel_tool]$ cat handlers/redhat.yml                                                                                                                           (12-16 14:55)
---
- name: Apply conf 
  shell: /usr/bin/docker-storage-setup

- name: restar docker
  service: name=docker state=restarted

- name: Restart Samba
  service: name={{ item }} state=restarted
  with_items:
  - smb
  - nmb

- name: Restart Vsftp
  service: name=vsftpd state=restarted 


And finally to the vars vault encrypted file, to access and read edit the file we need to use ansible-vault:

[liquid@liquid-ibm:roles/nickel_tool]$ ansible-vault view vars/main.yml                                                                                                                  (12-16 14:59)
Vault password: 
---                                                                                     
#gitlab:
gitlabuser: XXXXXX
gitlabpassword: XXXXXX
#Samba config:
sambaname: XXXXXXX
sambapassword: XXXXX
#OS user passwd nickel
nickel_user_pass: XXXXXX

Quick commands to create a vault encrypted file, we have to create a new file, and the copy our contents to the file:

[liquid@liquid-ibm:roles/nickel_tool]$ ansible-vault create vaultfile.yml                                                                                                                (12-16 15:00)
New Vault password: 
Confirm New Vault password: 

We then paste out vars:

---
#gitlab:
gitlabuser: XXXXXX
gitlabpassword: XXXXXX
#Samba config:
sambaname: XXXXXXX
sambapassword: XXXXX
#OS user passwd nickel
nickel_user_pass: XXXXXX

And save the file.

We can in the future edit the file with:

[liquid@liquid-ibm:roles/nickel_tool]$ ansible-vault edit vaultfile.yml                                                                                                                  (12-16 15:02)
Vault password: 



I am also going to leave here the debian taks file without comments, because it does the same things than the redhat yaml tasks but in a ubuntu way:

---

- name: Create the nickel tool user in the OS
  user:
    name: nickel
    comment: "nickel user for nickel tool"
    group: adm
    shell: /bin/bash
    home: "{{ docker_input_nickel }}"

- name: Create a passwd for the nickel user
  shell: echo "nickel:{{ nickel_user_pass }}" | /usr/sbin/chpasswd


- name: Create dirs to work on
  file: path={{ item }} state=directory owner=nickel group=adm 
  with_items:
     - "{{ docker_work_nickel }}"
     - "{{ docker_input_nickel }}"
     - "{{ docker_history_nickel }}"

- name: Mount tmpfs if option selected
  mount: name={{ docker_work_nickel }}  src=tmpfs fstype=tmpfs state=mounted opts=size={{ tmpfs_size }}
  when: use_tmpfs_workdir == true


- name: Install Software for Nickel-Tool
  apt:
        update_cache: yes
        state: latest
        name: "{{ item }}"
        cache_valid_time: 3600
  with_items:
   - python-pip
   - docker.io
   - git
   - net-tools
   - psmisc
   - zip
   - unzip
   - samba
   - vsftpd

- name: Pip install docker-py
  pip: name=docker-py


- name: Get updated files from git repository
  git: repo=https://{{ gitlabuser }}:{{ gitlabpassword }}@gitlab.com/liquidsmail/nickel_tool.git dest=/usr/local/bin/nickel force=yes
  register: git_deploy
  until: git_deploy|succeeded

- name: replace wrapper scripts with input dirs
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^INPUTDIR=.*' line=INPUTDIR={{ docker_input_nickel }}

- name: replace wrapper scripts with work dirs
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^WORKDIR=.*' line=WORKDIR={{ docker_work_nickel }}

- name: replace wrapper scripts public IP
  lineinfile: dest=/usr/local/bin/nickel/check-files.sh regexp='^IPPUBSUB=.*' line=IPPUBSUB={{ public_ip_nickel }}

- name: Configure CIFS server
  template: src=smb.j2 dest=/etc/samba/smb.conf validate='testparm -s %s'
  notify:
  - Restart Samba
  when: samba_nickel == true

- name: Start and enable Samba
  service: name={{ item }} state=started enabled=yes
  with_items:
  - smbd
  - nmbd
  when: samba_nickel == true

- name: Check if iptables is configured 
  shell: ufw status | grep active
  ignore_errors: yes
  register: iptables_status

- name: Add tcp iptables rules for samba
  ufw:
        rule: allow
        port: '139'
        proto: tcp
  when: iptables_status.rc == 0 and samba_nickel == true

- name: Add tcp iptables rules for samba
  ufw:
        rule: allow
        port: '445'
        proto: tcp
  when: iptables_status.rc == 0 and samba_nickel == true


- name: Add udp iptables rules for samba
  ufw:
        rule: allow
        port: '137:138'
        proto: udp
  when: iptables_status.rc == 0 and samba_nickel == true

- name: Add tcp iptables rules for ftp data
  ufw:
        rule: allow
        port: "20:21"
        proto: tcp
  when: iptables_status.rc == 0 and ftp_nickel == true

- name: Add tcp iptables rules for ftp passive
  ufw:
        rule: allow
        port: "10090:10100"
        proto: tcp
  when: iptables_status.rc == 0 and ftp_nickel == true

   
- name: start and enable Vsftp
  service: name=vsftpd state=started enabled=yes
  when: ftp_nickel == true

- name: Configure ftp server
  template: src=vsftpd.j2 dest=/etc/vsftpd.conf
  notify:
  - Restart Vsftp
  when: ftp_nickel == true

- name: Create nickel Samba user
  shell: >
    (pdbedit -L | grep {{ sambaname }} 2>&1 > /dev/null) 
    || (echo {{ sambapassword }}; echo {{ sambapassword }}) 
    | smbpasswd -s -a {{ sambaname }}
  when: samba_nickel == true


- name: Start the docker daemon
  service: name=docker state=started enabled=yes

- name: Log into gitlab
  docker_login:
    registry: registry.gitlab.com
    username: "{{ gitlabuser }}"
    password: "{{ gitlabpassword }}"
    reauthorize: yes

- name: Pull image
  docker_image:
    state: present
    name:  registry.gitlab.com/liquidsmail/nickel_tool
    tag: latest

- name: Add the check nickel wrapper to cron
  cron:
    name: "Add the check nickel wrapper to cron"
    job: "/usr/local/bin/nickel/check-files.sh"
    user: root

As we said all the tasks that are common to both OSes should be put in another common.yml file. Will have it in the next post

Unix Systems: 

Add new comment

Filtered HTML

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <blockquote> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.
By submitting this form, you accept the Mollom privacy policy.
Error | HP-UX Tips & Tricks Site

Error

Error message

  • Warning: Cannot modify header information - headers already sent by (output started at /homepages/37/d228974590/htdocs/includes/common.inc:2567) in drupal_send_headers() (line 1207 of /homepages/37/d228974590/htdocs/includes/bootstrap.inc).
  • PDOException: SQLSTATE[42000]: Syntax error or access violation: 1142 INSERT command denied to user 'dbo229817041'@'217.160.155.192' for table 'watchdog': INSERT INTO {watchdog} (uid, type, message, variables, severity, link, location, referer, hostname, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2, :db_insert_placeholder_3, :db_insert_placeholder_4, :db_insert_placeholder_5, :db_insert_placeholder_6, :db_insert_placeholder_7, :db_insert_placeholder_8, :db_insert_placeholder_9); Array ( [:db_insert_placeholder_0] => 0 [:db_insert_placeholder_1] => cron [:db_insert_placeholder_2] => Attempting to re-run cron while it is already running. [:db_insert_placeholder_3] => a:0:{} [:db_insert_placeholder_4] => 4 [:db_insert_placeholder_5] => [:db_insert_placeholder_6] => http://hpuxtips.es/?q=content/ansible-basics-example-configure-and-deploy-application [:db_insert_placeholder_7] => [:db_insert_placeholder_8] => 54.92.142.198 [:db_insert_placeholder_9] => 1502962267 ) in dblog_watchdog() (line 157 of /homepages/37/d228974590/htdocs/modules/dblog/dblog.module).
The website encountered an unexpected error. Please try again later.