0

I have a host with 2 servers: one has CentOS and the other Ubuntu installed.

I decided to install apache, nginx and php-fpm on both servers and wrote 3 playbooks.

  1. ubuntu.yml (/home/ansible/playbook):
---
- name: Ubuntu Playbook
  hosts: ubun
  become: true
  vars:
   - packages:
     - nginx
     - apache2
     - php-fpm 
  tasks:
   - name: Update apt package
   apt:
   name: "*"
   state: latest
   update_cache: yes
   - name: Install Packages
     apt:
       pkg: "{{ packages }}"
       state: latest
       update_cache: yes
   - name: Apache Service Start
     service:
       name: nginx
       state: restarted
       enabled: yes
  1. centos.yml (/home/ansible/playbook):
---
- name: CentOS Playbook
  hosts: cent
  become: true
  vars:
   packages:
   - epel-release
   - httpd
   - nginx
   - php-fpm
  tasks:
   - name: Update yum package
     yum:
       name: "*"
       state: latest
       update_cache: yes
   - name: Install Packages
     yum:
       name: "{{ packages }}"
       state: latest
       update_cache: yes
   - name: Apache Service Start
     service:
       name: nginx
       state: restarted
       enabled: yes
  1. base.yml (/home/ansible/playbook):
---
- name: Base Playbook
  hosts: aws
  become: true
  tasks:
    - name: Performing Tasks for CentOS
      when: ansible_facts['distribution'] == 'CentOS'
      include_tasks: centos.yml
    - name: Performing Tasks for Ubuntu
      when: ansible_facts['distribution'] == 'Ubuntu'
      include_tasks: ubuntu.yml

My 3 Ansible groups are:

  • [aws] which contains both the server

  • [cent] which contains CentOS server

  • [ubun] which contains Ubuntu server

I tried dry running centos.yml and ubuntu.yml separately and it worked, but when I try dry running base.yml the following error is raised:

    FAILED! => {"reason": "unexpected parameter type in action: <class 'ansible.parsing.yaml.objects.AnsibleSequence'>\n\nThe error appears to be in '/home/ansible/playbook/centos.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n---\n- name: CentOS Playbook\n  ^ here\n"}

    FAILED! => {"reason": "unexpected parameter type in action: <class 'ansible.parsing.yaml.objects.AnsibleSequence'>\n\nThe error appears to be in '/home/ansible/playbook/ubuntu.yml': line 2, column 3, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n---\n- name: Ubuntu Playbook\n  ^ here\n"}

I already tried replacing import_tasks with include_tasks but I get the same error.

creyD
  • 160
  • 5
  • you are no including tasks, but playbooks, in your tasks files you don't need hosts and so on, you need to provide the list of all hosts in the main playbook The main playbook will take care to install the packages based on the OS. – c4f4t0r Jan 27 '20 at 12:51
  • @c4f4t0r Thanks for your suggestion. As you said i have removed host, become and name. just kept vars and tasks. After that if i execute the main playbook it shows the following error: **FAILED! => {"reason": "included task files must contain a list of tasks"}** Pls Help – Subramanian Lakshmanan Jan 27 '20 at 14:06

2 Answers2

3

Its' better if you take a role as example, here you have the fixed code:

---

- hosts: aws
  remote_user: myuser
  become: true
  tasks:
  - name: Performing Tasks for CentOS
    include_tasks: centos.yml
    when: ansible_facts['distribution'] == 'CentOS'
  - name: Performing Tasks for Ubuntu
    include_tasks: ubuntu.yml
    when: ansible_facts['distribution'] == 'Ubuntu'

centos.yml tasks:

---

- name: installing httpd
  yum: pkg=httpd state=present

ubuntu.yml tasks:


- name: installing apache2
  apt: pkg=apache2 state=present

In the tasks files, you only need the tasks, without hosts,tasks and so on.

c4f4t0r
  • 5,301
  • 3
  • 31
  • 42
1

My solution is to merge these into one play, as they do the same thing.

---
- name: php-fpm play
  hosts: aws
  become: true
  vars:
  - repo:
      Debian:
      - apt # already installed, but need something here
      RedHat:
      - epel-release
  - packages:
      Debian:
      - apache2
      #- nginx # cannot have 2 listening on port 80
      - php-fpm
      RedHat:
      - httpd
      #- nginx
      - php-fpm
  - services:
      Debian: apache2
      RedHat: httpd

  tasks:
     # TODO move update * task to different play

   - name: Install repo
     # Seperate package transaction for EPEL
     # so it is available in the next task
     package:
       name: "{{ repo[ansible_os_family] }}"

   - name: Install Web Server Packages
     # Keyed by OS family fact to also support RHEL and Debian
     package:
       name: "{{ packages[ansible_os_family] }}"
       state: latest

   - name: Web Service Start
     service:
       name: "{{ services[ansible_os_family] }}"
       state: restarted
       enabled: yes

Can't have multiple servers listening on ports 80 and 443. I commented out nginx, as a task was mislabeled "Apache Service Start". If you want one of these proxying for the other or something, you will need to deploy a config file to change the ports.

Used the package: action which delegates to actual package manager. Enables a package install task to run on different OSes. Can't do update_cache that way, but yum doesn't need it when adding repos like apt does.

Vars structure is dicts of OS family specific values. This enables the package and service names to be indexed by facts. OS family, so this also works on RHEL and Debian in addition to CentOS and Ubuntu.

Indentation was wrong. Modules parameters need to be indented a level below task level directives like name:.

Can't include_tasks an entire play, that only works with import_playbook. include_tasks is easier when you have roles, which have a tasks directory for such files. (Play level tasks are a thing, but I am in favor of roles doing everything.)


There still is more work to make this useful.

When you need to use template to install configuration, EL puts configs in /etc/httpd/, while Debian is in /etc/apache2/.

Plenty of web server roles are open sourced, to look at if you want ideas. Check Galaxy.

Consider moving your tasks to roles, enables reuse.

John Mahowald
  • 32,050
  • 2
  • 19
  • 34