Ansible'da listelere ekleme veya sözlüklere anahtar ekleme


34

( Geriye Dönükler veya Kancalar ve Yeniden Kullanılabilir Görevler Dizisi ile ilgili olarak Ansible rollerinde ):

Bir listeye eklemek veya Ansible'daki bir sözlüğe anahtar eklemek için jina2 şablon ifadesini kullanmaktan daha iyi bir yöntem var mı?

Böyle bir şey yapabileceğini biliyorum:

- name: this is a hack
  shell: echo "{% originalvar.append('x') %}New value of originalvar is {{originalvar}}"

ama bunu yapacak bir meta görevi veya yardımcısı yok mu?

Kırılgan hissediyor, belgelenmemiş gibi görünüyor ve değişkenlerin Ansible'da nasıl çalıştığı hakkında pek çok varsayıma dayanıyor.

Kullanım durumum, her biri bir temel rolde (veritabanı sunucusu) bazı yapılandırmalar sağlaması gereken birden çok roldür (veritabanı sunucusu uzantıları). Db server config dosyasına bir satır eklemek kadar basit değildir; her değişiklik aynı satıra uygulanır , örneğin uzantılar bdrve pg_stat_statementsher ikisi de hedef satırda görünmelidir:

shared_preload_libaries = 'bdr, pg_stat_statements'

Bunu yapmanın Ansible yolu, yalnızca config dosyasını birden çok kez (uzantı başına bir kez) işlemek için geçerli değeri çıkaran, ayrıştıran ve sonra yeniden yazan bir regexp mi? Öyleyse, bu idrarı birden fazla çalıştırmada nasıl başarılı kılıyorsunuz?

Yapılandırma ayrıştırmak daha zor ise ve başka bir virgülle ayrılmış değer eklemek kadar basit değilse ne olur? XML yapılandırma dosyalarını düşünün.


Ne biliyor musun? Senin yan etki ful jib
kesimini seviyorum

Yanıtlar:


13

Bir değişkende iki listeyi birleştirebilirsiniz +. group_varsBu içeriğe sahip bir dosyanız olduğunu söyleyin :

---
# group_vars/all
pgsql_extensions:
  - ext1
  - ext2
  - ext3

Ve pgsql.conf.j2şunun gibi bir şablonda kullanılır :

# {{ ansible_managed }}
pgsql_extensions={% for item in pgsql_extensions %}{{ item }}, {% endfor %}

Daha sonra, bunun gibi test veritabanı sunucularına uzantıları ekleyebilirsiniz:

---
# group_vars/testing_db
append_exts:
  - ext4
  - ext5
pgsql_extensions: "{{ pgsql_extensions + append_exts }}"

Rol herhangi bir test sunucusunda çalıştırıldığında, ekli uzantılar eklenecektir.

Bunun sözlükler için de işe yarayacağından emin değilim ve aynı zamanda satırların sonunda boşluklara ve sarkan bir virgül bırakmaya dikkat edin.


Yapabilirsin, ama hepsini yapman gerekiyor group_vars, roller uzantıların kurulumunun detaylarıyla ilgilenemiyor. Özellikle aradığım rollerden değişkenler ekliyor , böylece bir rol başka bir rolün maruz kaldığı bir var'a eklenebilir.
Craig Ringer

Temel rolünüz her uzatma rolünü biliyor mu? Birleştirmeyi with_itemscümleye bırakabileceğim benzer bir durum daha vardı .
GnP

hayır, bu gerçekten sorun. Bir dağıtımda temel rol al olabilir
Craig Ringer,

4
İki listeyi birleştirmek için bunu yapmaya çalışırsanız, sol tarafın da sağ taraf olduğu için sonsuz derecede özyinelemeli bir şablon olduğunu düşünüyor gibi görünüyor. Bunu nasıl kullanacağımı yanlış mı anlıyorum?
Ibrahim,

2
@spectras En azından 2.7 Ansillerinden itibaren bu BİRLİKTE işe yaramıyor. İbrahim'in önerdiği gibi, bu bir hataya neden oluyor: "şablon dizesinde özyinelemeli döngü algılandı".
rluba

35

Ansible v2.x'ten beri şunları yapabilirsiniz:

# use case I: appending to LIST variable:

      - name: my appender
        set_fact:
          my_list_var: '{{my_list_myvar + new_items_list}}'

