【Ansible】关于创建自定义模块时调用变量的方法

我是一位有半年经验的新手基础设施工程师。

首先

我是一名在某个公司担任基础设施工程师的人,每天都忙于创建ansible的角色和playbook。
虽然我才使用ansible半年,但是最近终于逐渐熟悉了开发和运维。
在这期间,出现了一个任务,需要我创建一个“自定义模块”。

Ansible有许多已实现的模块。
(请参阅官方网站: http://docs.ansible.com/ansible/list_of_all_modules.html)
但是,这次的要求是与现有模块不兼容的。
我只是一个刚从一个月前开始学习Python的新手,因此一开始很担心自己是否能够完成这样一个很酷的工作,即创建自己的模块。

我感到不安,但是!

Ansible的模块,出人意料地可以很容易地创建。
只要创建,门槛就不高。
然而,独立模块与ansible是分离的,
所以如果不知道如何调用在ansible中定义的变量,
就有可能面临无法调用的压力和困扰。

话不多说,开始进入正题了。

在这个页面上,我们将介绍初学者在面对这种压力时可能会遇到的变量调用方法。

根据您提供的信息,我们可以使用任何语言进行开发。但是,我将使用我正在学习的Python语言来解释。

环境

・CentOS 7.2 -> CentOS 7.2
・Python 2.7.5 -> Python 2.7.5

准备好

首先,准备一个专属的模块存放位置。
在playbook内创建一个名为”library”的文件夹。
※请使用标准的文件夹名称,如果更改名称,将无法加载模块。
这次将在执行的角色内进行创建。
角色的结构如下所示。

ansible-test-playbook
  |_test-server.yml
  |_group_vars
  |_host_vars
  |_vars
  |_inventory
  |_roles
      |_role_test
          |_defaults
            |_main.yml
          |_tasks
            |_main.yml
          |_templates
          |_library  ⬅︎new!
            |_test.py  ⬅︎new!

由于准备工作已经完成,接下来我们将创建自定义模块。
即使只有简单的shell脚本也能运行,但这次我们将重点写“在 ansible 中声明的变量在模块中读取并执行”的方法。

在ansible中,一旦定义了变量,就可以自由地在其他地方调用它,对吧?
但是,在自定义模块中直接调用变量却行不通。
因此,需要通过任务(task)指定要调用的变量,并将其传递给自定义模块。
下面将说明如何将变量传递给自定义模块并将执行结果返回给ansible。

创建defaults/main.yml文件

本次调用的变量可以通过defaults进行声明,具体如下。(变量的书写方式本页面不进行展示)

un: "Hello"
deux: "World"

创建tasks/main.yml

接下来是准备任务。
在任务中,写如下所示。

- name: get hello world
  test: # .pyを除いた実行する独自モジュール名
    un: "{{ un }}" # 独自モジュールで使用したい変数
    deux: "{{ deux }}"
  register: cinq # 独自モジュールの実行結果を格納する変数名

创建独立的模块

让我们创建一个模块。
在库目录下创建一个名为“test.py”的文件。

#!/usr/bin/env python
# coding: utf-8

# 必要なものをインポート
import json, urllib2
from ansible.module_utils.basic import *

def main():
    # varsから情報を取得するおまじないのようなものです
    # この時に変数名を、taskで宣言したものと一致するように書いてください
    module = AnsibleModule(
        argument_spec=dict(
            un=dict(required=True, type='str'),
            deux=dict(required=True, type='str')
        ),
        # no skip
        supports_check_mode=True,
    )

    # 上記で取得した情報を格納して、モジュール内で使用できるようにする
    un = module.params['un']
    deux = module.params['deux']

    # このモジュールで実行する内容
    trois = un + deux

    # 実行結果を辞書型で格納
    # 後述のansible_factsが辞書型の形式で作られているので、この形は必須です
    quatre = {"quatre": trois}

    # 実行結果をansible側に引き渡す
    module.exit_json(changed=True, ansible_facts=quatre)

if __name__ == '__main__':
    main()

执行

现在准备工作已经就绪,我将执行上述内容。

PLAYBOOK: test-server.yml ********************************************************
1 plays in test-server.yml

PLAY [all] *********************************************************************

TASK [setup] *******************************************************************
ok: [localhost]

TASK [role-test : get hello world] *******************************************
changed: [localhost] => {
    "ansible_facts": {
        "quatre": "HelloWorld" ⬅︎実行結果
    }, 
    "changed": true, 
    "invocation": {
        "module_args": {
            "deux": "World", 
            "un": "Hello"
        }, 
        "module_name": "test"
    }
}

明白了独立模块的执行结果被存储在ansible_facts中。
那么,如果我们想在ansible端调用执行结果,应该如何编写呢?

"{{ cinq.ansible_facts.quatre }}"

如果在任务中的注册步骤中指定的变量名为「taskの中のregisterで指定した変数名.ansible_facts.独自モジュール内で宣言した辞書型のkey」,则可以在ansible中使用此写法来使用执行结果。

工作已经完成了。

作者留言

您对此有何感受?
能够稍微帮助到遇到类似困扰的人们,我将感到非常幸福。

因为今后还会持续接触ansible和python,所以如果有新的学习经历,我会继续发布。

非常感谢您的观看。

广告
将在 10 秒后关闭
bannerAds