mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-09-08 03:07:14 +02:00
Compare commits
9 Commits
d2dc2eab5f
...
4f8ce598a9
Author | SHA1 | Date | |
---|---|---|---|
4f8ce598a9 | |||
3769e66d8d | |||
33a5fadf67 | |||
699a6b6f1e | |||
61c29eee60 | |||
d5204fb5c2 | |||
751615b1a4 | |||
e2993d2912 | |||
24b6647bfb |
@@ -11,7 +11,7 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')
|
|||||||
from module_utils.entity_name_utils import get_entity_name
|
from module_utils.entity_name_utils import get_entity_name
|
||||||
|
|
||||||
# Paths to the group-vars files
|
# Paths to the group-vars files
|
||||||
PORTS_FILE = './group_vars/all/09_ports.yml'
|
PORTS_FILE = './group_vars/all/10_ports.yml'
|
||||||
NETWORKS_FILE = './group_vars/all/09_networks.yml'
|
NETWORKS_FILE = './group_vars/all/09_networks.yml'
|
||||||
ROLE_TEMPLATE_DIR = './templates/roles/web-app'
|
ROLE_TEMPLATE_DIR = './templates/roles/web-app'
|
||||||
ROLES_DIR = './roles'
|
ROLES_DIR = './roles'
|
||||||
|
@@ -98,6 +98,8 @@ defaults_networks:
|
|||||||
subnet: 192.168.103.176/28
|
subnet: 192.168.103.176/28
|
||||||
web-app-chess:
|
web-app-chess:
|
||||||
subnet: 192.168.103.192/28
|
subnet: 192.168.103.192/28
|
||||||
|
web-app-magento:
|
||||||
|
subnet: 192.168.103.208/28
|
||||||
|
|
||||||
# /24 Networks / 254 Usable Clients
|
# /24 Networks / 254 Usable Clients
|
||||||
web-app-bigbluebutton:
|
web-app-bigbluebutton:
|
||||||
|
@@ -73,6 +73,7 @@ ports:
|
|||||||
web-app-bookwyrm: 8049
|
web-app-bookwyrm: 8049
|
||||||
web-app-chess: 8050
|
web-app-chess: 8050
|
||||||
web-app-bluesky_view: 8051
|
web-app-bluesky_view: 8051
|
||||||
|
web-app-magento: 8052
|
||||||
web-app-bigbluebutton: 48087 # This port is predefined by bbb. @todo Try to change this to a 8XXX port
|
web-app-bigbluebutton: 48087 # This port is predefined by bbb. @todo Try to change this to a 8XXX port
|
||||||
public:
|
public:
|
||||||
# The following ports should be changed to 22 on the subdomain via stream mapping
|
# The following ports should be changed to 22 on the subdomain via stream mapping
|
@@ -37,7 +37,7 @@
|
|||||||
- name: "Reset LDAP Credentials"
|
- name: "Reset LDAP Credentials"
|
||||||
include_tasks: 01_credentials.yml
|
include_tasks: 01_credentials.yml
|
||||||
when:
|
when:
|
||||||
- applications | get_app_conf(application_id, 'network.local', True)
|
- applications | get_app_conf(application_id, 'network.local')
|
||||||
- applications | get_app_conf(application_id, 'provisioning.credentials', True)
|
- applications | get_app_conf(application_id, 'provisioning.credentials', True)
|
||||||
|
|
||||||
- name: "create directory {{openldap_ldif_host_path}}{{item}}"
|
- name: "create directory {{openldap_ldif_host_path}}{{item}}"
|
||||||
|
@@ -21,4 +21,4 @@ openldap_version: "{{ applications | get_app_conf(application_id,
|
|||||||
openldap_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
openldap_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
||||||
openldap_network: "{{ applications | get_app_conf(application_id, 'docker.network', True) }}"
|
openldap_network: "{{ applications | get_app_conf(application_id, 'docker.network', True) }}"
|
||||||
|
|
||||||
openldap_network_expose_local: "{{ applications | get_app_conf(application_id, 'network.public', True) | bool or applications | get_app_conf(application_id, 'network.local', True) | bool }}"
|
openldap_network_expose_local: "{{ applications | get_app_conf(application_id, 'network.public', True) | bool or applications | get_app_conf(application_id, 'network.local') | bool }}"
|
@@ -13,7 +13,7 @@ server:
|
|||||||
csp:
|
csp:
|
||||||
whitelist:
|
whitelist:
|
||||||
connect-src:
|
connect-src:
|
||||||
- "{{ WEB_PROTOCOL }}://{{ BLUESKY_API_DOMAIN }}"
|
- "{{ WEB_PROTOCOL }}://<< defaults_applications[web-app-bluesky].server.domains.canonical.api >>"
|
||||||
- https://plc.directory
|
- https://plc.directory
|
||||||
- https://bsky.social
|
- https://bsky.social
|
||||||
- https://api.bsky.app
|
- https://api.bsky.app
|
||||||
@@ -21,8 +21,13 @@ server:
|
|||||||
- https://events.bsky.app
|
- https://events.bsky.app
|
||||||
- https://statsigapi.net
|
- https://statsigapi.net
|
||||||
- https://ip.bsky.app
|
- https://ip.bsky.app
|
||||||
|
- https://video.bsky.app
|
||||||
- wss://bsky.network
|
- wss://bsky.network
|
||||||
- wss://*.bsky.app
|
- wss://*.bsky.app
|
||||||
|
media-src:
|
||||||
|
- "blob:"
|
||||||
|
worker-src:
|
||||||
|
- "blob:"
|
||||||
docker:
|
docker:
|
||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
# web-app-chess
|
# Chess
|
||||||
|
|
||||||
## Description
|
## Description
|
||||||
|
|
||||||
|
@@ -12,16 +12,18 @@ docker:
|
|||||||
volumes:
|
volumes:
|
||||||
data: "chess_data"
|
data: "chess_data"
|
||||||
features:
|
features:
|
||||||
matomo: false
|
matomo: true
|
||||||
css: false
|
css: true
|
||||||
desktop: false
|
desktop: true
|
||||||
central_database: true
|
central_database: true
|
||||||
logout: false
|
logout: false
|
||||||
oidc: false
|
oidc: false
|
||||||
server:
|
server:
|
||||||
csp:
|
csp:
|
||||||
whitelist: {}
|
whitelist: {}
|
||||||
flags: {}
|
flags:
|
||||||
|
script-src-elem:
|
||||||
|
unsafe-inline: true
|
||||||
domains:
|
domains:
|
||||||
canonical:
|
canonical:
|
||||||
- "chess.{{ PRIMARY_DOMAIN }}"
|
- "chess.{{ PRIMARY_DOMAIN }}"
|
||||||
|
69
roles/web-app-chess/files/Dockerfile
Normal file
69
roles/web-app-chess/files/Dockerfile
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
# Multi-stage build for castling.club
|
||||||
|
|
||||||
|
# Allow a dynamic base image version in both stages
|
||||||
|
ARG CHESS_VERSION
|
||||||
|
|
||||||
|
# -------- Stage 1: build --------
|
||||||
|
FROM node:${CHESS_VERSION} AS build
|
||||||
|
|
||||||
|
# Build-time inputs
|
||||||
|
ARG CHESS_REPO_URL
|
||||||
|
ARG CHESS_REPO_REF
|
||||||
|
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
git ca-certificates openssl dumb-init python3 build-essential \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /src
|
||||||
|
RUN git clone --depth 1 --branch "${CHESS_REPO_REF}" "${CHESS_REPO_URL}" ./
|
||||||
|
|
||||||
|
# Prepare Yarn 4 as root (safe during build stage)
|
||||||
|
RUN corepack enable && corepack prepare yarn@4.9.1 --activate && yarn -v
|
||||||
|
RUN yarn install --immutable --inline-builds
|
||||||
|
RUN yarn build
|
||||||
|
|
||||||
|
# -------- Stage 2: runtime --------
|
||||||
|
FROM node:${CHESS_VERSION}
|
||||||
|
|
||||||
|
# Runtime inputs (formerly Jinja variables)
|
||||||
|
ARG CHESS_ENTRYPOINT_REL
|
||||||
|
ARG CHESS_ENTRYPOINT_INT
|
||||||
|
ARG CHESS_APP_DATA_DIR
|
||||||
|
ARG CONTAINER_PORT
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Minimal runtime deps + curl for healthcheck
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
bash openssl dumb-init postgresql-client ca-certificates curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Copy built app
|
||||||
|
COPY --from=build /src /app
|
||||||
|
|
||||||
|
# Install entrypoint
|
||||||
|
COPY ${CHESS_ENTRYPOINT_REL} ${CHESS_ENTRYPOINT_INT}
|
||||||
|
RUN chmod +x ${CHESS_ENTRYPOINT_INT}
|
||||||
|
|
||||||
|
# Fix: enable Corepack/Yarn as root so shims land in /usr/local/bin
|
||||||
|
RUN corepack enable && corepack prepare yarn@4.9.1 --activate && yarn -v
|
||||||
|
|
||||||
|
# Create writable dirs and set ownership
|
||||||
|
RUN mkdir -p ${CHESS_APP_DATA_DIR} /app/.yarn/cache /home/node \
|
||||||
|
&& chown -R node:node /app /home/node
|
||||||
|
|
||||||
|
# Use project-local Yarn cache
|
||||||
|
ENV YARN_ENABLE_GLOBAL_CACHE=false \
|
||||||
|
YARN_CACHE_FOLDER=/app/.yarn/cache \
|
||||||
|
HOME=/home/node
|
||||||
|
|
||||||
|
# Drop privileges
|
||||||
|
USER node
|
||||||
|
|
||||||
|
# Expose the runtime port (build-time constant)
|
||||||
|
EXPOSE ${CONTAINER_PORT}
|
||||||
|
|
||||||
|
ENTRYPOINT ["dumb-init", "--"]
|
||||||
|
# Use a shell so the value can be expanded reliably
|
||||||
|
ENV CHESS_ENTRYPOINT_INT=${CHESS_ENTRYPOINT_INT}
|
||||||
|
CMD ["sh","-lc","exec \"$CHESS_ENTRYPOINT_INT\""]
|
@@ -7,9 +7,16 @@ APP_KEY_PUB="${APP_KEY_FILE}.pub"
|
|||||||
# 1) Generate signing key pair if missing
|
# 1) Generate signing key pair if missing
|
||||||
if [[ ! -f "${APP_KEY_FILE}" || ! -f "${APP_KEY_PUB}" ]]; then
|
if [[ ! -f "${APP_KEY_FILE}" || ! -f "${APP_KEY_PUB}" ]]; then
|
||||||
echo "[chess] generating RSA signing key pair at ${APP_KEY_FILE}"
|
echo "[chess] generating RSA signing key pair at ${APP_KEY_FILE}"
|
||||||
/app/tools/gen-signing-key.sh "${APP_KEY_FILE}"
|
key_dir="$(dirname "${APP_KEY_FILE}")"
|
||||||
|
key_base="$(basename "${APP_KEY_FILE}")"
|
||||||
|
( cd "${key_dir}" && bash /app/tools/gen-signing-key.sh "${key_base}" )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# 1.5) Ensure Yarn is ready and deps are installed (PnP, immutable)
|
||||||
|
echo "[chess] preparing yarn & installing deps (immutable)"
|
||||||
|
corepack enable || true
|
||||||
|
yarn install --immutable --inline-builds
|
||||||
|
|
||||||
# 2) Wait for PostgreSQL if env is provided
|
# 2) Wait for PostgreSQL if env is provided
|
||||||
if [[ -n "${PGHOST:-}" ]]; then
|
if [[ -n "${PGHOST:-}" ]]; then
|
||||||
echo "[chess] waiting for PostgreSQL at ${PGHOST}:${PGPORT}..."
|
echo "[chess] waiting for PostgreSQL at ${PGHOST}:${PGPORT}..."
|
||||||
|
0
roles/web-app-chess/schema/main.yml
Normal file
0
roles/web-app-chess/schema/main.yml
Normal file
@@ -6,5 +6,7 @@
|
|||||||
copy:
|
copy:
|
||||||
src: "{{ CHESS_ENTRYPOINT_FILE }}"
|
src: "{{ CHESS_ENTRYPOINT_FILE }}"
|
||||||
dest: "{{ CHESS_ENTRYPOINT_ABS }}"
|
dest: "{{ CHESS_ENTRYPOINT_ABS }}"
|
||||||
|
notify:
|
||||||
|
- docker compose build
|
||||||
|
|
||||||
- include_tasks: utils/run_once.yml
|
- include_tasks: utils/run_once.yml
|
||||||
|
@@ -1,45 +0,0 @@
|
|||||||
# Multi-stage build for castling.club
|
|
||||||
# Stage 1: build
|
|
||||||
FROM node:{{ CHESS_VERSION }} AS build
|
|
||||||
|
|
||||||
ARG CHESS_REPO_URL={{ CHESS_REPO_URL }}
|
|
||||||
ARG CHESS_REPO_REF={{ CHESS_REPO_REF }}
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
git ca-certificates openssl dumb-init python3 build-essential \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
WORKDIR /src
|
|
||||||
RUN git clone --depth 1 --branch "${CHESS_REPO_REF}" "${CHESS_REPO_URL}" ./
|
|
||||||
|
|
||||||
# Yarn is preinstalled in Node images via corepack; enable it.
|
|
||||||
RUN corepack enable
|
|
||||||
|
|
||||||
# Install deps and build TS
|
|
||||||
RUN yarn install --frozen-lockfile && yarn build
|
|
||||||
|
|
||||||
# Stage 2: runtime
|
|
||||||
FROM node:{{ CHESS_VERSION }}
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# Minimal runtime packages + dumb-init
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
||||||
openssl dumb-init postgresql-client \
|
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# Copy built app
|
|
||||||
COPY --from=build /src /app
|
|
||||||
|
|
||||||
# Create data dir for signing keys & cache
|
|
||||||
RUN mkdir -p {{ CHESS_APP_DATA_DIR }} && chown -R node:node /app
|
|
||||||
VOLUME ["{{ CHESS_APP_DATA_DIR }}"]
|
|
||||||
|
|
||||||
# Entrypoint script
|
|
||||||
COPY {{ CHESS_ENTRYPOINT_REL }} {{ CHESS_ENTRYPOINT_INT }}
|
|
||||||
RUN chmod +x {{ CHESS_ENTRYPOINT_INT }}
|
|
||||||
|
|
||||||
USER node
|
|
||||||
EXPOSE {{ container_port }}
|
|
||||||
ENTRYPOINT ["dumb-init", "--"]
|
|
||||||
CMD ["{{ CHESS_ENTRYPOINT_INT }}"]
|
|
@@ -4,8 +4,13 @@
|
|||||||
context: .
|
context: .
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
args:
|
args:
|
||||||
|
CHESS_VERSION: "{{ CHESS_VERSION }}"
|
||||||
CHESS_REPO_URL: "{{ CHESS_REPO_URL }}"
|
CHESS_REPO_URL: "{{ CHESS_REPO_URL }}"
|
||||||
CHESS_REPO_REF: "{{ CHESS_REPO_REF }}"
|
CHESS_REPO_REF: "{{ CHESS_REPO_REF }}"
|
||||||
|
CHESS_ENTRYPOINT_REL: "{{ CHESS_ENTRYPOINT_REL }}"
|
||||||
|
CHESS_ENTRYPOINT_INT: "{{ CHESS_ENTRYPOINT_INT }}"
|
||||||
|
CHESS_APP_DATA_DIR: "{{ CHESS_APP_DATA_DIR }}"
|
||||||
|
CONTAINER_PORT: "{{ container_port | string }}"
|
||||||
image: "{{ CHESS_CUSTOM_IMAGE }}"
|
image: "{{ CHESS_CUSTOM_IMAGE }}"
|
||||||
container_name: "{{ CHESS_CONTAINER }}"
|
container_name: "{{ CHESS_CONTAINER }}"
|
||||||
hostname: "{{ CHESS_HOSTNAME }}"
|
hostname: "{{ CHESS_HOSTNAME }}"
|
||||||
@@ -13,8 +18,6 @@
|
|||||||
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:{{ container_port }}"
|
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:{{ container_port }}"
|
||||||
volumes:
|
volumes:
|
||||||
- 'data:{{ CHESS_APP_DATA_DIR }}'
|
- 'data:{{ CHESS_APP_DATA_DIR }}'
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
{% include 'roles/docker-container/templates/healthcheck/curl.yml.j2' %}
|
{% include 'roles/docker-container/templates/healthcheck/curl.yml.j2' %}
|
||||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||||
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
||||||
|
@@ -10,7 +10,7 @@ container_hostname: "{{ domains | get_domain(application_id) }}"
|
|||||||
# CHESS_URL: "{{ domains | get_url(application_id, WEB_PROTOCOL) }}"
|
# CHESS_URL: "{{ domains | get_url(application_id, WEB_PROTOCOL) }}"
|
||||||
CHESS_HOSTNAME: "{{ container_hostname }}"
|
CHESS_HOSTNAME: "{{ container_hostname }}"
|
||||||
CHESS_ADMIN_URL: ""
|
CHESS_ADMIN_URL: ""
|
||||||
CHESS_ADMIN_EMAIL: "{{ users.users.administrator.email }}"
|
CHESS_ADMIN_EMAIL: "{{ users.administrator.email }}"
|
||||||
|
|
||||||
# Docker image
|
# Docker image
|
||||||
#CHESS_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.application.image') }}"
|
#CHESS_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.application.image') }}"
|
||||||
|
55
roles/web-app-magento/Administration.md
Normal file
55
roles/web-app-magento/Administration.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
# Administration
|
||||||
|
|
||||||
|
## 🗑️ Cleanup (Remove Instance & Volumes)
|
||||||
|
```bash
|
||||||
|
cd {{ PATH_DOCKER_COMPOSE_INSTANCES }}magento/
|
||||||
|
docker compose down
|
||||||
|
docker volume rm magento_data
|
||||||
|
cd {{ PATH_DOCKER_COMPOSE_INSTANCES }} && rm -vR {{ PATH_DOCKER_COMPOSE_INSTANCES }}magento
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔍 Access Container Shell
|
||||||
|
```bash
|
||||||
|
docker compose exec -it application /bin/bash
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🧰 Common Magento CLI Tasks
|
||||||
|
```bash
|
||||||
|
# Reindex
|
||||||
|
docker compose exec -it application bin/magento indexer:reindex
|
||||||
|
|
||||||
|
# Flush caches
|
||||||
|
docker compose exec -it application bin/magento cache:flush
|
||||||
|
|
||||||
|
# Enable maintenance mode
|
||||||
|
docker compose exec -it application bin/magento maintenance:enable
|
||||||
|
|
||||||
|
# Disable maintenance mode
|
||||||
|
docker compose exec -it application bin/magento maintenance:disable
|
||||||
|
|
||||||
|
# Recompile DI (when switching modes)
|
||||||
|
docker compose exec -it application bin/magento setup:di:compile
|
||||||
|
|
||||||
|
# Deploy static content (example for English/German)
|
||||||
|
docker compose exec -it application bin/magento setup:static-content:deploy en_US de_DE -f
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀 Performance
|
||||||
|
```bash
|
||||||
|
# Production mode
|
||||||
|
docker compose exec -it application bin/magento deploy:mode:set production
|
||||||
|
|
||||||
|
# Developer mode
|
||||||
|
docker compose exec -it application bin/magento deploy:mode:set developer
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔐 Admin User
|
||||||
|
```bash
|
||||||
|
# Create another admin (example)
|
||||||
|
docker compose exec -it application bin/magento admin:user:create \
|
||||||
|
--admin-user="admin2" \
|
||||||
|
--admin-password="ChangeMe_12345" \
|
||||||
|
--admin-email="{{ users.administrator.email }}" \
|
||||||
|
--admin-firstname="Admin" \
|
||||||
|
--admin-lastname="User"
|
||||||
|
```
|
30
roles/web-app-magento/Installation.md
Normal file
30
roles/web-app-magento/Installation.md
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
# ⚙️ Installation & First Run
|
||||||
|
|
||||||
|
## 1) Prepare DNS & Ports
|
||||||
|
Ensure a canonical domain is mapped (e.g. `shop.{{ PRIMARY_DOMAIN }}`) and a free localhost port in `group_vars/all/10_ports.yml`:
|
||||||
|
```
|
||||||
|
web-app-magento: 80xx
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2) Seed Credentials
|
||||||
|
Provide (at minimum) an admin password in your inventory (vault recommended):
|
||||||
|
```yaml
|
||||||
|
applications:
|
||||||
|
web-app-magento:
|
||||||
|
credentials:
|
||||||
|
admin_password: "use-a-strong-secret"
|
||||||
|
```
|
||||||
|
The admin username/email are taken from `users.administrator.*`.
|
||||||
|
|
||||||
|
## 3) Deploy
|
||||||
|
Run the Infinito.Nexus playbook for your host(s). The role will:
|
||||||
|
- Start OpenSearch (single node)
|
||||||
|
- Start MariaDB (if `central_database` is disabled, the app-local DB is used instead)
|
||||||
|
- Start Magento application container
|
||||||
|
- Wire environment via `templates/env.j2`
|
||||||
|
|
||||||
|
## 4) Verify
|
||||||
|
Open your domain (e.g. `https://shop.{{ PRIMARY_DOMAIN }}`) and complete any remaining onboarding steps in the admin panel.
|
||||||
|
|
||||||
|
**Admin Panel:** `{{ domains | get_url('web-app-magento', WEB_PROTOCOL) }}/admin`
|
||||||
|
(Default path can vary; set a custom `ADMINURI` later via `bin/magento setup:config:set` if desired.)
|
43
roles/web-app-magento/README.md
Normal file
43
roles/web-app-magento/README.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# Magento
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
**Magento (Adobe Commerce Open Source)** is a powerful, extensible e-commerce platform built with PHP. It supports multi-store setups, advanced catalog management, promotions, checkout flows, and a rich extension ecosystem.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This role deploys **Magento 2** via Docker Compose. It is aligned with the Infinito.Nexus stack patterns:
|
||||||
|
- Reverse-proxy integration (front proxy handled by platform roles)
|
||||||
|
- Optional **central database** (MariaDB) or app-local DB
|
||||||
|
- **OpenSearch** for catalog search (required by Magento 2.4+)
|
||||||
|
- Optional **Redis** cache/session (can be toggled)
|
||||||
|
- Health checks, volumes, and environment templating
|
||||||
|
- SMTP wired via platform's `SYSTEM_EMAIL` settings
|
||||||
|
|
||||||
|
For setup & operations, see:
|
||||||
|
- [Installation.md](./Installation.md)
|
||||||
|
- [Administration.md](./Administration.md)
|
||||||
|
- [Upgrade.md](./Upgrade.md)
|
||||||
|
- [User_Administration.md](./User_Administration.md)
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- **Modern search:** OpenSearch out of the box (single-node).
|
||||||
|
- **Flexible DB:** Use platform's central MariaDB or app-local DB.
|
||||||
|
- **Optional Redis:** Toggle cache/session backend.
|
||||||
|
- **Proxy-aware:** Exposes HTTP on localhost, picked up by front proxy role.
|
||||||
|
- **Automation-friendly:** Admin user seeded from inventory variables.
|
||||||
|
|
||||||
|
## Further Resources
|
||||||
|
|
||||||
|
- Magento Open Source: https://magento.com/
|
||||||
|
- DevDocs: https://developer.adobe.com/commerce/
|
||||||
|
- OpenSearch: https://opensearch.org/
|
||||||
|
|
||||||
|
## License / Credits
|
||||||
|
|
||||||
|
Developed and maintained by **Kevin Veen-Birkenbach**.
|
||||||
|
Learn more at [veen.world](https://www.veen.world).
|
||||||
|
|
||||||
|
Part of the [Infinito.Nexus Project](https://s.infinito.nexus/code)
|
||||||
|
Licensed under [Infinito.Nexus NonCommercial License](https://s.infinito.nexus/license).
|
19
roles/web-app-magento/Upgrade.md
Normal file
19
roles/web-app-magento/Upgrade.md
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# 🔼 Upgrade
|
||||||
|
|
||||||
|
> Always back up the database and the `magento_data` volume before upgrades.
|
||||||
|
|
||||||
|
1. Update images/versions in the application config (`roles/web-app-magento/config/main.yml` or inventory overrides).
|
||||||
|
2. Recreate containers:
|
||||||
|
```bash
|
||||||
|
cd {{ PATH_DOCKER_COMPOSE_INSTANCES }}magento/
|
||||||
|
docker compose pull
|
||||||
|
docker compose up -d --remove-orphans
|
||||||
|
```
|
||||||
|
3. Run upgrade routines:
|
||||||
|
```bash
|
||||||
|
docker compose exec -it application bin/magento maintenance:enable
|
||||||
|
docker compose exec -it application bin/magento setup:upgrade
|
||||||
|
docker compose exec -it application bin/magento setup:di:compile
|
||||||
|
docker compose exec -it application bin/magento cache:flush
|
||||||
|
docker compose exec -it application bin/magento maintenance:disable
|
||||||
|
```
|
15
roles/web-app-magento/User_Administration.md
Normal file
15
roles/web-app-magento/User_Administration.md
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
# 👤 User Administration
|
||||||
|
|
||||||
|
- Access the admin panel at:
|
||||||
|
`{{ domains | get_url('web-app-magento', WEB_PROTOCOL) }}/admin`
|
||||||
|
*(or your custom admin path if configured)*
|
||||||
|
|
||||||
|
- New admin accounts can be created via the web UI or CLI:
|
||||||
|
```bash
|
||||||
|
docker compose exec -it application bin/magento admin:user:create \
|
||||||
|
--admin-user="john" \
|
||||||
|
--admin-password="SuperSecret_12345" \
|
||||||
|
--admin-email="john@example.com" \
|
||||||
|
--admin-firstname="John" \
|
||||||
|
--admin-lastname="Doe"
|
||||||
|
```
|
37
roles/web-app-magento/config/main.yml
Normal file
37
roles/web-app-magento/config/main.yml
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
features:
|
||||||
|
matomo: true
|
||||||
|
css: true
|
||||||
|
desktop: true
|
||||||
|
central_database: true # Use platform DB (recommended). If false, app-local DB container is enabled.
|
||||||
|
oidc: false # Magento SSO via OIDC requires extensions; not wired by default
|
||||||
|
logout: true
|
||||||
|
ldap: false
|
||||||
|
|
||||||
|
server:
|
||||||
|
csp:
|
||||||
|
whitelist: {}
|
||||||
|
domains:
|
||||||
|
canonical:
|
||||||
|
- "shop.{{ PRIMARY_DOMAIN }}"
|
||||||
|
aliases:
|
||||||
|
- "magento.{{ PRIMARY_DOMAIN }}"
|
||||||
|
|
||||||
|
docker:
|
||||||
|
services:
|
||||||
|
application:
|
||||||
|
image: "bitnami/magento"
|
||||||
|
version: "latest"
|
||||||
|
name: "magento"
|
||||||
|
backup:
|
||||||
|
no_stop_required: true
|
||||||
|
database:
|
||||||
|
enabled: true # Central DB recommended; if disabled, app-local DB is created
|
||||||
|
redis:
|
||||||
|
enabled: true
|
||||||
|
search:
|
||||||
|
enabled: true
|
||||||
|
image: "opensearchproject/opensearch"
|
||||||
|
version: "latest"
|
||||||
|
name: "magento-opensearch"
|
||||||
|
volumes:
|
||||||
|
data: "magento_data"
|
25
roles/web-app-magento/meta/main.yml
Normal file
25
roles/web-app-magento/meta/main.yml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
---
|
||||||
|
galaxy_info:
|
||||||
|
author: "Kevin Veen-Birchenbach"
|
||||||
|
description: "Deploy Magento (Adobe Commerce Open Source) via Docker Compose with OpenSearch, MariaDB, optional Redis, and proxy integration for Infinito.Nexus."
|
||||||
|
license: "Infinito.Nexus NonCommercial License"
|
||||||
|
license_url: "https://s.infinito.nexus/license"
|
||||||
|
company: |
|
||||||
|
Kevin Veen-Birchenbach
|
||||||
|
Consulting & Coaching Solutions
|
||||||
|
https://www.veen.world
|
||||||
|
galaxy_tags:
|
||||||
|
- magento
|
||||||
|
- ecommerce
|
||||||
|
- php
|
||||||
|
- docker
|
||||||
|
- opensearch
|
||||||
|
- mariadb
|
||||||
|
repository: "https://s.infinito.nexus/code"
|
||||||
|
issue_tracker_url: "https://s.infinito.nexus/issues"
|
||||||
|
documentation: "https://docs.infinito.nexus"
|
||||||
|
logo:
|
||||||
|
class: "fa-solid fa-cart-shopping"
|
||||||
|
run_after:
|
||||||
|
- web-app-keycloak
|
||||||
|
dependencies: []
|
6
roles/web-app-magento/schema/main.yml
Normal file
6
roles/web-app-magento/schema/main.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
credentials:
|
||||||
|
admin_password:
|
||||||
|
description: "Password for the initial Magento admin account"
|
||||||
|
algorithm: "alphanumeric"
|
||||||
|
validation:
|
||||||
|
min_length: 12
|
6
roles/web-app-magento/tasks/01_core.yml
Normal file
6
roles/web-app-magento/tasks/01_core.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
- name: "load docker, db/redis/proxy for {{ application_id }}"
|
||||||
|
include_role:
|
||||||
|
name: sys-stk-full-stateful
|
||||||
|
|
||||||
|
- name: flush docker service
|
||||||
|
meta: flush_handlers
|
9
roles/web-app-magento/tasks/main.yml
Normal file
9
roles/web-app-magento/tasks/main.yml
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
- name: "construct {{ role_name }}"
|
||||||
|
include_tasks: 01_core.yml
|
||||||
|
when: run_once_web_app_magento is not defined
|
||||||
|
|
||||||
|
- name: run the docker magento tasks once
|
||||||
|
set_fact:
|
||||||
|
run_once_web_app_magento: true
|
||||||
|
when: run_once_web_app_magento is not defined
|
34
roles/web-app-magento/templates/docker-compose.yml.j2
Normal file
34
roles/web-app-magento/templates/docker-compose.yml.j2
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{% include 'roles/docker-compose/templates/base.yml.j2' %}
|
||||||
|
|
||||||
|
application:
|
||||||
|
{% set container_port = 8080 %}
|
||||||
|
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||||
|
image: "{{ magento_image }}:{{ magento_version }}"
|
||||||
|
container_name: "{{ magento_name }}"
|
||||||
|
ports:
|
||||||
|
- "127.0.0.1:{{ ports.localhost.http[application_id] }}:{{ container_port }}"
|
||||||
|
volumes:
|
||||||
|
- "data:/bitnami/magento"
|
||||||
|
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
||||||
|
depends_on:
|
||||||
|
- search
|
||||||
|
{% include 'roles/docker-container/templates/healthcheck/tcp.yml.j2' %}
|
||||||
|
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||||
|
|
||||||
|
search:
|
||||||
|
{% set container_port = 9200 %}
|
||||||
|
image: "{{ magento_search_image }}:{{ magento_search_version }}"
|
||||||
|
container_name: "{{ magento_search_name }}"
|
||||||
|
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||||
|
environment:
|
||||||
|
- discovery.type=single-node
|
||||||
|
- plugins.security.disabled=true
|
||||||
|
- OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m
|
||||||
|
{% include 'roles/docker-container/templates/healthcheck/tcp.yml.j2' %}
|
||||||
|
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||||
|
|
||||||
|
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
||||||
|
data:
|
||||||
|
name: {{ magento_data }}
|
||||||
|
|
||||||
|
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
39
roles/web-app-magento/templates/env.j2
Normal file
39
roles/web-app-magento/templates/env.j2
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# Magento environment
|
||||||
|
# Base references:
|
||||||
|
# - https://github.com/bitnami/containers/tree/main/bitnami/magento
|
||||||
|
|
||||||
|
# Host & URLs
|
||||||
|
MAGENTO_HOST="{{ domains | get_domain(application_id) }}"
|
||||||
|
MAGENTO_BASE_URL="{{ domains | get_url(application_id, WEB_PROTOCOL) }}/"
|
||||||
|
MAGENTO_ENABLE_HTTPS={{ (WEB_PORT == 443) | string | lower }}
|
||||||
|
|
||||||
|
# Admin (seed from global administrator)
|
||||||
|
MAGENTO_USERNAME="{{ users.administrator.username }}"
|
||||||
|
MAGENTO_PASSWORD="{{ applications | get_app_conf(application_id, 'credentials.admin_password') }}"
|
||||||
|
MAGENTO_EMAIL="{{ users.administrator.email }}"
|
||||||
|
MAGENTO_FIRST_NAME="{{ users.administrator.firstname | default('Admin') }}"
|
||||||
|
MAGENTO_LAST_NAME="{{ users.administrator.lastname | default('User') }}"
|
||||||
|
|
||||||
|
# Database (central DB preferred)
|
||||||
|
MARIADB_HOST="{{ database_host }}"
|
||||||
|
MARIADB_PORT_NUMBER="{{ database_port }}"
|
||||||
|
MAGENTO_DATABASE_USER="{{ database_username }}"
|
||||||
|
MAGENTO_DATABASE_PASSWORD="{{ database_password }}"
|
||||||
|
MAGENTO_DATABASE_NAME="{{ database_name }}"
|
||||||
|
|
||||||
|
# Search (Magento 2.4+)
|
||||||
|
MAGENTO_SEARCH_ENGINE="opensearch"
|
||||||
|
OPENSEARCH_HOST="search"
|
||||||
|
OPENSEARCH_PORT_NUMBER="9200"
|
||||||
|
|
||||||
|
# SMTP
|
||||||
|
SMTP_HOST="{{ SYSTEM_EMAIL.HOST }}"
|
||||||
|
SMTP_PORT="{{ SYSTEM_EMAIL.PORT }}"
|
||||||
|
SMTP_USER="{{ users['no-reply'].email }}"
|
||||||
|
SMTP_PASSWORD="{{ users['no-reply'].mailu_token }}"
|
||||||
|
SMTP_PROTOCOL={{ SYSTEM_EMAIL.TLS | ternary('tls','ssl') }}
|
||||||
|
|
||||||
|
# Misc
|
||||||
|
ALLOW_EMPTY_PASSWORD="no"
|
||||||
|
BITNAMI_DEBUG="false"
|
||||||
|
PHP_MEMORY_LIMIT="1024M"
|
17
roles/web-app-magento/vars/main.yml
Normal file
17
roles/web-app-magento/vars/main.yml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# General
|
||||||
|
application_id: "web-app-magento"
|
||||||
|
database_type: "mariadb"
|
||||||
|
|
||||||
|
# Magento (application container)
|
||||||
|
magento_version: "{{ applications | get_app_conf(application_id, 'docker.services.application.version', True) | default('latest') }}"
|
||||||
|
magento_image: "{{ applications | get_app_conf(application_id, 'docker.services.application.image', True) | default('bitnami/magento') }}"
|
||||||
|
magento_name: "{{ applications | get_app_conf(application_id, 'docker.services.application.name', True) | default('magento') }}"
|
||||||
|
magento_data: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) | default('magento_data') }}"
|
||||||
|
|
||||||
|
# Search (OpenSearch)
|
||||||
|
magento_search_version: "{{ applications | get_app_conf(application_id, 'docker.services.search.version', True) | default('latest') }}"
|
||||||
|
magento_search_image: "{{ applications | get_app_conf(application_id, 'docker.services.search.image', True) | default('opensearchproject/opensearch') }}"
|
||||||
|
magento_search_name: "{{ applications | get_app_conf(application_id, 'docker.services.search.name', True) | default('magento-opensearch') }}"
|
||||||
|
|
||||||
|
# Docker helpers
|
||||||
|
docker_compose_flush_handlers: true
|
@@ -1,5 +1,4 @@
|
|||||||
single_user_mode: false # Set true for initial setup
|
single_user_mode: false # Set true for initial setup
|
||||||
setup: true # Set true in inventory file to execute the setup and initializing procedures, don't know if this is still necessary @todo test it
|
|
||||||
features:
|
features:
|
||||||
matomo: true
|
matomo: true
|
||||||
css: true
|
css: true
|
||||||
|
@@ -19,5 +19,4 @@
|
|||||||
docker_compose_flush_handlers: true
|
docker_compose_flush_handlers: true
|
||||||
|
|
||||||
- name: "start setup procedures for mastodon"
|
- name: "start setup procedures for mastodon"
|
||||||
include_tasks: 01_setup.yml
|
include_tasks: 01_setup.yml
|
||||||
when: mastodon_setup | bool
|
|
@@ -3,8 +3,8 @@
|
|||||||
web:
|
web:
|
||||||
{% set container_port = 3000 %}
|
{% set container_port = 3000 %}
|
||||||
{% set container_healthcheck = 'health' %}
|
{% set container_healthcheck = 'health' %}
|
||||||
container_name: {{ mastodon_name }}
|
container_name: {{ MASTODON_NAME }}
|
||||||
image: "{{ mastodon_image }}:{{ mastodon_version }}"
|
image: "{{ MASTODON_IMAGE }}:{{ MASTODON_VERSION }}"
|
||||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||||
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p {{ container_port }}"
|
command: bash -c "rm -f /mastodon/tmp/pids/server.pid; bundle exec rails s -p {{ container_port }}"
|
||||||
{% include 'roles/docker-container/templates/healthcheck/wget.yml.j2' %}
|
{% include 'roles/docker-container/templates/healthcheck/wget.yml.j2' %}
|
||||||
@@ -18,8 +18,8 @@
|
|||||||
streaming:
|
streaming:
|
||||||
{% set container_port = 4000 %}
|
{% set container_port = 4000 %}
|
||||||
{% set container_healthcheck = 'api/v1/streaming/health' %}
|
{% set container_healthcheck = 'api/v1/streaming/health' %}
|
||||||
container_name: {{ mastodon_streaming_name }}
|
container_name: {{ MASTODON_STREAMING_NAME }}
|
||||||
image: "{{ mastodon_streaming_image }}:{{ mastodon_streaming_version }}"
|
image: "{{ MASTODON_STREAMING_IMAGE }}:{{ MASTODON_STREAMING_VERSION }}"
|
||||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||||
command: node ./streaming
|
command: node ./streaming
|
||||||
{% include 'roles/docker-container/templates/healthcheck/wget.yml.j2' %}
|
{% include 'roles/docker-container/templates/healthcheck/wget.yml.j2' %}
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
{% include 'roles/docker-container/templates/networks.yml.j2' %}
|
||||||
|
|
||||||
sidekiq:
|
sidekiq:
|
||||||
container_name: {{ mastodon_sidekiq_name }}
|
container_name: {{ MASTODON_SIDEKIQ_NAME }}
|
||||||
image: "{{ mastodon_image }}:{{ mastodon_version }}"
|
image: "{{ MASTODON_IMAGE }}:{{ MASTODON_VERSION }}"
|
||||||
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
{% include 'roles/docker-container/templates/base.yml.j2' %}
|
||||||
command: bundle exec sidekiq
|
command: bundle exec sidekiq
|
||||||
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
{% include 'roles/docker-container/templates/depends_on/dmbs_excl.yml.j2' %}
|
||||||
@@ -45,5 +45,5 @@
|
|||||||
|
|
||||||
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
{% include 'roles/docker-compose/templates/volumes.yml.j2' %}
|
||||||
data:
|
data:
|
||||||
name: "{{ mastodon_volume }}"
|
name: "{{ MASTODON_VOLUME }}"
|
||||||
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
{% include 'roles/docker-compose/templates/networks.yml.j2' %}
|
@@ -5,7 +5,8 @@
|
|||||||
|
|
||||||
LOCAL_DOMAIN={{ domains | get_domain(application_id) }}
|
LOCAL_DOMAIN={{ domains | get_domain(application_id) }}
|
||||||
ALTERNATE_DOMAINS="{{ domains['web-app-mastodon'][1:] | join(',') }}"
|
ALTERNATE_DOMAINS="{{ domains['web-app-mastodon'][1:] | join(',') }}"
|
||||||
SINGLE_USER_MODE={{ applications | get_app_conf(application_id, 'single_user_mode', True) }}
|
SINGLE_USER_MODE={{ applications | get_app_conf(application_id, 'single_user_mode') }}
|
||||||
|
ALLOWED_PRIVATE_ADDRESSES={{ MASTODON_ALLOWED_PRIVATE_ADDRESSES }}
|
||||||
|
|
||||||
# Credentials
|
# Credentials
|
||||||
|
|
||||||
|
@@ -3,12 +3,12 @@ application_id: "web-app-mastodon"
|
|||||||
database_type: "postgres"
|
database_type: "postgres"
|
||||||
|
|
||||||
# Mastodon Specific
|
# Mastodon Specific
|
||||||
mastodon_version: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.version', True) }}"
|
MASTODON_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.version') }}"
|
||||||
mastodon_image: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.image', True) }}"
|
MASTODON_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.image') }}"
|
||||||
mastodon_name: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.name', True) }}"
|
MASTODON_NAME: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.name') }}"
|
||||||
mastodon_volume: "{{ applications | get_app_conf(application_id, 'docker.volumes.data', True) }}"
|
MASTODON_VOLUME: "{{ applications | get_app_conf(application_id, 'docker.volumes.data') }}"
|
||||||
mastodon_streaming_version: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.version', True) }}"
|
MASTODON_STREAMING_VERSION: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.version') }}"
|
||||||
mastodon_streaming_image: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.image', True) }}"
|
MASTODON_STREAMING_IMAGE: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.image') }}"
|
||||||
mastodon_streaming_name: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.name', True) }}"
|
MASTODON_STREAMING_NAME: "{{ applications | get_app_conf(application_id, 'docker.services.streaming.name') }}"
|
||||||
mastodon_sidekiq_name: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.name', True) }}_sidekiq"
|
MASTODON_SIDEKIQ_NAME: "{{ applications | get_app_conf(application_id, 'docker.services.mastodon.name') }}_sidekiq"
|
||||||
mastodon_setup: "{{ applications | get_app_conf(application_id, 'setup', True) }}"
|
MASTODON_ALLOWED_PRIVATE_ADDRESSES: "{{ networks.local['svc-db-postgres'].subnet if 'web-app-chess' in group_names else ''}}"
|
@@ -11,7 +11,7 @@ class TestApplicationIDsInPorts(unittest.TestCase):
|
|||||||
# Path to the ports definition file
|
# Path to the ports definition file
|
||||||
ports_file = os.path.abspath(
|
ports_file = os.path.abspath(
|
||||||
os.path.join(
|
os.path.join(
|
||||||
os.path.dirname(__file__), '..', '..', 'group_vars', 'all', '09_ports.yml'
|
os.path.dirname(__file__), '..', '..', 'group_vars', 'all', '10_ports.yml'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
with open(ports_file, 'r', encoding='utf-8') as f:
|
with open(ports_file, 'r', encoding='utf-8') as f:
|
||||||
|
@@ -25,7 +25,7 @@ class TestCspConfigurationConsistency(unittest.TestCase):
|
|||||||
Accept entries that are:
|
Accept entries that are:
|
||||||
- Jinja expressions (contain '{{' and '}}')
|
- Jinja expressions (contain '{{' and '}}')
|
||||||
- Data or Blob URIs (start with 'data:' or 'blob:')
|
- Data or Blob URIs (start with 'data:' or 'blob:')
|
||||||
- HTTP/HTTPS URLs
|
- HTTP/HTTPS/WS/WSS URLs
|
||||||
"""
|
"""
|
||||||
if '{{' in entry and '}}' in entry:
|
if '{{' in entry and '}}' in entry:
|
||||||
return True
|
return True
|
||||||
@@ -34,7 +34,7 @@ class TestCspConfigurationConsistency(unittest.TestCase):
|
|||||||
if entry == '*':
|
if entry == '*':
|
||||||
return True
|
return True
|
||||||
parsed = urlparse(entry)
|
parsed = urlparse(entry)
|
||||||
return parsed.scheme in ('http', 'https') and bool(parsed.netloc)
|
return parsed.scheme in ('http', 'https','ws', 'wss') and bool(parsed.netloc)
|
||||||
|
|
||||||
def test_csp_configuration_structure(self):
|
def test_csp_configuration_structure(self):
|
||||||
"""
|
"""
|
||||||
|
@@ -8,7 +8,7 @@ class TestOAuth2ProxyPorts(unittest.TestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
# Set up root paths and load oauth2_proxy ports mapping
|
# Set up root paths and load oauth2_proxy ports mapping
|
||||||
cls.ROOT = Path(__file__).parent.parent.parent.resolve()
|
cls.ROOT = Path(__file__).parent.parent.parent.resolve()
|
||||||
cls.PORTS_FILE = cls.ROOT / 'group_vars' / 'all' / '09_ports.yml'
|
cls.PORTS_FILE = cls.ROOT / 'group_vars' / 'all' / '10_ports.yml'
|
||||||
with cls.PORTS_FILE.open() as f:
|
with cls.PORTS_FILE.open() as f:
|
||||||
data = yaml.safe_load(f)
|
data = yaml.safe_load(f)
|
||||||
cls.oauth2_ports = (
|
cls.oauth2_ports = (
|
||||||
@@ -50,7 +50,7 @@ class TestOAuth2ProxyPorts(unittest.TestCase):
|
|||||||
if app_id not in self.oauth2_ports:
|
if app_id not in self.oauth2_ports:
|
||||||
self.fail(
|
self.fail(
|
||||||
f"Missing oauth2_proxy port mapping for application '{app_id}' "
|
f"Missing oauth2_proxy port mapping for application '{app_id}' "
|
||||||
f"in group_vars/all/09_ports.yml"
|
f"in group_vars/all/10_ports.yml"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@@ -9,7 +9,7 @@ class TestPortReferencesValidity(unittest.TestCase):
|
|||||||
# locate and load the ports definition
|
# locate and load the ports definition
|
||||||
base = os.path.dirname(__file__)
|
base = os.path.dirname(__file__)
|
||||||
cls.ports_file = os.path.abspath(
|
cls.ports_file = os.path.abspath(
|
||||||
os.path.join(base, '..', '..', 'group_vars', 'all', '09_ports.yml')
|
os.path.join(base, '..', '..', 'group_vars', 'all', '10_ports.yml')
|
||||||
)
|
)
|
||||||
if not os.path.isfile(cls.ports_file):
|
if not os.path.isfile(cls.ports_file):
|
||||||
raise FileNotFoundError(f"{cls.ports_file} does not exist.")
|
raise FileNotFoundError(f"{cls.ports_file} does not exist.")
|
||||||
@@ -42,7 +42,7 @@ class TestPortReferencesValidity(unittest.TestCase):
|
|||||||
"""
|
"""
|
||||||
Scan all .j2, .yml, .yaml files under roles/, group_vars/, host_vars/, tasks/,
|
Scan all .j2, .yml, .yaml files under roles/, group_vars/, host_vars/, tasks/,
|
||||||
templates/, and playbooks/ for any ports.<host>.<category>.<service> references
|
templates/, and playbooks/ for any ports.<host>.<category>.<service> references
|
||||||
(dot, [''], or .get('')) and verify each triple is defined in 09_ports.yml.
|
(dot, [''], or .get('')) and verify each triple is defined in 10_ports.yml.
|
||||||
"""
|
"""
|
||||||
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
|
||||||
dirs_to_scan = ['roles', 'group_vars', 'host_vars', 'tasks', 'templates', 'playbooks']
|
dirs_to_scan = ['roles', 'group_vars', 'host_vars', 'tasks', 'templates', 'playbooks']
|
||||||
|
@@ -8,7 +8,7 @@ class TestPortsUniqueness(unittest.TestCase):
|
|||||||
def setUpClass(cls):
|
def setUpClass(cls):
|
||||||
base_dir = os.path.dirname(__file__)
|
base_dir = os.path.dirname(__file__)
|
||||||
cls.ports_file = os.path.abspath(
|
cls.ports_file = os.path.abspath(
|
||||||
os.path.join(base_dir, '..', '..', 'group_vars', 'all', '09_ports.yml')
|
os.path.join(base_dir, '..', '..', 'group_vars', 'all', '10_ports.yml')
|
||||||
)
|
)
|
||||||
# Try to load data; leave it as None if missing or invalid YAML
|
# Try to load data; leave it as None if missing or invalid YAML
|
||||||
try:
|
try:
|
||||||
|
@@ -18,7 +18,7 @@ class TestCreateDockerRoleCLI(unittest.TestCase):
|
|||||||
def setUp(self):
|
def setUp(self):
|
||||||
# Temporary directory for YAML files and templates
|
# Temporary directory for YAML files and templates
|
||||||
self.tmpdir = tempfile.mkdtemp()
|
self.tmpdir = tempfile.mkdtemp()
|
||||||
self.ports_file = os.path.join(self.tmpdir, '09_ports.yml')
|
self.ports_file = os.path.join(self.tmpdir, '10_ports.yml')
|
||||||
self.networks_file = os.path.join(self.tmpdir, '09_networks.yml')
|
self.networks_file = os.path.join(self.tmpdir, '09_networks.yml')
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
|
Reference in New Issue
Block a user