저는 특정 디렉터리에 대한 액세스를 허용하고 거부하기 위한 Ansible 플레이북을 작성 중입니다. Base는 사용자 사전 목록입니다.
users:
- {name: 'user1', dirs: ['dir1', 'dir2']}
- {name: 'user2', dirs: ['dir1', 'dir3']}
- {name: 'user3', dirs: []}
보조 사실로 모든 사용자 기록에 나타나는 모든 디렉터리 목록을 만들었습니다.
이제 이 목록을 두 개의 새로운 목록으로 변환하고 싶습니다.
dirs_allowed:
- {'dir1': ['user1', 'user2']}
- {'dir2': ['user1']}
- {'dir3': ['user2']}
이것은 간단하지만 이 문제에 대한 해결책을 찾을 수 없습니다.
dirs_forbidden:
- {'dir1': ['user3']}
- {'dir2': ['user2', 'user3']}
- {'dir3': ['user1', 'user3']}
그래서 내 질문은: "dirs" 속성에서 현재 디렉터리(=모든 디렉터리의 with_items 루프에 있는 항목)가 없는 모든 사용자 목록을 어떻게 얻을 수 있습니까?
작업에서 보조 변수/사실 또는 "언제" 조건을 사용하여 이 작업을 수행하는 것은 확실히 가능하지만 이러한 복잡한 변환을 처리하는 방법을 배우고 싶기 때문에 목록을 직접 변환하고 싶습니다. 그 뒤에 있는 아이디어는 사전을 입력으로 제공하고 중간에 많은 set_fact-task를 사용하지 않고 해당 사전에서 특정 작업에 필요한 모든 것을 추출하는 것입니다. 이렇게 하면 플레이북을 읽기 어렵게 만들고 정의되지 않은 변수로 인해 잠재적으로 오류가 발생할 수 있습니다. 변수가 아직 설정되지 않은 중간 변수로 작업이 이동되면 실패합니다.
답변1
필터 사용차이점. 예를 들어
- set_fact:
users_all: "{{ users|json_query('[].name') }}"
- set_fact:
dirs_forbidden: "{{ dirs_forbidden|default([]) + [
{(item.keys()|list|first):
(users_all|difference(item.values()|list|first))}] }}"
loop: "{{ dirs_allowed }}"
- debug:
var: dirs_forbidden
주다
"dirs_forbidden": [
{
"dir1": [
"user3"
]
},
{
"dir2": [
"user2",
"user3"
]
},
{
"dir3": [
"user1",
"user3"
]
}
]
FWIW. 이 경우 사전을 사용하면 코드가 더 간단해집니다. 예를 들어
- set_fact:
users_all: "{{ users|json_query('[].name') }}"
- set_fact:
dirs_all: "{{ users|
json_query('[].dirs')|flatten|unique }}"
- set_fact:
dirs_allowed: "{{ dirs_allowed|default({})|
combine({item: users|json_query(query)}) }}"
vars:
query: "[?dirs.contains(@, '{{ item }}')].name"
loop: "{{ dirs_all }}"
- debug:
var: dirs_allowed
- set_fact:
dirs_forbidden: "{{ dirs_forbidden|default({})|
combine({item: (users_all|difference(dirs_allowed[item]))}) }}"
loop: "{{ dirs_all }}"
- debug:
var: dirs_forbidden
주다
"dirs_allowed": {
"dir1": [
"user1",
"user2"
],
"dir2": [
"user1"
],
"dir3": [
"user2"
]
}
"dirs_forbidden": {
"dir1": [
"user3"
],
"dir2": [
"user2",
"user3"
],
"dir3": [
"user1",
"user3"
]
}