英文:
How can I pass variables to command module's argv parameter in Ansible?
问题
我试图编写一个配置Redis集群的Ansible角色。
创建集群的shell命令是:
$ /usr/bin/redis-cli --user admin --pass mypass --cluster create 10.226.2.194:6379 10.226.2.196:6379 10.226.2.195:6379 --cluster-replicas 1 --cluster-yes
我将用户名、密码、Redis服务器的IP地址和副本数量作为extra-vars
传递给shell脚本:
#!/bin/sh
ansible-playbook /etc/ansible/playbook-redis.yml -vv \
--extra-vars='redis_admin_user=admin redis_admin_password=mypass' \
--extra-vars='redis_cluster_members="10.226.2.194:6379 10.226.2.196:6379 10.226.2.195:6379" redis_cluster_replicas=1';
在阅读命令模块的文档后,我编写了以下任务:
- name: 创建Redis集群
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- "--user {{ redis_admin_user }}"
- "--pass {{ redis_admin_password }}"
- "--cluster create {{ redis_cluster_members }}"
- "--cluster-replicas {{ redis_cluster_replicas }}"
- --cluster-yes
但是当我运行它时,我收到以下错误消息:
"未识别的选项或参数数量不正确: '--user admin'"
这似乎是redis-cli不识别参数的错误。
通过更改任务,我成功解决了用户名和密码的问题,如下所示:
- name: 创建Redis集群
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- --cluster create
- "{{ redis_cluster_members }}"
- --cluster-replicas
- "{{ redis_cluster_replicas }}"
- --cluster-yes
这看起来不太美观,但至少传递了用户名和密码,因为以下任务有效:
- name: 获取服务器信息
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- info
但是现在它无法通过--cluster create
参数:
"未识别的选项或参数数量不正确: '--cluster create'"
我还尝试了- --cluster create "{{ redis_cluster_members }}"
以及以下方法,但都没有成功:
- --cluster
- create
- "{{ redis_cluster_members }}"
请问运行这个命令的正确语法是什么?
附言:
以下任务正常工作:
- name: 获取Redis版本
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- --version
并返回版本号。
附言:
以下也有效:
- name: 创建Redis集群
ansible.builtin.command:
cmd: "/usr/bin/redis-cli --user {{ redis_admin_user }} --pass {{ redis_admin_password }} --cluster create {{ redis_cluster_members }} --cluster-replicas {{ redis_cluster_replicas }} --cluster-yes"
英文:
I'm trying to write an Ansible role that configures Redis cluster.
The shell command that creates the cluster is:
$ /usr/bin/redis-cli --user admin --pass mypass --cluster create 10.226.2.194:6379 10.226.2.196:6379 10.226.2.195:6379 --cluster-replicas 1 --cluster-yes
I pass username, password, IP addresses of Redis servers and number of replicas as extra-vars
in shell script
#!/bin/sh
ansible-playbook /etc/ansible/playbook-redis.yml -vv \
--extra-vars='redis_admin_user=admin redis_admin_password=mypass' \
--extra-vars='redis_cluster_members="10.226.2.194:6379 10.226.2.196:6379 10.226.2.195:6379" redis_cluster_replicas=1'
After reading the documentation for the command module I wrote the following task:
- name: Create Redis cluster
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- "--user {{ redis_admin_user }}"
- "--pass {{ redis_admin_password }}"
- "--cluster create {{ redis_cluster_members }}"
- "--cluster-replicas {{ redis_cluster_replicas }}"
- --cluster-yes
But when I run it I get the following error:
"Unrecognized option or bad number of args for: '--user admin'"
which seems to be error of redis-cli that it doesn't recognize the argument.
I was able to get around the username and password by changing the task as following:
- name: Create Redis cluster
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- --cluster create
- "{{ redis_cluster_members }}"
- --cluster-replicas
- "{{ redis_cluster_replicas }}"
- --cluster-yes
This is not exactly nice looking, but at least it passes the username and the password, because the following task works:
- name: Get server info
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- info
But now it can't get past the --cluster create
argument:
"Unrecognized option or bad number of args for: '--cluster create'"
I also tried - --cluster create "{{ redis_cluster_members }}"
and
- --cluster
- create
- "{{ redis_cluster_members }}"
to no avail.
What is the correct syntax to run this command?
P.S.
The following task works correctly:
- name: Get Redis version
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- --version
and returns the version.
P.P.S
The following also works
- name: Create Redis cluster
ansible.builtin.command:
cmd: "/usr/bin/redis-cli --user {{ redis_admin_user }} --pass {{ redis_admin_password }} --cluster create {{ redis_cluster_members }} --cluster-replicas {{ redis_cluster_replicas }} --cluster-yes"
答案1
得分: 1
以下是翻译好的部分:
- 我不能测试,但我相当肯定您需要在
argv
列表中将每个集群成员分开为自己的项目。以下内容有点丑陋,但应该可以工作。
- name: 创建 Redis 集群
vars:
argv_start:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- --cluster
- create
argv_end:
- --cluster-replicas
- "{{ redis_cluster_replicas }}"
- --cluster-yes
ansible.builtin.command:
argv: "{{ argv_start + [redis_cluster_replicas] + argv_end }}"
英文:
I can't test but I'm pretty sure you need to separate each cluster member in its own item in the argv
list. The following is a bit ugly but should work.
- name: Create Redis cluster
vars:
argv_start:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- --cluster
- create
argv_end:
- --cluster-replicas
- "{{ redis_cluster_replicas }}"
- --cluster-yes
ansible.builtin.command:
argv: "{{ argv_start + redis_cluster_replicas | split + argv_end }}"
答案2
得分: 0
Got help from Ansible devs at GitHub. The reason for this behavior is how command module and redis-cli utility work with arguments.
argv
adds delimiters when passing the command to the command line. So this:
- name: Create Redis cluster
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- "--user {{ redis_admin_user }}"
- "--pass {{ redis_admin_password }}"
- "--cluster create {{ redis_cluster_members }}"
- "--cluster-replicas {{ redis_cluster_replicas }}"
- --cluster-yes
turns to (mind the single quotation marks)
/usr/bin/redis-cli '--user admin' '--pass mypass' '--cluster create 10.226.2.194:6379 10.226.2.196:6379 10.226.2.195:6379' '--cluster-replicas 1' '--cluster-yes'
If you enter the above command directly you'll get the same error when running the task - "Unrecognized option or bad number of args for: '--user admin'"
This is because how redis-cli delimits arguments. From redis-cli documentation:
> When redis-cli
parses a command, whitespace characters automatically delimit the arguments.
So, the correct command should be (note the single quotation marks)
/usr/bin/redis-cli '--user' 'admin' '--pass' 'mypass' '--cluster' 'create' '10.226.2.194:6379' '10.226.2.196:6379' '10.226.2.195:6379' '--cluster-replicas' '1' '--cluster-yes'
But for the Ansible task there is a problem - redis_cluster_members
variable.
The solution suggested to me at GitHub:
- name: Create Redis cluster
ansible.builtin.command:
argv: "{{ redis_argv | flatten }}"
vars:
redis_argv:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- --cluster
- create
- "{{ redis_cluster_members | split }}"
- --cluster-replicas
- "{{ redis_cluster_replicas }}"
- --cluster-yes
It works, but I decided to use a workaround. In vars/main.yml
I defined a variable
redis_create_cluster_command: >
/usr/bin/redis-cli --user {{ redis_admin_user | quote }} --pass {{ redis_admin_password | quote }}
--cluster create {{ redis_cluster_members }}
--cluster-replicas {{ redis_cluster_replicas | quote }} --cluster-yes
For the explanation about >
please read this article, particularly the second part.
The quote
filter is for, as suggested in command module's documentation, "to avoid injection issues". Note that it's missing from redis_cluster_members
line because it too breaks the arguments.
The task itself:
- name: Create Redis cluster
ansible.builtin.command:
cmd: "{{ redis_create_cluster_command }}"
creates: "{{ redis_etc }}/redis_cluster.created"
no_log: true
英文:
Got help from Ansible devs at GitHub. The reason for this behavior is how command module and redis-cli utility work with arguments.
argv
adds delimiters when passing the command to the command line. So this:
- name: Create Redis cluster
ansible.builtin.command:
argv:
- /usr/bin/redis-cli
- "--user {{ redis_admin_user }}"
- "--pass {{ redis_admin_password }}"
- "--cluster create {{ redis_cluster_members }}"
- "--cluster-replicas {{ redis_cluster_replicas }}"
- --cluster-yes
turns to (mind the single quotation marks)
/usr/bin/redis-cli '--user admin' '--pass mypass' '--cluster create 10.226.2.194:6379 10.226.2.196:6379 10.226.2.195:6379' '--cluster-replicas 1' '--cluster-yes'
If you enter the above command directly you'll get the same error when running the task - "Unrecognized option or bad number of args for: '--user admin'"
This is because how redis-cli delimits arguments. From redis-cli documentation:
> When redis-cli
parses a command, whitespace characters automatically delimit the arguments.
So, the correct command should be (note the single quotation marks)
/usr/bin/redis-cli '--user' 'admin' '--pass' 'mypass' '--cluster' 'create' '10.226.2.194:6379' '10.226.2.196:6379' '10.226.2.195:6379' '--cluster-replicas' '1' '--cluster-yes'
But for the Ansible task there is a problem - redis_cluster_members
variable.
The solution suggested to me at GitHub:
- name: Create Redis cluster
ansible.builtin.command:
argv: "{{ redis_argv | flatten }}"
vars:
redis_argv:
- /usr/bin/redis-cli
- --user
- "{{ redis_admin_user }}"
- --pass
- "{{ redis_admin_password }}"
- --cluster
- create
- "{{ redis_cluster_members | split }}"
- --cluster-replicas
- "{{ redis_cluster_replicas }}"
- --cluster-yes
It works, but I decided to use a workaround.
In vars/main.yml
I defined a variable
redis_create_cluster_command: >
/usr/bin/redis-cli --user {{ redis_admin_user | quote }} --pass {{ redis_admin_password | quote }}
--cluster create {{ redis_cluster_members }}
--cluster-replicas {{ redis_cluster_replicas | quote }} --cluster-yes
For the explanation about >
please read this article, particularly the second part.
The quote
filter is for, as suggested in command module's documentation, "to avoid injection issues". Note that it's missing from redis_cluster_members
line because it too breaks the arguments.
The task itself:
- name: Create Redis cluster
ansible.builtin.command:
cmd: "{{ redis_create_cluster_command }}"
creates: "{{ redis_etc }}/redis_cluster.created"
no_log: true
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论