
私は特定のディレクトリへのアクセスを許可および拒否するためのAnsibleプレイブックを作成しています。 Baseはユーザー辞書のリストです。
users:
- {name: 'user1', dirs: ['dir1', 'dir2']}
- {name: 'user2', dirs: ['dir1', 'dir3']}
- {name: 'user3', dirs: []}
セカンダリとして、すべてのユーザー履歴に表示されるすべてのディレクトリのリストを作成しました。
これで、このリストを2つの新しいリストに変換したいと思います。
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"
]
}