From d1813b939183d85fb24c381ed169fa53bf802151 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 27 Jul 2023 13:32:30 +0930 Subject: [PATCH 01/30] feat(migration): initial adding of role to repo !1 --- defaults/main.yml | 46 +++++++++ handlers/main.yaml | 29 ++++++ meta/main.yaml | 13 +++ tasks/configure.yaml | 111 +++++++++++++++++++++ tasks/install.yaml | 150 +++++++++++++++++++++++++++++ tasks/main.yaml | 33 +++++++ templates/fail2ban.filter-api.conf | 15 +++ templates/fail2ban.filter.conf | 17 ++++ 8 files changed, 414 insertions(+) create mode 100644 defaults/main.yml create mode 100644 handlers/main.yaml create mode 100644 meta/main.yaml create mode 100644 tasks/configure.yaml create mode 100644 tasks/install.yaml create mode 100644 tasks/main.yaml create mode 100644 templates/fail2ban.filter-api.conf create mode 100644 templates/fail2ban.filter.conf diff --git a/defaults/main.yml b/defaults/main.yml new file mode 100644 index 0000000..7f9b2cb --- /dev/null +++ b/defaults/main.yml @@ -0,0 +1,46 @@ +--- +# directory_logrotate_config: /etc/logrotate.d +install_glpi: 'true' +glpi_installed: false +# logfile_max_size: 10 # must be specified in MB (Mega Bytes) +# logrotate_configuration: [] # Global var for usage within group/host vars + +docker_image_name_glpi: nofusscomputing/docker-glpi +docker_image_tag_glpi: dev + +docker_container_name_glpi: glpi +# mysql_unix_socket: /run/mysql/mariadb/mysqld.sock +mysql_unix_socket: /var/lib/docker/volumes/socket-mysql/_data/mysqld.sock +mysql_login_user: root +mysql_login_password: admin + +glpi_plugins: + - filename: fail2ban_1.0.2-1.upstream1_all.deb + #url: https://github.com/pluginsGLPI/formcreator/releases/download/2.13.6/glpi-formcreator-2.13.6.tar.bz2 + url: https://api.github.com/repos/pluginsGLPI/formcreator/releases/tags/2.13.6 + + - filename: glpi-glpiinventory-1.2.3.tar.bz2 + #url: https://github.com/glpi-project/glpi-inventory-plugin/releases/download/1.2.3/glpi-glpiinventory-1.2.3.tar.bz2 + url: https://api.github.com/repos/glpi-project/glpi-inventory-plugin/releases/tags/1.2.3 + + # - filename: glpi-actualtime-2.1.0.tar.tgz + # url: https://api.github.com/repos/ticgal/actualtime/releases/tags/2.1.0/glpi-actualtime-2.1.0.tar.tgz + + +mysql_database_glpi: glpi + +# Configuration Example +# logrotate: +# - name: docker # Mandatory, used as logrotate difinition file name +# path: '/var/lib/docker/containers/*/*.log' # Mandatory, path to the logfile +# su: ingress ingress # Optional,, string user and group for log permissions +# interval: daily # optional example daily, weekly, monthly default=daily +# keep: # Optional, int, How many logs to keep default=7 +# size: 10 # Optional, max size of logfile in Mega Bytes. DONT specify unit. default={{}} +# compress: # Optional, bool default=true +# delaycompress: # Optional, bool, delay logfile compression default=true +# postrotate: 'docker restart $(docker ps -q)' # Optional, Command to run post rotate default=not defined +# create: # Optional, default=not defined +# mode: 640 # Mandatory, filemode +# owner: root # Mandatory, logfile owner +# group: adm # Mandatory, logfile group owner diff --git a/handlers/main.yaml b/handlers/main.yaml new file mode 100644 index 0000000..65abc11 --- /dev/null +++ b/handlers/main.yaml @@ -0,0 +1,29 @@ +--- +# - name: Log Rotate Configuration files +# ansible.builtin.template: +# src: definition.j2 +# dest: "{{ directory_logrotate_config }}/{{ item.name }}" +# owner: root +# mode: '0644' +# force: true +# loop: "{{ logrotate_configuration }}" +# listen: 'configure_logrotate' +# notify: restart_logrotate +# when: logrotate_installed | bool + + +# - name: Restart logrotate +# ansible.builtin.service: +# name: logrotate +# state: restarted +# listen: restart_logrotate +# when: logrotate_installed | bool + +- name: Restart GLPI + community.docker.docker_container: + name: "{{ docker_container_name_glpi }}" + state: started + restart: true + listen: restart_glpi + when: > + glpi_installed | bool diff --git a/meta/main.yaml b/meta/main.yaml new file mode 100644 index 0000000..31ab5e5 --- /dev/null +++ b/meta/main.yaml @@ -0,0 +1,13 @@ +galaxy_info: + role_name: nfc_glpi + author: No Fuss Computing + description: |- + A universal role to install and configure a glpi. + + This role is also desiged so that it can be included within other roles. + + issue_tracker_url: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi + + license: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi/-/blob/master/LICENSE + + min_ansible_version: '1.2' diff --git a/tasks/configure.yaml b/tasks/configure.yaml new file mode 100644 index 0000000..e72f601 --- /dev/null +++ b/tasks/configure.yaml @@ -0,0 +1,111 @@ +--- +- name: Clear Any downloaded files + ansible.builtin.file: + name: "/tmp/ansible" + state: absent + #loop: "{{ glpi_plugins }}" + +- name: Clear Any downloaded files + ansible.builtin.file: + name: "/tmp/ansible" + state: directory + #loop: "{{ glpi_plugins }}" + +# - name: Download Plugins +# ansible.builtin.get_url: +# url: "{{ item.url }}" +# dest: "/tmp/{{ item.filename }}" +# loop: "{{ glpi_plugins }}" + +# - name: Download plugins +# ansible.builtin.command: +# cmd: "bash -c echo $({{ item.url }})" +# loop: "{{ glpi_plugins }}" + +# wget https://github.com/pluginsGLPI/formcreator/releases/download/2.13.6/glpi-formcreator-2.13.6.tar.bz2 -O /tmp/plugin-form-creator.tar.bz2 +# tar -xjf /tmp/plugin-form-creator.tar.bz2 -C /var/lib/docker/volumes/glpi_glpi_plugins/_data/ + +# wget https://github.com/glpi-project/glpi-inventory-plugin/releases/download/1.2.3/glpi-glpiinventory-1.2.3.tar.bz2 -O /tmp/glpi-glpiinventory-1.2.3.tar.bz2 +# tar -xjf /tmp/glpi-glpiinventory-1.2.3.tar.bz2 -C /var/lib/docker/volumes/glpi_glpi_plugins/_data/ +# chown www-data:www-data -R /var/lib/docker/volumes/glpi_glpi_plugins/_data/ + +- name: Install bzip + ansible.builtin.apt: + name: "{{ item }}" + state: present + loop: "{{ apps }}" + vars: + apps: + - bzip2 + - jq + - wget + + +# - name: Example clone of a single branch +# ansible.builtin.git: +# repo: "{{ item.repo }}.git" +# dest: "/var/lib/docker/volumes/plugins_glpi/_data/{{ item.name }}" +# single_branch: true +# version: "{{ item.version }}" +# depth: 1 +# force: true +# loop: "{{ plugins }}" +# vars: +# plugins: +# - name: actualtime +# repo: https://github.com/ticgal/actualtime +# version: 2.1.0 + +# - name: glpiinventory +# repo: https://github.com/glpi-project/glpi-inventory-plugin +# version: 1.2.3 +# # for creator doesnt work +# # - name: formcreator +# # repo: https://github.com/pluginsGLPI/formcreator +# # version: 2.13.6 + +# - name: geninventorynumber +# repo: https://github.com/pluginsGLPI/geninventorynumber +# version: 2.8.3 + +# - name: releases +# repo: https://github.com/InfotelGLPI/releases +# version: 2.0.3 + +# - name: phpsaml +# repo: https://github.com/DonutsNL/phpsaml +# # version: e7357a49ca9f0b612bc28879a0c703cdbfc4463b +# version: master + +# - name: Download and Extract the plugins +# ansible.builtin.shell: +# cmd: | +# export URL=$(curl -s {{ item.url }} | jq .assets[0].browser_download_url | tr -d \"); +# wget $URL -O /tmp/ansible/$(basename ${URL}); +# tar -xjf /tmp/ansible/$(basename ${URL}) -C /var/lib/docker/volumes/plugins_glpi/_data/; +# loop: "{{ glpi_plugins }}" +# changed_when: false + + +- name: Fix file perms + ansible.builtin.command: + cmd: chown www-data:www-data -R /var/lib/docker/volumes/plugins_glpi/_data/ + changed_when: false + +# - name: Unarchive a file that needs to be downloaded (added in 2.0) +# ansible.builtin.unarchive: +# src: /tmp/{{ item.filename }} +# dest: /var/lib/docker/volumes/plugins_glpi/_data/ +# remote_src: true +# extra_opts: +# - -j +# loop: "{{ glpi_plugins }}" + +- name: Clear Any downloaded files + ansible.builtin.file: + name: "{{ item.filename }}" + state: absent + loop: "{{ glpi_plugins }}" + +- name: Reload logroate if required + ansible.builtin.meta: flush_handlers diff --git a/tasks/install.yaml b/tasks/install.yaml new file mode 100644 index 0000000..c9df8c6 --- /dev/null +++ b/tasks/install.yaml @@ -0,0 +1,150 @@ +--- +- name: GPLI Docker Container + ansible.builtin.include_role: + name: docker_management + vars: + docker_images: + - name: "{{ docker_image_name_glpi }}" + tag: "{{ docker_image_tag_glpi }}" + + docker_networks: + - name: "{{ docker_container_name_glpi }}-access" + internal: false # this needs to be added to the docker role + - name: "{{ docker_container_name_glpi }}-smtp-access" + internal: true + + docker_containers: + - name: "{{ docker_container_name_glpi }}" + image: "{{ docker_image_name_glpi }}:{{ docker_image_tag_glpi }}" + env: + TIMEZONE: UTC + networks: + - name: "{{ docker_container_name_glpi }}-access" + - name: "ingress-access" + - name: "{{ docker_container_name_glpi }}-smtp-access" + - name: ldap-access + - name: mysql-access + # published_ports: + # - 80:80 + volumes: + - /usr/share/zoneinfo/Etc/UTC:/etc/timezone:ro + - /usr/share/zoneinfo/Etc/UTC:/etc/localtime:ro + - "config_{{ docker_container_name_glpi }}:/var/www/html/config" + - "data_{{ docker_container_name_glpi }}:/var/www/html/files" + - "log_{{ docker_container_name_glpi }}:/var/log" + - "marketplace_{{ docker_container_name_glpi }}:/var/www/html/marketplace" + - "plugins_{{ docker_container_name_glpi }}:/var/www/html/plugins" + + docker_volumes: + - name: "plugins_{{ docker_container_name_glpi }}" + - name: "data_{{ docker_container_name_glpi }}" + - name: "config_{{ docker_container_name_glpi }}" + - name: "marketplace_{{ docker_container_name_glpi }}" + - name: "log_{{ docker_container_name_glpi }}" + - name: "varlog_{{ docker_container_name_glpi }}" + + +- name: Create GLPI database + community.mysql.mysql_db: + name: "{{ mysql_database_glpi }}" + state: present + login_unix_socket: "{{ mysql_unix_socket }}" + login_user: "{{ mysql_login_user }}" + login_password: "{{ mysql_login_password }}" + login_host: "{{ mysql_login_host | default('') }}" + config_file: '' + + +- name: Create user with password, all database privileges and 'WITH GRANT OPTION' in db1 and db2 + community.mysql.mysql_user: + state: "{{ item.state | default('present') }}" + name: "{{ item.name }}" + password: "{{ item.password }}" + host: "{{ item.host | default('localhost') }}" + priv: "{{ item.priv | default(omit) | from_yaml }}" + update_password: "{{ item.update_password | default('on_create') }}" + login_host: "{{ mysql_login_host | default('') }}" + login_unix_socket: "{{ mysql_unix_socket }}" + login_user: "{{ mysql_login_user }}" + login_password: "{{ mysql_login_password }}" + config_file: '' + loop: "{{ database_mysql_users }}" + vars: + database_mysql_users: + - name: glpi + password: admin + host: '%' + priv: + 'glpi.*': 'ALL,GRANT' + +# sudo cp -r /var/www/html/glpi/config/* /var/lib/docker/volumes/glpi_config_glpi/_data/ +# sudo cp -r /var/www/html/glpi/files/* /var/lib/docker/volumes/glpi_data_glpi/_data/ +# sudo cp -r /var/www/html/glpi/plugins/* /var/lib/docker/volumes/glpi_glpi_plugins/_data/ +# sudo cp -r /var/www/html/glpi/marketplace/* /var/lib/docker/volumes/glpi_marketplace_glpi/_data/ + + +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_config_glpi/_data/ +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_data_glpi/_data/ +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_glpi_plugins/_data/ +# sudo chmod -R 777 /var/lib/docker/volumes/glpi_marketplace_glpi/_data/ + +- name: Add fail2ban filters + ansible.builtin.template: + src: "{{ item.src }}" + dest: "{{ item.dest }}" + mode: '760' + owner: root + group: root + loop: "{{ the_files }}" + # notify: reload_fail2ban + when: > + install_fail2ban | default(false) | bool + vars: + the_files: + - src: fail2ban.filter.conf + dest: "/etc/fail2ban/filter.d/glpi.local" + - src: fail2ban.filter.conf + dest: "/etc/fail2ban/filter.d/glpi-api.local" + + +- name: "Fail2Ban Jail for GLPI" + ansible.builtin.include_role: + name: nfc_firewall + when: > + install_fail2ban | default(false) | bool + vars: + fail2ban: + config: + - name: "glpi-{{ docker_container_name_glpi }}" + sub_path: jail.d + sections: + DEFAULT: + "glpi_log": "/var/lib/docker/volumes/data_{{ docker_container_name_glpi }}/_data/_log/event.log" + glpi: + enabled: true + mode: polling + chain: DOCKER-USER + port: http,https + logpath: "%(glpi_log)s" + filter: glpi + findtime: 600 + maxretry: 5 + - name: "api_glpi-{{ docker_container_name_glpi }}" + sub_path: jail.d + sections: + DEFAULT: + "api_glpi_log": "/var/lib/docker/volumes/log_{{ docker_container_name_glpi }}/_data/apache2/access-glpi.log" + api_glpi: + enabled: true + mode: polling + chain: DOCKER-USER + port: http,https + logpath: "%(api_glpi_log)s" + filter: glpi-api + findtime: 600 + maxretry: 5 + + +- name: Task Final playbook variables + ansible.builtin.set_fact: + glpi_installed: true diff --git a/tasks/main.yaml b/tasks/main.yaml new file mode 100644 index 0000000..8f54866 --- /dev/null +++ b/tasks/main.yaml @@ -0,0 +1,33 @@ +--- +- name: Install GLPI + ansible.builtin.include_tasks: + file: install.yaml + apply: + tags: + - always + tags: + - always + when: > + install_glpi | bool + and + not glpi_installed | bool + + + +- name: Configure Log Rotate + ansible.builtin.include_tasks: + file: configure.yaml + apply: + tags: + - always + tags: + - always + when: glpi_installed | bool +# and +# ansible_os_family == "Debian" +# and +# ( +# logrotate is defined +# and +# logrotate | default([]) | length | int > 0 +# ) diff --git a/templates/fail2ban.filter-api.conf b/templates/fail2ban.filter-api.conf new file mode 100644 index 0000000..4224099 --- /dev/null +++ b/templates/fail2ban.filter-api.conf @@ -0,0 +1,15 @@ +# +# Fail2ban Filter, GLPI API Denied access +# +# Managed By: Ansible +# Role: nfc_glpi +# +# Do not edit this file directly as it will be automagically updated by ansible. +# to make changes update the ansible play that deploys this file. +[Init] +maxlines = 2 + +[Definition] + +failregex = ^([\d|\.?]{1,3}).+apirest.php.+"\s40\d\s\d{1,5} + diff --git a/templates/fail2ban.filter.conf b/templates/fail2ban.filter.conf new file mode 100644 index 0000000..faf7b68 --- /dev/null +++ b/templates/fail2ban.filter.conf @@ -0,0 +1,17 @@ +# +# Fail2ban Filter, GLPI +# +# Managed By: Ansible +# Role: nfc_glpi +# +# Do not edit this file directly as it will be automagically updated by ansible. +# to make changes update the ansible play that deploys this file. +[Init] +maxlines = 2 + +[Definition] +# failregex = ^(?P\d{4}-\d{2}-\d{2}\s?\d{2}:\d{2}:\d{2})\s+?\S+\n?\[login\]\s+?[\d+]?:?[\s+]?Failed\s+?login\s+?for\s(?P.+)\s+?from\s+?IP\s+?(?P\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$ + +# failregex = ^(.+)ogin] \d+: Failed login for (.+) from IP (\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$ +failregex = ^.*?(Failed login for)[\S\s]+(from IP) .*$ +# ^.*\s(\[\S).*?(Failed login for) \S+ (from IP) .*$ From 62081982e83ed1fbbec2e221ddcfc3df2a849258 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 27 Jul 2023 13:36:11 +0930 Subject: [PATCH 02/30] feat(ci): added ci repo !1 --- .cz.yaml | 7 +++++++ .gitlab-ci.yml | 14 ++++++++++++++ .gitmodules | 4 ++++ .nfc_automation.yaml | 8 ++++++++ gitlab-ci | 1 + 5 files changed, 34 insertions(+) create mode 100644 .cz.yaml create mode 100644 .gitlab-ci.yml create mode 100644 .gitmodules create mode 100644 .nfc_automation.yaml create mode 160000 gitlab-ci diff --git a/.cz.yaml b/.cz.yaml new file mode 100644 index 0000000..62b2ada --- /dev/null +++ b/.cz.yaml @@ -0,0 +1,7 @@ +commitizen: + bump_message: "build(version): bump version $current_version \u2192 $new_version" + changelog_incremental: false + name: cz_conventional_commits + tag_format: $major.$minor.$patch$prerelease + update_changelog_on_bump: true + version: 0.0.1 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..7b6e78d --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,14 @@ +--- + +include: + - project: nofusscomputing/projects/gitlab-ci + ref: development + file: + - .gitlab-ci_common.yaml + - template/automagic.gitlab-ci.yaml + + +variables: + MY_PROJECT_ID: "48046854" + GIT_SYNC_URL: "https://$GITHUB_USERNAME_ROBOT:$GITHUB_TOKEN_ROBOT@github.com/NoFussComputing/ansible_role_glpi.git" + diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..cc4d8a5 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "gitlab-ci"] + path = gitlab-ci + url = https://gitlab.com/nofusscomputing/projects/gitlab-ci.git + branch = development diff --git a/.nfc_automation.yaml b/.nfc_automation.yaml new file mode 100644 index 0000000..077d7f4 --- /dev/null +++ b/.nfc_automation.yaml @@ -0,0 +1,8 @@ +--- + +role_git_conf: + gitlab: + submodule_branch: "development" + default_branch: development + mr_labels: ~"type::automation" ~"impact::0" ~"priority::0" + auto_merge: true diff --git a/gitlab-ci b/gitlab-ci new file mode 160000 index 0000000..975de7a --- /dev/null +++ b/gitlab-ci @@ -0,0 +1 @@ +Subproject commit 975de7aca210667d1e93d02a4036ca4ae70808ff From 1c78ec036ccaa2a822c419d9b5b8c0f28cb5b131 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 14:49:36 +0930 Subject: [PATCH 03/30] feat(docs): added docs !1 --- .gitmodules | 4 ++++ docs/articles/index.md | 0 docs/contact.md | 0 docs/index.md | 0 docs/operations/index.md | 0 docs/projects/index.md | 0 docs/projects/nfc_glpi/index.md | 25 +++++++++++++++++++++++++ mkdocs.yml | 31 +++++++++++++++++++++++++++++++ website-template | 1 + 9 files changed, 61 insertions(+) create mode 100644 docs/articles/index.md create mode 100644 docs/contact.md create mode 100644 docs/index.md create mode 100644 docs/operations/index.md create mode 100644 docs/projects/index.md create mode 100644 docs/projects/nfc_glpi/index.md create mode 100644 mkdocs.yml create mode 160000 website-template diff --git a/.gitmodules b/.gitmodules index cc4d8a5..de6bfdd 100644 --- a/.gitmodules +++ b/.gitmodules @@ -2,3 +2,7 @@ path = gitlab-ci url = https://gitlab.com/nofusscomputing/projects/gitlab-ci.git branch = development +[submodule "website-template"] + path = website-template + url = https://gitlab.com/nofusscomputing/infrastructure/website-template.git + branch = development diff --git a/docs/articles/index.md b/docs/articles/index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/contact.md b/docs/contact.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/operations/index.md b/docs/operations/index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/projects/index.md b/docs/projects/index.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/projects/nfc_glpi/index.md b/docs/projects/nfc_glpi/index.md new file mode 100644 index 0000000..558380a --- /dev/null +++ b/docs/projects/nfc_glpi/index.md @@ -0,0 +1,25 @@ +--- +title: Ansible Role nfc_glpi +description: How to use No Fuss Computings Ansible role to manage GLPI from configuration as code. +date: 2023-07-28 +template: project.html +about: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi +--- + +This Ansible role is designed to manage GLPI specifically installation and configuration. + + +## Features + +- install GLPI using our [docker container](https://gitlab.com/nofusscomputing/projects/docker-glpi) + + +## Default Variables + +Here's an example playbook that demonstrates how to use the `docker_management` role: + +```yaml title="defaults/main.yaml" linenums="1 + +--8<-- "defaults/main.yaml" + +``` diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..b717883 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,31 @@ +INHERIT: website-template/mkdocs.yml + +docs_dir: 'docs' + +repo_name: Docker Management +repo_url: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi +edit_uri: '/-/ide/project/nofusscomputing/projects/ansible/nfc_glpi/edit/development/-/docs/' + +nav: +- Home: index.md + +- Articles: + + - articles/index.md + +- Projects: + + - projects/index.md + + - Ansible Roles: + + - GLPI: + + - projects/nfc_glpi/index.md + +- Operations: + + - operations/index.md + +- Contact Us: contact.md + diff --git a/website-template b/website-template new file mode 160000 index 0000000..992b548 --- /dev/null +++ b/website-template @@ -0,0 +1 @@ +Subproject commit 992b54805b8b6c78a3d2a5ea7de71c7be2b070c8 From 741107e0b20f63d98e8044254be4fee2abe81204 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:08:10 +0930 Subject: [PATCH 04/30] feat(api): search for entities_id by name !1 --- tasks/api/search/entities_id.yaml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tasks/api/search/entities_id.yaml diff --git a/tasks/api/search/entities_id.yaml b/tasks/api/search/entities_id.yaml new file mode 100644 index 0000000..af3e485 --- /dev/null +++ b/tasks/api/search/entities_id.yaml @@ -0,0 +1,31 @@ +--- +- name: Fetch entities_id + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/Entity?searchText[name]={{ item.entities_id | urlencode }}" + method: "GET" + return_content: true + body: '' + # status_code: "{{ item.status_code | from_yaml | list }}" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + register: glpi_search + no_log: true + + +- name: Set entities_id + ansible.builtin.set_fact: + new_data: + entities_id: "{{ glpi_search.json[0].id | int }}" + when: glpi_search.json | length | int == 1 + + +- name: Append entities_id + ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + glpi_search: {} + new_data: {} + no_log: true + when: glpi_search.json | length | int == 1 From 4624f5c80d43c76d1b658c4852507b26a2c1a30d Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:08:22 +0930 Subject: [PATCH 05/30] feat(api): search for item_id by name !1 --- tasks/api/search/item_id.yaml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tasks/api/search/item_id.yaml diff --git a/tasks/api/search/item_id.yaml b/tasks/api/search/item_id.yaml new file mode 100644 index 0000000..846bf4b --- /dev/null +++ b/tasks/api/search/item_id.yaml @@ -0,0 +1,31 @@ +--- +- name: Find Item ID + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}?searchText[name]={{ item.body.name | urlencode }}" + method: "GET" + return_content: true + body: '' + # status_code: "{{ item.status_code | from_yaml | list }}" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + register: glpi_search + no_log: true + + +- name: Set id + ansible.builtin.set_fact: + new_data: + id: "{{ glpi_search.json[0].id | int }}" + when: glpi_search.json | length | int == 1 + + +- name: Append id + ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + glpi_search: {} + new_data: {} + no_log: true + when: glpi_search.json | length | int == 1 From 825aade159aed773161ff8ca946ce25065359026 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:08:48 +0930 Subject: [PATCH 06/30] feat(api): search for tickettemplates_id_demand by name !1 --- tasks/api/search/itilcategories_id.yaml | 31 +++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tasks/api/search/itilcategories_id.yaml diff --git a/tasks/api/search/itilcategories_id.yaml b/tasks/api/search/itilcategories_id.yaml new file mode 100644 index 0000000..abbd9cb --- /dev/null +++ b/tasks/api/search/itilcategories_id.yaml @@ -0,0 +1,31 @@ +--- +- name: Fetch itilcategories_id + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/ITILCategory?searchText[name]={{ item.itilcategories_id | urlencode }}" + method: "GET" + return_content: true + body: '' + # status_code: "{{ item.status_code | from_yaml | list }}" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + register: glpi_search + no_log: true + + +- name: Set itilcategories_id + ansible.builtin.set_fact: + new_data: + itilcategories_id: "{{ glpi_search.json[0].id | int }}" + when: glpi_search.json | length | int == 1 + + +- name: Append itilcategories_id + ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + glpi_search: {} + new_data: {} + no_log: true + when: item.itilcategories_id is defined From a0103570f5d8e6cffee374c32fc1a2c279ae1ed4 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:09:11 +0930 Subject: [PATCH 07/30] feat(api): search for itilcategory_id by name !1 --- .../api/search/tickettemplates_id_demand.yaml | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 tasks/api/search/tickettemplates_id_demand.yaml diff --git a/tasks/api/search/tickettemplates_id_demand.yaml b/tasks/api/search/tickettemplates_id_demand.yaml new file mode 100644 index 0000000..5453874 --- /dev/null +++ b/tasks/api/search/tickettemplates_id_demand.yaml @@ -0,0 +1,31 @@ +--- +- name: Fetch tickettemplates_id_demand + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/TicketTemplate?searchText[name]={{ item.tickettemplates_id_demand | urlencode }}" + method: "GET" + return_content: true + body: '' + # status_code: "{{ item.status_code | from_yaml | list }}" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + register: glpi_search + no_log: true + + +- name: Set tickettemplates_id_demand + ansible.builtin.set_fact: + new_data: + tickettemplates_id_demand: "{{ glpi_search.json[0].id | int }}" + when: glpi_search.json | length | int == 1 + + +- name: Append tickettemplates_id_demand + ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + glpi_search: {} + new_data: {} + no_log: true + when: glpi_search.json | length | int == 1 From e1d6dba5ef9de34b90992f04ee1ebae1e93b6f43 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:09:28 +0930 Subject: [PATCH 08/30] feat(api): search for users_id by name !1 --- tasks/api/search/users_id.yaml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 tasks/api/search/users_id.yaml diff --git a/tasks/api/search/users_id.yaml b/tasks/api/search/users_id.yaml new file mode 100644 index 0000000..07e1afb --- /dev/null +++ b/tasks/api/search/users_id.yaml @@ -0,0 +1,32 @@ +--- + +- name: Fetch users_id + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/User?searchText[name]={{ item.users_id | urlencode }}" + method: "GET" + return_content: true + body: '' + # status_code: "{{ item.status_code | from_yaml | list }}" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + register: glpi_search + no_log: true + + +- name: Set users_id + ansible.builtin.set_fact: + new_data: + users_id: "{{ glpi_search.json[0].id | int }}" + when: glpi_search.json | length | int == 1 + + +- name: Append users_id (have item_body) + ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + glpi_search: {} + new_data: {} + no_log: true + when: glpi_search.json | length | int == 1 From e8a5edda5cb2a28366f3aba6bd4313e68f593708 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:10:47 +0930 Subject: [PATCH 09/30] feat(api): fetch session id !1 --- tasks/api/session-create.yaml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 tasks/api/session-create.yaml diff --git a/tasks/api/session-create.yaml b/tasks/api/session-create.yaml new file mode 100644 index 0000000..1a430d0 --- /dev/null +++ b/tasks/api/session-create.yaml @@ -0,0 +1,29 @@ +--- +- name: Fetch API Session Token + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/initSession?get_full_session=true" + method: GET + return_content: true + body: "" + status_code: 200 + headers: + App-Token: "{{ glpi.app_token }}" + Authorization: "user_token {{ glpi.user_token }}" + body_format: json + register: glpi_session_get + no_log: true + tags: + - always + + +- name: Session Data + ansible.builtin.set_fact: + glpi_session: + session: "{{ glpi_session_get.json.session }}" + no_log: true + + +- name: Session fact + ansible.builtin.set_fact: + glpi: "{{ glpi | ansible.builtin.combine(glpi_session) }}" + no_log: true From 15573f03cdb37aef2cc8c6fa5df2f9fb868041fc Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:11:02 +0930 Subject: [PATCH 10/30] feat(api): end a session !1 --- tasks/api/session-end.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tasks/api/session-end.yaml diff --git a/tasks/api/session-end.yaml b/tasks/api/session-end.yaml new file mode 100644 index 0000000..3e771db --- /dev/null +++ b/tasks/api/session-end.yaml @@ -0,0 +1,13 @@ +--- +- name: End API Session + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/killSession" + method: GET + return_content: true + body: '' + status_code: 200 + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi_session_get.json.session.valid_id }}" + body_format: json + no_log: true From febce3aa5e6bb07ca62aae627a1110acc075038a Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:15:33 +0930 Subject: [PATCH 11/30] feat(api): Create and end a session !1 --- defaults/{main.yml => main.yaml} | 4 ++++ tasks/api/api.yaml | 18 ++++++++++++++++++ tasks/main.yaml | 9 ++++++++- 3 files changed, 30 insertions(+), 1 deletion(-) rename defaults/{main.yml => main.yaml} (98%) create mode 100644 tasks/api/api.yaml diff --git a/defaults/main.yml b/defaults/main.yaml similarity index 98% rename from defaults/main.yml rename to defaults/main.yaml index 7f9b2cb..2806058 100644 --- a/defaults/main.yml +++ b/defaults/main.yaml @@ -44,3 +44,7 @@ mysql_database_glpi: glpi # mode: 640 # Mandatory, filemode # owner: root # Mandatory, logfile owner # group: adm # Mandatory, logfile group owner + + + +glpi_config_as_code_json: [] diff --git a/tasks/api/api.yaml b/tasks/api/api.yaml new file mode 100644 index 0000000..d24253d --- /dev/null +++ b/tasks/api/api.yaml @@ -0,0 +1,18 @@ +--- +- name: Always End Session + block: + + + - name: Start Session + ansible.builtin.include_tasks: + file: api/session-create.yaml + when: glpi.api.session | default('') == '' + + + always: + + + - name: End Session + ansible.builtin.include_tasks: + file: api/session-end.yaml + when: glpi_session_get.status | default(0) | int == 200 diff --git a/tasks/main.yaml b/tasks/main.yaml index 8f54866..db78c4f 100644 --- a/tasks/main.yaml +++ b/tasks/main.yaml @@ -13,7 +13,6 @@ not glpi_installed | bool - - name: Configure Log Rotate ansible.builtin.include_tasks: file: configure.yaml @@ -31,3 +30,11 @@ # and # logrotate | default([]) | length | int > 0 # ) + +- name: API tasks + ansible.builtin.include_tasks: + file: api/api.yaml + apply: + tags: + - always + when: glpi_config_as_code_json length | int > 0 From 70a48341a4f1ec510626b0db212a6c6d3fd60826 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:22:54 +0930 Subject: [PATCH 12/30] feat(config): Configure GLPI from json config files !1 --- docs/projects/nfc_glpi/config_from_code.md | 74 +++++++++++++++++++++ docs/projects/nfc_glpi/index.md | 3 +- mkdocs.yml | 2 + tasks/api/api.yaml | 6 ++ tasks/api/append-create-item.yaml | 77 ++++++++++++++++++++++ 5 files changed, 161 insertions(+), 1 deletion(-) create mode 100644 docs/projects/nfc_glpi/config_from_code.md create mode 100644 tasks/api/append-create-item.yaml diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md new file mode 100644 index 0000000..9092675 --- /dev/null +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -0,0 +1,74 @@ +--- +title: Config as code +description: How to use No Fuss Computings Ansible role to configure GLPI from configuration as code. +date: 2023-07-28 +template: project.html +about: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi +--- + +To configure GLPI using this role, the config/settings are saved as json files. The workflow to create the json files, is to (preferably within a test environment) make the required setting changes in GLPI using the GUI. one the changes have been made, conduct an API `GET` query to GLPI for the item you changed. The JSON body that is returned, is placed within the Config file (detailed below) under path `.body`. You must however, remove any fields that are not required, for example dynamic fields (fields that update themselves or are auto created) for example date fields. + + + +## Config files Example + +Each tab provides an example of the JSON file layout, including any additional variables. Any variable listed at path `.` that are empty strings, you would complete with the items name as it is exactly within GLPI. These fields are used to fetch the itm_id of the field by name. this enables having the config saved in a more human readable format. For example, for the field `entities_id` you would complete it as `"entities_id": "My entity name"`. + +=== "AuthLDAP" + + ``` json title="example.json" linenums="1 + { + "api_path": "AuthLDAP", + "body": { + // JSON from API Query + } + } + ``` +=== "Entity" + + ``` json title="example.json" linenums="1 + { + "api_path": "Entity", + "entities_id": "", + "body": { + // JSON from API Query + } + } + ``` + +=== "ITILCategory" + + ``` json title="example.json" linenums="1 + { + "api_path": "ITILCategory", + "users_id": "", + "itilcategories_id": "", + "entities_id": "", + "tickettemplates_id_demand": "", + "body": { + // JSON from API Query + } + } + ``` + +=== "Profile" + + ``` json title="example.json" linenums="1 + { + "api_path": "Profile", + "body": { + // JSON from API Query + } + } + ``` + +With the config files structured as per the examples, within your playbook(s), load the json files in a list of json objects using variable `glpi_config_as_code_json` + +example + +``` yaml title="my_vars.yaml" linenums="1 +glpi_config_as_code_json: + - "{{ lookup('file', '/workdir/files/glpi/ITILCategory-new-ldap-user.json') | from_json }}" + - "{{ lookup('file', '/workdir/files/glpi/LDAPAuth-local_ldap.json') | from_json }}" + +``` diff --git a/docs/projects/nfc_glpi/index.md b/docs/projects/nfc_glpi/index.md index 558380a..53f0682 100644 --- a/docs/projects/nfc_glpi/index.md +++ b/docs/projects/nfc_glpi/index.md @@ -1,5 +1,5 @@ --- -title: Ansible Role nfc_glpi +title: nfc_glpi - Ansible Role description: How to use No Fuss Computings Ansible role to manage GLPI from configuration as code. date: 2023-07-28 template: project.html @@ -13,6 +13,7 @@ This Ansible role is designed to manage GLPI specifically installation and confi - install GLPI using our [docker container](https://gitlab.com/nofusscomputing/projects/docker-glpi) +- [Configure using Config from Code](config_from_code.md) ## Default Variables diff --git a/mkdocs.yml b/mkdocs.yml index b717883..7bfdd1c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -23,6 +23,8 @@ nav: - projects/nfc_glpi/index.md + - projects/nfc_glpi/config_from_code.md + - Operations: - operations/index.md diff --git a/tasks/api/api.yaml b/tasks/api/api.yaml index d24253d..f5e43f5 100644 --- a/tasks/api/api.yaml +++ b/tasks/api/api.yaml @@ -9,6 +9,12 @@ when: glpi.api.session | default('') == '' + - name: Append/Create Item + ansible.builtin.include_tasks: + file: append-create-item.yaml + loop: "{{ glpi_config_as_code_json }}" + + always: diff --git a/tasks/api/append-create-item.yaml b/tasks/api/append-create-item.yaml new file mode 100644 index 0000000..a862917 --- /dev/null +++ b/tasks/api/append-create-item.yaml @@ -0,0 +1,77 @@ +--- + +- name: Create item_body + ansible.builtin.set_fact: + item_body: "{{ item.body }}" + no_log: true + + +- name: Search item_id + ansible.builtin.include_tasks: + file: api/search/item_id.yaml + when: not item.body.id is defined + + +- name: Search entities_id + ansible.builtin.include_tasks: + file: api/search/entities_id.yaml + when: item.entities_id is defined + + +- name: Search tickettemplates_id_demand + ansible.builtin.include_tasks: + file: api/search/tickettemplates_id_demand.yaml + when: item.tickettemplates_id_demand is defined + + +- name: Search itilcategories_id + ansible.builtin.include_tasks: + file: api/search/itilcategories_id.yaml + when: item.itilcategories_id is defined + + +- name: Search users_id + ansible.builtin.include_tasks: + file: api/search/users_id.yaml + when: item.users_id is defined + + +- name: Show Body + ansible.builtin.debug: + msg: "{{ item_body }}" + when: item_body is defined + + +- name: Create Item + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}" + method: "POST" + return_content: true + body: "{\"input\": {{ item_body | from_yaml | to_json }} }" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + no_log: true + when: not item_body.id is defined + + +- name: Update Item + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}/{{ item_body.id }}" + method: "PATCH" + return_content: true + body: "{\"input\": {{ item_body | from_yaml | to_json }} }" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + no_log: true + when: item_body.id is defined + + +- name: Clear temp vars + ansible.builtin.set_fact: + item_body: {} From 024d6c6d6e1f04a2159ff31d3f31e276aa4ad983 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:24:06 +0930 Subject: [PATCH 13/30] ci(pages): added pages environment path !1 --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7b6e78d..71f2c7b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -11,4 +11,5 @@ include: variables: MY_PROJECT_ID: "48046854" GIT_SYNC_URL: "https://$GITHUB_USERNAME_ROBOT:$GITHUB_TOKEN_ROBOT@github.com/NoFussComputing/ansible_role_glpi.git" + PAGES_ENVIRONMENT_PATH: projects/nfc_glpi/ From b91acddf16d420ff8fbc0578a3fdb0c771fc3a64 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 15:31:58 +0930 Subject: [PATCH 14/30] docs(fix): wasnt rendering correctly !1 --- docs/projects/nfc_glpi/config_from_code.md | 21 ++++++++++++++++----- docs/projects/nfc_glpi/index.md | 5 ++--- mkdocs.yml | 2 +- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md index 9092675..7bb0803 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -16,17 +16,21 @@ Each tab provides an example of the JSON file layout, including any additional v === "AuthLDAP" - ``` json title="example.json" linenums="1 + ``` json title="example.json" linenums="1" + { "api_path": "AuthLDAP", "body": { // JSON from API Query } } + ``` + === "Entity" - ``` json title="example.json" linenums="1 + ``` json title="example.json" linenums="1" + { "api_path": "Entity", "entities_id": "", @@ -34,11 +38,13 @@ Each tab provides an example of the JSON file layout, including any additional v // JSON from API Query } } + ``` === "ITILCategory" - ``` json title="example.json" linenums="1 + ``` json title="example.json" linenums="1" + { "api_path": "ITILCategory", "users_id": "", @@ -49,24 +55,29 @@ Each tab provides an example of the JSON file layout, including any additional v // JSON from API Query } } + ``` === "Profile" - ``` json title="example.json" linenums="1 + ``` json title="example.json" linenums="1" + { "api_path": "Profile", "body": { // JSON from API Query } } + ``` + With the config files structured as per the examples, within your playbook(s), load the json files in a list of json objects using variable `glpi_config_as_code_json` example -``` yaml title="my_vars.yaml" linenums="1 +``` yaml title="my_vars.yaml" linenums="1" + glpi_config_as_code_json: - "{{ lookup('file', '/workdir/files/glpi/ITILCategory-new-ldap-user.json') | from_json }}" - "{{ lookup('file', '/workdir/files/glpi/LDAPAuth-local_ldap.json') | from_json }}" diff --git a/docs/projects/nfc_glpi/index.md b/docs/projects/nfc_glpi/index.md index 53f0682..fed6c82 100644 --- a/docs/projects/nfc_glpi/index.md +++ b/docs/projects/nfc_glpi/index.md @@ -15,11 +15,10 @@ This Ansible role is designed to manage GLPI specifically installation and confi - [Configure using Config from Code](config_from_code.md) + ## Default Variables -Here's an example playbook that demonstrates how to use the `docker_management` role: - -```yaml title="defaults/main.yaml" linenums="1 +``` yaml title="defaults/main.yaml" linenums="1" --8<-- "defaults/main.yaml" diff --git a/mkdocs.yml b/mkdocs.yml index 7bfdd1c..984fab6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,7 +2,7 @@ INHERIT: website-template/mkdocs.yml docs_dir: 'docs' -repo_name: Docker Management +repo_name: nfc_glpi repo_url: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi edit_uri: '/-/ide/project/nofusscomputing/projects/ansible/nfc_glpi/edit/development/-/docs/' From 4407e57fdd56dc49be7b7b5e3550069b2ab7eca4 Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 18:27:59 +0930 Subject: [PATCH 15/30] feat(config): Add General Settings Config from code !1 --- docs/projects/nfc_glpi/config_from_code.md | 26 ++++++- tasks/api/api.yaml | 2 +- tasks/api/append-create-item.yaml | 35 +-------- tasks/api/config.yaml | 91 ++++++++++++++++++++++ tasks/api/search-add.yaml | 47 +++++++++++ tasks/main.yaml | 2 +- 6 files changed, 165 insertions(+), 38 deletions(-) create mode 100644 tasks/api/config.yaml create mode 100644 tasks/api/search-add.yaml diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md index 7bb0803..1257d79 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -1,18 +1,20 @@ --- -title: Config as code +title: GLPI Config as code description: How to use No Fuss Computings Ansible role to configure GLPI from configuration as code. date: 2023-07-28 template: project.html about: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi --- -To configure GLPI using this role, the config/settings are saved as json files. The workflow to create the json files, is to (preferably within a test environment) make the required setting changes in GLPI using the GUI. one the changes have been made, conduct an API `GET` query to GLPI for the item you changed. The JSON body that is returned, is placed within the Config file (detailed below) under path `.body`. You must however, remove any fields that are not required, for example dynamic fields (fields that update themselves or are auto created) for example date fields. - +To configure GLPI using this role, the config/settings are saved as json files. The workflow to create the json files, is to (preferably within a test environment) make the required setting changes in GLPI using the GUI. one the changes have been made, conduct an API `GET` query to GLPI for the item you changed. The JSON body that is returned, is placed within the Config file (detailed below) under path `.body`. You must however, remove any fields that are not required, for example dynamic fields (fields that update themselves or are auto created) for example date fields. it's also recommended to remove the items `id` entry from the body, this option enables the updating and creation of the item by the name field. ## Config files Example -Each tab provides an example of the JSON file layout, including any additional variables. Any variable listed at path `.` that are empty strings, you would complete with the items name as it is exactly within GLPI. These fields are used to fetch the itm_id of the field by name. this enables having the config saved in a more human readable format. For example, for the field `entities_id` you would complete it as `"entities_id": "My entity name"`. +Each tab provides an example of the JSON file layout, including any additional variables. Any variable listed at path `.` that are empty strings, you would complete with the items name as it is exactly within GLPI. These fields are used to fetch the item_id of the field by name. This enables having the config saved in a more human readable format. For example, for the field `entities_id` you would complete it as `"entities_id": "My entity name"`. + +!!! tip + If you leave the item ID in the config file under path `.body.id`, the item that matches this ID, will be updated, not the item matching the name. === "AuthLDAP" @@ -27,6 +29,22 @@ Each tab provides an example of the JSON file layout, including any additional v ``` +=== "Config (GLPI General Settings)" + + This config file contains the settings found in `General Settings`. The full API JSON response is added to the body. When this file is processed, each individual item is added via the API without using the `id` as found in the JSON file. This is done as the ID's can change, so the workflow includes a step that matches the config item name to the found id in the database, then patches with the values from the JSON file. + + ``` json title="example.json" linenums="1" + { + "api_path": "Config", + "body": [ + // JSON from API Query the full response (see note below) + ] + } + ``` + + !!! info + The structure of this JSON file is different than the rest. The body is a **list** of **ALL** of the Config options. This includes the item ID. it was done this way, so that only one API query is required to export all config options. + === "Entity" ``` json title="example.json" linenums="1" diff --git a/tasks/api/api.yaml b/tasks/api/api.yaml index f5e43f5..f11cb5d 100644 --- a/tasks/api/api.yaml +++ b/tasks/api/api.yaml @@ -11,7 +11,7 @@ - name: Append/Create Item ansible.builtin.include_tasks: - file: append-create-item.yaml + file: search-add.yaml loop: "{{ glpi_config_as_code_json }}" diff --git a/tasks/api/append-create-item.yaml b/tasks/api/append-create-item.yaml index a862917..0e479e2 100644 --- a/tasks/api/append-create-item.yaml +++ b/tasks/api/append-create-item.yaml @@ -1,39 +1,10 @@ --- -- name: Create item_body - ansible.builtin.set_fact: - item_body: "{{ item.body }}" - no_log: true - - - name: Search item_id ansible.builtin.include_tasks: file: api/search/item_id.yaml - when: not item.body.id is defined - - -- name: Search entities_id - ansible.builtin.include_tasks: - file: api/search/entities_id.yaml - when: item.entities_id is defined - - -- name: Search tickettemplates_id_demand - ansible.builtin.include_tasks: - file: api/search/tickettemplates_id_demand.yaml - when: item.tickettemplates_id_demand is defined - - -- name: Search itilcategories_id - ansible.builtin.include_tasks: - file: api/search/itilcategories_id.yaml - when: item.itilcategories_id is defined - - -- name: Search users_id - ansible.builtin.include_tasks: - file: api/search/users_id.yaml - when: item.users_id is defined + when: > + not item.body.id is defined - name: Show Body @@ -59,7 +30,7 @@ - name: Update Item ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}/{{ item_body.id }}" + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.api_path != 'Config' %}/{{ item_body.id }}{% endif %}" method: "PATCH" return_content: true body: "{\"input\": {{ item_body | from_yaml | to_json }} }" diff --git a/tasks/api/config.yaml b/tasks/api/config.yaml new file mode 100644 index 0000000..fb6fc1e --- /dev/null +++ b/tasks/api/config.yaml @@ -0,0 +1,91 @@ +--- + +- name: Show {{ list_item.body.name }} + ansible.builtin.debug: + msg: "{{ list_item }}" + +- name: Fetch ID for {{ list_item.body.name }} + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}?searchText[name]={{ list_item.body.name | urlencode }}" + method: "GET" + return_content: true + body: '' + # status_code: "{{ item.status_code | from_yaml | list }}" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + no_log: true + register: glpi_search + + +- name: Build API Body for {{ list_item.body.name }} + ansible.builtin.set_fact: + config_item: + api_path: "{{ list_item.api_path }}" + body: + context: "{{ list_item.body.context }}" + name: "{{ list_item.body.name }}" + value: "{{ list_item.body.value }}" + when: glpi_search.json | length | int == 0 + no_log: true + + +- name: Build API Body (with ID) for {{ list_item.body.name }} + ansible.builtin.set_fact: + config_item: + api_path: "{{ list_item.api_path }}" + body: + id: "{% for found_id in glpi_search.json %}{%if list_item.body.name == found_id.name %}{{ found_id.id }}{% endif %}{% endfor %}" + context: "{{ list_item.body.context }}" + name: "{{ list_item.body.name }}" + value: "{{ list_item.body.value }}" + when: glpi_search.json | length | int > 0 + no_log: true + + +- name: "Item [{{ config_item.body.id + ']: ' + config_item.body.name }}" + ansible.builtin.debug: + msg: "{{ config_item }}" + when: config_item is defined + + +# ToDo: figure out why cant create item????? + +# - name: Create Config Item +# ansible.builtin.uri: +# url: "http://{{ glpi.host }}/apirest.php/{{ config_item.api_path }}" +# method: "POST" +# return_content: true +# body: "{\"input\": {{ config_item.body | from_yaml | to_json }} }" +# status_code: [200, 201] +# headers: +# App-Token: "{{ glpi.app_token }}" +# Session-Token: "{{ glpi.session.valid_id }}" +# body_format: json +# # no_log: true +# when: not config_item.body.id is defined + + +- name: Update Config Item + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}/{{ config_item.body.id }}" + method: "PATCH" + return_content: true + body: "{\"input\": {{ config_item.body | from_yaml | to_json }} }" + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + no_log: true + when: config_item.body.id is defined + + +- name: Clear temp vars + ansible.builtin.set_fact: + config_item: {} + glpi_search: {} + list_item: {} + no_log: true diff --git a/tasks/api/search-add.yaml b/tasks/api/search-add.yaml new file mode 100644 index 0000000..3234ec8 --- /dev/null +++ b/tasks/api/search-add.yaml @@ -0,0 +1,47 @@ +--- + +- name: Create item_body + ansible.builtin.set_fact: + item_body: "{{ item.body }}" + no_log: true + + +- name: Append/Create Item + ansible.builtin.include_tasks: + file: api/append-create-item.yaml + when: not item.api_path == 'Config' + + +- name: Config Items to skip + ansible.builtin.set_fact: + skip_config: + - cas_version + - dbversion + - _dbslave_status + - schema_version + - version + when: item.api_path == 'Config' + + +- name: Config + ansible.builtin.include_tasks: + file: api/config.yaml + when: > + item.api_path == 'Config' + and + not sub_item.name in skip_config + loop: "{{ item_body }}" + loop_control: + loop_var: sub_item + vars: + list_item: + api_path: "{{ item.api_path }}" + body: + context: "{{ sub_item.context }}" + name: "{{ sub_item.name }}" + value: "{{ sub_item.value | default('') }}" + + +- name: Clear temp vars + ansible.builtin.set_fact: + item_body: {} diff --git a/tasks/main.yaml b/tasks/main.yaml index db78c4f..6461bab 100644 --- a/tasks/main.yaml +++ b/tasks/main.yaml @@ -37,4 +37,4 @@ apply: tags: - always - when: glpi_config_as_code_json length | int > 0 + when: glpi_config_as_code_json | length | int > 0 From d2902b9ab055cc0b3e599da1f0f4ecb4d9e7b474 Mon Sep 17 00:00:00 2001 From: Jon Date: Sat, 29 Jul 2023 12:03:40 +0930 Subject: [PATCH 16/30] refactor(api_config): updated flow and docs !1 --- docs/projects/nfc_glpi/config_from_code.md | 9 +++++++++ tasks/api/config.yaml | 5 ----- tasks/api/excluded_config.yaml | 16 ++++++++++++++++ tasks/api/search-add.yaml | 14 +++++--------- 4 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 tasks/api/excluded_config.yaml diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md index 1257d79..7d73a28 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -45,6 +45,15 @@ Each tab provides an example of the JSON file layout, including any additional v !!! info The structure of this JSON file is different than the rest. The body is a **list** of **ALL** of the Config options. This includes the item ID. it was done this way, so that only one API query is required to export all config options. + !!! info "Further Information" + Any config item that does not contain a value field, is excluded from being added or updated. In addition, the following items by name, are excluded + + ``` yaml title="tasks/api/excluded_config.yaml" linenums="1" + + --8<-- "tasks/api/excluded_config.yaml" + + ``` + === "Entity" ``` json title="example.json" linenums="1" diff --git a/tasks/api/config.yaml b/tasks/api/config.yaml index fb6fc1e..4a86aff 100644 --- a/tasks/api/config.yaml +++ b/tasks/api/config.yaml @@ -1,16 +1,11 @@ --- -- name: Show {{ list_item.body.name }} - ansible.builtin.debug: - msg: "{{ list_item }}" - - name: Fetch ID for {{ list_item.body.name }} ansible.builtin.uri: url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}?searchText[name]={{ list_item.body.name | urlencode }}" method: "GET" return_content: true body: '' - # status_code: "{{ item.status_code | from_yaml | list }}" status_code: [200, 201] headers: App-Token: "{{ glpi.app_token }}" diff --git a/tasks/api/excluded_config.yaml b/tasks/api/excluded_config.yaml new file mode 100644 index 0000000..75995d2 --- /dev/null +++ b/tasks/api/excluded_config.yaml @@ -0,0 +1,16 @@ +--- + +- name: Config Items to skip + ansible.builtin.set_fact: + skip_config: + - cas_version + - dbversion + - _dbslave_status + - init_all + - notification_uuid + - proxy_passwd + - registration_uuid + - schema_version + - smtp_passwd + - version + when: item.api_path == 'Config' diff --git a/tasks/api/search-add.yaml b/tasks/api/search-add.yaml index 3234ec8..03bd8a1 100644 --- a/tasks/api/search-add.yaml +++ b/tasks/api/search-add.yaml @@ -13,14 +13,8 @@ - name: Config Items to skip - ansible.builtin.set_fact: - skip_config: - - cas_version - - dbversion - - _dbslave_status - - schema_version - - version - when: item.api_path == 'Config' + ansible.builtin.import_tasks: + file: api/excluded_config.yaml - name: Config @@ -30,6 +24,8 @@ item.api_path == 'Config' and not sub_item.name in skip_config + and + sub_item.value is defined loop: "{{ item_body }}" loop_control: loop_var: sub_item @@ -39,7 +35,7 @@ body: context: "{{ sub_item.context }}" name: "{{ sub_item.name }}" - value: "{{ sub_item.value | default('') }}" + value: "{{ sub_item.value }}" - name: Clear temp vars From 910663eb19fcd61bfa9b7419bcb75b3a4d1be62b Mon Sep 17 00:00:00 2001 From: Jon Date: Sat, 29 Jul 2023 12:10:06 +0930 Subject: [PATCH 17/30] feat(api_config): exlude instance_uuid item from configuration !1 --- tasks/api/excluded_config.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tasks/api/excluded_config.yaml b/tasks/api/excluded_config.yaml index 75995d2..efcb4cc 100644 --- a/tasks/api/excluded_config.yaml +++ b/tasks/api/excluded_config.yaml @@ -1,5 +1,9 @@ --- - +# +# Config items excluded from Adding/Updating. +# +# Each list item is the name of the config item. +# - name: Config Items to skip ansible.builtin.set_fact: skip_config: @@ -7,6 +11,7 @@ - dbversion - _dbslave_status - init_all + - instance_uuid - notification_uuid - proxy_passwd - registration_uuid From baf086de642513657d4f70dbb497f9e755b7e557 Mon Sep 17 00:00:00 2001 From: Jon Date: Sat, 29 Jul 2023 12:48:24 +0930 Subject: [PATCH 18/30] feat(api_config): force an empty list if not config !1 --- tasks/api/search-add.yaml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/tasks/api/search-add.yaml b/tasks/api/search-add.yaml index 03bd8a1..20f916c 100644 --- a/tasks/api/search-add.yaml +++ b/tasks/api/search-add.yaml @@ -17,16 +17,14 @@ file: api/excluded_config.yaml -- name: Config +- name: Add/Update GLPI Config ansible.builtin.include_tasks: file: api/config.yaml when: > - item.api_path == 'Config' - and not sub_item.name in skip_config and sub_item.value is defined - loop: "{{ item_body }}" + loop: "{% if item.api_path == 'Config' %}{{ item_body }}{% else %}{{ [] }}{% endif %}" loop_control: loop_var: sub_item vars: From 40e629974128b3788cdfadea37e7aa2caae115de Mon Sep 17 00:00:00 2001 From: Jon Date: Sat, 29 Jul 2023 21:23:02 +0930 Subject: [PATCH 19/30] feat(config): Add Ticket Template Config from code !1 --- defaults/main.yaml | 1 + docs/projects/nfc_glpi/config_from_code.md | 35 +++++++ tasks/api/append-create-item.yaml | 62 ++++++++++++- tasks/api/search-add.yaml | 13 ++- tasks/api/search/item_id.yaml | 96 ++++++++++++++++++- tasks/api/search/tickettemplates_id.yaml | 31 +++++++ tasks/api/ticket_template.yaml | 103 +++++++++++++++++++++ 7 files changed, 329 insertions(+), 12 deletions(-) create mode 100644 tasks/api/search/tickettemplates_id.yaml create mode 100644 tasks/api/ticket_template.yaml diff --git a/defaults/main.yaml b/defaults/main.yaml index 2806058..1a1d295 100644 --- a/defaults/main.yaml +++ b/defaults/main.yaml @@ -48,3 +48,4 @@ mysql_database_glpi: glpi glpi_config_as_code_json: [] +search_items: [] diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md index 7d73a28..46922e2 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -98,6 +98,41 @@ Each tab provides an example of the JSON file layout, including any additional v ``` +=== "TicketTemplate" + + This config file covers all parts of a ticket template. with this template you can create and update an existing ticket template. + + !!! warning + Assosiated Items do not get updated or removed. They will be added if they don't exist. No checks are done for more assosiated items then are specified in the template. + + ``` json title="example.json" linenums="1" + + { + "api_path": "TicketTemplate", + "entities_id": "", + "body": { + // JSON from API Query + }, + "_TicketTemplateMandatoryField": [ + + // JSON from API Query path TicketTemplate/{ticket_template_id}/TicketTemplateMandatoryField + ], + "_TicketTemplatePredefinedField": [ + + // JSON from API Query path TicketTemplate/{ticket_template_id}/TicketTemplatePredefinedField + + ], + "_TicketTemplateHiddenField": [ + + // JSON from API Query path TicketTemplate/{ticket_template_id}/TicketTemplateHiddenField + + ] + } + + ``` + + Sub-items to the ticket are `TicketTemplateMandatoryField`, `TicketTemplatePredefinedField` and `TicketTemplateHiddenField` and are at json path `._{sub-item}`. These items are a **list of dicts** and can contain the `id` of the item, however it is ignored as the update is base off of `tickettemplates_id`, `num` for all and `tickettemplates_id`, `num` and `value` for `num=13` which is an assosiated item. With the exception of the latter, all of these values will be updated if they exist. + With the config files structured as per the examples, within your playbook(s), load the json files in a list of json objects using variable `glpi_config_as_code_json` diff --git a/tasks/api/append-create-item.yaml b/tasks/api/append-create-item.yaml index 0e479e2..0f59d86 100644 --- a/tasks/api/append-create-item.yaml +++ b/tasks/api/append-create-item.yaml @@ -1,10 +1,48 @@ --- +- name: Show item + ansible.builtin.debug: + msg: "{{ item }}" + +- name: Create item_body + ansible.builtin.set_fact: + item_body: "{{ item.body }}" + no_log: true + - name: Search item_id ansible.builtin.include_tasks: file: api/search/item_id.yaml - when: > - not item.body.id is defined + when: not item.body.id is defined + + +- name: Search entities_id + ansible.builtin.include_tasks: + file: api/search/entities_id.yaml + when: item.entities_id is defined + + +- name: Search itilcategories_id + ansible.builtin.include_tasks: + file: api/search/itilcategories_id.yaml + when: item.itilcategories_id is defined + + +- name: Search tickettemplates_id_demand + ansible.builtin.include_tasks: + file: api/search/itickettemplates_id_demand.yaml + when: item.tickettemplates_id_demand is defined + + +- name: Search tickettemplates_id + ansible.builtin.include_tasks: + file: api/search/tickettemplates_id.yaml + when: item.tickettemplates_id is defined + + +- name: Search users_id + ansible.builtin.include_tasks: + file: api/search/users_id.yaml + when: item.users_id is defined - name: Show Body @@ -15,7 +53,7 @@ - name: Create Item ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}" + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% endif %}" method: "POST" return_content: true body: "{\"input\": {{ item_body | from_yaml | to_json }} }" @@ -25,12 +63,14 @@ Session-Token: "{{ glpi.session.valid_id }}" body_format: json no_log: true - when: not item_body.id is defined + register: create_item + when: > + not item_body.id is defined - name: Update Item ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.api_path != 'Config' %}/{{ item_body.id }}{% endif %}" + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% else %}{% if item.api_path != 'Config' %}/{{ item_body.id | default('') }}{% endif %}{% endif %}" method: "PATCH" return_content: true body: "{\"input\": {{ item_body | from_yaml | to_json }} }" @@ -40,9 +80,21 @@ Session-Token: "{{ glpi.session.valid_id }}" body_format: json no_log: true + register: update_item when: item_body.id is defined +- name: Fail on no action + ansible.builtin.fail: + msg: No action carried out, stop. + when: > + update_item.skipped | default(false) | bool + and + create_item.skipped | default(false) | bool + + - name: Clear temp vars ansible.builtin.set_fact: item_body: {} + create_item: {} + update_item: {} diff --git a/tasks/api/search-add.yaml b/tasks/api/search-add.yaml index 20f916c..11c09f8 100644 --- a/tasks/api/search-add.yaml +++ b/tasks/api/search-add.yaml @@ -1,15 +1,18 @@ --- -- name: Create item_body - ansible.builtin.set_fact: - item_body: "{{ item.body }}" - no_log: true +- name: Ticket Template + ansible.builtin.include_tasks: + file: api/ticket_template.yaml + when: item.api_path == 'TicketTemplate' - name: Append/Create Item ansible.builtin.include_tasks: file: api/append-create-item.yaml - when: not item.api_path == 'Config' + when: > + not item.api_path == 'Config' + and + not item.api_path == 'TicketTemplate' - name: Config Items to skip diff --git a/tasks/api/search/item_id.yaml b/tasks/api/search/item_id.yaml index 846bf4b..1d637cb 100644 --- a/tasks/api/search/item_id.yaml +++ b/tasks/api/search/item_id.yaml @@ -1,7 +1,7 @@ --- - name: Find Item ID ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}?searchText[name]={{ item.body.name | urlencode }}" + url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% endif%}{% if search_items | length | int > 0%}?{% for search in search_items %}searchText[{{ search.name }}]={{ search.value | urlencode }}&{% endfor %}{% else%}?searchText[name]={{ item.body.name | urlencode }}{% endif %}" method: "GET" return_content: true body: '' @@ -22,10 +22,102 @@ when: glpi_search.json | length | int == 1 +- name: Iterate over results for TicketTemplateMandatoryField id/TicketTemplateHiddenField + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 1 + and + ( + 'TicketTemplateMandatoryField' in item.sub_path | default('') + or + 'TicketTemplateHiddenField' in item.sub_path | default('') + ) + + +- name: Set iterate id + ansible.builtin.set_fact: + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout is defined + + +- name: Iterate over results for TicketTemplatePredefinedField id + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 1 + and + 'TicketTemplatePredefinedField' in item.sub_path | default('') + + +- name: Set iterate id + ansible.builtin.set_fact: + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout is defined + + - name: Append id ansible.builtin.set_fact: item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + no_log: true + when: new_data | default({}) | length | int > 0 + +- name: Item_id fact Cleanup + ansible.builtin.set_fact: glpi_search: {} new_data: {} no_log: true - when: glpi_search.json | length | int == 1 diff --git a/tasks/api/search/tickettemplates_id.yaml b/tasks/api/search/tickettemplates_id.yaml new file mode 100644 index 0000000..8901d89 --- /dev/null +++ b/tasks/api/search/tickettemplates_id.yaml @@ -0,0 +1,31 @@ +--- +- name: Fetch tickettemplates_id + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/TicketTemplate?searchText[name]={{ item.tickettemplates_id | urlencode }}" + method: "GET" + return_content: true + body: '' + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + register: glpi_search + no_log: true + + +- name: Set tickettemplates_id + ansible.builtin.set_fact: + new_data: + tickettemplates_id: "{{ glpi_search.json[0].id | int }}" + when: glpi_search.json | length | int == 1 + + +- name: Append tickettemplates_id + ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + new_data: {} + tickettemplates_id: "{{ glpi_search.json[0].id | int }}" + glpi_search: {} + no_log: true + when: glpi_search.json | length | int == 1 diff --git a/tasks/api/ticket_template.yaml b/tasks/api/ticket_template.yaml new file mode 100644 index 0000000..b0e2387 --- /dev/null +++ b/tasks/api/ticket_template.yaml @@ -0,0 +1,103 @@ +--- + +- name: Template item + ansible.builtin.set_fact: + template_item: "{{ item }}" + + +- name: Append/Create TicketTemplate + ansible.builtin.include_tasks: + file: api/append-create-item.yaml + when: item.api_path == 'TicketTemplate' + vars: + item: + api_path: TicketTemplate + entities_id: "{{ template_item.entities_id }}" + body: "{{ template_item.body }}" + + +- name: Search tickettemplates_id + ansible.builtin.include_tasks: + file: api/search/tickettemplates_id.yaml + vars: + item: + tickettemplates_id: "{{ template_item.body.name }}" + + +- name: Append/Create Ticket Template Mandatory Fields + ansible.builtin.include_tasks: + file: api/append-create-item.yaml + when: > + template_item._TicketTemplateMandatoryField is defined + and + template_item._TicketTemplateMandatoryField | length | int > 0 + loop: "{{ template_item._TicketTemplateMandatoryField }}" + loop_control: + loop_var: sub_item + vars: + search_items: + - name: tickettemplates_id + value: "{{ tickettemplates_id }}" + - name: num + value: "{{ sub_item.num }}" + item: + api_path: TicketTemplate + sub_path: "{{ tickettemplates_id }}/TicketTemplateMandatoryField" + body: + num: "{{ sub_item.num }}" + tickettemplates_id: "{{ tickettemplates_id | int }}" + + +- name: Append/Create Ticket Template Predefined Fields + ansible.builtin.include_tasks: + file: api/append-create-item.yaml + when: > + template_item._TicketTemplatePredefinedField is defined + and + template_item._TicketTemplatePredefinedField | length | int > 0 + loop: "{{ template_item._TicketTemplatePredefinedField }}" + loop_control: + loop_var: sub_item + vars: + search_items: + - name: tickettemplates_id + value: "{{ tickettemplates_id }}" + - name: num + value: "{{ sub_item.num }}" + item: + api_path: TicketTemplate + sub_path: "{{ tickettemplates_id }}/TicketTemplatePredefinedField" + body: + num: "{{ sub_item.num | int }}" + tickettemplates_id: "{{ tickettemplates_id | int }}" + value: "{{ sub_item.value | string }}" + + +- name: Append/Create Ticket Template Hidden Fields + ansible.builtin.include_tasks: + file: api/append-create-item.yaml + when: > + template_item._TicketTemplateHiddenField is defined + and + template_item._TicketTemplateHiddenField | length | int > 0 + loop: "{{ template_item._TicketTemplateHiddenField }}" + loop_control: + loop_var: sub_item + vars: + search_items: + - name: tickettemplates_id + value: "{{ tickettemplates_id }}" + - name: num + value: "{{ sub_item.num }}" + item: + api_path: TicketTemplate + sub_path: "{{ tickettemplates_id }}/TicketTemplateHiddenField" + body: + num: "{{ sub_item.num | int }}" + tickettemplates_id: "{{ tickettemplates_id | int }}" + + +- name: Clear temp vars + ansible.builtin.set_fact: + template_item: {} + no_log: true From b0ce3b00227c0141e9c9f7cd0b5be40ed7e735ee Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 11:31:20 +0930 Subject: [PATCH 20/30] refactor(api_config): dont log data manipulation !1 --- tasks/api/append-create-item.yaml | 1 + tasks/api/search-add.yaml | 1 + tasks/api/search/item_id.yaml | 2 ++ 3 files changed, 4 insertions(+) diff --git a/tasks/api/append-create-item.yaml b/tasks/api/append-create-item.yaml index 0f59d86..f33af6c 100644 --- a/tasks/api/append-create-item.yaml +++ b/tasks/api/append-create-item.yaml @@ -98,3 +98,4 @@ item_body: {} create_item: {} update_item: {} + no_log: true diff --git a/tasks/api/search-add.yaml b/tasks/api/search-add.yaml index 11c09f8..8fc2e0a 100644 --- a/tasks/api/search-add.yaml +++ b/tasks/api/search-add.yaml @@ -42,3 +42,4 @@ - name: Clear temp vars ansible.builtin.set_fact: item_body: {} + no_log: true diff --git a/tasks/api/search/item_id.yaml b/tasks/api/search/item_id.yaml index 1d637cb..b2543dd 100644 --- a/tasks/api/search/item_id.yaml +++ b/tasks/api/search/item_id.yaml @@ -44,6 +44,7 @@ executable: bash register: itarate_id changed_when: false + no_log: true when: > glpi_search.json | length | int > 1 and @@ -98,6 +99,7 @@ executable: bash register: itarate_id changed_when: false + no_log: true when: > glpi_search.json | length | int > 1 and From 6d7c169bc8cfffbcf094469871316282435a35d8 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 11:35:08 +0930 Subject: [PATCH 21/30] refactor(api_config): move all search by name to own tasks file !1 --- docs/projects/nfc_glpi/config_from_code.md | 22 ++++++++++++- tasks/api/append-create-item.yaml | 36 ++-------------------- tasks/api/search.yaml | 36 ++++++++++++++++++++++ 3 files changed, 60 insertions(+), 34 deletions(-) create mode 100644 tasks/api/search.yaml diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md index 46922e2..8dcb078 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -9,9 +9,29 @@ about: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi To configure GLPI using this role, the config/settings are saved as json files. The workflow to create the json files, is to (preferably within a test environment) make the required setting changes in GLPI using the GUI. one the changes have been made, conduct an API `GET` query to GLPI for the item you changed. The JSON body that is returned, is placed within the Config file (detailed below) under path `.body`. You must however, remove any fields that are not required, for example dynamic fields (fields that update themselves or are auto created) for example date fields. it's also recommended to remove the items `id` entry from the body, this option enables the updating and creation of the item by the name field. +!!! warning + To utilise the config from json files, it's important that any configurable item from json files, that it's name is unique for that item type within GLPI. This is due to the feature "find item_id by name" i.e. you can't have two items named `my name` and `my name` of type `x`, even if in different entities. + + ## Config files Example -Each tab provides an example of the JSON file layout, including any additional variables. Any variable listed at path `.` that are empty strings, you would complete with the items name as it is exactly within GLPI. These fields are used to fetch the item_id of the field by name. This enables having the config saved in a more human readable format. For example, for the field `entities_id` you would complete it as `"entities_id": "My entity name"`. +Each tab provides an example of the JSON file layout, including any additional variables. Variable listed at path `.`, with the exception of `api_path`, `body` or have asuffix of `_` are provided to use that items name. These fields are used to fetch the item_id of the field by name. available fields are: + +- entities_id + +- item_id + +- itilcategories_id + +- tickettemplates_id_demand + +- tickettemplates_id + +- users_id + + +For example, to have an item placed in the entity `NoFussComputing` provided value would be `"entities_id": "NoFussComputing"`. As part of the item workflow a search for an entity named `NoFussComputing` is conducted, and if found, adds it's `entity_id` to path `.body.entities_id: {entity_id}`. + !!! tip If you leave the item ID in the config file under path `.body.id`, the item that matches this ID, will be updated, not the item matching the name. diff --git a/tasks/api/append-create-item.yaml b/tasks/api/append-create-item.yaml index f33af6c..6a392c9 100644 --- a/tasks/api/append-create-item.yaml +++ b/tasks/api/append-create-item.yaml @@ -9,40 +9,10 @@ item_body: "{{ item.body }}" no_log: true -- name: Search item_id + +- name: Search for item IDs ansible.builtin.include_tasks: - file: api/search/item_id.yaml - when: not item.body.id is defined - - -- name: Search entities_id - ansible.builtin.include_tasks: - file: api/search/entities_id.yaml - when: item.entities_id is defined - - -- name: Search itilcategories_id - ansible.builtin.include_tasks: - file: api/search/itilcategories_id.yaml - when: item.itilcategories_id is defined - - -- name: Search tickettemplates_id_demand - ansible.builtin.include_tasks: - file: api/search/itickettemplates_id_demand.yaml - when: item.tickettemplates_id_demand is defined - - -- name: Search tickettemplates_id - ansible.builtin.include_tasks: - file: api/search/tickettemplates_id.yaml - when: item.tickettemplates_id is defined - - -- name: Search users_id - ansible.builtin.include_tasks: - file: api/search/users_id.yaml - when: item.users_id is defined + file: api/search.yaml - name: Show Body diff --git a/tasks/api/search.yaml b/tasks/api/search.yaml new file mode 100644 index 0000000..53540cf --- /dev/null +++ b/tasks/api/search.yaml @@ -0,0 +1,36 @@ +--- + +- name: Search item_id + ansible.builtin.include_tasks: + file: api/search/item_id.yaml + when: not item.body.id is defined + + +- name: Search entities_id + ansible.builtin.include_tasks: + file: api/search/entities_id.yaml + when: item.entities_id is defined + + +- name: Search itilcategories_id + ansible.builtin.include_tasks: + file: api/search/itilcategories_id.yaml + when: item.itilcategories_id is defined + + +- name: Search tickettemplates_id_demand + ansible.builtin.include_tasks: + file: api/search/itickettemplates_id_demand.yaml + when: item.tickettemplates_id_demand is defined + + +- name: Search tickettemplates_id + ansible.builtin.include_tasks: + file: api/search/tickettemplates_id.yaml + when: item.tickettemplates_id is defined + + +- name: Search users_id + ansible.builtin.include_tasks: + file: api/search/users_id.yaml + when: item.users_id is defined From 9a820cd1a0db9144bc13b859d8dc25a77c19eee5 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 11:36:12 +0930 Subject: [PATCH 22/30] feat(api): search for groups_id by name !1 --- docs/projects/nfc_glpi/config_from_code.md | 2 ++ tasks/api/search.yaml | 6 ++++ tasks/api/search/groups_id.yaml | 32 ++++++++++++++++++++++ 3 files changed, 40 insertions(+) create mode 100644 tasks/api/search/groups_id.yaml diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md index 8dcb078..00f2704 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -19,6 +19,8 @@ Each tab provides an example of the JSON file layout, including any additional v - entities_id +- groups_id + - item_id - itilcategories_id diff --git a/tasks/api/search.yaml b/tasks/api/search.yaml index 53540cf..efbc277 100644 --- a/tasks/api/search.yaml +++ b/tasks/api/search.yaml @@ -12,6 +12,12 @@ when: item.entities_id is defined +- name: Search groups_id + ansible.builtin.include_tasks: + file: api/search/groups_id.yaml + when: item.groups_id is defined + + - name: Search itilcategories_id ansible.builtin.include_tasks: file: api/search/itilcategories_id.yaml diff --git a/tasks/api/search/groups_id.yaml b/tasks/api/search/groups_id.yaml new file mode 100644 index 0000000..545cd74 --- /dev/null +++ b/tasks/api/search/groups_id.yaml @@ -0,0 +1,32 @@ +--- + +- name: Fetch users_id + ansible.builtin.uri: + url: "http://{{ glpi.host }}/apirest.php/Group?searchText[name]={{ item.groups_id | urlencode }}" + method: "GET" + return_content: true + body: '' + status_code: [200, 201] + headers: + App-Token: "{{ glpi.app_token }}" + Session-Token: "{{ glpi.session.valid_id }}" + body_format: json + register: glpi_search + no_log: true + + +- name: Set groups_id + ansible.builtin.set_fact: + new_data: + groups_id: "{{ glpi_search.json[0].id | int }}" + when: glpi_search.json | length | int == 1 + + +- name: Append groups (have item_body) + ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + glpi_search: {} + new_data: {} + no_log: true + when: glpi_search.json | length | int == 1 + From 23569ee76a53fb4ae0c815bc086d5eac374ff455 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 11:47:31 +0930 Subject: [PATCH 23/30] docs(issue_1): add note about exporting !1 --- docs/projects/nfc_glpi/config_from_code.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/projects/nfc_glpi/config_from_code.md b/docs/projects/nfc_glpi/config_from_code.md index 00f2704..2a6b647 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -6,8 +6,9 @@ template: project.html about: https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi --- -To configure GLPI using this role, the config/settings are saved as json files. The workflow to create the json files, is to (preferably within a test environment) make the required setting changes in GLPI using the GUI. one the changes have been made, conduct an API `GET` query to GLPI for the item you changed. The JSON body that is returned, is placed within the Config file (detailed below) under path `.body`. You must however, remove any fields that are not required, for example dynamic fields (fields that update themselves or are auto created) for example date fields. it's also recommended to remove the items `id` entry from the body, this option enables the updating and creation of the item by the name field. +To configure GLPI using this role, the config/settings are saved as json files. The workflow to create the json files, is to (preferably within a test environment) make the required setting changes in GLPI using the GUI. once the changes have been made, conduct an API `GET` query to GLPI for the item you changed. The JSON body that is returned, is placed within the Config file (detailed below) under path `.body`. You must however, remove any fields that are not required, for example dynamic fields (fields that update themselves or are auto created) for example date fields. it's also recommended to remove the items `id` entry from the body, this option enables the updating and creation of the item by the name field. +As the export process is manual to create the json files, it is possible that errors could occur. another side effect is that when updating an item, when checking it into an SCM (git for example), that the commit may contain more than the item that changed. This is planned to be rectified in [gitlab-#1](https://gitlab.com/nofusscomputing/projects/ansible/nfc_glpi/-/issues/1). !!! warning To utilise the config from json files, it's important that any configurable item from json files, that it's name is unique for that item type within GLPI. This is due to the feature "find item_id by name" i.e. you can't have two items named `my name` and `my name` of type `x`, even if in different entities. From 93f069c1b39e882e0a1a341c6352de600b68af17 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 12:57:55 +0930 Subject: [PATCH 24/30] fix(api_search): typo in tickettemplates_id_demand !1 --- tasks/api/search.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/api/search.yaml b/tasks/api/search.yaml index efbc277..97998b7 100644 --- a/tasks/api/search.yaml +++ b/tasks/api/search.yaml @@ -26,7 +26,7 @@ - name: Search tickettemplates_id_demand ansible.builtin.include_tasks: - file: api/search/itickettemplates_id_demand.yaml + file: api/search/tickettemplates_id_demand.yaml when: item.tickettemplates_id_demand is defined From 00ecd6e0e30254c2e87f84b1196d534df576cfd9 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 12:58:25 +0930 Subject: [PATCH 25/30] fix(api_config): typo in Add/Update GLPI Config !1 --- tasks/api/search-add.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/api/search-add.yaml b/tasks/api/search-add.yaml index 8fc2e0a..31a1b34 100644 --- a/tasks/api/search-add.yaml +++ b/tasks/api/search-add.yaml @@ -27,7 +27,7 @@ not sub_item.name in skip_config and sub_item.value is defined - loop: "{% if item.api_path == 'Config' %}{{ item_body }}{% else %}{{ [] }}{% endif %}" + loop: "{% if item.api_path == 'Config' %}{{ item.body }}{% else %}{{ [] }}{% endif %}" loop_control: loop_var: sub_item vars: From d637f915c5de32fdd854b9f72f3c1a6eb5ca1d04 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 12:59:52 +0930 Subject: [PATCH 26/30] refactor(api_config): iterate over results changed to iterate over results as the api search is not exact, it's contains. now workflow iterates over results and on name match, exact; Adds the item id. !1 --- tasks/api/search/entities_id.yaml | 32 ++++++++++++++--- tasks/api/search/groups_id.yaml | 33 +++++++++++++---- tasks/api/search/item_id.yaml | 8 ++--- tasks/api/search/itilcategories_id.yaml | 32 ++++++++++++++--- tasks/api/search/tickettemplates_id.yaml | 35 +++++++++++++++---- .../api/search/tickettemplates_id_demand.yaml | 32 ++++++++++++++--- tasks/api/search/users_id.yaml | 32 ++++++++++++++--- 7 files changed, 165 insertions(+), 39 deletions(-) diff --git a/tasks/api/search/entities_id.yaml b/tasks/api/search/entities_id.yaml index af3e485..c0de592 100644 --- a/tasks/api/search/entities_id.yaml +++ b/tasks/api/search/entities_id.yaml @@ -15,17 +15,39 @@ no_log: true +- name: Iterate over results for ID search + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 0 + + - name: Set entities_id ansible.builtin.set_fact: - new_data: - entities_id: "{{ glpi_search.json[0].id | int }}" - when: glpi_search.json | length | int == 1 + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout | default({}) | length | int > 0 - name: Append entities_id ansible.builtin.set_fact: - item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" glpi_search: {} + itarate_id: {} new_data: {} no_log: true - when: glpi_search.json | length | int == 1 diff --git a/tasks/api/search/groups_id.yaml b/tasks/api/search/groups_id.yaml index 545cd74..51bbcfe 100644 --- a/tasks/api/search/groups_id.yaml +++ b/tasks/api/search/groups_id.yaml @@ -15,18 +15,39 @@ no_log: true +- name: Iterate over results for ID search + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 0 + + - name: Set groups_id ansible.builtin.set_fact: - new_data: - groups_id: "{{ glpi_search.json[0].id | int }}" - when: glpi_search.json | length | int == 1 + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout | default({}) | length | int > 0 - name: Append groups (have item_body) ansible.builtin.set_fact: - item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" glpi_search: {} + itarate_id: {} new_data: {} no_log: true - when: glpi_search.json | length | int == 1 - diff --git a/tasks/api/search/item_id.yaml b/tasks/api/search/item_id.yaml index b2543dd..10fe58b 100644 --- a/tasks/api/search/item_id.yaml +++ b/tasks/api/search/item_id.yaml @@ -112,14 +112,10 @@ when: itarate_id.stdout is defined -- name: Append id - ansible.builtin.set_fact: - item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" - no_log: true - when: new_data | default({}) | length | int > 0 - - name: Item_id fact Cleanup ansible.builtin.set_fact: + item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" glpi_search: {} + itarate_id: {} new_data: {} no_log: true diff --git a/tasks/api/search/itilcategories_id.yaml b/tasks/api/search/itilcategories_id.yaml index abbd9cb..6fdb33a 100644 --- a/tasks/api/search/itilcategories_id.yaml +++ b/tasks/api/search/itilcategories_id.yaml @@ -15,17 +15,39 @@ no_log: true +- name: Iterate over results for ID search + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 0 + + - name: Set itilcategories_id ansible.builtin.set_fact: - new_data: - itilcategories_id: "{{ glpi_search.json[0].id | int }}" - when: glpi_search.json | length | int == 1 + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout | default({}) | length | int > 0 - name: Append itilcategories_id ansible.builtin.set_fact: - item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" glpi_search: {} + itarate_id: {} new_data: {} no_log: true - when: item.itilcategories_id is defined diff --git a/tasks/api/search/tickettemplates_id.yaml b/tasks/api/search/tickettemplates_id.yaml index 8901d89..f296703 100644 --- a/tasks/api/search/tickettemplates_id.yaml +++ b/tasks/api/search/tickettemplates_id.yaml @@ -14,18 +14,39 @@ no_log: true +- name: Iterate over results for ID search + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 0 + + - name: Set tickettemplates_id ansible.builtin.set_fact: - new_data: - tickettemplates_id: "{{ glpi_search.json[0].id | int }}" - when: glpi_search.json | length | int == 1 + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout | default({}) | length | int > 0 - name: Append tickettemplates_id ansible.builtin.set_fact: - item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" - new_data: {} - tickettemplates_id: "{{ glpi_search.json[0].id | int }}" + item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" glpi_search: {} + itarate_id: {} + new_data: {} no_log: true - when: glpi_search.json | length | int == 1 diff --git a/tasks/api/search/tickettemplates_id_demand.yaml b/tasks/api/search/tickettemplates_id_demand.yaml index 5453874..396662f 100644 --- a/tasks/api/search/tickettemplates_id_demand.yaml +++ b/tasks/api/search/tickettemplates_id_demand.yaml @@ -15,17 +15,39 @@ no_log: true +- name: Iterate over results for ID search + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 0 + + - name: Set tickettemplates_id_demand ansible.builtin.set_fact: - new_data: - tickettemplates_id_demand: "{{ glpi_search.json[0].id | int }}" - when: glpi_search.json | length | int == 1 + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout | default({}) | length | int > 0 - name: Append tickettemplates_id_demand ansible.builtin.set_fact: - item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" glpi_search: {} + itarate_id: {} new_data: {} no_log: true - when: glpi_search.json | length | int == 1 diff --git a/tasks/api/search/users_id.yaml b/tasks/api/search/users_id.yaml index 07e1afb..68f653d 100644 --- a/tasks/api/search/users_id.yaml +++ b/tasks/api/search/users_id.yaml @@ -16,17 +16,39 @@ no_log: true +- name: Iterate over results for ID search + ansible.builtin.shell: + cmd: | + cat < + glpi_search.json | length | int > 0 + + - name: Set users_id ansible.builtin.set_fact: - new_data: - users_id: "{{ glpi_search.json[0].id | int }}" - when: glpi_search.json | length | int == 1 + new_data: "{{ itarate_id.stdout | from_yaml }}" + when: itarate_id.stdout | default({}) | length | int > 0 - name: Append users_id (have item_body) ansible.builtin.set_fact: - item_body: "{{ item_body | ansible.builtin.combine(new_data) }}" + item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" glpi_search: {} + itarate_id: {} new_data: {} no_log: true - when: glpi_search.json | length | int == 1 From b50a3e9156f3d18dd43fe495c86cca465ccd38c6 Mon Sep 17 00:00:00 2001 From: Jon Date: Sun, 30 Jul 2023 13:12:06 +0930 Subject: [PATCH 27/30] fix(api_search): set var tickettemplates_id for ticket template item !1 --- tasks/api/search/tickettemplates_id.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/api/search/tickettemplates_id.yaml b/tasks/api/search/tickettemplates_id.yaml index f296703..dddcf2b 100644 --- a/tasks/api/search/tickettemplates_id.yaml +++ b/tasks/api/search/tickettemplates_id.yaml @@ -46,6 +46,7 @@ - name: Append tickettemplates_id ansible.builtin.set_fact: item_body: "{{ item_body | ansible.builtin.combine(new_data | default({})) }}" + tickettemplates_id: "{{ new_data.tickettemplates_id | default(omit) | int }}" glpi_search: {} itarate_id: {} new_data: {} From d2d4826247289debfa4d073baefc15d8048a5436 Mon Sep 17 00:00:00 2001 From: Jon Date: Mon, 31 Jul 2023 17:44:16 +0930 Subject: [PATCH 28/30] fix(find_id): remove empty id from dict !1 --- tasks/api/config.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/tasks/api/config.yaml b/tasks/api/config.yaml index 4a86aff..6f18d99 100644 --- a/tasks/api/config.yaml +++ b/tasks/api/config.yaml @@ -40,6 +40,18 @@ no_log: true +- name: Remove Empty ID from body + ansible.builtin.set_fact: + config_item: + api_path: "{{ list_item.api_path }}" + body: + context: "{{ list_item.body.context }}" + name: "{{ list_item.body.name }}" + value: "{{ list_item.body.value }}" + when: config_item.body.id | default('0') == '' + no_log: true + + - name: "Item [{{ config_item.body.id + ']: ' + config_item.body.name }}" ansible.builtin.debug: msg: "{{ config_item }}" From 7c82e3a18d992db25577a8611fa964ae555469a9 Mon Sep 17 00:00:00 2001 From: Jon Date: Sat, 5 Aug 2023 10:25:14 +0930 Subject: [PATCH 29/30] feat(url): specify url seperate from protocol, defaults to httpt !1 --- tasks/api/append-create-item.yaml | 4 ++-- tasks/api/config.yaml | 4 ++-- tasks/api/search/entities_id.yaml | 3 ++- tasks/api/search/groups_id.yaml | 2 +- tasks/api/search/item_id.yaml | 2 +- tasks/api/search/itilcategories_id.yaml | 2 +- tasks/api/search/tickettemplates_id.yaml | 2 +- tasks/api/search/tickettemplates_id_demand.yaml | 2 +- tasks/api/search/users_id.yaml | 2 +- tasks/api/session-create.yaml | 2 +- tasks/api/session-end.yaml | 2 +- 11 files changed, 14 insertions(+), 13 deletions(-) diff --git a/tasks/api/append-create-item.yaml b/tasks/api/append-create-item.yaml index 6a392c9..3a72a04 100644 --- a/tasks/api/append-create-item.yaml +++ b/tasks/api/append-create-item.yaml @@ -23,7 +23,7 @@ - name: Create Item ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% endif %}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% endif %}" method: "POST" return_content: true body: "{\"input\": {{ item_body | from_yaml | to_json }} }" @@ -40,7 +40,7 @@ - name: Update Item ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% else %}{% if item.api_path != 'Config' %}/{{ item_body.id | default('') }}{% endif %}{% endif %}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% else %}{% if item.api_path != 'Config' %}/{{ item_body.id | default('') }}{% endif %}{% endif %}" method: "PATCH" return_content: true body: "{\"input\": {{ item_body | from_yaml | to_json }} }" diff --git a/tasks/api/config.yaml b/tasks/api/config.yaml index 6f18d99..20d4f41 100644 --- a/tasks/api/config.yaml +++ b/tasks/api/config.yaml @@ -2,7 +2,7 @@ - name: Fetch ID for {{ list_item.body.name }} ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}?searchText[name]={{ list_item.body.name | urlencode }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/{{ item.api_path }}?searchText[name]={{ list_item.body.name | urlencode }}" method: "GET" return_content: true body: '' @@ -77,7 +77,7 @@ - name: Update Config Item ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}/{{ config_item.body.id }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/{{ item.api_path }}/{{ config_item.body.id }}" method: "PATCH" return_content: true body: "{\"input\": {{ config_item.body | from_yaml | to_json }} }" diff --git a/tasks/api/search/entities_id.yaml b/tasks/api/search/entities_id.yaml index c0de592..de0c3c2 100644 --- a/tasks/api/search/entities_id.yaml +++ b/tasks/api/search/entities_id.yaml @@ -1,7 +1,7 @@ --- - name: Fetch entities_id ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/Entity?searchText[name]={{ item.entities_id | urlencode }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/Entity?searchText[name]={{ item.entities_id | urlencode }}" method: "GET" return_content: true body: '' @@ -11,6 +11,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_search no_log: true diff --git a/tasks/api/search/groups_id.yaml b/tasks/api/search/groups_id.yaml index 51bbcfe..e27ae0c 100644 --- a/tasks/api/search/groups_id.yaml +++ b/tasks/api/search/groups_id.yaml @@ -2,7 +2,7 @@ - name: Fetch users_id ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/Group?searchText[name]={{ item.groups_id | urlencode }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/Group?searchText[name]={{ item.groups_id | urlencode }}" method: "GET" return_content: true body: '' diff --git a/tasks/api/search/item_id.yaml b/tasks/api/search/item_id.yaml index 10fe58b..024a6fc 100644 --- a/tasks/api/search/item_id.yaml +++ b/tasks/api/search/item_id.yaml @@ -1,7 +1,7 @@ --- - name: Find Item ID ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% endif%}{% if search_items | length | int > 0%}?{% for search in search_items %}searchText[{{ search.name }}]={{ search.value | urlencode }}&{% endfor %}{% else%}?searchText[name]={{ item.body.name | urlencode }}{% endif %}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/{{ item.api_path }}{% if item.sub_path is defined %}/{{ item.sub_path }}{% endif%}{% if search_items | length | int > 0%}?{% for search in search_items %}searchText[{{ search.name }}]={{ search.value | urlencode }}&{% endfor %}{% else%}?searchText[name]={{ item.body.name | urlencode }}{% endif %}" method: "GET" return_content: true body: '' diff --git a/tasks/api/search/itilcategories_id.yaml b/tasks/api/search/itilcategories_id.yaml index 6fdb33a..007708f 100644 --- a/tasks/api/search/itilcategories_id.yaml +++ b/tasks/api/search/itilcategories_id.yaml @@ -1,7 +1,7 @@ --- - name: Fetch itilcategories_id ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/ITILCategory?searchText[name]={{ item.itilcategories_id | urlencode }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/ITILCategory?searchText[name]={{ item.itilcategories_id | urlencode }}" method: "GET" return_content: true body: '' diff --git a/tasks/api/search/tickettemplates_id.yaml b/tasks/api/search/tickettemplates_id.yaml index dddcf2b..f654d86 100644 --- a/tasks/api/search/tickettemplates_id.yaml +++ b/tasks/api/search/tickettemplates_id.yaml @@ -1,7 +1,7 @@ --- - name: Fetch tickettemplates_id ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/TicketTemplate?searchText[name]={{ item.tickettemplates_id | urlencode }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/TicketTemplate?searchText[name]={{ item.tickettemplates_id | urlencode }}" method: "GET" return_content: true body: '' diff --git a/tasks/api/search/tickettemplates_id_demand.yaml b/tasks/api/search/tickettemplates_id_demand.yaml index 396662f..3f1adf8 100644 --- a/tasks/api/search/tickettemplates_id_demand.yaml +++ b/tasks/api/search/tickettemplates_id_demand.yaml @@ -1,7 +1,7 @@ --- - name: Fetch tickettemplates_id_demand ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/TicketTemplate?searchText[name]={{ item.tickettemplates_id_demand | urlencode }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/TicketTemplate?searchText[name]={{ item.tickettemplates_id_demand | urlencode }}" method: "GET" return_content: true body: '' diff --git a/tasks/api/search/users_id.yaml b/tasks/api/search/users_id.yaml index 68f653d..6946384 100644 --- a/tasks/api/search/users_id.yaml +++ b/tasks/api/search/users_id.yaml @@ -2,7 +2,7 @@ - name: Fetch users_id ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/User?searchText[name]={{ item.users_id | urlencode }}" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/User?searchText[name]={{ item.users_id | urlencode }}" method: "GET" return_content: true body: '' diff --git a/tasks/api/session-create.yaml b/tasks/api/session-create.yaml index 1a430d0..ec88a10 100644 --- a/tasks/api/session-create.yaml +++ b/tasks/api/session-create.yaml @@ -1,7 +1,7 @@ --- - name: Fetch API Session Token ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/initSession?get_full_session=true" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/initSession?get_full_session=true" method: GET return_content: true body: "" diff --git a/tasks/api/session-end.yaml b/tasks/api/session-end.yaml index 3e771db..b2e2922 100644 --- a/tasks/api/session-end.yaml +++ b/tasks/api/session-end.yaml @@ -1,7 +1,7 @@ --- - name: End API Session ansible.builtin.uri: - url: "http://{{ glpi.host }}/apirest.php/killSession" + url: "{{ http_protocol | default('https') | string }}://{{ glpi.host }}/apirest.php/killSession" method: GET return_content: true body: '' From 33c882f005c26e86bd19e5ed4f2ad11ab7f5b0b6 Mon Sep 17 00:00:00 2001 From: Jon Date: Sat, 5 Aug 2023 10:27:04 +0930 Subject: [PATCH 30/30] feat(http_cert_validation): new option specify cert validation, default true !1 --- tasks/api/append-create-item.yaml | 2 ++ tasks/api/config.yaml | 2 ++ tasks/api/search/groups_id.yaml | 1 + tasks/api/search/item_id.yaml | 1 + tasks/api/search/itilcategories_id.yaml | 1 + tasks/api/search/tickettemplates_id.yaml | 1 + tasks/api/search/tickettemplates_id_demand.yaml | 1 + tasks/api/search/users_id.yaml | 1 + tasks/api/session-create.yaml | 1 + tasks/api/session-end.yaml | 1 + 10 files changed, 12 insertions(+) diff --git a/tasks/api/append-create-item.yaml b/tasks/api/append-create-item.yaml index 3a72a04..ef6af18 100644 --- a/tasks/api/append-create-item.yaml +++ b/tasks/api/append-create-item.yaml @@ -32,6 +32,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" no_log: true register: create_item when: > @@ -49,6 +50,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" no_log: true register: update_item when: item_body.id is defined diff --git a/tasks/api/config.yaml b/tasks/api/config.yaml index 20d4f41..306cc07 100644 --- a/tasks/api/config.yaml +++ b/tasks/api/config.yaml @@ -11,6 +11,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" no_log: true register: glpi_search @@ -86,6 +87,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" no_log: true when: config_item.body.id is defined diff --git a/tasks/api/search/groups_id.yaml b/tasks/api/search/groups_id.yaml index e27ae0c..2f33281 100644 --- a/tasks/api/search/groups_id.yaml +++ b/tasks/api/search/groups_id.yaml @@ -11,6 +11,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_search no_log: true diff --git a/tasks/api/search/item_id.yaml b/tasks/api/search/item_id.yaml index 024a6fc..1ec44a8 100644 --- a/tasks/api/search/item_id.yaml +++ b/tasks/api/search/item_id.yaml @@ -11,6 +11,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_search no_log: true diff --git a/tasks/api/search/itilcategories_id.yaml b/tasks/api/search/itilcategories_id.yaml index 007708f..6be3a5b 100644 --- a/tasks/api/search/itilcategories_id.yaml +++ b/tasks/api/search/itilcategories_id.yaml @@ -11,6 +11,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_search no_log: true diff --git a/tasks/api/search/tickettemplates_id.yaml b/tasks/api/search/tickettemplates_id.yaml index f654d86..44b14ec 100644 --- a/tasks/api/search/tickettemplates_id.yaml +++ b/tasks/api/search/tickettemplates_id.yaml @@ -10,6 +10,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_search no_log: true diff --git a/tasks/api/search/tickettemplates_id_demand.yaml b/tasks/api/search/tickettemplates_id_demand.yaml index 3f1adf8..dc8e25f 100644 --- a/tasks/api/search/tickettemplates_id_demand.yaml +++ b/tasks/api/search/tickettemplates_id_demand.yaml @@ -11,6 +11,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_search no_log: true diff --git a/tasks/api/search/users_id.yaml b/tasks/api/search/users_id.yaml index 6946384..31daa45 100644 --- a/tasks/api/search/users_id.yaml +++ b/tasks/api/search/users_id.yaml @@ -12,6 +12,7 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_search no_log: true diff --git a/tasks/api/session-create.yaml b/tasks/api/session-create.yaml index ec88a10..00c7b77 100644 --- a/tasks/api/session-create.yaml +++ b/tasks/api/session-create.yaml @@ -10,6 +10,7 @@ App-Token: "{{ glpi.app_token }}" Authorization: "user_token {{ glpi.user_token }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" register: glpi_session_get no_log: true tags: diff --git a/tasks/api/session-end.yaml b/tasks/api/session-end.yaml index b2e2922..54a5d5f 100644 --- a/tasks/api/session-end.yaml +++ b/tasks/api/session-end.yaml @@ -10,4 +10,5 @@ App-Token: "{{ glpi.app_token }}" Session-Token: "{{ glpi_session_get.json.session.valid_id }}" body_format: json + validate_certs: "{{ glpi.validate_certs | default(true) | bool }}" no_log: true