You are here

Ansible Basics Continued. Lamp config with php test app cloned from git for latest version

Just to finish off this series, we are going to configure php in the webserver role, add a very very basic php app, that does a connection to the DB and inserts to a table the hostname and ip of the webserver that runs the request. The PHP app will get downloaded from git each time we run the play.

Here is the git repo with all the files that we work with:

https://github.com/likid0/AnsibleSeries.git

Ok, so first of all, lets add the php software config to the webserver role tasks:

[liquid@liquid-ibm:ansible/roles]$ tree webserver                                                                                                                                        (10-16 02:41)
webserver
├── handlers
│   └── main.yaml
├── tasks
│   └── main.yaml
├── templates
│   ├── httpd.j2
│   ├── index.php.j2
│   └── README.md
└── vars
    ├── db.yaml -> /home/liquid/vagrant/ansible/ansible/roles/dbserver/vars/main.yaml
    └── main.yaml

4 directories, 7 files
[liquid@liquid-ibm:ansible/roles]$ cat webserver/tasks/main.yaml                                                                                                                         (10-16 02:42)
---


#here we have included a db.yaml file with all the db variables we need for our APP:
- include_vars: "db.yaml"
#here we have added the php php-mysql and git software
- name: Ensure HTTPD is installed
  yum:  name={{ item }} state=latest
  with_items: 
     - httpd
     - php
     - php-mysql
     - git

- name: Start HTTPD and enable on boot
  service: name=httpd enabled=yes state=started

- name: Deploy config httpd
  template: src=httpd.j2 dest=/etc/httpd/conf/httpd.conf
  notify:
    - Restart Apache

- name: Check if doc_root exists
  stat: path={{doc_root}}
  register: check_path

- name: Create doc_root if it doesn't exist
  file: path={{doc_root}} state=directory
  when: check_path.stat.exists == false

#here we are adding our php app instead of the index.html
- name: Insert custom index.php in host
  template: src=index.php.j2 dest={{doc_root}}/index.php

- name: Open webserver ports in iptables
  iptables: action=insert chain=INPUT source=0.0.0.0/0 ctstate=NEW state=present protocol=tcp match=tcp destination_port=80 jump=ACCEPT

thats all from the tasks.

In the templates, we have the apache httpd conf file:

