
estou começando comansiblee irá utilizá-lo, entre outros, para instalar pacotes em diversas distros Linux.
Vejo nos documentos que os comandos yum
e apt
estão separados - qual seria a maneira mais fácil de unificá-los e usar algo assim:
- name: install the latest version of Apache
unified_install: name=httpd state=latest
em vez de
- name: install the latest version of Apache on CentOS
yum: name=httpd state=latest
when: ansible_os_family == "RedHat"
- name: install the latest version of Apache on Debian
apt: pkg=httpd state=latest
when: ansible_os_family == "Debian"
Entendo que os dois gerenciadores de pacotes são diferentes, mas ainda têm um conjunto de usos básicos comuns. Outros orquestradores (sal por exemplo) têm um único comando de instalação.
Responder1
Atualização: A partir do Ansible 2.0, agora existe um genérico e abstraídopackage
módulo
Exemplos de uso:
Agora, quando o nome do pacote é o mesmo em diferentes famílias de sistemas operacionais, é tão simples quanto:
---
- name: Install foo
package: name=foo state=latest
Quando o nome do pacote difere entre as famílias de sistemas operacionais, você pode lidar com isso com arquivos vars específicos da distribuição ou da família de sistemas operacionais:
---
# 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
Então, para cada sistema operacional que você deve tratar de maneira diferente... crie um arquivo vars:
---
# 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
EDITAR: Desde Michael DeHaan (criador do Ansible)optou por não abstrair os módulos do gerenciador de pacotescomoChefe de cozinhafaz,
Se você ainda estiver usando uma versão mais antiga do Ansible (Ansible <2.0), infelizmente você precisará lidar com isso emtodosde seus manuais e funções. Na minha humilde opiniãoisso empurra muito trabalho repetitivo desnecessário para os autores de manuais e funções... mas é assim que é atualmente. Observe que não estou dizendo que devemos tentar abstrair os gerenciadores de pacotes enquanto ainda tentamos oferecer suporte a todas as suas opções e comandos específicos, mas apenas ter uma maneira fácil de instalar um pacote que seja independente do gerenciador de pacotes. Também não estou dizendo que todos deveríamos pular noGerenciador de pacotes inteligentemovimento, mas algum tipo de camada de abstração de instalação de pacote em sua ferramenta de gerenciamento de configuração é muito útil para simplificar manuais/livros de receitas de plataforma cruzada. O projeto Smart parece interessante, mas é bastante ambicioso para unificar o gerenciamento de pacotes entre distros e plataformas sem muita adoção ainda... será interessante ver se terá sucesso. A verdadeira questão é que os nomes dos pacotes às vezes tendem a ser diferentes entre as distros, então ainda temos que fazer declarações case ou when:
declarações para lidar com as diferenças.
A maneira como tenho lidado com isso é seguir esta tasks
estrutura de diretórios em um manual ou função:
roles/foo
└── tasks
├── apt_package.yml
├── foo.yml
├── homebrew_package.yml
├── main.yml
└── yum_package.yml
E então coloque isso no meu main.yml
:
---
# foo: entry point for tasks
# Generally only include other file(s) and add tags here.
- include: foo.yml tags=foo
Isto em foo.yml
(para o pacote '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'
Então, para os diferentes gerenciadores de pacotes:
Apto:
---
# 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
Hum:
---
# 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
Preparação caseira:
---
- name: Tap homebrew foobar/foo
homebrew_tap: >
name=foobar/foo
state=present
- homebrew: >
name=foo
state=latest
Observe que isso é terrivelmente repetitivo e nãoSECOe embora algumas coisaspoderser diferente nas diferentes plataformas e terá que ser tratado, geralmente acho que isso é detalhado e complicado quando comparado ao do Chef:
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
E sim, há o argumento de quealgunsos nomes dos pacotes são diferentes entre as distros. E embora exista atualmente umafalta de dados facilmente acessíveis, atrevo-me a adivinhar quemaiorianomes de pacotes populares são comuns em distros e podem ser instalados por meio de um módulo gerenciador de pacotes abstrato. Casos especiais precisariam ser tratados de qualquer maneira e já exigiriam trabalho extra para tornar as coisas menos SECAS. Em caso de dúvida, verifiquepkgs.org.
Responder2
Você pode abstrair os gerenciadores de pacotes por meio de fatos
- name: Install packages
with_items: package_list
action: "{{ ansible_pkg_mgr }} state=installed name={{ item }}"
Tudo que você precisa é de alguma lógica que defina ansible_pkg_mgr
como apt
ou yum
etc.
Ansibletambém estamos trabalhando para fazer o que quiser em um módulo futuro.
Responder3
Do Ansible 2.0 existe o novo Package
-modul.
http://docs.ansible.com/ansible/package_module.html
Você pode então usá-lo como sua proposta:
- name: install the latest version of Apache
package: name=httpd state=latest
Você ainda precisa considerar as diferenças de nomes.
Responder4
Você não quer fazer isso porque certos nomes de pacotes diferem entre distros. Por exemplo, em distros relacionadas ao RHEL, o popular pacote de servidor web é denominado httpd
, enquanto nas distros relacionadas ao Debian é denominado apache2
. Da mesma forma, com uma lista enorme de outros sistemas e bibliotecas de suporte.
Pode haver um conjunto de parâmetros básicos comuns, mas também há vários parâmetros mais avançados que são diferentes entre gerenciadores de pacotes. E você não quer estar em uma situação ambígua em que para alguns comandos você usa uma sintaxe e para outros comandos você usa outra sintaxe.