Timpa variabel host dari Buku pedoman yang mungkin dari baris perintah

110

Ini adalah bagian dari playbook yang saya gunakan ( server.yml):

- name: Determine Remote User
  hosts: web
  gather_facts: false
  roles:
    - { role: remote-user, tags: [remote-user, always] }

File host saya memiliki grup server yang berbeda, mis

[web]
x.x.x.x

[droplets]
x.x.x.x

Sekarang saya ingin menjalankan ansible-playbook -i hosts/<env> server.ymldan menimpa hosts: webdari server.ymluntuk menjalankan pedoman ini [droplets].

Bisakah saya menimpa sebagai satu kali waktu, tanpa mengedit server.ymlsecara langsung?

Terima kasih.

luqo33
sumber

Jawaban:

128

Menurut saya Ansible tidak menyediakan fitur ini, yang seharusnya. Inilah yang dapat Anda lakukan:

hosts: "{{ variable_host | default('web') }}"

dan Anda dapat meneruskan variable_hostdari baris perintah atau dari file vars, misalnya:

ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
wallydrag.dll
sumber
3
Diperlukan sedikit koreksi. Seharusnyahosts: "{{ variable_host | default('web')}}"
SPM
16
Berikut adalah catatan yang saya rasa akan melengkapi jawaban untuk pemula yang mungkin mencari solusi ini: Contoh:ansible-playbook server.yml --extra-vars "variable_host=newtarget(s)"
Frobbit
1
KETIKA (yaitu dalam rangka apa) tidak ansible variabel parse Variabel dalam group_vars/allmuncul dapat dipecah setelah pada hosts:garis pedoman tersebut. Namun, variabel di vars:dan variabel di vars_files:diurai sebelum hosts:baris? CATATAN Saya tidak bertanya tentang prioritas.
Felipe Alvarez
2
Anda juga dapat menggunakan -ebukan --extra-vars.
kata benda
Lihat jawaban lain untuk lebih jelasnya
Anand Varkey Philips
63

Untuk siapapun yang mungkin datang mencari solusinya.
Mainkan Buku

- hosts: '{{ host }}'
  tasks:
  - debug: msg="Host is {{ ansible_fqdn }}"

Inventaris

[web]
x.x.x.x

[droplets]
x.x.x.x

Command: ansible-playbook deplyment.yml -i hosts --extra-vars "host=droplets" Jadi Anda dapat menentukan nama grup di extra-vars

Mrunal Gosar
sumber
2
Perhatikan, hati-hati dengan penamaan var. Saya menguji ini menggunakan play_hostsdan tidak mendapatkan hasil yang diharapkan karena saya lupa bahwa itu play_hostsadalah var Ansible internal untuk semua tuan rumah dalam permainan saat ini.
Ryan Fisher
Saya kira default harus ditetapkan seperti pada jawaban di atas.
kakaz
19

Ini agak terlambat, tetapi saya pikir Anda dapat menggunakan --limit or -lperintah untuk membatasi pola ke host yang lebih spesifik. (versi 2.3.2.0)

Kamu bisa saja - hosts: all (or group) tasks: - some_task

dan kemudian ansible-playbook playbook.yml -l some_more_strict_host_or_pattern gunakan --list-hostsbendera untuk melihat di host mana konfigurasi ini akan diterapkan.

Jonathan Hamel
sumber
3
Saya sangat baru dalam hal ansible tetapi saya menganggap ini sebagai solusi yang sangat efektif, jauh lebih kompak daripada yang lain. Mengapa itu tidak disukai?
Alessandro Dentella
16
Ini berbahaya. Dalam kasus seseorang lupa limitdaftar host yang terkena dampak playbook dapat menyebabkan banyak kerusakan.
Alexander Shcheblikin
3
Saya menemukan bahwa menggunakan --extra-vars "variable_host=newtarget(s)"seperti solusi yang diterima sama berbahayanya dan solusi yang lebih rumit. Ini menggunakan host default webyang dapat diterapkan di sini juga sebagai ganti all. Anda dapat menggunakan grup host yang ketat sebagai default untuk menghindari membuat kesalahan dan menggunakan --list-hoststanda untuk memiliki pemahaman yang jelas tentang host mana yang Anda pengaruhi.
Jonathan Hamel
3
Solusi dengan extra-vars memungkinkan untuk menentukan grup kosong (atau tidak ada) sebagai nilai default. Jadi jika Anda lupa memberikan variabel melalui baris perintah, tidak ada hal buruk yang terjadi. Solusi dengan opsi "--limit" lebih berbahaya karena playbook tidak dapat menggunakan grup kosong sebagai nilai default untuk host. Opsi "--llmit" diterapkan ke nilai host sehingga akan diterapkan ke grup kosong dan akan memberikan hasil kosong. Jadi, Anda HARUS menggunakan "semua" atau beberapa host tidak kosong lainnya sebagai nilai default. Dan suatu hari Anda akan lupa untuk memberikan argumen "--limit" dan pedoman akan diterapkan ke semua host.
Gregory Petukhov
4
Ini harus digabungkan dengan jawaban @ TmTron untuk menangkap kasus di mana pemanggil gagal menyediakan --limit(jika tidak maka akan mempengaruhi semua host yang mungkin, yang mungkin bukan perilaku yang Anda inginkan)
ncoghlan
14

Kami menggunakan sederhana tugas gagal untuk memaksa pengguna menentukan opsi Batas yang memungkinkan , sehingga kami tidak mengeksekusi pada semua host secara default / tidak sengaja.

Cara termudah yang saya temukan adalah ini:

