你可以如何将变量传递给Ansible中命令模块的argv参数?

huangapple go评论96阅读模式
英文:

How can I pass variables to command module's argv parameter in Ansible?

问题

我试图编写一个配置Redis集群的Ansible角色。

创建集群的shell命令是:

  1. $ /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脚本:

  1. #!/bin/sh
  2. ansible-playbook /etc/ansible/playbook-redis.yml -vv \
  3. --extra-vars='redis_admin_user=admin redis_admin_password=mypass' \
  4. --extra-vars='redis_cluster_members="10.226.2.194:6379 10.226.2.196:6379 10.226.2.195:6379" redis_cluster_replicas=1';

在阅读命令模块的文档后,我编写了以下任务:

  1. - name: 创建Redis集群
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - "--user {{ redis_admin_user }}"
  6. - "--pass {{ redis_admin_password }}"
  7. - "--cluster create {{ redis_cluster_members }}"
  8. - "--cluster-replicas {{ redis_cluster_replicas }}"
  9. - --cluster-yes

但是当我运行它时,我收到以下错误消息:

  1. "未识别的选项或参数数量不正确: '--user admin'"

这似乎是redis-cli不识别参数的错误。

通过更改任务,我成功解决了用户名和密码的问题,如下所示:

  1. - name: 创建Redis集群
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - --user
  6. - "{{ redis_admin_user }}"
  7. - --pass
  8. - "{{ redis_admin_password }}"
  9. - --cluster create
  10. - "{{ redis_cluster_members }}"
  11. - --cluster-replicas
  12. - "{{ redis_cluster_replicas }}"
  13. - --cluster-yes

这看起来不太美观,但至少传递了用户名和密码,因为以下任务有效:

  1. - name: 获取服务器信息
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - --user
  6. - "{{ redis_admin_user }}"
  7. - --pass
  8. - "{{ redis_admin_password }}"
  9. - info

但是现在它无法通过--cluster create参数:

  1. "未识别的选项或参数数量不正确: '--cluster create'"

我还尝试了- --cluster create "{{ redis_cluster_members }}"以及以下方法,但都没有成功:

  1. - --cluster
  2. - create
  3. - "{{ redis_cluster_members }}"

请问运行这个命令的正确语法是什么?

附言:
以下任务正常工作:

  1. - name: 获取Redis版本
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - --version

并返回版本号。

附言:
以下也有效:

  1. - name: 创建Redis集群
  2. ansible.builtin.command:
  3. 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:

  1. $ /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

  1. #!/bin/sh
  2. ansible-playbook /etc/ansible/playbook-redis.yml -vv \
  3. --extra-vars='redis_admin_user=admin redis_admin_password=mypass' \
  4. --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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - "--user {{ redis_admin_user }}"
  6. - "--pass {{ redis_admin_password }}"
  7. - "--cluster create {{ redis_cluster_members }}"
  8. - "--cluster-replicas {{ redis_cluster_replicas }}"
  9. - --cluster-yes

But when I run it I get the following error:

  1. "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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - --user
  6. - "{{ redis_admin_user }}"
  7. - --pass
  8. - "{{ redis_admin_password }}"
  9. - --cluster create
  10. - "{{ redis_cluster_members }}"
  11. - --cluster-replicas
  12. - "{{ redis_cluster_replicas }}"
  13. - --cluster-yes

This is not exactly nice looking, but at least it passes the username and the password, because the following task works:

  1. - name: Get server info
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - --user
  6. - "{{ redis_admin_user }}"
  7. - --pass
  8. - "{{ redis_admin_password }}"
  9. - info

But now it can't get past the --cluster create argument:

  1. "Unrecognized option or bad number of args for: '--cluster create'"

I also tried - --cluster create "{{ redis_cluster_members }}" and

  1. - --cluster
  2. - create
  3. - "{{ redis_cluster_members }}"

to no avail.

What is the correct syntax to run this command?

P.S.

The following task works correctly:

  1. - name: Get Redis version
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - --version