[liquid@liquid-ibm:ansible/roles]$ cat webserver/templates/httpd.j2                                                                                                                      (10-16 02:44)
ServerRoot "/etc/httpd"                                            
Listen {{ http_port }}
Include conf.modules.d/*.conf
User {{ http_user }}
Group apache
#ServerName www.example.com:80

    AllowOverride none
    Require all denied

DocumentRoot {{ doc_root }}

    AllowOverride None
    # Allow open access:
    Require all granted

    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted


# we have modified the DirectoryIndex so if a index.php file is found its read first


    DirectoryIndex index.php index.html


ErrorLog "logs/error_log"

LogLevel warn



    Alias {{ doc_dir }} {{ doc_root }}
    ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"

    AllowOverride None
    Options None
    Require all granted

    TypesConfig /etc/mime.types
    AddType application/x-compress .Z
    AddType application/x-gzip .gz .tgz
    AddType text/html .shtml
    AddOutputFilter INCLUDES .shtml


AddDefaultCharset UTF-8


    MIMEMagicFile conf/magic


# We added this part for php


    SetHandler application/x-httpd-php


EnableSendfile on
IncludeOptional conf.d/*.conf


The other template file is our actual app, here is the code, the finest coding you have ever seen.

Ass we sed before it creates a table called Hosts, and does and insert of hostname,ip and distro from the current web server, then it prints a select of the hole Hosts table.

[liquid@liquid-ibm:ansible/roles]$ cat webserver/templates/index.php.j2                                                                                                                  (10-16 02:45)

Ansible LAMP application Test. Server IP: {{ansible_default_ipv4['address']}} hostname: {{ansible_hostname}} Distro: {{ansible_distribution}}

connect_error) { die("Connection failed: " . $conn->connect_error); } $sql = "CREATE TABLE Hosts ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, hostname VARCHAR(30) NOT NULL, ip VARCHAR(30) NOT NULL, distro VARCHAR(50), reg_date TIMESTAMP )"; if ($conn->query($sql) === TRUE) { echo "Table MyGuests created successfully"; } else { echo "Error creating table: " . $conn->error; } $sql = "INSERT INTO Hosts (hostname, ip, distro) VALUES ('{{ ansible_hostname }}', '{{ ansible_default_ipv4['address'] }}', '{{ ansible_distribution }}')"; if ($conn->query($sql) === TRUE) { echo "New record created successfullyi \n"; } else { echo "Error: " . $sql . "
" . $conn->error; } $sql = "SELECT id, hostname, ip, distro FROM Hosts"; $result = $conn->query($sql); if ($result->num_rows > 0) { // output data of each row while($row = $result->fetch_assoc()) { echo " id: " . $row["id"]. " - Name: " . $row["hostname"]. " " . $row["ip"]. " " . $row["distro"]. "
"; } } else { echo "0 results"; } Ok, now lets go to the vars section: Nothing new here: [liquid@liquid-ibm:ansible/roles]$ cat webserver/vars/main.yaml (10-16 02:49) --- http_port: 80 http_user: apache doc_dir: /ansible doc_root: /var/www/html/ansible The db.yaml file is a symbolic link to the dbserver role main.yaml vars file, it contains all the database vars quid@liquid-ibm:ansible/roles]$ cat webserver/vars/db.yaml (10-16 02:51) --- mysql_port: '3306' root_db_pass: 'rootpass' db: 'lampdb' db_test: 'testdb' dbuser: 'lampuser' dbupass: 'userpass' dbhost: 'db1' mysql_log: '/var/log/mysql' mysql_run: '/var/run/mysqld' mysql_var: '/var/lib/mysql' [liquid@liquid-ibm:ansible/roles]$ ls -l webserver/vars/ (10-16 02:51) total 4 lrwxrwxrwx 1 liquid liquid 66 Oct 16 00:10 db.yaml -> /home/liquid/vagrant/ansible/ansible/roles/dbserver/vars/main.yaml -rw-rw-r-- 1 liquid liquid 138 Oct 16 02:18 main.yaml Ok so with this config we have php configured and our supper APP ready, but there is and issue, if you check out the vars i'm using: dbhost: 'db1' to use the hostname I need to have the name resolved, So I'm going to create a dynamic /etc/hosts file, to get basic nameresolution working: I'm going to add another file to our tasks dir in the server_basic called hosts.yaml: [liquid@liquid-ibm:ansible/roles]$ tree server_basic (10-16 02:55) server_basic ├── handlers │   └── main.yaml ├── tasks │   ├── hosts.yaml │   ├── iptables.yaml │   ├── main.yaml │   ├── ntp.yaml │   ├── selinux.yaml │   └── update-soft.yaml ├── templates │   ├── hosts.j2 │   └── ntp.j2 └── vars ├── Debian.yaml ├── main.yaml └── RedHat.yaml I add the include in the main.yaml [liquid@liquid-ibm:ansible/roles]$ cat server_basic/tasks/main.yaml (10-16 02:55) --- - include_vars: "{{ ansible_os_family }}.yaml" - include: update-soft.yaml - include: iptables.yaml - include: ntp.yaml - include: selinux.yaml - include: hosts.yaml [liquid@liquid-ibm:ansible/roles]$ cat server_basic/tasks/hosts.yaml (10-16 02:56) --- - name: "generate /etc/hosts file" template: "src=hosts.j2 dest='/etc/hosts' owner=root group=root mode=0644" And here is the template: [liquid@liquid-ibm:ansible/roles]$ cat server_basic/templates/hosts.j2 (10-16 02:57) # {{ ansible_managed }} 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback # The following lines are desirable for IPv6 capable hosts. fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters # This loops all the dc-madrid group hosts, and gets the ip of eth2 {% for host in groups['dc-madrid'] %} {% if 'ansible_eth2' in hostvars[host] %} {{ hostvars[host]['ansible_eth2']['ipv4']['address'] }} {{ host }} {% endif %} {% endfor %} Ok, so we have the hosts file also ready. On the other hand I wan't to allways have the latest version of my app deployed when the playbook is run, my app is on github, and I want to checkout the app each time I run the playbook. So I'm creating a very basic role to checkout the latest version in github of the app and that is run on localhost: [liquid@liquid-ibm:ansible/roles]$ tree git-app (10-16 03:02) git-app ├── tasks │   └── main.yaml └── vars └── main.yaml 2 directories, 2 files [liquid@liquid-ibm:ansible/roles]$ cat git-app/tasks/main.yaml (10-16 03:02) --- - name: Copy the code from repository git: repo={{ repository }} dest=/home/liquid/vagrant/ansible/ansible/roles/webserver/templates/ [liquid@liquid-ibm:ansible/roles]$ cat git-app/vars/main.yaml (10-16 03:02) --- repository: https://github.com/likid0/lamptest.git As you can see the only thing I do is clone the git repo into my webserver role templates, were I have my app template index.php.j2, this way I'm sure I have the latest version. To make this work I have to modify the inventory file, I add the local group with the localhost host and using ansible_connection=local for localhost connections. [liquid@liquid-ibm:ansible/ansible]$ cat inventory (10-16 03:06) [web] web1 ansible_ssh_host=10.0.1.5 web2 ansible_ssh_host=10.0.2.5 web3 ansible_ssh_host=10.0.5.5 [lb] lb1 ansible_ssh_host=10.0.3.5 [db] db1 ansible_ssh_host=10.0.4.5 [local] localhost ansible_connection=local ansible_user=liquid [dc1-madrid:children] web lb [dc2-madrid:children] db [dc-madrid:children] dc1-madrid dc2-madrid [dc-madrid:vars] ansible_ssh_user=vagrant Another thing I need to modify is my site.yaml file, I have created a new play with the server_basic role for all hosts(dc-madrid group) This way the for loop with the hosts file works ok. And I have included another play for the git-app role. [liquid@liquid-ibm:ansible/ansible]$ cat site.yaml (10-16 03:07) --- - hosts: dc-madrid become: yes gather_facts: yes roles: - server_basic tags: - basic - hosts: local become: yes gather_facts: no roles: - git-app tags: - update-app - hosts: web become: yes gather_facts: yes roles: - webserver tags: - web - hosts: db become: yes gather_facts: yes roles: - dbserver tags: - db - hosts: lb become: yes gather_facts: yes roles: - load_balancer tags: - lb Ok, so we have all the work done, lets try it out: [liquid@liquid-ibm:ansible/ansible]$ ansible-playbook site.yaml (10-16 02:38) PLAY [dc-madrid] *************************************************************** TASK [setup] ******************************************************************* ok: [web3] ok: [web2] ok: [db1] ok: [web1] ok: [lb1] TASK [server_basic : include_vars] ********************************************* ok: [web1] ok: [web3] ok: [web2] ok: [db1] ok: [lb1] TASK [server_basic : Update-software on node] ********************************** skipping: [lb1] ok: [web2] ok: [db1] ok: [web1] ok: [web3] TASK [server_basic : update apt cache] ***************************************** skipping: [web1] skipping: [web3] skipping: [web2] skipping: [db1] ok: [lb1] TASK [server_basic : Update all packages on node] ****************************** skipping: [web1] skipping: [web2] skipping: [web3] skipping: [db1] ok: [lb1] TASK [server_basic : Ensure Iptables is installed] ***************************** skipping: [web1] skipping: [web3] skipping: [web2] skipping: [db1] ok: [lb1] TASK [server_basic : Disable firewall ufw] ************************************* skipping: [web1] skipping: [web2] skipping: [web3] skipping: [db1] ok: [lb1] TASK [server_basic : Ensure Iptables is installed] ***************************** skipping: [lb1] ok: [web3] ok: [web1] ok: [db1] ok: [web2] TASK [server_basic : Ensure iptables-services is installed] ******************** skipping: [lb1] ok: [web1] ok: [web3] ok: [web2] ok: [db1] TASK [server_basic : disable firewalld] **************************************** skipping: [lb1] ok: [db1] ok: [web2] ok: [web1] ok: [web3] TASK [server_basic : Start iptables service] *********************************** skipping: [lb1] changed: [web3] changed: [web1] changed: [web2] changed: [db1] TASK [server_basic : Check if ntp is installed and updated] ******************** skipping: [lb1] ok: [web1] ok: [web2] ok: [web3] ok: [db1] TASK [server_basic : Check if ntp is installed and updated] ******************** skipping: [web3] skipping: [web1] skipping: [web2] skipping: [db1] ok: [lb1] TASK [server_basic : Configure the ntp daemon with a template] ***************** ok: [lb1] ok: [web1] ok: [web3] ok: [db1] ok: [web2] TASK [server_basic : disable selinux] ****************************************** skipping: [lb1] ok: [db1] ok: [web3] ok: [web1] ok: [web2] TASK [server_basic : generate /etc/hosts file] ********************************* ok: [lb1] ok: [db1] ok: [web1] ok: [web3] ok: [web2] PLAY [local] ******************************************************************* TASK [git-app : Copy the code from repository] ********************************* ok: [localhost] PLAY [web] ********************************************************************* TASK [setup] ******************************************************************* ok: [web3] ok: [web1] ok: [web2] TASK [webserver : include_vars] ************************************************ ok: [web1] ok: [web2] ok: [web3] TASK [webserver : Ensure HTTPD is installed] *********************************** ok: [web2] => (item=[u'httpd', u'php', u'php-mysql', u'git']) ok: [web3] => (item=[u'httpd', u'php', u'php-mysql', u'git']) ok: [web1] => (item=[u'httpd', u'php', u'php-mysql', u'git']) TASK [webserver : Start HTTPD and enable on boot] ****************************** ok: [web2] ok: [web3] ok: [web1] TASK [webserver : Deploy config httpd] ***************************************** ok: [web3] ok: [web2] ok: [web1] TASK [webserver : Check if doc_root exists] ************************************ ok: [web1] ok: [web3] ok: [web2] TASK [webserver : Create doc_root if it doesn't exist] ************************* skipping: [web3] skipping: [web1] skipping: [web2] TASK [webserver : Insert custom index.html in host] **************************** ok: [web2] ok: [web1] ok: [web3] TASK [webserver : Open webserver ports in iptables] **************************** changed: [web3] changed: [web1] changed: [web2] PLAY [db] ********************************************************************** TASK [setup] ******************************************************************* ok: [db1] TASK [dbserver : Install Mysql package] **************************************** ok: [db1] => (item=[u'mariadb-server', u'MySQL-python']) TASK [dbserver : Check if needed dirs for mariadb exist] *********************** ok: [db1] TASK [dbserver : Create logs dir for mariadb if it doesn't exist] ************** skipping: [db1] TASK [dbserver : Check if needed dirs for mariadb exist] *********************** ok: [db1] TASK [dbserver : Create run dir for mariadb if it doesn't exist] *************** skipping: [db1] TASK [dbserver : Check if needed dirs for mariadb exist] *********************** ok: [db1] TASK [dbserver : Create run var/lib for mariadb if it doesn't exist] *********** skipping: [db1] TASK [dbserver : Configure Mysql template] ************************************* ok: [db1] TASK [dbserver : Start Mysql and enable on boot] ******************************* ok: [db1] TASK [dbserver : ensure anonymous users are not in the database] *************** ok: [db1] => (item=localhost) ok: [db1] => (item=db1) TASK [dbserver : remove the test database] ************************************* ok: [db1] TASK [dbserver : update mysql root password for all root accounts] ************* ok: [db1] => (item=db1) ok: [db1] => (item=127.0.0.1) ok: [db1] => (item=::1) ok: [db1] => (item=localhost) TASK [dbserver : copy .my.cnf file with root password credentials] ************* ok: [db1] TASK [dbserver : open iptables 3306 port for mysql] **************************** changed: [db1] TASK [dbserver : Test that port 3306 is open, and the continue] **************** ok: [db1] TASK [dbserver : Drop test Database just in case it existed before] ************ ok: [db1] TASK [dbserver : Create test Database] ***************************************** changed: [db1] TASK [dbserver : copy mysql test dump to userdb database] ********************** ok: [db1] TASK [dbserver : import test dump to userdb test database] ********************* changed: [db1] TASK [dbserver : Create Application DB User] *********************************** changed: [db1] TASK [dbserver : Query the test DB to check the import worked ok] ************** changed: [db1] TASK [dbserver : delete the test database] ************************************* changed: [db1] TASK [dbserver : Create Application Database] ********************************** changed: [db1] TASK [dbserver : Add access to dbuser to lamp database] ************************ changed: [db1] PLAY [lb] ********************************************************************** TASK [setup] ******************************************************************* ok: [lb1] TASK [load_balancer : install haproxy] ***************************************** ok: [lb1] TASK [load_balancer : Enable init script] ************************************** ok: [lb1] TASK [load_balancer : Update HAProxy config] *********************************** ok: [lb1] TASK [load_balancer : haproxy service running and enabled] ********************* ok: [lb1] PLAY RECAP ********************************************************************* db1 : ok=33 changed=9 unreachable=0 failed=0 lb1 : ok=14 changed=0 unreachable=0 failed=0 localhost : ok=1 changed=0 unreachable=0 failed=0 web1 : ok=19 changed=2 unreachable=0 failed=0 web2 : ok=19 changed=2 unreachable=0 failed=0 web3 : ok=19 changed=2 unreachable=0 failed=0 Ok, lets check our hosts file: [liquid@liquid-ibm:ansible/ansible]$ ansible lb1 -a "cat /etc/hosts" --become (10-16 03:14) lb1 | SUCCESS | rc=0 >> # Ansible managed: /home/liquid/vagrant/ansible/ansible/roles/server_basic/templates/hosts.j2 modified on 2016-10-16 01:36:30 by liquid on liquid-ibm 127.0.0.1 localhost ::1 localhost ip6-localhost ip6-loopback # The following lines are desirable for IPv6 capable hosts. fe00::0 ip6-localnet ff00::0 ip6-mcastprefix ff02::1 ip6-allnodes ff02::2 ip6-allrouters # Network nodes as generated through Ansible. 10.0.1.5 web1 10.0.2.5 web2 10.0.5.5 web3 10.0.3.5 lb1 10.0.4.5 db1 Lets check if the DB is there: [liquid@liquid-ibm:ansible/ansible]$ ansible db1 -a "mysql -e 'show databases'" --become | grep lamp (10-16 03:16) lampdb Ok, lets check the App is working: [liquid@liquid-ibm:ansible/ansible]$ curl http://10.0.3.5 (10-16 03:16)

Ansible LAMP application Test. Server IP: 192.168.121.149 hostname: web3 Distro: CentOS

id: 1 - Name: web3 192.168.121.149 CentOS
% [liquid@liquid-ibm:ansible/ansible]$ curl http://10.0.3.5 (10-16 03:17)

Ansible LAMP application Test. Server IP: 192.168.121.158 hostname: web2 Distro: CentOS

id: 1 - Name: web3 192.168.121.149 CentOS
id: 2 - Name: web2 192.168.121.158 CentOS
% [liquid@liquid-ibm:ansible/ansible]$ curl http://10.0.3.5 (10-16 03:17)

Ansible LAMP application Test. Server IP: 192.168.121.52 hostname: web1 Distro: CentOS

id: 1 - Name: web3 192.168.121.149 CentOS
id: 2 - Name: web2 192.168.121.158 CentOS
id: 3 - Name: web1 192.168.121.52 CentOS
% The app is working ok, as you can see each time we access the php it inserts a row into the table, we have the 3 ips of our webservers [liquid@liquid-ibm:~/Docker-Ansible-courses]$
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-continued-lamp-config-php-test-app-cloned-git-latest-version [:db_insert_placeholder_7] => [:db_insert_placeholder_8] => 54.162.3.15 [:db_insert_placeholder_9] => 1503350898 ) in dblog_watchdog() (line 157 of /homepages/37/d228974590/htdocs/modules/dblog/dblog.module).
The website encountered an unexpected error. Please try again later.