Difficulties to loop over array result - ansible

I have to modified all bashrc files of all users on my linux servers.
I have this playbook to get all bashrc files :
- hosts: all
become: yes
gather_facts: no
tasks:
- name: List all bashrc in home directories
ansible.builtin.find:
path: /home/
pattern: '*.bashrc'
recurse: yes
hidden: yes
file_type: file
register: files_matched
- name: debug
debug:
var: item.path
loop: "{{ files_matched.files }}"
The result is I have on my screen all values for all bashrc files like this :
TASK [debug] ************************************************************************************************************************************************************************************
ok: [REDHAT7-DEV-01] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1556196786.966984, u'gr_name': u'root', u'path': u'/home/.bashrc', u'xusr': False, u'atime': 1556194629.8001442, u'inode': 12, u'isgid': False, u'size': 531, u'isdir': False, u'ctime': 1556196786.966984, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64773, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True}) => {
"ansible_loop_var": "item",
"item": {
"atime": 1556194629.8001442,
"ctime": 1556196786.966984,
"dev": 64773,
"gid": 0,
"gr_name": "root",
"inode": 12,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1556196786.966984,
"nlink": 1,
"path": "/home/.bashrc",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 531,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
"item.path": "/home/.bashrc"
}
I have this for all users in /home/
When I do this
- name: debug
debug:
var: files_matched
I have an array :
TASK [debug] ************************************************************************************************************************************************************************************
ok: [REDHAT7-DEV-01] => {
"files_matched": {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"examined": 2268,
"failed": false,
"files": [
{
"atime": 1556194629.8001442,
"ctime": 1556196786.966984,
"dev": 64773,
"gid": 0,
"gr_name": "root",
"inode": 12,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1556196786.966984,
"nlink": 1,
"path": "/home/.bashrc",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 531,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
How I can have just the path in order to loop over it and add my modification ?
I have some difficulties with loop and array, I don't find a solution.
Thank you for your help.

I have done a modification on the last taks :
- name: debug
debug:
msg: "path is {{ item.path }}."
loop: "{{ files_matched.files }}"
I have what I want but I don't understand why I have all informations :
ok: [REDHAT7-DEV-01] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1666709700.946537, u'gr_name': u'root', u'path': u'/tmp/testdpi2.txt', u'xusr': False, u'atime': 1666709714.4843469, u'inode': 25, u'isgid': False, u'size': 14, u'isdir': False, u'ctime': 1666709700.946537, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64775, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True}) => {
"msg": "path is /tmp/testdpi2.txt."
}
ok: [REDHAT7-DEV-01] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1666709644.4183307, u'gr_name': u'root', u'path': u'/tmp/testdpi.txt', u'xusr': False, u'atime': 1666709706.733456, u'inode': 24, u'isgid': False, u'size': 6, u'isdir': False, u'ctime': 1666709644.4183307, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64775, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True}) => {
"msg": "path is /tmp/testdpi.txt."
}
ok: [REDHAT7-DEV-01] => (item={u'rusr': True, u'uid': 0, u'rgrp': True, u'xoth': False, u'islnk': False, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1666709689.7376943, u'gr_name': u'root', u'path': u'/tmp/testdpi3.txt', u'xusr': False, u'atime': 1666709691.5566688, u'inode': 26, u'isgid': False, u'size': 21, u'isdir': False, u'ctime': 1666709689.7376943, u'isblk': False, u'wgrp': False, u'xgrp': False, u'isuid': False, u'dev': 64775, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True}) => {
"msg": "path is /tmp/testdpi3.txt."
}
item.path is the variable I have to use to do my modification but how I can avoid the informations I don't want to see ((item={u'rusr': True, u'uid': 0, etc...) ?

Related

How to resolve the dependencies for locally downloaded packages in Ansible? When package A is depends on Package B

I have simple playbook where trying to install the Debian packages downloaded locally in my server. This playbook runs on localhost and install the Debian packages in the same system. But this playbook gives an error "Dependency is not satisfiable for some of the packages even tough the dependency package is available in the local repository.
I can download all the dependencies required for the specific package in my local repository using apt-get install --download-only package_name
But in my playbook, i should have a mechanism to install the dependencies first than install the actual package. This task should be dynamic, playbook should resolve the dependencies by itself for any package install.
When the package has dependency over another package, How the playbook resolve dynamically.
Some of the options explored:
Using ordered indexed_items, using gdebi.. Looking for efficient Logic.
Local Repository has packages -> It can grow depends on the requirement:
wireshark_3.0.5-1_amd64.deb wireshark-qt_3.0.5-1_amd64.deb
Here wireshark_3.0.5-1_amd64.deb has dependency over wireshark-qt_3.0.5-1_amd64.deb.
install_dependencies.yml
---
- hosts: localhost
vars:
remote_media_directory: "/home/local_repository"
become: yes
tasks:
- name: find all debian Packages
find:
paths:
- "{{ remote_media_directory }}"
file_type: file
recurse: yes
use_regex: yes
patterns:
- '.*deb$'
register: files_matched_subdirectory
- name: installation debian packages
apt:
deb: "{{ item.path }}"
with_items: "{{ files_matched_subdirectory.files }}"
when: ansible_distribution == "Ubuntu"
ansible-playbook install_dependencies.yml
PLAY [localhost] **********************************************************************************************************************************************************************************************
TASK [Gathering Facts] ****************************************************************************************************************************************************************************************
ok: [localhost]
TASK [find all debian Packages] *******************************************************************************************************************************************************************************
ok: [localhost]
TASK [installation debian packages] ***************************************************************************************************************************************************************************
failed: [localhost] (item={u'uid': 0, u'woth': False, u'mtime': 1571850269.5720358, u'inode': 31195175, u'isgid': False, u'size': 46700, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/wireshark_3.0.5-1_amd64.deb', u'xusr': False, u'atime': 1571850391.3553286, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False}) => {"changed": false, "item": {"atime": 1571850391.3553286, "ctime": 1571850312.2437878, "dev": 2051, "gid": 0, "gr_name": "root", "inode": 31195175, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "mode": "0644", "mtime": 1571850269.5720358, "nlink": 1, "path": "/home/local_repository/wireshark_3.0.5-1_amd64.deb", "pw_name": "root", "rgrp": true, "roth": true, "rusr": true, "size": 46700, "uid": 0, "wgrp": false, "woth": false, "wusr": true, "xgrp": false, "xoth": false, "xusr": false}, "msg": "Dependency is not satisfiable: wireshark-qt (= 3.0.5-1)\n"}
failed: [localhost] (item={u'uid': 0, u'woth': False, u'mtime': 1571850269.4560366, u'inode': 31195174, u'isgid': False, u'size': 3605060, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/wireshark-qt_3.0.5-1_amd64.deb', u'xusr': False, u'atime': 1571850394.3993108, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False}) => {"changed": false, "item": {"atime": 1571850394.3993108, "ctime": 1571850312.2437878, "dev": 2051, "gid": 0, "gr_name": "root", "inode": 31195174, "isblk": false, "ischr": false, "isdir": false, "isfifo": false, "isgid": false, "islnk": false, "isreg": true, "issock": false, "isuid": false, "mode": "0644", "mtime": 1571850269.4560366, "nlink": 1, "path": "/home/local_repository/wireshark-qt_3.0.5-1_amd64.deb", "pw_name": "root", "rgrp": true, "roth": true, "rusr": true, "size": 3605060, "uid": 0, "wgrp": false, "woth": false, "wusr": true, "xgrp": false, "xoth": false, "xusr": false}, "msg": "Dependency is not satisfiable: libc6 (>= 2.29)\n"}
ok: [localhost] => (item={u'uid': 0, u'woth': False, u'mtime': 1571850217.1323407, u'inode': 31195169, u'isgid': False, u'size': 40654, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/tree_1.7.0-5_amd64.deb', u'xusr': False, u'atime': 1571850397.4392931, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False})
ok: [localhost] => (item={u'uid': 0, u'woth': False, u'mtime': 1571850217.0163412, u'inode': 31195168, u'isgid': False, u'size': 52132, u'roth': True, u'isuid': False, u'isreg': True, u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True, u'xoth': False, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'gr_name': u'root', u'path': u'/home/local_repository/dstat_0.7.3-1_all.deb', u'xusr': False, u'atime': 1571850399.3192823, u'isdir': False, u'ctime': 1571850312.2437878, u'wgrp': False, u'xgrp': False, u'dev': 2051, u'isblk': False, u'isfifo': False, u'mode': u'0644', u'islnk': False})
to retry, use: --limit #/home/upgrade/ansible/install_dependencies.retry
PLAY RECAP ****************************************************************************************************************************************************************************************************
localhost : ok=2 changed=0 unreachable=0 failed=1
First Setup local repository in the remote server and download install packages using apt-get install --download-only package_name in the remote server. Modify local system /etc/apt/sources.list to point to the local repository packages.
When ansible script try to install using apt-get -y install , it will connect to the local repository and fetches the packages and resolves the dependencies.
Please check the below links for more info
https://kerneltalks.com/package/how-to-configure-local-apt-repository/
https://askubuntu.com/questions/170348/how-to-create-a-local-apt-repository

How to grab filepath from ansibles find module

I'm using Ansible for some IAC(infra as code) tasks.
I have a playbook where I'm using the find module recursively to search for readable files.
Here is an example of it:
- name: Application logs with read access
become: true
find:
paths: /
file_type: file
recurse: yes
patterns:
- '*.log'
- '*.config'
register: rapplogs
- set_fact: read_app_logs={{rapplogs.matched}}
- debug: var=read_app_logs
- set_fact: read_log_list={{rapplogs.files}}
- debug: var=read_log_list
run_once: True
failed_when: read_app_logs >= 1
ignore_errors: True
The output of it is like this:
TASK [infra_pt : set_fact] ******************************************************************
ok: [192.168.47.135]
TASK [infra_pt : debug] *********************************************************************
ok: [192.168.47.135] => {
"read_app_logs": "72"
}
TASK [infra_pt : set_fact] ******************************************************************
ok: [192.168.47.135]
TASK [infra_pt : debug] *********************************************************************
fatal: [192.168.47.135]: FAILED! => {
"failed_when_result": true,
"read_log_list": {
"changed": false,
"examined": 210060,
"failed": false,
"files": [
{
"atime": 1558446815.3474104,
"ctime": 1558446815.3474104,
"dev": 64768,
"gid": 0,
"gr_name": "root",
"inode": 2065610,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1558446815.3474104,
"nlink": 1,
"path": "/test2.log",
"pw_name": "root",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 0,
"uid": 0,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
},
From the output list I actually want to access only the "mode" and "path" objects, how this can be done? Any idea?
Try json_query
- set_fact:
read_app_logs: "{{ rapplogs.files|json_query('[].{path: path, mode: mode}') }}"
(not tested)
Sure. You can just iterate over the list of matched files and refer to whichever keys are of interest:
- debug:
msg: "mode of {{ item.path }} is {{ item.mode }}"
loop: "{{ read_log_list.files }}"
Which, given your example output, would produce something like this:
TASK [debug] **********************************************************************************
ok: [localhost] => (item={u'islnk': False, u'uid': 0, u'rgrp': True, u'xoth': False, u'rusr': True, u'woth': False, u'nlink': 1, u'issock': False, u'mtime': 1558446815.3474104, u'gr_name': u'root', u'path': u'/test2.log', u'xusr': False, u'atime': 1558446815.3474104, u'inode': 2065610, u'isgid': False, u'size': 0, u'isdir': False, u'wgrp': False, u'ctime': 1558446815.3474104, u'isblk': False, u'xgrp': False, u'isuid': False, u'dev': 64768, u'roth': True, u'isreg': True, u'isfifo': False, u'mode': u'0644', u'pw_name': u'root', u'gid': 0, u'ischr': False, u'wusr': True}) => {
"msg": "mode of /test2.log is 0644"
}

Need to find conf file on the system and need to replace a line

Everyone, I am using the below script to find all the httpd.conf file in /tmp using the find module and after that, i need to change the server root for all the httpd.conf files that I got from the find module. I am using the Below code.
getting the below error while executing the lineinline module.
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Destination {'files': [{'uid': 0, 'woth': False, 'mtime': 1554392266.9903164, 'inode': 4232796, 'isgid': False, 'size': 11753, 'roth': True, 'isuid': False, 'isreg': True, 'pw_name': 'root', 'gid': 0, 'ischr': False, 'wusr': True, 'xoth': False, 'rusr': True, 'nlink': 1, 'issock': False, 'rgrp': True, 'gr_name': 'root', 'path': '/tmp/httpd.conf', 'xusr': False, 'atime': 1554391744.8432574, 'isdir': False, 'ctime': 1554392266.9903164, 'wgrp': False, 'xgrp': False, 'dev': 51714, 'isblk': False, 'isfifo': False, 'mode': '0644', 'islnk': False}], 'changed': False, 'failed': False, 'examined': 14, 'msg': '', 'matched': 1} does not exist !", "rc": 257}
to retry, use: --limit #/etc/ansible/findnew.retry
---
- name: Recursively find httpd.conf file in /tmp
connection: local
hosts: localhost
tasks:
- find:
paths: /tmp
patterns: '*.conf'
recurse: yes
register: filestoser
- debug: var=filestoser
- lineinfile:
path: '{{ filestoser }}'
state: present
regexp: '^ServerRoot'
line: 'ServerRoot_new'
Your problem is that you're trying to use the variable filestoser as a filename, but it's not: it's the result of the find task. If you take a look at the output of your debug task you'll see something like this:
TASK [debug] **********************************************************************************
ok: [localhost] => {
"filestoser": {
"changed": false,
"examined": 44,
"failed": false,
"files": [
{
"atime": 1554394659.885133,
"ctime": 1554394659.885133,
"dev": 45,
"gid": 21937,
"gr_name": "lars",
"inode": 172846,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0644",
"mtime": 1554394659.885133,
"nlink": 1,
"path": "/tmp/etc/httpd/httpd.conf",
"pw_name": "lars",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 11753,
"uid": 21937,
"wgrp": false,
"woth": false,
"wusr": true,
"xgrp": false,
"xoth": false,
"xusr": false
}
],
"matched": 1,
"msg": ""
}
}
In other words, filestoser is a dictionary. The files key contains a list of files that were matched by the files task. You could rewrite your lineinfile task like this, if you want to operate on the first file found:
- lineinfile:
path: '{{ filestoser.files.0.path }}'
state: present
regexp: '^ServerRoot'
line: 'ServerRoot_new'

Ansible replace command is not working find module

I am new to Ansible, I have to find some file and then replace some pattern in the all files. so I am using the find and replace module as follows.
- name: My Great Playbook
hosts: all
gather_facts: False
accelerate: False
strategy: free
vars:
dbname: "#DBNAME#"
repldbname: "connect to mydb"
tasks:
- block:
- name: finding fl
find:
paths: "/home/username1/temp"
patterns: "*.sql"
file_type: "file"
register: repos
- name: some thing
debug: msg="{{ item }}"
with_items: "{{ repos.files }}"
- name: replacing string
replace:
path: "{{ item }}"
#path: "/home/username1/temp/1.sql"
regexp: ({{ dbname }})
replace: '{{ repldbname }}'
backup: no
unsafe_writes: yes
with_items: "{{ repos.files }}"
I am getting following error as follows
failed: [localhost] (item={u'uid': 575479814, u'woth': True, u'mtime': 1504541305.603901, u'inode': 8433422, u'isgid': False, u'size': 256, u'roth': True, u'isuid': False, u'isreg': True, u'gid': 575144449, u'ischr': False, u'wusr': True, u'xoth': True, u'rusr': True, u'nlink': 1, u'issock': False, u'rgrp': True, u'path': u'/home/username1/temp/1.sql', u'xusr': True, u'atime': 1504541305.604901, u'isdir': False, u'ctime': 1504541305.6059012, u'wgrp': True, u'xgrp': True, u'dev': 64772, u'isblk': False, u'isfifo': False, u'mode': u'0777', u'islnk': False}) => {
"failed": true,
"item": {
"atime": 1504541305.604901,
"ctime": 1504541305.6059012,
"dev": 64772,
"gid": 575144449,
"inode": 8433422,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": true,
"issock": false,
"isuid": false,
"mode": "0777",
"mtime": 1504541305.603901,
"nlink": 1,
"path": "/home/username1/temp/1.sql",
"rgrp": true,
"roth": true,
"rusr": true,
"size": 256,
"uid": 575479814,
"wgrp": true,
"woth": true,
"wusr": true,
"xgrp": true,
"xoth": true,
"xusr": true
},
"rc": 257
}
MSG:
Path {'uid': 575479814, 'woth': True, 'mtime': 1504541305.603901, 'inode': 8433422, 'isgid': False, 'size': 256, 'wgrp': True, 'isuid': False, 'isreg': True, 'gid': 575144449, 'ischr': False, 'wusr': True, 'xoth': True, 'islnk': False, 'nlink': 1, 'issock': False, 'rgrp': True, 'path': '/home/username1/temp/1.sql', 'xusr': True, 'atime': 1504541305.604901, 'isdir': False, 'ctime': 1504541305.6059012, 'isblk': False, 'xgrp': True, 'dev': 64772, 'roth': True, 'isfifo': False, 'mode': '0777', 'rusr': True} does not exist !
Please let me know what is issue here ?
Replace:
path: "{{ item }}"
With:
path: "{{ item.path }}"
You are trying to pass a dictionary object to an argument which requires a string value.

How do i filter on ansible stat existence flags?

I'm executing a simple stat task (Ansible 2.3.1.0) on the named pipe created by wpa_supplicant:
- stat:
path: "/var/run/wpa_supplicant/{{ item }}"
with_items:
- wifi
register: wpa_stats
sudo: true
The variable contains the following data after execution:
ok: [10.10.23.187] => {
"wpa_stats": {
"changed": false,
"msg": "All items completed",
"results": [
{
"_ansible_item_result": true,
"_ansible_no_log": false,
"_ansible_parsed": true,
"changed": false,
"invocation": {
"module_args": {
"checksum_algorithm": "sha1",
"follow": false,
"get_attributes": true,
"get_checksum": true,
"get_md5": true,
"get_mime": true,
"path": "/var/run/wpa_supplicant/wifi"
}
},
"item": "wifi",
"stat": {
"atime": 1497900522.6306846,
"attr_flags": "",
"attributes": [],
"block_size": 4096,
"blocks": 0,
"charset": "binary",
"ctime": 1497900290.0605242,
"dev": 18,
"device_type": 0,
"executable": true,
"exists": true,
"gid": 0,
"gr_name": "root",
"inode": 796,
"isblk": false,
"ischr": false,
"isdir": false,
"isfifo": false,
"isgid": false,
"islnk": false,
"isreg": false,
"issock": true,
"isuid": false,
"mimetype": "inode/socket",
"mode": "0770",
"mtime": 1497900290.0605242,
"nlink": 1,
"path": "/var/run/wpa_supplicant/wifi",
"pw_name": "root",
"readable": true,
"rgrp": true,
"roth": false,
"rusr": true,
"size": 0,
"uid": 0,
"version": null,
"wgrp": true,
"woth": false,
"writeable": true,
"wusr": true,
"xgrp": true,
"xoth": false,
"xusr": true
}
}
]
}
}
But this filter returns an empty result:
- debug:
msg: "{{ wpa_stats | json_query('results[*].stat[?exists].path') | list }}"
If I remove the [?exists] filter it works fine:
- debug:
msg: "{{ wpa_stats | json_query('results[*].stat.path') | list }}"
I've also tried using ==. Jmespath is installed and I'm querying other values with JSON filters successfully.
What am I missing?
I guess you want to use pipe expression:
results[*].stat | [?exists].path
From my understating of JMESPath in stat[?filter] filter is applied inside stat (to select elements that are down the path), but you want to apply filter to select/reject stat siblings, so you should stop further projections with pipe and filter elements.

Resources