and returns the version.

P.P.S
The following also works

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. 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列表中将每个集群成员分开为自己的项目。以下内容有点丑陋,但应该可以工作。
  1. - name: 创建 Redis 集群
  2. vars:
  3. argv_start:
  4. - /usr/bin/redis-cli
  5. - --user
  6. - "{{ redis_admin_user }}"
  7. - --pass
  8. - "{{ redis_admin_password }}"
  9. - --cluster
  10. - create
  11. argv_end:
  12. - --cluster-replicas
  13. - "{{ redis_cluster_replicas }}"
  14. - --cluster-yes
  15. ansible.builtin.command:
  16. 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.

  1. - name: Create Redis cluster
  2. vars:
  3. argv_start:
  4. - /usr/bin/redis-cli
  5. - --user
  6. - "{{ redis_admin_user }}"
  7. - --pass
  8. - "{{ redis_admin_password }}"
  9. - --cluster
  10. - create
  11. argv_end:
  12. - --cluster-replicas
  13. - "{{ redis_cluster_replicas }}"
  14. - --cluster-yes
  15. ansible.builtin.command:
  16. 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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - "--user {{ redis_admin_user }}"
  6. - "--pass {{ redis_admin_password }}"
  7. - "--cluster create {{ redis_cluster_members }}"
  8. - "--cluster-replicas {{ redis_cluster_replicas }}"
  9. - --cluster-yes

turns to (mind the single quotation marks)

  1. /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)

  1. /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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. argv: "{{ redis_argv | flatten }}"
  4. vars:
  5. redis_argv:
  6. - /usr/bin/redis-cli
  7. - --user
  8. - "{{ redis_admin_user }}"
  9. - --pass
  10. - "{{ redis_admin_password }}"
  11. - --cluster
  12. - create
  13. - "{{ redis_cluster_members | split }}"
  14. - --cluster-replicas
  15. - "{{ redis_cluster_replicas }}"
  16. - --cluster-yes

It works, but I decided to use a workaround. In vars/main.yml I defined a variable

  1. redis_create_cluster_command: >
  2. /usr/bin/redis-cli --user {{ redis_admin_user | quote }} --pass {{ redis_admin_password | quote }}
  3. --cluster create {{ redis_cluster_members }}
  4. --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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. cmd: "{{ redis_create_cluster_command }}"
  4. creates: "{{ redis_etc }}/redis_cluster.created"
  5. 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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. argv:
  4. - /usr/bin/redis-cli
  5. - "--user {{ redis_admin_user }}"
  6. - "--pass {{ redis_admin_password }}"
  7. - "--cluster create {{ redis_cluster_members }}"
  8. - "--cluster-replicas {{ redis_cluster_replicas }}"
  9. - --cluster-yes

turns to (mind the single quotation marks)

  1. /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)

  1. /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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. argv: "{{ redis_argv | flatten }}"
  4. vars:
  5. redis_argv:
  6. - /usr/bin/redis-cli
  7. - --user
  8. - "{{ redis_admin_user }}"
  9. - --pass
  10. - "{{ redis_admin_password }}"
  11. - --cluster
  12. - create
  13. - "{{ redis_cluster_members | split }}"
  14. - --cluster-replicas
  15. - "{{ redis_cluster_replicas }}"
  16. - --cluster-yes

It works, but I decided to use a workaround.
In vars/main.yml I defined a variable

  1. redis_create_cluster_command: >
  2. /usr/bin/redis-cli --user {{ redis_admin_user | quote }} --pass {{ redis_admin_password | quote }}
  3. --cluster create {{ redis_cluster_members }}
  4. --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:

  1. - name: Create Redis cluster
  2. ansible.builtin.command:
  3. cmd: "{{ redis_create_cluster_command }}"
  4. creates: "{{ redis_etc }}/redis_cluster.created"
  5. no_log: true

huangapple
  • 本文由 发表于 2023年2月9日 00:23:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/75388765.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定