# use case II: appending to LIST variable one by one:

      - name: my appender
        set_fact:
          my_list_var: '{{my_list_var + [item]}}'
        with_items: '{{my_new_items|list}}'

# use case III: appending more keys DICT variable in a "batch":

      - name: my appender
        set_fact:
          my_dict_var: '{{my_dict_var|combine(my_new_keys_in_a_dict)}}'

# use case IV: appending keys DICT variable one by one from tuples
      - name: setup list of tuples (for 2.4.x and up
        set_fact:
          lot: >
            [('key1', 'value1',), ('key2', 'value2',), ..., ('keyN', 'valueN',)],
      - name: my appender
        set_fact:
          my_dict_var: '{{my_dict_var|combine({item[0]: item[1]})}}'
        with_items: '{{lot}}'
# use case V: appending keys DICT variable one by one from list of dicts (thanks to @ssc)

  - name: add new key / value pairs to dict
    set_fact:
      my_dict_var: "{{ my_dict_var | combine({item.key: item.value}) }}"
    with_items:
    - { key: 'key01', value: 'value 01' }
    - { key: 'key02', value: 'value 03' }
    - { key: 'key03', value: 'value 04' }

Yukarıdakilerin hepsi belgelenmiştir: http://docs.ansible.com/ansible/playbooks_filters.html


1
dava IV kullanın sadece ekleru'(': u\"'\"}"
ssc

1
teşekkürler, @ssc. Ansible 2.4.x(FIXED) ile çalışmadığını fark ettim
Max Kovgan

4. Usecase göre, ben işlemek için varsayılan değer eklemiş tanımsız hata benim senaryoda: set_fact: my_dict_var: '{{my_dict_var|default({})|combine({item[0]: item[1]})}}'. Tanımsız hata, bazı filtreleme kullanıldığında veya hiçbir sonuç kaydedilmediğinde ortaya çıkar.
SK Venkat

Bay SK Venkat, buradaki örnek kod sadece çok özel bir şey gösterir (sözlükten sözlük maddeleri ekleyerek). Başka bir şey yapman gerekirse, bu kod senin kopyala yapıştırın değil.
Max Kovgan

3

döngüyü ikiye bölmeniz gerekir

--- 
- ev sahibi: localhost
  görevler: 
    - include_vars: yığınları
    - set_facts: roles = {{stacks.Roles | Bölünmüş(' ')}}
    - dahil: addhost.yml
      with_items: "{{roles}}"

ve addhost.yml

- set_facts: groupname = {{item}}
- set_facts: ips = {{yığınlar [öğe] | split ('')}}
- local_action: add_host ana bilgisayar adı = {{item}} grup adı = {{grup adı}}
  with_items: {{ips}}

1

Değil emin ne zaman onlar bu katma, ama en azından sözlükleri / sağlamalarının (NOT listeleri / diziler) için, değişken ayarlayabilirsiniz hash_behaviour şöyle: hash_behaviour = mergeGözlerinde farklı ansible.cfg.

Yanlışlıkla bu ayarın yanılmaması için birkaç saatimi aldı: S


bu çok kullanışlıdır, ancak mevcut kod tabanında e2e'yi etkinleştirmeye dikkat edin. bazı yumurtaları kırabilir.
Max Kovgan

0

Buradaki hemen hemen tüm cevaplar görevlerde değişiklik gerektiriyor, ancak çalışma sırasında sözlükleri vars tanımında dinamik olarak birleştirmem gerekiyordu.

Örneğin ben bazı paylaşılan değişkenler tanımlamak istediğiniz all group_varsve sonra diğer bazı bunları genişletmek istiyorum groupya host_vars. Rol için çalışırken çok faydalıdır.

Orijinal değişkenin üzerine yazılan combineveya unionvar dosyalarındaki filtreleri kullanmaya çalışırsanız, şablon oluşturma sırasında sonsuz döngüye son verirsiniz, bu yüzden bu geçici çözümü oluşturdum (çözüm değil).

Bazı ad desenlerine göre birden fazla değişken tanımlayabilir ve ardından bunları otomatik olarak rolde yükleyebilirsiniz.

group_vars/all.yml

dictionary_of_bla:
  - name: blabla
    value1 : blabla
    value2 : blabla

group_vars/group1.yml

dictionary_of_bla_group1:
  - name: blabla2
    value1 : blabla2
    value2 : blabla2

rol kodu pasajı

tasks:
  - name: Run for all dictionary_of_bla.* variations
    include_tasks: do_some_stuff.yml
    with_items: "{{ lookup('varnames','dictionary_of_bla.*').split(',') }}"
    loop_control:
      loop_var: _dictionary_of_bla

do_some_stuff.yml

- name: do magic
  magic:
    trick_name: item.name
    trick_value1: item.value1
    trick_value2: item.value2
  with_items: "{{ vars[_dictionary_of_bla] }}"

Bu sadece bir pasaj, ama nasıl çalıştığı hakkında bir fikir edinmelisin. not: arama sonuçları ('varnames', '') 2.8'ten beri geçerlidir.

Sanırım dictionary_of_bla.*aynı aramayı kullanarak çalışma sırasında tüm değişkenleri tek bir sözlükte birleştirmek mümkün olacak .

Bu yaklaşımın avantajı, değişken adlarının tam listelerini ayarlamanıza gerek kalmamasıdır, ancak yalnızca desen ve kullanıcı bunu dinamik olarak ayarlayabilir.


-4

Ansiblebir otomasyon sistemidir ve yapılandırma dosyası yönetimi ile ilgili olarak, çok farklı değildir apt. Giderek daha fazla yazılımın, bir dizinden yapılandırma parçacıklarını okuma özelliği sunmasının nedeni, bu conf.dtür otomasyon sistemlerinin farklı paket / rollerin yazılıma yapılandırma ekleyebilmesini sağlamaktır. Bence Ansibleaklınızdan geçenleri yapmanın felsefesi değil, bunun yerine conf.dhileyi kullanmaktır . Yapılandırılan yazılım bu işlevi sunmuyorsa, başınız belada olabilir.

XML yapılandırma dosyalarından bahsettiğinizden beri, biraz sızlanma yapma fırsatı buluyorum. Unix geleneğinin düz metin yapılandırma dosyalarını kullanmasının bir nedeni var. İkili konfigürasyon dosyaları sistem otomasyonuna iyi bir şekilde borç vermez, bu nedenle her türlü ikili format size sorun çıkartacaktır ve muhtemelen konfigürasyonu ele almak için bir program oluşturmanızı gerektirecektir. (Herhangi biri XML'in düz bir metin formatı olduğunu düşünüyorsa, beyinlerini incelemeye devam etmelidir.)

Şimdi, kendi PostgreSQLprobleminizde. numarayı PostgreSQLdestekliyor conf.d. İlk önce, shared_preload_librariesdefalarca belirtilip belirtilemeyeceğini kontrol ederim . Belgelerde bulabileceği hiçbir ipucu bulamadım, ancak yine de denerdim. Birden çok kez belirtilemezse, sorunumun PostgreSQLfikirleri olması halinde erkeklere açıklardım ; bu bir PostgreSQLmeseledir , mesele değil Ansible. Çözüm yoksa ve farklı rolleri birebir birleştiremezsem, yönetilen ana bilgisayardaki yapılandırmayı derlemek için bir sistem uygulardım. Bu durumda, muhtemelen bir komut dosyası oluşturmak istiyorum /usr/local/sbin/update_postgresql_configderlemek olur /etc/postgresql/postgresql.conf.jinjaiçine /etc/postgresql/9.x/main/postgresql.conf. Komut, paylaşılan önyükleme kitaplıklarını /etc/postgresql/shared_preload_libraries.txtsatır başına bir kitaplıktan okuyacak ve onlara jinja sağlayacaktır.

Otomasyon sistemlerinin bunu yapması nadir değildir. Bir örnek Debian exim4paketidir.


PostgreSQL bir conf.diçerme mekanizmasını destekler ve neyse ki düz metin dosyaları kullanır. Bununla birlikte, çoklu uzantıların bu konuda görüş sahibi olabileceği bazı konfigürasyon seçenekleri vardır - örneğin, "max_wal_senders ürününü öncekinden 10'a kadar artırın".
Craig Ringer

4
Uygulamanın yapılandırma yönetim sistemindeki sınırlamalar etrafında çalışacak şekilde değiştirilmesi gerektiğini ya da yeniden kullanılabilir rollere sahip olmamdan vazgeçmem gerektiğini söylüyor gibisiniz.
Craig Ringer,
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.