2016-10-26 83 views

回答

2
  1. 創建一個名爲/etc/ansible/facts.d/zoneadm.fact的腳本並收集您需要的任何信息。這可以是任何你想要的(bash/python/etc)。

  2. 當你完成,echo它以標準輸出爲json格式。

  3. 部署通過ansible該腳本,使其可執行

  4. 收集的事實和發現新的事實存在下ansible_local.zoneadm

更多的相關信息,可以發現here

+0

你是什麼意思的'靜態'?每次執行設置步驟時都會運行該腳本,即「ansible all -m setup」。 – user2599522

+0

也許我很想理解它。此腳本是在目標主機上還是在Ansible主機上執行? – ceving

+1

它們將在它們所在的機器上運行,這就是爲什麼@ user2599522建議您首先將事實腳本部署到所有主機。更多關於[這裏](https://docs.ansible.com/ansible/playbooks_variables.html#local-facts-facts-d)。 –

2

我〜2年前處理相同的困境。以前的答覆是正確的,但你必須在之前部署一些東西,並重新運行Ansible以獲得新的事實。

有寫自己的Ansible模塊,它返回JSON看起來像一個選項:然後通過這樣的模塊返回

{ 
    'changed': false, 
    'ansible_facts': { 
    'sunos': { 
     'zonename': 'global', 
     'zones': {}, 
    } 
} 

事實被合併到那些從setup模塊來。爲了更加便於攜帶,最好將此模塊包含到Ansible角色中,並且只包含一個調用此模塊的任務,並添加標記always,即使您通過在cmdline上指定標記來選擇任務子集,也可以運行此事實集合。

我有我的舊角色pushed here on GitHub。可能不會開箱即用......與Ansible 1.0一起使用,但獲得啓發。

+0

您的解決方案有點不同。您不用事實腳本收集數據,而是編寫了一個繞過事實收集過程的模塊。任何額外的'setup-sunos'模塊必須在'setup'自動運行時明確使用。你是怎麼做到的? – ceving

+0

你錯過了這一點,它沒有繞過任何東西。 'setup'模塊的工作方式相同。試試'ansible -vvv your_host -m setup',你會看到非常相似的'JSON'。任何時候某個模塊返回'ansible_facts',它將被合併而不被覆蓋。 – nudzo

0

我誤解的原因是,我認爲,我必須在Ansible機器上放置一些東西,它會自動部署到目標系統,就像完成模塊一樣。但事實收集工作不同!一個人必須吃蛋糕,在setup開始工作之前,fatcs收集腳本已經在目標系統上。我會說這是Ansible中的一個設計錯誤,或者至少還有一個尚未實現的功能。

要添加此缺少的功能,有必要編寫一個播放,它在所有其他事情之前工作。我想出了以下解決方案:

--- 
- name: facts deployment 
    gather_facts: false 
    hosts: all 
    become: true 
    tasks: 
    - set_fact: setup_necessary=false 
    - file: 
     path: "/etc/ansible/facts.d" 
     state: directory 
     recurse: yes 
     register: facts_directory 
    - set_fact: setup_necessary=true 
     when: facts_directory.changed 

- name: solaris facts 
    gather_facts: false 
    hosts: solaris 
    become: true 
    tasks: 
    - include: deploy_fact.yml 
     with_items: 
     - { shell: bash, file: nonglobal_zones } 
     - { shell: bash, file: solaris_eeprom } 

- name: setup after facts update 
    gather_facts: false 
    hosts: all 
    tasks: 
    - setup: 
     when: setup_necessary 

以上的劇本做所有戲劇與gather_facts: false,以防止任何setup運行的事實已經部署之前。當對目標系統進行任何更改時,所有播放都設置變量setup_necessary。這是不可能使用處理程序的,因爲處理程序在遊戲結束時運行,但不在遊戲結束時或在某些遊戲結束後運行(Ansible限制1)。

首先創建目錄,然後部署所有事實文件。有必要將外觀的主體放入單獨的任務文件中,因爲無法將兩個任務組合在一個劇本中(Ansible限制2)。

deploy_fact.yml文件的內容使用template模塊將事實腳本傳輸到目標系統。

--- 
- name: "/etc/ansible/facts.d/{{item.file}}.fact" 
    template: 
    src: "{{inventory_dir}}/facts.d/{{item.shell}}.j2" 
    dest: "/etc/ansible/facts.d/{{item.file}}.fact" 
    mode: 0755 
    register: facts_file 
- set_fact: setup_necessary=true 
    when: facts_file.changed 

爲什麼我用template模塊,每一個事實腳本需要某種形式的錯誤處理這需要照顧,適當的JSON得到一個錯誤的情況下產生的原因。這是我目前的錯誤處理,但仍可以改進。有些人也不喜歡set -eu,這在某種程度上是品味的問題。

#! /bin/bash 
{% include item.file + '.bash' %} 


set -eu 

_stderr=$(mktemp) 
trap 'rm -f "$_stderr"' EXIT 
if _stdout=$(main 2>$_stderr); then 
    if [ "$_stdout" ]; then 
    echo "$_stdout" 
    else 
    echo null 
    fi 
else 
    jq -Rsc "{\"ERROR\":{\"failed\":true,\"exit\":$?,\"msg\":.}}" $_stderr 
fi 

模板什麼也不做的不僅僅是包括通過隱item變量由循環傳遞的文件更多。包裝器期望從包含的文件中定義一個main函數。這是我對非全局區域的主要功能:

main() 
{ 
    zoneadm list -i | 
    grep -v global | 
    jq -Rc . | 
    jq -sc . 
} 

而這其中收集了Solaris EEPROM數據:

main() 
{ 
    eeprom | 
    sed 's/^\([^=]*\)=\(.*\)$/{"\1":"\2"}/' | 
    sed 's/^\(.*\): data not available.$/{"\1":null}/' | 
    sed 's/:"false"}$/:false}/g' | 
    sed 's/:"true"}$/:true}/g' | 
    sed 's/:"\([0-9][0-9]*\)"}$/:\1}/' | 
    sed '/^{"boot-device"/{s/":"/":["/;s/ /","/g;s/"}$/"]}/;}' | 
    jq -sc add 
} 

我的底線是,它在某種程度上可以延長Ansible的事實收集,但它遠非明顯,並且有點痛苦,因爲它不可能臨時使用setup模塊。 Ansible不要求用戶實現上述內容,而應將以上所有內容移至setup模塊(Ansible限制3)。