@ -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"
|
||||
|
@ -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 }}"
|
||||
|
||||
|
||||
|
@ -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
91
tasks/api/config.yaml
Normal 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
47
tasks/api/search-add.yaml
Normal 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: {}
|
@ -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
|
||||
|
Reference in New Issue
Block a user