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

2 python ssh ansible

我正在管理两个配置不同的服务器环境.我访问通过指定命令行上不同的SSH配置两个环境,因为我需要指定一个不同的User,ProxyCommand以及对SSH其他选项列表.

例如

ssh oldserver.example.org -F config_legacy

ssh newserver.example.org -F config
Run Code Online (Sandbox Code Playgroud)

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

...
ssh_args =  -F some_configuration_file
...
Run Code Online (Sandbox Code Playgroud)

ansible.cfg装入多种方式:

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
Run Code Online (Sandbox Code Playgroud)

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

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

  • a)将目标作为ssh_args = -F <<config_file>>打开的脚本
  • b)将目标作为p.read(path)扩展的脚本以生成有效的ansible.cfg
  • c)只维护不同的ansible.cfg文件,并利用Ansible按环境变量cwd的顺序选择此文件的事实.

小智 5

选项C是我能看到完成此任务的唯一方法.你可以让你的默认/最常用的ansible.cfg是在cwd ansible.cfg中读取的那个,然后可选地设置/取消设置一个环境变量,该变量指向指定ssh_args = -F config_legacy你需要的行的版本(ANSIBLE_SSH_ARGS).

需要执行ansible.cfg而不是仅使用SSH选项传递envvar的原因是因为Ansible不尊重Userssh配置文件中的设置 - 它已经决定了它想要在启动命令时运行谁.

ec2.py由于维护原因,动态库存()文件是非常糟糕的变更黑客的地方,这就是为什么通常看到--user=REMOTE_USER标志,加上设置ANSIBLE_SSH_ARGS="-F some_ssh_config"环境变量,使得一个丑陋的命令给一个Ansible repo的临时用户.

例如

ANSIBLE_SSH_ARGS="-F other_ssh_config" ansible-playbook playbooks/why_i_am_doing_this.yml -u ubuntu
Run Code Online (Sandbox Code Playgroud)

ansible-playbook playbooks/why_i_am_doing_this.yml -F other_ansible.cfg
Run Code Online (Sandbox Code Playgroud)

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

这是ansible.cfg从系统角度看加载的方式:

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

74947/0x11eadf:    312284       3      2 stat64("/Users/tfisher/code/ansible/ansible.cfg\0", 0x7FFF55D936C0, 0x7FD70207EA00)             = 0 0
74947/0x11eadf:    312308      19     17 open_nocancel("/Users/tfisher/code/ansible/ansible.cfg\0", 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\0", 0x0, 0x1B6)          = 5 0
Run Code Online (Sandbox Code Playgroud)

选项B不起作用的原因与A不起作用的原因相同 - 即使您使用正确的读/读/读取线sigatures创建模拟Python文件对象,该文件仍然只是为了读取而不是执行而打开.

如果这是OpenSSH的正确repo,则配置文件如下所示:

#define _PATH_HOST_CONFIG_FILE      SSHDIR "/ssh_config"
Run Code Online (Sandbox Code Playgroud)

像这样处理:

    /* 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);
Run Code Online (Sandbox Code Playgroud)

并在这里阅读一个fopen,没有留下"文件作为脚本"schenanigans的空间.