From 8226e8c1e5611368796ff3e4c4926bae3c1ff56f Mon Sep 17 00:00:00 2001 From: Jon Date: Sat, 29 Jul 2023 21:23:02 +0930 Subject: [PATCH] feat(config): Add Ticket Template Config from code !1 --- defaults/main.yaml | 1 + docs/projects/nfc_glpi/config_from_code.md | 42 +++++++++ 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, 336 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..449e77a 100644 --- a/docs/projects/nfc_glpi/config_from_code.md +++ b/docs/projects/nfc_glpi/config_from_code.md @@ -98,6 +98,48 @@ 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", + "body": { + // JSON from API Query + }, + "_TicketTemplateMandatoryField": [ + { + "id": 10, + "tickettemplates_id": 3, + "num": 1 + }, + { + "id": 11, + "tickettemplates_id": 3, + "num": 21 + } + ], + "_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