From 43d59fe48f124492e0defe0a382444a284bb00d2 Mon Sep 17 00:00:00 2001 From: reachableceo Date: Fri, 4 Sep 2026 06:09:53 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20glpi-change.sh=20=E2=80=94=20log=20GLPI?= =?UTF-8?q?=20Change=20entries=20from=20the=20CLI=20(OQ7)=20[#769]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit First entry created live (Change id=1, backfill of the repo split). GLPI API allowlist resolved — sessions work from the workstation. https://projects.knownelement.com/issues/769#note-4152 --- scripts/glpi-change.sh | 70 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100755 scripts/glpi-change.sh diff --git a/scripts/glpi-change.sh b/scripts/glpi-change.sh new file mode 100755 index 0000000..931e493 --- /dev/null +++ b/scripts/glpi-change.sh @@ -0,0 +1,70 @@ +#!/usr/bin/env bash +# glpi-change.sh — create GLPI Change entries from the CLI [#769] +# +# Charles ruling (questions-v10 OQ7, 2026-09-03): GLPI Changes are logged +# from NOW ON for converge/infra work — no Redmine-only exception path. +# Pair this with the Redmine ticket: put the ticket ref in --title. +# +# Env (from ~/.creds/glpi.env): GLPI_URL, GLPI_USER_TOKEN, GLPI_APP_TOKEN +# +# Usage: +# echo "what changed, why, where" | \ +# glpi-change.sh create --title "[#769] " [--urgency 2] +# glpi-change.sh show +set -euo pipefail + +die() { printf 'FAIL: %s\n' "$*" >&2; exit 1; } +[ -f "$HOME/.creds/glpi.env" ] || die "'$HOME/.creds/glpi.env' missing" + +set -a; . "$HOME/.creds/glpi.env"; set +a +BASE="${GLPI_URL%/}" +[ -n "${GLPI_USER_TOKEN:-}" ] && [ -n "${GLPI_APP_TOKEN:-}" ] || die "tokens missing in glpi.env" + +sess_request() { + curl -s -m 30 -H "Content-Type: application/json" \ + -H "App-Token: $GLPI_APP_TOKEN" \ + -H "Authorization: user_token $GLPI_USER_TOKEN" \ + "$BASE/apirest.php/initSession" +} + +session="$(sess_request)" +S_TOKEN="$(printf '%s' "$session" | jq -r '.session_token // empty')" +[ -n "$S_TOKEN" ] || die "initSession failed: $session" +cleanup() { curl -s -m 15 -o /dev/null -H "Session-Token: $S_TOKEN" \ + -H "App-Token: $GLPI_APP_TOKEN" "$BASE/apirest.php/killSession" || true; } +trap cleanup EXIT + +auth=(-H "Session-Token: $S_TOKEN" -H "App-Token: $GLPI_APP_TOKEN" -H "Content-Type: application/json") + +cmd="${1:-create}"; shift || true + +case "$cmd" in +create) + title=""; urgency=3; impact=3; content="" + while [ $# -gt 0 ]; do + case "$1" in + --title) title="$2"; shift 2 ;; + --urgency) urgency="$2"; shift 2 ;; + --impact) impact="$2"; shift 2 ;; + *) die "unknown option $1" ;; + esac + done + [ -n "$title" ] || die "--title required" + content="$(cat)" + [ -n "$content" ] || die "change body required on stdin" + body="$(jq -n --arg t "$title" --arg c "$content" \ + --argjson u "$urgency" --argjson i "$impact" \ + '{input: {name: $t, content: $c, urgency: $u, impact: $i}}')" + resp="$(curl -s -m 30 -X POST "${auth[@]}" -d "$body" "$BASE/apirest.php/Change")" + cid="$(printf '%s' "$resp" | jq -r '.id // empty')" + [ -n "$cid" ] || die "create failed: $resp" + echo "created Change id=$cid — $BASE/front/change.form.php?id=$cid" + ;; +show) + cid="${1:?change-id}" + curl -s -m 30 "${auth[@]}" "$BASE/apirest.php/Change/$cid" | jq . + ;; +*) + die "unknown command $cmd" + ;; +esac