How to catch, ONLY the total number of slots an specific master node has in Ansible?
I know that if you run:
redis-cli --cluster check
You'll get this output for example:
192.168.56.115:6379 (7d0fb9ab...) -> 0 keys | 4242 slots | 0 slaves.
192.168.56.116:6379 (9fe57cd1...) -> 0 keys | 3950 slots | 0 slaves.
192.168.56.117:6379 (d37e89a6...) -> 0 keys | 4096 slots | 0 slaves.
192.168.56.118:6379 (e0eb74db...) -> 0 keys | 4096 slots | 0 slaves.
[OK] 0 keys in 4 masters.
0.00 keys per slot on average.
>>> Performing Cluster Check (using node 192.168.56.115:6379)
M: 7d0fb9abd91d6397f11e6f606c8ecf919ba2d1fe 192.168.56.115:6379
slots:[0-4241] (4242 slots) master
M: 9fe57cd1faaa6e77d0e89c504b9f8b69f72c52aa 192.168.56.116:6379
slots:[4242-8191] (3950 slots) master
M: d37e89a685ec31f3ce85544203132f862d8330a7 192.168.56.117:6379
slots:[8192-12287] (4096 slots) master
M: e0eb74db5c6ccbc469538d05bf98302d056c7e05 192.168.56.118:6379
slots:[12288-16383] (4096 slots) master
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
I want to write an Ansible playbook that given the target node's ip as target_node_ip
, it gives this output: for example for target_node_ip = 192.168.56.116
3950
I've tried many regex patterns, but they didn't help me.
For example, I wrote these tasks:
- name: Catch --cluster check
command: >
redis-cli --user default --cluster check 192.168.56.115:6379
register: cluster_check_output
- name: Catch the number of slots the target currently has
set_fact:
node_slots: "{{cluster_check_output.stdout | regex_replace('.*{{ target_node_ip }}:6379 \\(.{8}\\.{3}\\) -> \\d+ keys | (\\d+) slots | \\d+ slaves.*', '\\1')}}"
- name: Debug node_slots
debug:
var: node_slots
And the output is this:
TASK [Debug node_slots] ***********************************************************************************************************************
task path: /home/behnia/projects/redis-test/redis-cluster/redis-cluster-management/playbooks/remove_node.yml:64
ok: [server3] => {
"node_slots": "192.168.56.115:6379 (7d0fb9ab...) -> 0 keys |4242|\n192.168.56.116:6379 (9fe57cd1...) -> 0 keys |3950|\n192.168.56.117:6379 (d37e89a6...) -> 0 keys |4096|\n192.168.56.118:6379 (e0eb74db...) -> 0 keys |4096|\n\u001b[32;1m[OK] 0 keys in 4 masters.\n\u001b[0m0.00 keys per slot on average.\n\u001b[29;1m>>> Performing Cluster Check (using node 192.168.56.115:6379)\n\u001b[0mM: 7d0fb9abd91d6397f11e6f606c8ecf919ba2d1fe 192.168.56.115:6379\n slots:[0-4241] (4242 slots) master\nM: 9fe57cd1faaa6e77d0e89c504b9f8b69f72c52aa 192.168.56.116:6379\n slots:[4242-8191] (3950 slots) master\nM: d37e89a685ec31f3ce85544203132f862d8330a7 192.168.56.117:6379\n slots:[8192-12287] (4096 slots) master\nM: e0eb74db5c6ccbc469538d05bf98302d056c7e05 192.168.56.118:6379\n slots:[12288-16383] (4096 slots) master\n\u001b[32;1m[OK] All nodes agree about slots configuration.\n\u001b[0m\u001b[29;1m>>> Check for open slots...\n\u001b[0m\u001b[29;1m>>> Check slots coverage...\n\u001b[0m\u001b[32;1m[OK] All16384covered.\n\u001b[0m"
}
If you see, instead of replacing the whole output with 3950, it replaced every | <#> slots |
with |#|
, where # is number of slots (in this context 4242, 3950, 4096, 4096
).
What I want is just 3950 (for target_node_ip = 192.168.56.116
)
As already mentioned within the comments one minimal example playbook ...
Pre-processing in shell
on Remote Node(s) and in order to catch up the final result set only.
---
- hosts: localhost
become: false
gather_facts: false
vars:
target_node_ip: 192.168.56.116
tasks:
- name: Catch --cluster check
shell: |
cat redis.stdout | # redis-cli --cluster check
grep {{ target_node_ip }} | # for specific node only
head -n 1 | # first line found
cut -d '|' -f 2 | # result between pipes
grep -o '[0-9]' | # and numbers only
tr -d '\n' #
register: slots
- name: Show the number of slots the target currently has
debug:
var: slots.stdout
will result into an output of
TASK [Show the number of slots the target currently has] ******
ok: [localhost] =>
slots.stdout: '3950'
Ansible Custom Fact
Somehow similar can be implemented as a Custom fact. Then just gather_facts
or setup
would be necessary. See How to implement and use a Custom Fact?