I have the following test setup and result:
$ cat hosts
[test]
abc-1
abc-ecs
abc-x
ecs-1
ecs-y
$ cat test-regex.yaml
- name: test
hosts:
- test
tasks:
- name: set var
set_fact:
myvar: "this is a test"
$ cat hosts | sed "s: ::g" | ggrep -P '^(?!ecs).*'
[test]
abc-1
abc-ecs
abc-x
$ ansible-playbook -i hosts -l ~'^(?!ecs).*' test-regex.yaml -D -C --list-hosts --list-tasks
playbook: test-regex.yaml
play #1 (test): test TAGS: []
pattern: ['test']
hosts (5):
abc-ecs
abc-x
ecs-1
ecs-y
abc-1
tasks:
set var TAGS: []
As shown with ggrep
, ^(?!ecs).*
does not match ecs-1
and ecs-y
, but Ansible says it matches, can you explain?
I would like to apply to hosts starting with ecs
only. I tested with Ansnile Core 2.13.3.
Also for testing purpose, can I maintain one file instead of two as shown here?
The question of the original post asks why -l ~'^(?!ecs).*'
matches every host in the test group:
[test]
abc-1
abc-ecs
abc-x
ecs-1
ecs-y
but not those three abc-*
hosts only as intended. This is because -l ~'^(?!ecs).*'
not only matches hosts, but groups as well, and ansible creates two default groups: all
and ungrouped
. In this case, the regular expression matches:
test
group which contains all 5 hosts listed aboveall
group which contains all 5 hosts listed aboveungrouped
group which contains 0 hostsabc-1
hostabc-x
hostabc-ecs
hostThe union of all above consists the 5 hosts as shown in the output in the original post, so this is an expected behavior. To get what I intended, which is every hosts not starting with ecs, I should exclude the test
and all
groups also. The regular expression and the intended result are copied below.
$ ansible-playbook -i hosts -l ~'^(?!ecs|test|all).*' test-regex.yaml -D -C --list-hosts --list-tasks
playbook: test-regex.yaml
play #1 (test): regexcheck TAGS: []
pattern: ['test']
hosts (3):
abc-1
abc-x
abc-ecs
tasks:
set var TAGS: []
The "mystery" resolved.