Update: Ab Ansible 2.0 gibt es jetzt ein generisches & abstrahiertes package
Modul
Anwendungsbeispiele:
Wenn der Paketname für verschiedene Betriebssystemfamilien gleich ist, ist dies so einfach wie folgt:
---
- name: Install foo
package: name=foo state=latest
Wenn sich der Paketname in den Betriebssystemfamilien unterscheidet, können Sie ihn mit verteilungs- oder betriebssystemfamilienspezifischen vars-Dateien verarbeiten:
---
# roles/apache/apache.yml: Tasks entry point for 'apache' role. Called by main.yml
# Load a variable file based on the OS type, or a default if not found.
- include_vars: "{{ item }}"
with_first_found:
- "../vars/{{ ansible_distribution }}-{{ ansible_distribution_major_version | int}}.yml"
- "../vars/{{ ansible_distribution }}.yml"
- "../vars/{{ ansible_os_family }}.yml"
- "../vars/default.yml"
when: apache_package_name is not defined or apache_service_name is not defined
- name: Install Apache
package: >
name={{ apache_package_name }}
state=latest
- name: Enable apache service
service: >
name={{ apache_service_name }}
state=started
enabled=yes
tags: packages
Erstellen Sie dann für jedes Betriebssystem, mit dem Sie anders umgehen müssen, eine vars-Datei:
---
# roles/apache/vars/default.yml
apache_package_name: apache2
apache_service_name: apache2
---
# roles/apache/vars/RedHat.yml
apache_package_name: httpd
apache_service_name: httpd
---
# roles/apache/vars/SLES.yml
apache_package_name: apache2
apache_service_name: apache2
---
# roles/apache/vars/Debian.yml
apache_package_name: apache2
apache_service_name: apache2
---
# roles/apache/vars/Archlinux.yml
apache_package_name: apache
apache_service_name: httpd
BEARBEITEN: Da Michael DeHaan (der Schöpfer von Ansible) sich dafür entschieden hat, die Module des Paketmanagers nicht zu abstrahieren, wie es Chef tut,
Wenn Sie noch eine ältere Version von Ansible (Ansible <2.0) verwenden , müssen Sie dies leider in all Ihren Playbooks und Rollenerledigen. IMHO, dies bringt eine Menge unnötiger sich wiederholender Arbeit auf die Autoren von Spielbüchern und Rollen ... aber es ist so, wie es derzeit ist. Beachten Sie, dass wir nicht versuchen sollten, Paketmanager zu abstrahieren, während wir weiterhin versuchen, alle ihre spezifischen Optionen und Befehle zu unterstützen, sondern nur einen einfachen Weg haben, ein Paket zu installieren, das paketmanager-unabhängig ist. Ich sage auch nicht, dass wir alle auf den Smart Package Manager umsteigen solltenDiese Art von Paketinstallations-Abstraktionsschicht in Ihrem Konfigurationsmanagement-Tool ist jedoch sehr nützlich, um plattformübergreifende Playbooks / Kochbücher zu vereinfachen. Das Smart-Projekt sieht interessant aus, aber es ist ziemlich ehrgeizig, das Paketmanagement über Distributionen und Plattformen hinweg zu vereinheitlichen, ohne dass es viel Akzeptanz findet. Es wird interessant sein zu sehen, ob es erfolgreich ist. Das eigentliche Problem ist nur, dass die Paketnamen manchmal in verschiedenen Distributionen unterschiedlich sind. Wir müssen also noch case-Anweisungen oder when:
Anweisungen ausführen, um die Unterschiede zu behandeln.
Die Art und Weise, wie ich damit umgegangen bin, besteht darin, dieser tasks
Verzeichnisstruktur in einem Playbook oder einer Rolle zu folgen :
roles/foo
└── tasks
├── apt_package.yml
├── foo.yml
├── homebrew_package.yml
├── main.yml
└── yum_package.yml
Und dann haben Sie dies in meinem main.yml
:
---
# foo: entry point for tasks
# Generally only include other file(s) and add tags here.
- include: foo.yml tags=foo
Dies in foo.yml
(für Paket 'foo'):
---
# foo: Tasks entry point. Called by main.yml
- include: apt_package.yml
when: ansible_pkg_mgr == 'apt'
- include: yum_package.yml
when: ansible_pkg_mgr == 'yum'
- include: homebrew_package.yml
when: ansible_os_family == 'Darwin'
- name: Enable foo service
service: >
name=foo
state=started
enabled=yes
tags: packages
when: ansible_os_family != 'Darwin'
Dann für die verschiedenen Paketmanager:
Geeignet:
---
# tasks file for installing foo on apt based distros
- name: Install foo package via apt
apt: >
name=foo{% if foo_version is defined %}={{ foo_version }}{% endif %}
state={% if foo_install_latest is defined and foo_version is not defined %}latest{% else %}present{% endif %}
tags: packages
Lecker
---
# tasks file for installing foo on yum based distros
- name: Install EPEL 6.8 repos (...because it's RedHat and foo is in EPEL for example purposes...)
yum: >
name={{ docker_yum_repo_url }}
state=present
tags: packages
when: ansible_os_family == "RedHat" and ansible_distribution_major_version|int == 6
- name: Install foo package via yum
yum: >
name=foo{% if foo_version is defined %}-{{ foo_version }}{% endif %}
state={% if foo_install_latest is defined and foo_version is not defined %}latest{% else %}present{% endif %}
tags: packages
- name: Install RedHat/yum-based distro specific stuff...
yum: >
name=some-other-custom-dependency-on-redhat
state=latest
when: ansible_os_family == "RedHat"
tags: packages
Homebrew:
---
- name: Tap homebrew foobar/foo
homebrew_tap: >
name=foobar/foo
state=present
- homebrew: >
name=foo
state=latest
Beachten Sie, dass diese schrecklich repetitive und nicht DRY , und obwohl einige Dinge vielleicht anders auf den verschiedenen Plattformen und werden gehandhabt werden müssen, in der Regel denke ich , das ausführlich und unhandlich ist , wenn zu Koch verglichen:
package 'foo' do
version node['foo']['version']
end
case node["platform"]
when "debian", "ubuntu"
# do debian/ubuntu things
when "redhat", "centos", "fedora"
# do redhat/centos/fedora things
end
Und ja, es gibt das Argument, dass einige Paketnamen in Distributionen unterschiedlich sind. Und obwohl es derzeit an leicht zugänglichen Daten mangelt , würde ich vermuten, dass die beliebtesten Paketnamen in Distributionen häufig vorkommen und über ein abstrahiertes Paketmanagermodul installiert werden könnten. Sonderfälle müssten ohnehin behandelt werden und würden bereits zusätzliche Arbeit erfordern, um die Dinge weniger trocken zu machen .