From b7b934783bc0a411e582c662bbf1d9146b30c19c Mon Sep 17 00:00:00 2001 From: Jon Date: Fri, 28 Jul 2023 18:27:59 +0930 Subject: [PATCH] feat(config): Add General Settings Config from code !1 --- docs/projects/nfc_glpi/config_from_code.md | 17 +++- 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, 159 insertions(+), 35 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..84d627e 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -9,7 +9,6 @@ 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"`. @@ -27,6 +26,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