在 Ansible 1.9 中 运行 时指定 SSH 配置文件

Specify SSH configuration file at run time in Ansible 1.9

我正在管理两个配置不同的服务器环境。我通过在命令行上指定不同的 SSH 配置来访问这两个环境,因为我需要为 SSH 指定不同的 UserProxyCommand 和其他选项列表。

例如

ssh oldserver.example.org -F config_legacy

ssh newserver.example.org -F config

为了在我的服务器上配置和维护状态,我一直在使用 Ansible(版本 1.9.0.1),它读取 SSH 配置文件,该文件由其 ansible.cfg 中的一行指定:

...
ssh_args =  -F some_configuration_file
...

ansible.cfgloaded a number of ways:

def load_config_file():
    ''' Load Config File order(first found is used): ENV, CWD, HOME, /etc/ansible '''

    p = configparser.ConfigParser()

    path0 = os.getenv("ANSIBLE_CONFIG", None)
    if path0 is not None:
        path0 = os.path.expanduser(path0)
    path1 = os.getcwd() + "/ansible.cfg"
    path2 = os.path.expanduser("~/.ansible.cfg")
    path3 = "/etc/ansible/ansible.cfg"

    for path in [path0, path1, path2, path3]:
        if path is not None and os.path.exists(path):
            try:
                p.read(path)
            except configparser.Error as e:
                print("Error reading config file: \n{0}".format(e))
                sys.exit(1)
            return p
    return None

我可以使用此行为在每个命令加载完全不同的 ansible.cfg 之前设置一个环境变量,但这看起来很乱,因为我只需要 fiddle ssh_args。不幸的是,Ansible 没有公开命令开关来指定 SSH 配置。

我不想维护对 Ansible 的任何修改我不想包装对 ansibleansible-playbook 命令的所有调用。为了保留 Ansible 命令的行为,我相信我的选择是:

选项 C 是我认为实现此目的的唯一方法。你可以让你的 default/most-used ansible.cfg 成为在 cwd ansible.cfg 中读取的那个,然后可选地 setting/unsetting 一个环境变量指向指定 ssh_args = -F config_legacy 行 (ANSIBLE_SSH_ARGS).

之所以需要执行 ansible.cfg 而不是仅仅传递带有 SSH 选项的 envvar,是因为 Ansible 不遵守 ssh 配置文件中的 User 设置——它已经决定了谁它想要 运行 作为命令的开始。

动态清单 (ec2.py) 文件是出于维护原因修改更改的非常糟糕的地方,这就是为什么通常会看到 --user=REMOTE_USER 标志,再加上设置 ANSIBLE_SSH_ARGS="-F some_ssh_config" 环境变量,为 Ansible 存储库的临时用户提供难看的命令。

例如

ANSIBLE_SSH_ARGS="-F other_ssh_config" ansible-playbook playbooks/why_i_am_doing_this.yml -u ubuntu

v.

ansible-playbook playbooks/why_i_am_doing_this.yml -F other_ansible.cfg

选项 A 不起作用,因为根据上面的 p.read(),文件被一次性打开以加载到 Python,这并不重要,因为如果文件可以任意决定打开为脚本,我们将生活在一个非常可怕的世界中。

从系统的角度来看,ansible.cfg 加载是这样的:

$ sudo dtruss -a ansible ......

74947/0x11eadf:    312284       3      2 stat64("/Users/tfisher/code/ansible/ansible.cfg[=12=]", 0x7FFF55D936C0, 0x7FD70207EA00)             = 0 0
74947/0x11eadf:    312308      19     17 open_nocancel("/Users/tfisher/code/ansible/ansible.cfg[=12=]", 0x0, 0x1B6)          = 5 0
74947/0x11eadf:    312316       3      1 read_nocancel(0x5, "# ansible.cfg \n#\n# Config-file load order is:\n#   envvar ANSIBLE_CONFIG\n#   `pwd`/ansible.cfg\n#   ~/.ansible.cfg\n#   /etc/ansible/ansible.cfg\n\n# Some unmodified settings are left as comments to encourage research/suggest modific", 0x1000)               = 3477 0
74947/0x11eadf:    312308      19     17 open_nocancel("/Users/tfisher/code/ansible/ansible.cfg[=12=]", 0x0, 0x1B6)          = 5 0

选项 B 不起作用的原因与 A 不起作用的原因相同——即使您创建了一个具有适当 read/readline/readlines 签名的模拟 Python 文件对象,该文件仍在打开只读,不执行。

如果这是 OpenSSH 的正确存储库,config file is specified like so:

#define _PATH_HOST_CONFIG_FILE      SSHDIR "/ssh_config"

processed like so:

    /* Read systemwide configuration file after user config. */
    (void)read_config_file(_PATH_HOST_CONFIG_FILE, pw,
        host, host_arg, &options,
        post_canon ? SSHCONF_POSTCANON : 0);

and read here with an fopen,这没有给 "file as a script" 恶作剧留下空间。

另一个选项是将环境变量 ANSIBLE_SSH_ARGS 设置为您希望 Ansible 传递给 ssh 命令的参数。