mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 19:56:53 +00:00
A generated lockup drew its title in the primary color with an on-primary outline. On a header or sidebar that a role maps onto the frame token, that put primary-colored text on a primary-toned ground. A slot now takes `frame: true` in the role's design entry. The asset action receives a second color pair from the palette, the on-frame color as fill and the frame color as outline, and the renderer picks the pair per slot. Slots without the flag render as before. Keycloak calls the asset action directly and already rendered its brand slot in the on-frame color, so it passes that color for both pairs and keeps its output. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
from __future__ import annotations
|
|
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from ansible.errors import AnsibleError
|
|
from ansible.plugins.loader import lookup_loader
|
|
from ansible.plugins.lookup import LookupBase
|
|
|
|
from utils.design.branding import asset_urls, resolve_branding
|
|
|
|
ASSET_DIR = "design"
|
|
|
|
|
|
class LookupModule(LookupBase):
|
|
"""
|
|
lookup('design', application_id)
|
|
|
|
Returns the resolved corporate branding of one role:
|
|
logo absolute logo path, or False when the replacement is disabled
|
|
title title text, or False when the replacement is disabled
|
|
name role README H1
|
|
label title, else name (for installers that require a site name)
|
|
slots {name: {width, height, text_only, frame}}
|
|
domain canonical domain of the role
|
|
dest CDN directory the generated assets are written to
|
|
urls {"favicon_ico": url, "<slot>": {"png": url, "svg": url}}
|
|
"""
|
|
|
|
def _sub(self, name: str, terms: list, variables: dict[str, Any]) -> Any:
|
|
plugin = lookup_loader.get(
|
|
name,
|
|
loader=getattr(self, "_loader", None),
|
|
templar=getattr(self, "_templar", None),
|
|
)
|
|
return plugin.run(terms, variables=variables)[0]
|
|
|
|
def run(self, terms, variables: dict[str, Any] | None = None, **kwargs):
|
|
variables = variables or {}
|
|
if len(terms) != 1:
|
|
raise AnsibleError("design: expects exactly one application_id")
|
|
application_id = str(terms[0]).strip()
|
|
root = variables.get("playbook_dir")
|
|
if not root:
|
|
raise AnsibleError("design: 'playbook_dir' is unavailable")
|
|
|
|
applications = self._sub("applications", [], variables)
|
|
try:
|
|
branding = resolve_branding(applications, application_id, Path(str(root)))
|
|
except (KeyError, ValueError) as exc:
|
|
raise AnsibleError(f"design: {exc}") from exc
|
|
|
|
cdn = self._sub("cdn", [application_id], variables)
|
|
base_url = f"{cdn['urls']['role']['release']['img'].rstrip('/')}/{ASSET_DIR}"
|
|
|
|
return [
|
|
{
|
|
**branding,
|
|
"domain": self._sub("domain", [application_id], variables),
|
|
"dest": str(Path(cdn["role"]["release"]["img"]) / ASSET_DIR),
|
|
"urls": asset_urls(base_url, branding["slots"]),
|
|
}
|
|
]
|