feat(config): Add General Settings Config from code

!1
This commit is contained in:
2023-07-28 18:27:59 +09:30
parent b91acddf16
commit 4407e57fdd
6 changed files with 165 additions and 38 deletions

View File

@ -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"

View File

@ -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 }}"

View File

@ -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 }} }"

91
tasks/api/config.yaml Normal file
View File

@ -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

47
tasks/api/search-add.yaml Normal file
View File

@ -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: {}

View File

@ -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