---
- name: Force limit
  # 'all' is okay here, because the fail task will force the user to specify a limit on the command line, using -l or --limit
  hosts: 'all'

  tasks:
  - name: checking limit arg
    fail:
      msg: "you must use -l or --limit - when you really want to use all hosts, use -l 'all'"
    when: ansible_limit is not defined
    run_once: true

Sekarang kita harus menggunakan -l (= --limitoption) saat menjalankan playbook, mis

ansible-playbook playbook.yml -l www.example.com

Batasi dokumen opsi :

Batasi untuk satu atau lebih host. Ini diperlukan ketika seseorang ingin menjalankan playbook melawan grup host, tetapi hanya melawan satu atau lebih anggota grup itu.

Batasi untuk satu host

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1"

Batasi untuk beberapa host

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit "host1,host2"

Batas dinegasikan.
CATATAN: Tanda kutip tunggal HARUS digunakan untuk mencegah interpolasi bash.

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'all:!host1'

Batasi untuk grup tuan rumah

ansible-playbook playbooks/PLAYBOOK_NAME.yml --limit 'group1'

TmTron
sumber
7

Saya menggunakan pendekatan lain yang tidak memerlukan inventaris apa pun dan bekerja dengan perintah sederhana ini:

ansible-playbook site.yml -e working_host=myhost

Untuk melakukan itu, Anda memerlukan pedoman dengan dua drama:

  • permainan pertama berjalan di localhost dan menambahkan host (dari variabel yang diberikan) dalam grup yang dikenal di inventaris memori
  • Permainan kedua berlangsung di grup yang dikenal ini

Contoh yang berfungsi (salin dan jalankan dengan perintah sebelumnya):

- hosts: localhost
  connection: local
  tasks:
  - add_host:
      name: "{{ working_host }}"
      groups: working_group
    changed_when: false

- hosts: working_group
  gather_facts: false
  tasks:
  - debug:
      msg: "I'm on {{ ansible_host }}"

Saya menggunakan kemungkinan 2.4.3 dan 2.3.3

Nelson G.
sumber
7

Saya mengubah milik saya ke default menjadi tidak ada host dan memiliki cek untuk menangkapnya. Dengan begitu pengguna atau cron dipaksa untuk menyediakan satu host atau grup, dll. Saya suka logika dari komentar dari @wallydrag. Tidak empty_groupberisi host di inventaris.

- host: "{{variable_host | default ('empty_group')}}"

Kemudian tambahkan tugas check in:

   tugas:
   - name: Skrip gagal jika parameter variabel_host yang diperlukan tidak ada
     gagal:
       msg: "Anda harus menambahkan --extra-vars = 'variable_host ='"
     when: (variable_host tidak ditentukan) atau (variable_host == "")
Tony-Caffe
sumber
5

Baru saja menemukan googling ini untuk mendapatkan solusi. Sebenarnya, ada satu di Ansible 2.5. Anda dapat menentukan file inventaris Anda dengan --inventory, seperti ini:ansible --inventory configs/hosts --list-hosts all

Bebef
sumber
Saya percaya ini adalah jawaban yang paling benar di Tahun Tuhan Kita 2019. Dari Ansible 2.8.4's -h:-i INVENTORY, --inventory=INVENTORY, --inventory-file=INVENTORY specify inventory host path or comma separated host list. --inventory-file is deprecated
pyansharp
3

Jika Anda ingin menjalankan tugas yang terkait dengan sebuah host, tetapi pada host yang berbeda, Anda harus mencoba delegate_to .

Dalam kasus Anda, Anda harus mendelegasikan ke localhost Anda (master yang memungkinkan) dan ansible-playbookperintah panggilan

nghnam
sumber
2

Saya menggunakan ansible 2.5 (persis 2.5.3), dan tampaknya file vars dimuat sebelum param host dijalankan. Jadi, Anda dapat mengatur host di vars.yml file dan menuliskannya hosts: {{ host_var }}di playbook Anda

Misalnya, di playbook.yml saya:

---
- hosts: "{{ host_name }}"
  become: yes
  vars_files:
    - vars/project.yml
  tasks:
    ... 

Dan di dalam vars / project.yml:

---

# general
host_name: your-fancy-host-name
LightMan
sumber
0

Inilah solusi keren yang saya temukan untuk menentukan host dengan aman melalui --limitopsi. Dalam contoh ini, permainan akan berakhir jika pedoman dijalankan tanpa host yang ditentukan melalui--limit opsi.

Ini telah diuji pada Ansible versi 2.7.10

---
- name: Playbook will fail if hosts not specified via --limit option.
  # Hosts must be set via limit. 
  hosts: "{{ play_hosts }}"
  connection: local
  gather_facts: false
  tasks:
  - set_fact:
      inventory_hosts: []
  - set_fact:
      inventory_hosts: "{{inventory_hosts + [item]}}"
    with_items: "{{hostvars.keys()|list}}"

  - meta: end_play
    when: "(play_hosts|length) == (inventory_hosts|length)"

  - debug:
      msg: "About to execute tasks/roles for {{inventory_hostname}}"
sudo jiwa
sumber
0

Solusi lain adalah menggunakan variabel khusus ansible_limityang merupakan konten --limitopsi CLI untuk eksekusi Ansible saat ini.

- hosts: "{{ ansible_limit | default(omit) }}"

Jika --limitopsi dihilangkan, maka Ansible mengeluarkan peringatan, tetapi tidak melakukan apa-apa karena tidak ada host yang cocok.

[WARNING]: Could not match supplied host pattern, ignoring: None

PLAY ****************************************************************
skipping: no hosts matched
Manolo
sumber