Install and configure Scriptorium
This commit is contained in:
79
README.md
79
README.md
@@ -1,3 +1,78 @@
|
|||||||
# ansible-role-scriptorium
|
# Ansible Role: Scriptorium
|
||||||
|
|
||||||
Ansible role to install the Scriptorium application.
|
Installs and configures [Scriptorium](https://gitea.maximumdirect.net/eric/scriptorium)
|
||||||
|
from source on Ubuntu 26.04 (`x86_64` or `aarch64`). The role requires gathered
|
||||||
|
facts and uses privilege escalation only for dependency installation and
|
||||||
|
root-owned application state.
|
||||||
|
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
scriptorium_version: v0.13.0
|
||||||
|
scriptorium_repository_url: https://gitea.maximumdirect.net/eric/scriptorium.git
|
||||||
|
scriptorium_source_dir: /usr/local/src/scriptorium
|
||||||
|
scriptorium_binary_path: /usr/local/bin/scriptorium
|
||||||
|
scriptorium_manage_build_dependencies: true
|
||||||
|
scriptorium_go_snap_channel: 1.26/stable
|
||||||
|
scriptorium_go_binary: /snap/bin/go
|
||||||
|
scriptorium_config_path: /usr/local/etc/scriptorium/config.yml
|
||||||
|
scriptorium_prompt_dir: null
|
||||||
|
scriptorium_profile_dir: null
|
||||||
|
scriptorium_schema_dir: null
|
||||||
|
scriptorium_server_addr: null
|
||||||
|
scriptorium_server_artifact_root: null
|
||||||
|
scriptorium_server_max_request_bytes: null
|
||||||
|
scriptorium_server_max_artifact_bytes: null
|
||||||
|
scriptorium_server_max_response_bytes: null
|
||||||
|
scriptorium_defaults_render_format: null
|
||||||
|
scriptorium_backends: null
|
||||||
|
```
|
||||||
|
|
||||||
|
When `scriptorium_manage_build_dependencies` is `false`, Git and the executable
|
||||||
|
selected by `scriptorium_go_binary` must already be available. Otherwise, the
|
||||||
|
role installs Git with APT and the classic Go Snap from
|
||||||
|
`scriptorium_go_snap_channel`. It checks out `scriptorium_version`
|
||||||
|
authoritatively, builds `./cmd/scriptorium` directly to
|
||||||
|
`scriptorium_binary_path`, and rebuilds only when that checkout changes or the
|
||||||
|
binary is absent. The source tree is recursively owned by `root:root`; the
|
||||||
|
binary is `root:root` mode `0755`.
|
||||||
|
|
||||||
|
Every application configuration variable defaults to `null`, so it and any
|
||||||
|
empty parent section are omitted and Scriptorium retains ownership of its
|
||||||
|
built-in defaults. When no values are selected, the role writes `{}` to
|
||||||
|
`scriptorium_config_path` as `root:root` mode `0644`. Non-null falsey values
|
||||||
|
are retained. `scriptorium_backends` is the native mapping supplied by the
|
||||||
|
caller; the role does not merge or rewrite it. For example, inventory can
|
||||||
|
compose fragments in the ordinary way:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
scriptorium_backends: "{{ scriptorium_local_backends | combine(scriptorium_remote_backends) }}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Backend entries may name a credential environment variable through
|
||||||
|
`api_key_env`; credential values themselves belong outside this role. The role
|
||||||
|
does not install prompt, profile, or schema content and does not manage a
|
||||||
|
service.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- hosts: scriptorium_hosts
|
||||||
|
roles:
|
||||||
|
- role: ansible-role-scriptorium
|
||||||
|
```
|
||||||
|
|
||||||
|
## Validation
|
||||||
|
|
||||||
|
The repository-local integration suite installs its pinned collection, runs
|
||||||
|
syntax checking and production-profile lint, and applies the default role. It
|
||||||
|
uses an offline native profile inspection with the managed configuration, then
|
||||||
|
requires clean repeated convergence. It mutates only the managed source,
|
||||||
|
binary, configuration, and a private temporary directory, then restores the
|
||||||
|
default deployment during cleanup.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tests/integration
|
||||||
|
```
|
||||||
|
|
||||||
|
Ansible role to install the Scriptorium application.
|
||||||
|
|||||||
2
ansible.cfg
Normal file
2
ansible.cfg
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
[defaults]
|
||||||
|
roles_path = ..
|
||||||
4
collections/requirements.yml
Normal file
4
collections/requirements.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
collections:
|
||||||
|
- name: community.general
|
||||||
|
version: 13.3.0
|
||||||
19
defaults/main.yml
Normal file
19
defaults/main.yml
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
---
|
||||||
|
scriptorium_version: v0.13.0
|
||||||
|
scriptorium_repository_url: https://gitea.maximumdirect.net/eric/scriptorium.git
|
||||||
|
scriptorium_source_dir: /usr/local/src/scriptorium
|
||||||
|
scriptorium_binary_path: /usr/local/bin/scriptorium
|
||||||
|
scriptorium_manage_build_dependencies: true
|
||||||
|
scriptorium_go_snap_channel: 1.26/stable
|
||||||
|
scriptorium_go_binary: /snap/bin/go
|
||||||
|
scriptorium_config_path: /usr/local/etc/scriptorium/config.yml
|
||||||
|
scriptorium_prompt_dir: null
|
||||||
|
scriptorium_profile_dir: null
|
||||||
|
scriptorium_schema_dir: null
|
||||||
|
scriptorium_server_addr: null
|
||||||
|
scriptorium_server_artifact_root: null
|
||||||
|
scriptorium_server_max_request_bytes: null
|
||||||
|
scriptorium_server_max_artifact_bytes: null
|
||||||
|
scriptorium_server_max_response_bytes: null
|
||||||
|
scriptorium_defaults_render_format: null
|
||||||
|
scriptorium_backends: null
|
||||||
59
meta/argument_specs.yml
Normal file
59
meta/argument_specs.yml
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
argument_specs:
|
||||||
|
main:
|
||||||
|
short_description: Install and configure Scriptorium from source
|
||||||
|
options:
|
||||||
|
scriptorium_version:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
scriptorium_repository_url:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
scriptorium_source_dir:
|
||||||
|
type: path
|
||||||
|
required: true
|
||||||
|
scriptorium_binary_path:
|
||||||
|
type: path
|
||||||
|
required: true
|
||||||
|
scriptorium_manage_build_dependencies:
|
||||||
|
type: bool
|
||||||
|
required: true
|
||||||
|
scriptorium_go_snap_channel:
|
||||||
|
type: str
|
||||||
|
required: true
|
||||||
|
scriptorium_go_binary:
|
||||||
|
type: path
|
||||||
|
required: true
|
||||||
|
scriptorium_config_path:
|
||||||
|
type: path
|
||||||
|
required: true
|
||||||
|
scriptorium_prompt_dir:
|
||||||
|
type: path
|
||||||
|
required: false
|
||||||
|
scriptorium_profile_dir:
|
||||||
|
type: path
|
||||||
|
required: false
|
||||||
|
scriptorium_schema_dir:
|
||||||
|
type: path
|
||||||
|
required: false
|
||||||
|
scriptorium_server_addr:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
scriptorium_server_artifact_root:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
scriptorium_server_max_request_bytes:
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
scriptorium_server_max_artifact_bytes:
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
scriptorium_server_max_response_bytes:
|
||||||
|
type: int
|
||||||
|
required: false
|
||||||
|
scriptorium_defaults_render_format:
|
||||||
|
type: str
|
||||||
|
required: false
|
||||||
|
scriptorium_backends:
|
||||||
|
type: dict
|
||||||
|
required: false
|
||||||
18
meta/main.yml
Normal file
18
meta/main.yml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
role_name: scriptorium
|
||||||
|
namespace: rakestraw
|
||||||
|
author: Eric Rakestraw
|
||||||
|
description: Install and configure Scriptorium from source
|
||||||
|
license: CC0-1.0
|
||||||
|
min_ansible_version: "2.18"
|
||||||
|
issue_tracker_url: https://gitea.maximumdirect.net/eric/ansible-role-scriptorium/issues
|
||||||
|
platforms:
|
||||||
|
- name: Ubuntu
|
||||||
|
versions:
|
||||||
|
- resolute
|
||||||
|
galaxy_tags:
|
||||||
|
- scriptorium
|
||||||
|
- promptkit
|
||||||
|
- processing
|
||||||
|
dependencies: []
|
||||||
101
tasks/main.yml
Normal file
101
tasks/main.yml
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
---
|
||||||
|
- name: Validate the supported platform
|
||||||
|
ansible.builtin.assert:
|
||||||
|
that:
|
||||||
|
- ansible_facts.distribution == "Ubuntu"
|
||||||
|
- ansible_facts.distribution_version == "26.04"
|
||||||
|
- ansible_facts.architecture in ["x86_64", "aarch64"]
|
||||||
|
fail_msg: Scriptorium supports Ubuntu 26.04 on x86_64 or aarch64.
|
||||||
|
|
||||||
|
- name: Install Git
|
||||||
|
become: true
|
||||||
|
ansible.builtin.apt:
|
||||||
|
name: git
|
||||||
|
state: present
|
||||||
|
update_cache: true
|
||||||
|
cache_valid_time: 3600
|
||||||
|
when: scriptorium_manage_build_dependencies
|
||||||
|
|
||||||
|
- name: Install Go
|
||||||
|
become: true
|
||||||
|
community.general.snap:
|
||||||
|
name: go
|
||||||
|
channel: "{{ scriptorium_go_snap_channel }}"
|
||||||
|
classic: true
|
||||||
|
state: present
|
||||||
|
when: scriptorium_manage_build_dependencies
|
||||||
|
|
||||||
|
- name: Create installation parent directories
|
||||||
|
become: true
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item }}"
|
||||||
|
state: directory
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0755"
|
||||||
|
loop:
|
||||||
|
- "{{ scriptorium_source_dir | dirname }}"
|
||||||
|
- "{{ scriptorium_binary_path | dirname }}"
|
||||||
|
- "{{ scriptorium_config_path | dirname }}"
|
||||||
|
|
||||||
|
- name: Check out Scriptorium source
|
||||||
|
become: true
|
||||||
|
ansible.builtin.git:
|
||||||
|
repo: "{{ scriptorium_repository_url }}"
|
||||||
|
dest: "{{ scriptorium_source_dir }}"
|
||||||
|
version: "{{ scriptorium_version }}"
|
||||||
|
force: true
|
||||||
|
register: scriptorium_checkout
|
||||||
|
|
||||||
|
- name: Inspect the installed binary
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ scriptorium_binary_path }}"
|
||||||
|
register: scriptorium_binary
|
||||||
|
|
||||||
|
- name: Build Scriptorium
|
||||||
|
become: true
|
||||||
|
ansible.builtin.command:
|
||||||
|
argv:
|
||||||
|
- "{{ scriptorium_go_binary }}"
|
||||||
|
- build
|
||||||
|
- -trimpath
|
||||||
|
- -ldflags
|
||||||
|
- -s -w
|
||||||
|
- -o
|
||||||
|
- "{{ scriptorium_binary_path }}"
|
||||||
|
- ./cmd/scriptorium
|
||||||
|
chdir: "{{ scriptorium_source_dir }}"
|
||||||
|
environment:
|
||||||
|
CGO_ENABLED: "0"
|
||||||
|
GOWORK: "off"
|
||||||
|
GOTOOLCHAIN: local
|
||||||
|
changed_when: true
|
||||||
|
when: >-
|
||||||
|
scriptorium_checkout.changed or
|
||||||
|
not scriptorium_binary.stat.exists
|
||||||
|
|
||||||
|
- name: Converge installed metadata
|
||||||
|
become: true
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ item.path }}"
|
||||||
|
state: "{{ item.state }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "{{ item.mode | default(omit) }}"
|
||||||
|
recurse: "{{ item.recurse | default(omit) }}"
|
||||||
|
loop:
|
||||||
|
- path: "{{ scriptorium_source_dir }}"
|
||||||
|
state: directory
|
||||||
|
recurse: true
|
||||||
|
- path: "{{ scriptorium_binary_path }}"
|
||||||
|
state: file
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Write Scriptorium configuration
|
||||||
|
become: true
|
||||||
|
ansible.builtin.template:
|
||||||
|
src: config.yml.j2
|
||||||
|
dest: "{{ scriptorium_config_path }}"
|
||||||
|
owner: root
|
||||||
|
group: root
|
||||||
|
mode: "0644"
|
||||||
38
templates/config.yml.j2
Normal file
38
templates/config.yml.j2
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{% if scriptorium_prompt_dir is none and scriptorium_profile_dir is none and scriptorium_schema_dir is none and scriptorium_server_addr is none and scriptorium_server_artifact_root is none and scriptorium_server_max_request_bytes is none and scriptorium_server_max_artifact_bytes is none and scriptorium_server_max_response_bytes is none and scriptorium_defaults_render_format is none and scriptorium_backends is none %}
|
||||||
|
{}
|
||||||
|
{% else %}
|
||||||
|
{% if scriptorium_prompt_dir is not none %}
|
||||||
|
prompt_dir: {{ scriptorium_prompt_dir | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_profile_dir is not none %}
|
||||||
|
profile_dir: {{ scriptorium_profile_dir | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_schema_dir is not none %}
|
||||||
|
schema_dir: {{ scriptorium_schema_dir | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_server_addr is not none or scriptorium_server_artifact_root is not none or scriptorium_server_max_request_bytes is not none or scriptorium_server_max_artifact_bytes is not none or scriptorium_server_max_response_bytes is not none %}
|
||||||
|
server:
|
||||||
|
{% if scriptorium_server_addr is not none %}
|
||||||
|
addr: {{ scriptorium_server_addr | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_server_artifact_root is not none %}
|
||||||
|
artifact_root: {{ scriptorium_server_artifact_root | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_server_max_request_bytes is not none %}
|
||||||
|
max_request_bytes: {{ scriptorium_server_max_request_bytes | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_server_max_artifact_bytes is not none %}
|
||||||
|
max_artifact_bytes: {{ scriptorium_server_max_artifact_bytes | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_server_max_response_bytes is not none %}
|
||||||
|
max_response_bytes: {{ scriptorium_server_max_response_bytes | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_defaults_render_format is not none %}
|
||||||
|
defaults:
|
||||||
|
render_format: {{ scriptorium_defaults_render_format | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% if scriptorium_backends is not none %}
|
||||||
|
backends: {{ scriptorium_backends | to_json }}
|
||||||
|
{% endif %}
|
||||||
|
{% endif %}
|
||||||
6
tests/converge.yml
Normal file
6
tests/converge.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
- name: Converge Scriptorium role
|
||||||
|
hosts: localhost
|
||||||
|
gather_facts: true
|
||||||
|
roles:
|
||||||
|
- role: ansible-role-scriptorium
|
||||||
56
tests/integration
Executable file
56
tests/integration
Executable file
@@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
repository_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
||||||
|
workspace_venv="$repository_root/../.venv"
|
||||||
|
test_tmp=$(mktemp -d)
|
||||||
|
chmod 0700 "$test_tmp"
|
||||||
|
|
||||||
|
export ANSIBLE_COLLECTIONS_PATH="$test_tmp/collections"
|
||||||
|
export ANSIBLE_ROLES_PATH="$(dirname "$repository_root")"
|
||||||
|
|
||||||
|
inventory="$repository_root/tests/inventory"
|
||||||
|
converge="$repository_root/tests/converge.yml"
|
||||||
|
ansible_playbook="$workspace_venv/bin/ansible-playbook"
|
||||||
|
binary_path=/usr/local/bin/scriptorium
|
||||||
|
config_path=/usr/local/etc/scriptorium/config.yml
|
||||||
|
profile_dir="$test_tmp/profiles"
|
||||||
|
|
||||||
|
cleanup() {
|
||||||
|
exit_status=$?
|
||||||
|
trap - EXIT
|
||||||
|
"$ansible_playbook" -i "$inventory" "$converge" >/dev/null 2>&1 || true
|
||||||
|
rm -rf -- "$test_tmp"
|
||||||
|
exit "$exit_status"
|
||||||
|
}
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
require_clean_recap() {
|
||||||
|
grep -Eq 'changed=0 .*failed=0' "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
run_converge() {
|
||||||
|
output_file=$1
|
||||||
|
"$ansible_playbook" -i "$inventory" "$converge" | tee "$output_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p "$profile_dir"
|
||||||
|
printf '%s\n' \
|
||||||
|
'id: endpoint-profile' \
|
||||||
|
'endpoint: http://127.0.0.1:8000/v1' \
|
||||||
|
'model: offline-fixture' > "$profile_dir/endpoint-profile.yml"
|
||||||
|
|
||||||
|
cd "$repository_root"
|
||||||
|
"$workspace_venv/bin/ansible-galaxy" collection install \
|
||||||
|
-r collections/requirements.yml \
|
||||||
|
-p "$ANSIBLE_COLLECTIONS_PATH"
|
||||||
|
"$ansible_playbook" -i "$inventory" --syntax-check "$converge"
|
||||||
|
"$workspace_venv/bin/ansible-lint" "$converge"
|
||||||
|
|
||||||
|
baseline_log="$test_tmp/baseline.log"
|
||||||
|
run_converge "$baseline_log"
|
||||||
|
"$binary_path" inspect profile --config "$config_path" \
|
||||||
|
--profile-dir "$profile_dir" --profile endpoint-profile
|
||||||
|
baseline_repeat_log="$test_tmp/baseline-repeat.log"
|
||||||
|
run_converge "$baseline_repeat_log"
|
||||||
|
require_clean_recap "$baseline_repeat_log"
|
||||||
1
tests/inventory
Normal file
1
tests/inventory
Normal file
@@ -0,0 +1 @@
|
|||||||
|
localhost ansible_connection=local
|
||||||
Reference in New Issue
Block a user