diff --git a/5.2/5.2.14/alpine/Dockerfile b/5.2/5.2.14/alpine/Dockerfile
new file mode 100644
index 0000000..21babe5
--- /dev/null
+++ b/5.2/5.2.14/alpine/Dockerfile
@@ -0,0 +1,71 @@
+FROM python:3.8-alpine
+
+ENV PIP=22.2.2 \
+ ZC_BUILDOUT=3.0.1 \
+ SETUPTOOLS=65.7.0 \
+ WHEEL=0.38.4 \
+ PLONE_MAJOR=5.2 \
+ PLONE_VERSION=5.2.13 \
+ PLONE_VERSION_RELEASE=Plone-5.2.13-UnifiedInstaller-1.0 \
+ PLONE_MD5=12c037fae9413385149e8677f8457b84
+
+RUN addgroup -g 500 plone \
+ && adduser -S -D -G plone -u 500 plone \
+ && mkdir -p /plone/instance /data/filestorage /data/blobstorage
+
+COPY buildout.cfg /plone/instance/
+
+RUN apk add --no-cache --virtual .build-deps \
+ build-base \
+ libc-dev \
+ zlib-dev \
+ libjpeg-turbo-dev \
+ libpng-dev \
+ libxml2-dev \
+ libxslt-dev \
+ mariadb-dev \
+ openldap-dev \
+ pcre-dev \
+ postgresql-dev \
+ libffi-dev \
+&& wget -O Plone.tgz https://launchpad.net/plone/$PLONE_MAJOR/$PLONE_VERSION/+download/$PLONE_VERSION_RELEASE.tgz \
+&& echo "$PLONE_MD5 Plone.tgz" | md5sum -c - \
+&& tar -zxvf Plone.tgz \
+&& cp -rv ./$PLONE_VERSION_RELEASE/base_skeleton/* /plone/instance/ \
+&& cp -v ./$PLONE_VERSION_RELEASE/buildout_templates/buildout.cfg /plone/instance/buildout-base.cfg \
+&& pip install pip==$PIP setuptools==$SETUPTOOLS zc.buildout==$ZC_BUILDOUT wheel==$WHEEL \
+# some package needs PyYAML 5.4.1, and this can only be built with cython<3.0.0
+&& pip install "cython<3.0.0" && pip install --no-build-isolation pyyaml==5.4.1 \
+&& cd /plone/instance \
+&& buildout \
+&& ln -s /data/filestorage/ /plone/instance/var/filestorage \
+&& ln -s /data/blobstorage /plone/instance//var/blobstorage \
+&& find /data -not -user plone -exec chown plone:plone {} \+ \
+&& find /plone -not -user plone -exec chown plone:plone {} \+ \
+&& rm -rf /Plone* \
+&& apk del .build-deps \
+&& apk add --no-cache --virtual .run-deps \
+ su-exec \
+ bash \
+ git \
+ rsync \
+ libldap \
+ libxml2 \
+ libxslt \
+ libjpeg-turbo \
+ mariadb-connector-c \
+ postgresql-client \
+&& rm -rf /plone/buildout-cache/downloads/*
+
+VOLUME /data
+
+COPY docker-initialize.py docker-entrypoint.sh /
+
+EXPOSE 8080
+WORKDIR /plone/instance
+
+HEALTHCHECK --interval=1m --timeout=5s --start-period=1m \
+ CMD nc -z -w5 127.0.0.1 8080 || exit 1
+
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["start"]
diff --git a/5.2/5.2.14/alpine/buildout.cfg b/5.2/5.2.14/alpine/buildout.cfg
new file mode 100644
index 0000000..02ca654
--- /dev/null
+++ b/5.2/5.2.14/alpine/buildout.cfg
@@ -0,0 +1,106 @@
+[buildout]
+extends =
+ buildout-base.cfg
+
+index = https://pypi.org/simple/
+
+extensions =
+effective-user = plone
+buildout-user = plone
+var-dir=/data
+user=admin:admin
+parts +=
+ zeo
+ mrbob
+ plonesite
+
+eggs +=
+ RelStorage[mysql,postgresql,oracle]
+ pas.plugins.ldap
+
+[client1]
+recipe =
+
+[instance_base]
+resources = ${buildout:directory}/resources
+
+[zeo]
+<= zeoserver_base
+recipe = plone.recipe.zeoserver
+zeo-address = 8080
+
+[instance]
+zcml-additional =
+
+
+
+event-log-handler = StreamHandler
+event-log-args = (sys.stderr,)
+access-log-handler = StreamHandler
+access-log-args = (sys.stdout,)
+
+# Requires gcc, thus install it on image build
+[mrbob]
+recipe = zc.recipe.egg
+eggs =
+ mr.bob
+ bobtemplates.plone
+
+[plonesite]
+recipe = collective.recipe.plonesite
+instance = instance
+site-id = Plone
+profiles-initial = Products.CMFPlone:dependencies
+profiles =
+ plonetheme.barceloneta:default
+ plone.app.caching:default
+ plone.app.contenttypes:plone-content
+ plone.restapi:default
+upgrade-portal = False
+upgrade-all-profiles = False
+enabled = False
+
+[versions]
+setuptools =
+zc.buildout =
+
+plone.restapi = 8.43.1
+plone.rest = 3.0.0
+
+RelStorage = 3.4.5
+argparse = 1.4.0
+bda.cache = 1.3.0
+bobtemplates.plone = 5.2.2
+case-conversion = 2.1.0
+collective.checkdocs = 0.2
+collective.recipe.plonesite = 1.12.0
+cx-Oracle = 8.3.0
+isort = 5.11.5
+mr.bob = 1.0.0
+mysqlclient = 2.1.1
+node = 1.2.1
+node.ext.ldap = 1.2
+node.ext.ugm = 1.1
+odict = 1.9.0
+pas.plugins.ldap = 1.8.2
+passlib = 1.7.4
+perfmetrics = 3.3.0
+plumber = 1.7
+psycopg2 = 2.9.3
+pyasn1 = 0.5.0
+pyasn1-modules = 0.3.0
+python-ldap = 3.4.2
+python-memcached = 1.59
+regex = 2023.6.3
+yafowil = 3.1.0
+yafowil.plone = 4.0.0a5
+yafowil.widget.array = 1.7
+yafowil.widget.dict = 1.8
+yafowil.yaml = 2.0
diff --git a/5.2/5.2.14/alpine/docker-entrypoint.sh b/5.2/5.2.14/alpine/docker-entrypoint.sh
new file mode 100755
index 0000000..dcfd834
--- /dev/null
+++ b/5.2/5.2.14/alpine/docker-entrypoint.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e
+
+COMMANDS="adduser debug fg foreground help kill logreopen logtail reopen_transcript run show status stop wait"
+START="console start restart"
+
+# Fixing permissions for external /data volumes
+mkdir -p /data/blobstorage /data/cache /data/filestorage /data/instance /data/log /data/zeoserver
+mkdir -p /plone/instance/src
+find /data -not -user plone -exec chown plone:plone {} \+
+find /plone -not -user plone -exec chown plone:plone {} \+
+
+# Initializing from environment variables
+su-exec plone python /docker-initialize.py
+
+if [ -e "custom.cfg" ]; then
+ if [ ! -e "bin/develop" ]; then
+ buildout -c custom.cfg
+ find /data -not -user plone -exec chown plone:plone {} \+
+ find /plone -not -user plone -exec chown plone:plone {} \+
+ su-exec plone python /docker-initialize.py
+ fi
+fi
+
+# ZEO Server
+if [[ "$1" == "zeo"* ]]; then
+ exec su-exec plone bin/$1 fg
+fi
+
+# Plone instance start
+if [[ $START == *"$1"* ]]; then
+ exec su-exec plone bin/instance console
+fi
+
+# Plone instance helpers
+if [[ $COMMANDS == *"$1"* ]]; then
+ exec su-exec plone bin/instance "$@"
+fi
+
+# Custom
+exec "$@"
diff --git a/5.2/5.2.14/alpine/docker-initialize.py b/5.2/5.2.14/alpine/docker-initialize.py
new file mode 100755
index 0000000..cfbf6d2
--- /dev/null
+++ b/5.2/5.2.14/alpine/docker-initialize.py
@@ -0,0 +1,382 @@
+#!/usr/local/bin/python
+
+import re
+import os
+
+class Environment(object):
+ """ Configure container via environment variables
+ """
+ def __init__(self, env=os.environ,
+ zope_conf="/plone/instance/parts/instance/etc/zope.conf",
+ custom_conf="/plone/instance/custom.cfg",
+ zeopack_conf="/plone/instance/bin/zeopack",
+ zeoserver_conf="/plone/instance/parts/zeoserver/etc/zeo.conf",
+ cors_conf="/plone/instance/parts/instance/etc/package-includes/999-additional-overrides.zcml"
+ ):
+ self.env = env
+ self.zope_conf = zope_conf
+ self.custom_conf = custom_conf
+ self.zeopack_conf = zeopack_conf
+ self.zeoserver_conf = zeoserver_conf
+ self.cors_conf = cors_conf
+
+ def zeoclient(self):
+ """ ZEO Client
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ config = ""
+ with open(self.zope_conf, "r") as cfile:
+ config = cfile.read()
+
+ # Already initialized
+ if "" not in config:
+ return
+
+ read_only = self.env.get("ZEO_READ_ONLY", "false")
+ zeo_ro_fallback = self.env.get("ZEO_CLIENT_READ_ONLY_FALLBACK", "false")
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+ zeo_storage=self.env.get("ZEO_STORAGE", "1")
+ zeo_client_cache_size=self.env.get("ZEO_CLIENT_CACHE_SIZE", "128MB")
+ zeo_conf = ZEO_TEMPLATE.format(
+ zeo_address=server,
+ read_only=read_only,
+ zeo_client_read_only_fallback=zeo_ro_fallback,
+ shared_blob_dir=shared_blob_dir,
+ zeo_storage=zeo_storage,
+ zeo_client_cache_size=zeo_client_cache_size
+ )
+
+ pattern = re.compile(r".+", re.DOTALL)
+ config = re.sub(pattern, zeo_conf, config)
+
+ with open(self.zope_conf, "w") as cfile:
+ cfile.write(config)
+
+ def zeopack(self):
+ """ ZEO Pack
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ if ":" in server:
+ host, port = server.split(":")
+ else:
+ host, port = (server, "8100")
+
+ with open(self.zeopack_conf, 'r') as cfile:
+ text = cfile.read()
+ text = text.replace('address = "8100"', 'address = "%s"' % server)
+ text = text.replace('host = "127.0.0.1"', 'host = "%s"' % host)
+ text = text.replace('port = "8100"', 'port = "%s"' % port)
+
+ with open(self.zeopack_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def zeoserver(self):
+ """ ZEO Server
+ """
+ pack_keep_old = self.env.get("ZEO_PACK_KEEP_OLD", '')
+ if pack_keep_old.lower() in ("false", "no", "0", "n", "f"):
+ with open(self.zeoserver_conf, 'r') as cfile:
+ text = cfile.read()
+ if 'pack-keep-old' not in text:
+ text = text.replace(
+ '',
+ ' pack-keep-old false\n'
+ )
+
+ with open(self.zeoserver_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def cors(self):
+ """ Configure CORS Policies
+ """
+ if not [e for e in self.env if e.startswith("CORS_")]:
+ return
+
+ allow_origin = self.env.get("CORS_ALLOW_ORIGIN",
+ "http://localhost:3000,http://127.0.0.1:3000")
+ allow_methods = self.env.get("CORS_ALLOW_METHODS",
+ "DELETE,GET,OPTIONS,PATCH,POST,PUT")
+ allow_credentials = self.env.get("CORS_ALLOW_CREDENTIALS", "true")
+ expose_headers = self.env.get("CORS_EXPOSE_HEADERS",
+ "Content-Length,X-My-Header")
+ allow_headers = self.env.get("CORS_ALLOW_HEADERS",
+ "Accept,Authorization,Content-Type,X-Custom-Header,Lock-Token")
+ max_age = self.env.get("CORS_MAX_AGE", "3600")
+ cors_conf = CORS_TEMPLATE.format(
+ allow_origin=allow_origin,
+ allow_methods=allow_methods,
+ allow_credentials=allow_credentials,
+ expose_headers=expose_headers,
+ allow_headers=allow_headers,
+ max_age=max_age
+ )
+ with open(self.cors_conf, "w") as cfile:
+ cfile.write(cors_conf)
+
+ def relstorage_conf(self):
+ """ RelStorage configuration from environment variables
+ """
+ if not [e for e in self.env if e.startswith("RELSTORAGE_")]:
+ return ""
+
+ # Database specific adapter options
+ # https://relstorage.readthedocs.io/en/latest/supported-databases.html
+ adapter_options = self.env.get(
+ "RELSTORAGE_ADAPTER_OPTIONS",
+ "",
+ ).strip().split(",")
+
+ settings = {
+ # General Settings
+ "name": self.env.get("RELSTORAGE_NAME"),
+ "read-only": self.env.get("RELSTORAGE_READ_ONLY"),
+ "keep-history": self.env.get("RELSTORAGE_KEEP_HISTORY"),
+ "commit-lock-timeout": self.env.get(
+ "RELSTORAGE_COMMIT_LOCK_TIMEOUT",
+ ),
+ "commit-lock-id": self.env.get("RELSTORAGE_COMMIT_LOCK_ID"),
+ "create-schema": self.env.get("RELSTORAGE_CREATE_SCHEMA"),
+
+ # Blobs
+ "blob-dir": self.env.get("RELSTORAGE_BLOB_DIR",
+ "/plone/instance/var/blobstorage"),
+ "shared-blob-dir": self.env.get("RELSTORAGE_SHARED_BLOB_DIR"),
+ "blob-cache-size": self.env.get("RELSTORAGE_BLOB_CACHE_SIZE"),
+ "blob-cache-size-check": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK",
+ ),
+ "blob-cache-size-check-external": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK_EXTERNAL",
+ ),
+ "blob-chunk-size": self.env.get("RELSTORAGE_BLOB_CHUNK_SIZE"),
+
+ # Replication
+ "replica-conf": self.env.get("RELSTORAGE_REPLICA_CONF"),
+ "ro-replica-conf": self.env.get("RELSTORAGE_RO_REPLICA_CONF"),
+ "replica-timeout": self.env.get("RELSTORAGE_REPLICA_TIMEOUT"),
+ "revert-when-stale": self.env.get("RELSTORAGE_REVERT_WHEN_STALE"),
+
+ # GC and Packing
+ "pack-gc": self.env.get("RELSTORAGE_PACK_GC"),
+ "pack-prepack-only": self.env.get("RELSTORAGE_PACK_PREPACK_ONLY"),
+ "pack-skip-prepack": self.env.get("RELSTORAGE_PACK_SKIP_PREPACK"),
+ "pack-batch-timeout": self.env.get("RELSTORAGE_PACK_BATCH_TIMEOUT"),
+ "pack-commit-busy-delay": self.env.get(
+ "RELSTORAGE_PACK_COMMIT_BUSY_DELAY",
+ ),
+
+ # Database Caching
+ "cache-prefix": self.env.get("RELSTORAGE_CACHE_PREFIX"),
+
+ # Local Caching
+ "cache-local-mb": self.env.get("RELSTORAGE_CACHE_LOCAL_MB"),
+ "cache-local-object-max": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_OBJECT_MAX",
+ ),
+ "cache-local-compression": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_COMPRESSION",
+ ),
+ "cache-delta-size-limit": self.env.get(
+ "RELSTORAGE_CACHE_DELTA_SIZE_LIMIT",
+ ),
+
+ # Persistent Local Caching
+ "cache-local-dir": self.env.get("RELSTORAGE_CACHE_LOCAL_DIR"),
+
+ # Deprecated Options
+ # ...
+ }
+
+ return "\n ".join(adapter_options + [
+ "{} {}".format(x[0], x[1].strip()) for x in settings.items() if x[1]
+ ])
+
+ def buildout(self):
+ """ Buildout from environment variables
+ """
+ # Already configured
+ if os.path.exists(self.custom_conf):
+ return
+
+ findlinks = self.env.get("FIND_LINKS", "").strip().split()
+
+ eggs = self.env.get("PLONE_ADDONS",
+ self.env.get("ADDONS", "")).strip().split()
+
+ zcml = self.env.get("PLONE_ZCML",
+ self.env.get("ZCML", "")).strip().split()
+
+ develop = self.env.get("PLONE_DEVELOP",
+ self.env.get("DEVELOP", "")).strip().split()
+
+ site = self.env.get("PLONE_SITE",
+ self.env.get("SITE", "")).strip()
+
+ profiles = self.env.get("PLONE_PROFILES",
+ self.env.get("PROFILES", "")).strip().split()
+
+ versions = self.env.get("PLONE_VERSIONS",
+ self.env.get("VERSIONS", "")).strip().split()
+
+ file_logging = self.env.get("FILE_LOGGING")
+
+ sources = self.env.get("SOURCES", "").strip()
+ sources = sources and [x.strip() for x in sources.split(",")]
+
+ relstorage = self.relstorage_conf()
+
+ buildout_extends = ((develop or sources)
+ and ["develop.cfg"] or ["buildout.cfg"])
+ extra_extends = self.env.get("BUILDOUT_EXTENDS", "").strip().split()
+ buildout_extends.extend(extra_extends)
+
+ # If profiles not provided. Install ADDONS :default profiles
+ if not profiles:
+ for egg in eggs:
+ base = egg.split("=")[0]
+ profiles.append("%s:default" % base)
+
+ enabled = bool(site)
+ if not (
+ eggs or zcml or relstorage or develop or enabled or extra_extends or file_logging
+ ):
+ return
+
+ buildout = BUILDOUT_TEMPLATE.format(
+ buildout_extends="\n\t".join(buildout_extends),
+ findlinks="\n\t".join(findlinks),
+ eggs="\n\t".join(eggs),
+ zcml="\n\t".join(zcml),
+ develop="\n\t".join(develop),
+ profiles="\n\t".join(profiles),
+ versions="\n".join(versions),
+ site=site or "Plone",
+ enabled=enabled,
+ )
+
+ # If we need to create a plonesite and we have a zeo setup
+ # configure collective.recipe.plonesite properly
+ server = self.env.get("ZEO_ADDRESS", None)
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+
+ if server:
+ buildout += ZEO_INSTANCE_TEMPLATE.format(zeoaddress=server,
+ shared_blob_dir=shared_blob_dir)
+
+ # Add RelStorage configuration if needed
+ if relstorage:
+ buildout += RELSTORAGE_TEMPLATE.format(relstorage=relstorage)
+
+ # Add file logging configuration if needed
+ if file_logging:
+ buildout += FILE_LOGGING_INSTANCE
+
+ # Add sources configuration if needed
+ if sources:
+ buildout += SOURCES_TEMPLATE.format(sources="\n".join(sources))
+
+ with open(self.custom_conf, 'w') as cfile:
+ cfile.write(buildout)
+
+ def setup(self, **kwargs):
+ self.buildout()
+ self.cors()
+ self.zeoclient()
+ self.zeopack()
+ self.zeoserver()
+
+ __call__ = setup
+
+ZEO_TEMPLATE = """
+
+ read-only {read_only}
+ read-only-fallback {zeo_client_read_only_fallback}
+ blob-dir /data/blobstorage
+ shared-blob-dir {shared_blob_dir}
+ server {zeo_address}
+ storage {zeo_storage}
+ name zeostorage
+ var /plone/instance/parts/instance/var
+ cache-size {zeo_client_cache_size}
+
+""".strip()
+
+CORS_TEMPLATE = """
+
+
+
+
+"""
+
+BUILDOUT_TEMPLATE = """
+[buildout]
+extends = {buildout_extends}
+find-links += {findlinks}
+develop += {develop}
+eggs += {eggs}
+zcml += {zcml}
+
+[plonesite]
+enabled = {enabled}
+site-id = {site}
+profiles += {profiles}
+
+[versions]
+{versions}
+"""
+
+ZEO_INSTANCE_TEMPLATE = """
+
+[instance]
+zeo-client = true
+zeo-address = {zeoaddress}
+shared-blob = {shared_blob_dir}
+http-fast-listen = off
+"""
+
+RELSTORAGE_TEMPLATE = """
+
+[instance]
+rel-storage =
+ {relstorage}
+"""
+
+SOURCES_TEMPLATE = """
+
+[sources]
+{sources}
+"""
+
+FILE_LOGGING_INSTANCE = """
+
+[instance]
+event-log-handler = FileHandler
+event-log-args = ('${buildout:var-dir}/log/instance.log', 'a')
+access-log-handler = FileHandler
+access-log-args = ('${buildout:var-dir}/log/instance-access.log', 'a')
+"""
+
+def initialize():
+ """ Configure Plone instance as ZEO Client
+ """
+ environment = Environment()
+ environment.setup()
+
+if __name__ == "__main__":
+ initialize()
diff --git a/5.2/5.2.14/debian/Dockerfile b/5.2/5.2.14/debian/Dockerfile
new file mode 100644
index 0000000..41f437e
--- /dev/null
+++ b/5.2/5.2.14/debian/Dockerfile
@@ -0,0 +1,50 @@
+FROM python:3.8-slim-bullseye
+
+ENV PIP=22.2.2 \
+ ZC_BUILDOUT=3.0.1 \
+ SETUPTOOLS=65.7.0 \
+ WHEEL=0.38.4 \
+ PLONE_MAJOR=5.2 \
+ PLONE_VERSION=5.2.13 \
+ PLONE_VERSION_RELEASE=Plone-5.2.13-UnifiedInstaller-1.0 \
+ PLONE_MD5=12c037fae9413385149e8677f8457b84
+
+RUN useradd --system -m -d /plone -U -u 500 plone \
+ && mkdir -p /plone/instance/ /data/filestorage /data/blobstorage
+
+COPY buildout.cfg /plone/instance/
+
+RUN buildDeps="default-libmysqlclient-dev dpkg-dev gcc libbz2-dev libc6-dev libffi-dev libjpeg62-turbo-dev libldap2-dev libopenjp2-7-dev libpcre3-dev libpq-dev libsasl2-dev libssl-dev libtiff5-dev libxml2-dev libxslt1-dev wget zlib1g-dev" \
+ && runDeps="default-libmysqlclient-dev git gosu libjpeg62 libopenjp2-7 libpq5 libtiff5 libxml2 libxslt1.1 lynx netcat poppler-utils rsync wv" \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends $buildDeps \
+ && wget -O Plone.tgz https://launchpad.net/plone/$PLONE_MAJOR/$PLONE_VERSION/+download/$PLONE_VERSION_RELEASE.tgz \
+ && echo "$PLONE_MD5 Plone.tgz" | md5sum -c - \
+ && tar -xzf Plone.tgz \
+ && cp -rv ./$PLONE_VERSION_RELEASE/base_skeleton/* /plone/instance/ \
+ && cp -v ./$PLONE_VERSION_RELEASE/buildout_templates/buildout.cfg /plone/instance/buildout-base.cfg \
+ && pip install pip==$PIP setuptools==$SETUPTOOLS zc.buildout==$ZC_BUILDOUT wheel==$WHEEL \
+ && cd /plone/instance \
+ && buildout \
+ && ln -s /data/filestorage/ /plone/instance/var/filestorage \
+ && ln -s /data/blobstorage /plone/instance/var/blobstorage \
+ && find /data -not -user plone -exec chown plone:plone {} \+ \
+ && find /plone -not -user plone -exec chown plone:plone {} \+ \
+ && rm -rf /Plone* \
+ && apt-get purge -y --auto-remove $buildDeps \
+ && apt-get install -y --no-install-recommends $runDeps \
+ && rm -rf /var/lib/apt/lists/* \
+ && rm -rf /plone/buildout-cache/downloads/*
+
+VOLUME /data
+
+COPY docker-initialize.py docker-entrypoint.sh /
+
+EXPOSE 8080
+WORKDIR /plone/instance
+
+HEALTHCHECK --interval=1m --timeout=5s --start-period=1m \
+ CMD nc -z -w5 127.0.0.1 8080 || exit 1
+
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["start"]
diff --git a/5.2/5.2.14/debian/buildout.cfg b/5.2/5.2.14/debian/buildout.cfg
new file mode 100644
index 0000000..02ca654
--- /dev/null
+++ b/5.2/5.2.14/debian/buildout.cfg
@@ -0,0 +1,106 @@
+[buildout]
+extends =
+ buildout-base.cfg
+
+index = https://pypi.org/simple/
+
+extensions =
+effective-user = plone
+buildout-user = plone
+var-dir=/data
+user=admin:admin
+parts +=
+ zeo
+ mrbob
+ plonesite
+
+eggs +=
+ RelStorage[mysql,postgresql,oracle]
+ pas.plugins.ldap
+
+[client1]
+recipe =
+
+[instance_base]
+resources = ${buildout:directory}/resources
+
+[zeo]
+<= zeoserver_base
+recipe = plone.recipe.zeoserver
+zeo-address = 8080
+
+[instance]
+zcml-additional =
+
+
+
+event-log-handler = StreamHandler
+event-log-args = (sys.stderr,)
+access-log-handler = StreamHandler
+access-log-args = (sys.stdout,)
+
+# Requires gcc, thus install it on image build
+[mrbob]
+recipe = zc.recipe.egg
+eggs =
+ mr.bob
+ bobtemplates.plone
+
+[plonesite]
+recipe = collective.recipe.plonesite
+instance = instance
+site-id = Plone
+profiles-initial = Products.CMFPlone:dependencies
+profiles =
+ plonetheme.barceloneta:default
+ plone.app.caching:default
+ plone.app.contenttypes:plone-content
+ plone.restapi:default
+upgrade-portal = False
+upgrade-all-profiles = False
+enabled = False
+
+[versions]
+setuptools =
+zc.buildout =
+
+plone.restapi = 8.43.1
+plone.rest = 3.0.0
+
+RelStorage = 3.4.5
+argparse = 1.4.0
+bda.cache = 1.3.0
+bobtemplates.plone = 5.2.2
+case-conversion = 2.1.0
+collective.checkdocs = 0.2
+collective.recipe.plonesite = 1.12.0
+cx-Oracle = 8.3.0
+isort = 5.11.5
+mr.bob = 1.0.0
+mysqlclient = 2.1.1
+node = 1.2.1
+node.ext.ldap = 1.2
+node.ext.ugm = 1.1
+odict = 1.9.0
+pas.plugins.ldap = 1.8.2
+passlib = 1.7.4
+perfmetrics = 3.3.0
+plumber = 1.7
+psycopg2 = 2.9.3
+pyasn1 = 0.5.0
+pyasn1-modules = 0.3.0
+python-ldap = 3.4.2
+python-memcached = 1.59
+regex = 2023.6.3
+yafowil = 3.1.0
+yafowil.plone = 4.0.0a5
+yafowil.widget.array = 1.7
+yafowil.widget.dict = 1.8
+yafowil.yaml = 2.0
diff --git a/5.2/5.2.14/debian/docker-entrypoint.sh b/5.2/5.2.14/debian/docker-entrypoint.sh
new file mode 100755
index 0000000..ecf7f76
--- /dev/null
+++ b/5.2/5.2.14/debian/docker-entrypoint.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e
+
+COMMANDS="adduser debug fg foreground help kill logreopen logtail reopen_transcript run show status stop wait"
+START="console start restart"
+
+# Fixing permissions for external /data volumes
+mkdir -p /data/blobstorage /data/cache /data/filestorage /data/instance /data/log /data/zeoserver
+mkdir -p /plone/instance/src
+find /data -not -user plone -exec chown plone:plone {} \+
+find /plone -not -user plone -exec chown plone:plone {} \+
+
+# Initializing from environment variables
+gosu plone python /docker-initialize.py
+
+if [ -e "custom.cfg" ]; then
+ if [ ! -e "bin/develop" ]; then
+ buildout -c custom.cfg
+ find /data -not -user plone -exec chown plone:plone {} \+
+ find /plone -not -user plone -exec chown plone:plone {} \+
+ gosu plone python /docker-initialize.py
+ fi
+fi
+
+# ZEO Server
+if [[ "$1" == "zeo"* ]]; then
+ exec gosu plone bin/$1 fg
+fi
+
+# Plone instance start
+if [[ $START == *"$1"* ]]; then
+ exec gosu plone bin/instance console
+fi
+
+# Plone instance helpers
+if [[ $COMMANDS == *"$1"* ]]; then
+ exec gosu plone bin/instance "$@"
+fi
+
+# Custom
+exec "$@"
diff --git a/5.2/5.2.14/debian/docker-initialize.py b/5.2/5.2.14/debian/docker-initialize.py
new file mode 100755
index 0000000..cfbf6d2
--- /dev/null
+++ b/5.2/5.2.14/debian/docker-initialize.py
@@ -0,0 +1,382 @@
+#!/usr/local/bin/python
+
+import re
+import os
+
+class Environment(object):
+ """ Configure container via environment variables
+ """
+ def __init__(self, env=os.environ,
+ zope_conf="/plone/instance/parts/instance/etc/zope.conf",
+ custom_conf="/plone/instance/custom.cfg",
+ zeopack_conf="/plone/instance/bin/zeopack",
+ zeoserver_conf="/plone/instance/parts/zeoserver/etc/zeo.conf",
+ cors_conf="/plone/instance/parts/instance/etc/package-includes/999-additional-overrides.zcml"
+ ):
+ self.env = env
+ self.zope_conf = zope_conf
+ self.custom_conf = custom_conf
+ self.zeopack_conf = zeopack_conf
+ self.zeoserver_conf = zeoserver_conf
+ self.cors_conf = cors_conf
+
+ def zeoclient(self):
+ """ ZEO Client
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ config = ""
+ with open(self.zope_conf, "r") as cfile:
+ config = cfile.read()
+
+ # Already initialized
+ if "" not in config:
+ return
+
+ read_only = self.env.get("ZEO_READ_ONLY", "false")
+ zeo_ro_fallback = self.env.get("ZEO_CLIENT_READ_ONLY_FALLBACK", "false")
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+ zeo_storage=self.env.get("ZEO_STORAGE", "1")
+ zeo_client_cache_size=self.env.get("ZEO_CLIENT_CACHE_SIZE", "128MB")
+ zeo_conf = ZEO_TEMPLATE.format(
+ zeo_address=server,
+ read_only=read_only,
+ zeo_client_read_only_fallback=zeo_ro_fallback,
+ shared_blob_dir=shared_blob_dir,
+ zeo_storage=zeo_storage,
+ zeo_client_cache_size=zeo_client_cache_size
+ )
+
+ pattern = re.compile(r".+", re.DOTALL)
+ config = re.sub(pattern, zeo_conf, config)
+
+ with open(self.zope_conf, "w") as cfile:
+ cfile.write(config)
+
+ def zeopack(self):
+ """ ZEO Pack
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ if ":" in server:
+ host, port = server.split(":")
+ else:
+ host, port = (server, "8100")
+
+ with open(self.zeopack_conf, 'r') as cfile:
+ text = cfile.read()
+ text = text.replace('address = "8100"', 'address = "%s"' % server)
+ text = text.replace('host = "127.0.0.1"', 'host = "%s"' % host)
+ text = text.replace('port = "8100"', 'port = "%s"' % port)
+
+ with open(self.zeopack_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def zeoserver(self):
+ """ ZEO Server
+ """
+ pack_keep_old = self.env.get("ZEO_PACK_KEEP_OLD", '')
+ if pack_keep_old.lower() in ("false", "no", "0", "n", "f"):
+ with open(self.zeoserver_conf, 'r') as cfile:
+ text = cfile.read()
+ if 'pack-keep-old' not in text:
+ text = text.replace(
+ '',
+ ' pack-keep-old false\n'
+ )
+
+ with open(self.zeoserver_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def cors(self):
+ """ Configure CORS Policies
+ """
+ if not [e for e in self.env if e.startswith("CORS_")]:
+ return
+
+ allow_origin = self.env.get("CORS_ALLOW_ORIGIN",
+ "http://localhost:3000,http://127.0.0.1:3000")
+ allow_methods = self.env.get("CORS_ALLOW_METHODS",
+ "DELETE,GET,OPTIONS,PATCH,POST,PUT")
+ allow_credentials = self.env.get("CORS_ALLOW_CREDENTIALS", "true")
+ expose_headers = self.env.get("CORS_EXPOSE_HEADERS",
+ "Content-Length,X-My-Header")
+ allow_headers = self.env.get("CORS_ALLOW_HEADERS",
+ "Accept,Authorization,Content-Type,X-Custom-Header,Lock-Token")
+ max_age = self.env.get("CORS_MAX_AGE", "3600")
+ cors_conf = CORS_TEMPLATE.format(
+ allow_origin=allow_origin,
+ allow_methods=allow_methods,
+ allow_credentials=allow_credentials,
+ expose_headers=expose_headers,
+ allow_headers=allow_headers,
+ max_age=max_age
+ )
+ with open(self.cors_conf, "w") as cfile:
+ cfile.write(cors_conf)
+
+ def relstorage_conf(self):
+ """ RelStorage configuration from environment variables
+ """
+ if not [e for e in self.env if e.startswith("RELSTORAGE_")]:
+ return ""
+
+ # Database specific adapter options
+ # https://relstorage.readthedocs.io/en/latest/supported-databases.html
+ adapter_options = self.env.get(
+ "RELSTORAGE_ADAPTER_OPTIONS",
+ "",
+ ).strip().split(",")
+
+ settings = {
+ # General Settings
+ "name": self.env.get("RELSTORAGE_NAME"),
+ "read-only": self.env.get("RELSTORAGE_READ_ONLY"),
+ "keep-history": self.env.get("RELSTORAGE_KEEP_HISTORY"),
+ "commit-lock-timeout": self.env.get(
+ "RELSTORAGE_COMMIT_LOCK_TIMEOUT",
+ ),
+ "commit-lock-id": self.env.get("RELSTORAGE_COMMIT_LOCK_ID"),
+ "create-schema": self.env.get("RELSTORAGE_CREATE_SCHEMA"),
+
+ # Blobs
+ "blob-dir": self.env.get("RELSTORAGE_BLOB_DIR",
+ "/plone/instance/var/blobstorage"),
+ "shared-blob-dir": self.env.get("RELSTORAGE_SHARED_BLOB_DIR"),
+ "blob-cache-size": self.env.get("RELSTORAGE_BLOB_CACHE_SIZE"),
+ "blob-cache-size-check": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK",
+ ),
+ "blob-cache-size-check-external": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK_EXTERNAL",
+ ),
+ "blob-chunk-size": self.env.get("RELSTORAGE_BLOB_CHUNK_SIZE"),
+
+ # Replication
+ "replica-conf": self.env.get("RELSTORAGE_REPLICA_CONF"),
+ "ro-replica-conf": self.env.get("RELSTORAGE_RO_REPLICA_CONF"),
+ "replica-timeout": self.env.get("RELSTORAGE_REPLICA_TIMEOUT"),
+ "revert-when-stale": self.env.get("RELSTORAGE_REVERT_WHEN_STALE"),
+
+ # GC and Packing
+ "pack-gc": self.env.get("RELSTORAGE_PACK_GC"),
+ "pack-prepack-only": self.env.get("RELSTORAGE_PACK_PREPACK_ONLY"),
+ "pack-skip-prepack": self.env.get("RELSTORAGE_PACK_SKIP_PREPACK"),
+ "pack-batch-timeout": self.env.get("RELSTORAGE_PACK_BATCH_TIMEOUT"),
+ "pack-commit-busy-delay": self.env.get(
+ "RELSTORAGE_PACK_COMMIT_BUSY_DELAY",
+ ),
+
+ # Database Caching
+ "cache-prefix": self.env.get("RELSTORAGE_CACHE_PREFIX"),
+
+ # Local Caching
+ "cache-local-mb": self.env.get("RELSTORAGE_CACHE_LOCAL_MB"),
+ "cache-local-object-max": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_OBJECT_MAX",
+ ),
+ "cache-local-compression": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_COMPRESSION",
+ ),
+ "cache-delta-size-limit": self.env.get(
+ "RELSTORAGE_CACHE_DELTA_SIZE_LIMIT",
+ ),
+
+ # Persistent Local Caching
+ "cache-local-dir": self.env.get("RELSTORAGE_CACHE_LOCAL_DIR"),
+
+ # Deprecated Options
+ # ...
+ }
+
+ return "\n ".join(adapter_options + [
+ "{} {}".format(x[0], x[1].strip()) for x in settings.items() if x[1]
+ ])
+
+ def buildout(self):
+ """ Buildout from environment variables
+ """
+ # Already configured
+ if os.path.exists(self.custom_conf):
+ return
+
+ findlinks = self.env.get("FIND_LINKS", "").strip().split()
+
+ eggs = self.env.get("PLONE_ADDONS",
+ self.env.get("ADDONS", "")).strip().split()
+
+ zcml = self.env.get("PLONE_ZCML",
+ self.env.get("ZCML", "")).strip().split()
+
+ develop = self.env.get("PLONE_DEVELOP",
+ self.env.get("DEVELOP", "")).strip().split()
+
+ site = self.env.get("PLONE_SITE",
+ self.env.get("SITE", "")).strip()
+
+ profiles = self.env.get("PLONE_PROFILES",
+ self.env.get("PROFILES", "")).strip().split()
+
+ versions = self.env.get("PLONE_VERSIONS",
+ self.env.get("VERSIONS", "")).strip().split()
+
+ file_logging = self.env.get("FILE_LOGGING")
+
+ sources = self.env.get("SOURCES", "").strip()
+ sources = sources and [x.strip() for x in sources.split(",")]
+
+ relstorage = self.relstorage_conf()
+
+ buildout_extends = ((develop or sources)
+ and ["develop.cfg"] or ["buildout.cfg"])
+ extra_extends = self.env.get("BUILDOUT_EXTENDS", "").strip().split()
+ buildout_extends.extend(extra_extends)
+
+ # If profiles not provided. Install ADDONS :default profiles
+ if not profiles:
+ for egg in eggs:
+ base = egg.split("=")[0]
+ profiles.append("%s:default" % base)
+
+ enabled = bool(site)
+ if not (
+ eggs or zcml or relstorage or develop or enabled or extra_extends or file_logging
+ ):
+ return
+
+ buildout = BUILDOUT_TEMPLATE.format(
+ buildout_extends="\n\t".join(buildout_extends),
+ findlinks="\n\t".join(findlinks),
+ eggs="\n\t".join(eggs),
+ zcml="\n\t".join(zcml),
+ develop="\n\t".join(develop),
+ profiles="\n\t".join(profiles),
+ versions="\n".join(versions),
+ site=site or "Plone",
+ enabled=enabled,
+ )
+
+ # If we need to create a plonesite and we have a zeo setup
+ # configure collective.recipe.plonesite properly
+ server = self.env.get("ZEO_ADDRESS", None)
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+
+ if server:
+ buildout += ZEO_INSTANCE_TEMPLATE.format(zeoaddress=server,
+ shared_blob_dir=shared_blob_dir)
+
+ # Add RelStorage configuration if needed
+ if relstorage:
+ buildout += RELSTORAGE_TEMPLATE.format(relstorage=relstorage)
+
+ # Add file logging configuration if needed
+ if file_logging:
+ buildout += FILE_LOGGING_INSTANCE
+
+ # Add sources configuration if needed
+ if sources:
+ buildout += SOURCES_TEMPLATE.format(sources="\n".join(sources))
+
+ with open(self.custom_conf, 'w') as cfile:
+ cfile.write(buildout)
+
+ def setup(self, **kwargs):
+ self.buildout()
+ self.cors()
+ self.zeoclient()
+ self.zeopack()
+ self.zeoserver()
+
+ __call__ = setup
+
+ZEO_TEMPLATE = """
+
+ read-only {read_only}
+ read-only-fallback {zeo_client_read_only_fallback}
+ blob-dir /data/blobstorage
+ shared-blob-dir {shared_blob_dir}
+ server {zeo_address}
+ storage {zeo_storage}
+ name zeostorage
+ var /plone/instance/parts/instance/var
+ cache-size {zeo_client_cache_size}
+
+""".strip()
+
+CORS_TEMPLATE = """
+
+
+
+
+"""
+
+BUILDOUT_TEMPLATE = """
+[buildout]
+extends = {buildout_extends}
+find-links += {findlinks}
+develop += {develop}
+eggs += {eggs}
+zcml += {zcml}
+
+[plonesite]
+enabled = {enabled}
+site-id = {site}
+profiles += {profiles}
+
+[versions]
+{versions}
+"""
+
+ZEO_INSTANCE_TEMPLATE = """
+
+[instance]
+zeo-client = true
+zeo-address = {zeoaddress}
+shared-blob = {shared_blob_dir}
+http-fast-listen = off
+"""
+
+RELSTORAGE_TEMPLATE = """
+
+[instance]
+rel-storage =
+ {relstorage}
+"""
+
+SOURCES_TEMPLATE = """
+
+[sources]
+{sources}
+"""
+
+FILE_LOGGING_INSTANCE = """
+
+[instance]
+event-log-handler = FileHandler
+event-log-args = ('${buildout:var-dir}/log/instance.log', 'a')
+access-log-handler = FileHandler
+access-log-args = ('${buildout:var-dir}/log/instance-access.log', 'a')
+"""
+
+def initialize():
+ """ Configure Plone instance as ZEO Client
+ """
+ environment = Environment()
+ environment.setup()
+
+if __name__ == "__main__":
+ initialize()
diff --git a/5.2/5.2.14/python2/Dockerfile b/5.2/5.2.14/python2/Dockerfile
new file mode 100644
index 0000000..0f87b18
--- /dev/null
+++ b/5.2/5.2.14/python2/Dockerfile
@@ -0,0 +1,50 @@
+FROM python:2.7-slim-buster
+
+ENV PIP=20.3.4 \
+ ZC_BUILDOUT=2.13.8 \
+ SETUPTOOLS=44.1.1 \
+ WHEEL=0.37.1 \
+ PLONE_MAJOR=5.2 \
+ PLONE_VERSION=5.2.13 \
+ PLONE_VERSION_RELEASE=Plone-5.2.13-UnifiedInstaller-1.0 \
+ PLONE_MD5=12c037fae9413385149e8677f8457b84
+
+RUN useradd --system -m -d /plone -U -u 500 plone \
+ && mkdir -p /plone/instance/ /data/filestorage /data/blobstorage
+
+COPY buildout.cfg /plone/instance/
+
+RUN buildDeps="default-libmysqlclient-dev dpkg-dev gcc libbz2-dev libc6-dev libffi-dev libjpeg62-turbo-dev libldap2-dev libopenjp2-7-dev libpcre3-dev libpq-dev libsasl2-dev libssl-dev libtiff5-dev libxml2-dev libxslt1-dev wget zlib1g-dev" \
+ && runDeps="default-libmysqlclient-dev git gosu libjpeg62 libopenjp2-7 libpq5 libtiff5 libxml2 libxslt1.1 lynx netcat poppler-utils rsync wv" \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends $buildDeps \
+ && wget -O Plone.tgz https://launchpad.net/plone/$PLONE_MAJOR/$PLONE_VERSION/+download/$PLONE_VERSION_RELEASE.tgz \
+ && echo "$PLONE_MD5 Plone.tgz" | md5sum -c - \
+ && tar -xzf Plone.tgz \
+ && cp -rv ./$PLONE_VERSION_RELEASE/base_skeleton/* /plone/instance/ \
+ && cp -v ./$PLONE_VERSION_RELEASE/buildout_templates/buildout.cfg /plone/instance/buildout-base.cfg \
+ && pip install pip==$PIP setuptools==$SETUPTOOLS zc.buildout==$ZC_BUILDOUT wheel==$WHEEL \
+ && cd /plone/instance \
+ && buildout \
+ && ln -s /data/filestorage/ /plone/instance/var/filestorage \
+ && ln -s /data/blobstorage /plone/instance/var/blobstorage \
+ && find /data -not -user plone -exec chown plone:plone {} \+ \
+ && find /plone -not -user plone -exec chown plone:plone {} \+ \
+ && rm -rf /Plone* \
+ && apt-get purge -y --auto-remove $buildDeps \
+ && apt-get install -y --no-install-recommends $runDeps \
+ && rm -rf /var/lib/apt/lists/* \
+ && rm -rf /plone/buildout-cache/downloads/*
+
+VOLUME /data
+
+COPY docker-initialize.py docker-entrypoint.sh /
+
+EXPOSE 8080
+WORKDIR /plone/instance
+
+HEALTHCHECK --interval=1m --timeout=5s --start-period=1m \
+ CMD nc -z -w5 127.0.0.1 8080 || exit 1
+
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["start"]
diff --git a/5.2/5.2.14/python2/buildout.cfg b/5.2/5.2.14/python2/buildout.cfg
new file mode 100644
index 0000000..6f0312d
--- /dev/null
+++ b/5.2/5.2.14/python2/buildout.cfg
@@ -0,0 +1,104 @@
+[buildout]
+extends =
+ buildout-base.cfg
+
+extensions =
+effective-user = plone
+buildout-user = plone
+var-dir=/data
+user=admin:admin
+parts +=
+ zeo
+ mrbob
+ plonesite
+
+eggs +=
+ RelStorage[mysql,postgresql,oracle]
+ pas.plugins.ldap
+
+[client1]
+recipe =
+
+[instance_base]
+resources = ${buildout:directory}/resources
+
+[zeo]
+<= zeoserver_base
+recipe = plone.recipe.zeoserver
+zeo-address = 8080
+
+[instance]
+zcml-additional =
+
+
+
+event-log-handler = StreamHandler
+event-log-args = (sys.stderr,)
+access-log-handler = StreamHandler
+access-log-args = (sys.stdout,)
+
+# Requires gcc, thus install it on image build
+[mrbob]
+recipe = zc.recipe.egg
+eggs =
+ mr.bob
+ bobtemplates.plone
+
+[plonesite]
+recipe = collective.recipe.plonesite
+instance = instance
+site-id = Plone
+profiles-initial = Products.CMFPlone:dependencies
+profiles =
+ plonetheme.barceloneta:default
+ plone.app.caching:default
+ plone.app.contenttypes:plone-content
+ plone.restapi:default
+upgrade-portal = False
+upgrade-all-profiles = False
+enabled = False
+
+[versions]
+setuptools =
+zc.buildout =
+
+plone.restapi = 7.8.2
+
+RelStorage = 3.4.0
+argparse = 1.4.0
+bda.cache = 1.3.0
+bobtemplates.plone = 5.2.0
+case-conversion = 2.1.0
+collective.checkdocs = 0.2
+collective.recipe.plonesite = 1.12.0
+cx-Oracle = 7.3.0
+importlib-resources = 3.3.1
+isort = 5.7.0
+mr.bob = 0.1.2
+mysqlclient = 1.4.6
+node = 1.2.1
+node.ext.ldap = 1.2
+node.ext.ugm = 1.1
+odict = 1.9.0
+pas.plugins.ldap = 1.8.2
+passlib = 1.7.4
+perfmetrics = 3.3.0
+plumber = 1.6
+psycopg2 = 2.8.6
+pyasn1 = 0.5.0
+pyasn1-modules = 0.3.0
+python-ldap = 3.3.1
+python-memcached = 1.59
+regex = 2020.7.14
+yafowil = 2.3.3
+yafowil.plone = 4.0.0a5
+yafowil.widget.array = 1.7
+yafowil.widget.dict = 1.8
+yafowil.yaml = 1.3.1
diff --git a/5.2/5.2.14/python2/docker-entrypoint.sh b/5.2/5.2.14/python2/docker-entrypoint.sh
new file mode 100755
index 0000000..ecf7f76
--- /dev/null
+++ b/5.2/5.2.14/python2/docker-entrypoint.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e
+
+COMMANDS="adduser debug fg foreground help kill logreopen logtail reopen_transcript run show status stop wait"
+START="console start restart"
+
+# Fixing permissions for external /data volumes
+mkdir -p /data/blobstorage /data/cache /data/filestorage /data/instance /data/log /data/zeoserver
+mkdir -p /plone/instance/src
+find /data -not -user plone -exec chown plone:plone {} \+
+find /plone -not -user plone -exec chown plone:plone {} \+
+
+# Initializing from environment variables
+gosu plone python /docker-initialize.py
+
+if [ -e "custom.cfg" ]; then
+ if [ ! -e "bin/develop" ]; then
+ buildout -c custom.cfg
+ find /data -not -user plone -exec chown plone:plone {} \+
+ find /plone -not -user plone -exec chown plone:plone {} \+
+ gosu plone python /docker-initialize.py
+ fi
+fi
+
+# ZEO Server
+if [[ "$1" == "zeo"* ]]; then
+ exec gosu plone bin/$1 fg
+fi
+
+# Plone instance start
+if [[ $START == *"$1"* ]]; then
+ exec gosu plone bin/instance console
+fi
+
+# Plone instance helpers
+if [[ $COMMANDS == *"$1"* ]]; then
+ exec gosu plone bin/instance "$@"
+fi
+
+# Custom
+exec "$@"
diff --git a/5.2/5.2.14/python2/docker-initialize.py b/5.2/5.2.14/python2/docker-initialize.py
new file mode 100755
index 0000000..cfbf6d2
--- /dev/null
+++ b/5.2/5.2.14/python2/docker-initialize.py
@@ -0,0 +1,382 @@
+#!/usr/local/bin/python
+
+import re
+import os
+
+class Environment(object):
+ """ Configure container via environment variables
+ """
+ def __init__(self, env=os.environ,
+ zope_conf="/plone/instance/parts/instance/etc/zope.conf",
+ custom_conf="/plone/instance/custom.cfg",
+ zeopack_conf="/plone/instance/bin/zeopack",
+ zeoserver_conf="/plone/instance/parts/zeoserver/etc/zeo.conf",
+ cors_conf="/plone/instance/parts/instance/etc/package-includes/999-additional-overrides.zcml"
+ ):
+ self.env = env
+ self.zope_conf = zope_conf
+ self.custom_conf = custom_conf
+ self.zeopack_conf = zeopack_conf
+ self.zeoserver_conf = zeoserver_conf
+ self.cors_conf = cors_conf
+
+ def zeoclient(self):
+ """ ZEO Client
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ config = ""
+ with open(self.zope_conf, "r") as cfile:
+ config = cfile.read()
+
+ # Already initialized
+ if "" not in config:
+ return
+
+ read_only = self.env.get("ZEO_READ_ONLY", "false")
+ zeo_ro_fallback = self.env.get("ZEO_CLIENT_READ_ONLY_FALLBACK", "false")
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+ zeo_storage=self.env.get("ZEO_STORAGE", "1")
+ zeo_client_cache_size=self.env.get("ZEO_CLIENT_CACHE_SIZE", "128MB")
+ zeo_conf = ZEO_TEMPLATE.format(
+ zeo_address=server,
+ read_only=read_only,
+ zeo_client_read_only_fallback=zeo_ro_fallback,
+ shared_blob_dir=shared_blob_dir,
+ zeo_storage=zeo_storage,
+ zeo_client_cache_size=zeo_client_cache_size
+ )
+
+ pattern = re.compile(r".+", re.DOTALL)
+ config = re.sub(pattern, zeo_conf, config)
+
+ with open(self.zope_conf, "w") as cfile:
+ cfile.write(config)
+
+ def zeopack(self):
+ """ ZEO Pack
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ if ":" in server:
+ host, port = server.split(":")
+ else:
+ host, port = (server, "8100")
+
+ with open(self.zeopack_conf, 'r') as cfile:
+ text = cfile.read()
+ text = text.replace('address = "8100"', 'address = "%s"' % server)
+ text = text.replace('host = "127.0.0.1"', 'host = "%s"' % host)
+ text = text.replace('port = "8100"', 'port = "%s"' % port)
+
+ with open(self.zeopack_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def zeoserver(self):
+ """ ZEO Server
+ """
+ pack_keep_old = self.env.get("ZEO_PACK_KEEP_OLD", '')
+ if pack_keep_old.lower() in ("false", "no", "0", "n", "f"):
+ with open(self.zeoserver_conf, 'r') as cfile:
+ text = cfile.read()
+ if 'pack-keep-old' not in text:
+ text = text.replace(
+ '',
+ ' pack-keep-old false\n'
+ )
+
+ with open(self.zeoserver_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def cors(self):
+ """ Configure CORS Policies
+ """
+ if not [e for e in self.env if e.startswith("CORS_")]:
+ return
+
+ allow_origin = self.env.get("CORS_ALLOW_ORIGIN",
+ "http://localhost:3000,http://127.0.0.1:3000")
+ allow_methods = self.env.get("CORS_ALLOW_METHODS",
+ "DELETE,GET,OPTIONS,PATCH,POST,PUT")
+ allow_credentials = self.env.get("CORS_ALLOW_CREDENTIALS", "true")
+ expose_headers = self.env.get("CORS_EXPOSE_HEADERS",
+ "Content-Length,X-My-Header")
+ allow_headers = self.env.get("CORS_ALLOW_HEADERS",
+ "Accept,Authorization,Content-Type,X-Custom-Header,Lock-Token")
+ max_age = self.env.get("CORS_MAX_AGE", "3600")
+ cors_conf = CORS_TEMPLATE.format(
+ allow_origin=allow_origin,
+ allow_methods=allow_methods,
+ allow_credentials=allow_credentials,
+ expose_headers=expose_headers,
+ allow_headers=allow_headers,
+ max_age=max_age
+ )
+ with open(self.cors_conf, "w") as cfile:
+ cfile.write(cors_conf)
+
+ def relstorage_conf(self):
+ """ RelStorage configuration from environment variables
+ """
+ if not [e for e in self.env if e.startswith("RELSTORAGE_")]:
+ return ""
+
+ # Database specific adapter options
+ # https://relstorage.readthedocs.io/en/latest/supported-databases.html
+ adapter_options = self.env.get(
+ "RELSTORAGE_ADAPTER_OPTIONS",
+ "",
+ ).strip().split(",")
+
+ settings = {
+ # General Settings
+ "name": self.env.get("RELSTORAGE_NAME"),
+ "read-only": self.env.get("RELSTORAGE_READ_ONLY"),
+ "keep-history": self.env.get("RELSTORAGE_KEEP_HISTORY"),
+ "commit-lock-timeout": self.env.get(
+ "RELSTORAGE_COMMIT_LOCK_TIMEOUT",
+ ),
+ "commit-lock-id": self.env.get("RELSTORAGE_COMMIT_LOCK_ID"),
+ "create-schema": self.env.get("RELSTORAGE_CREATE_SCHEMA"),
+
+ # Blobs
+ "blob-dir": self.env.get("RELSTORAGE_BLOB_DIR",
+ "/plone/instance/var/blobstorage"),
+ "shared-blob-dir": self.env.get("RELSTORAGE_SHARED_BLOB_DIR"),
+ "blob-cache-size": self.env.get("RELSTORAGE_BLOB_CACHE_SIZE"),
+ "blob-cache-size-check": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK",
+ ),
+ "blob-cache-size-check-external": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK_EXTERNAL",
+ ),
+ "blob-chunk-size": self.env.get("RELSTORAGE_BLOB_CHUNK_SIZE"),
+
+ # Replication
+ "replica-conf": self.env.get("RELSTORAGE_REPLICA_CONF"),
+ "ro-replica-conf": self.env.get("RELSTORAGE_RO_REPLICA_CONF"),
+ "replica-timeout": self.env.get("RELSTORAGE_REPLICA_TIMEOUT"),
+ "revert-when-stale": self.env.get("RELSTORAGE_REVERT_WHEN_STALE"),
+
+ # GC and Packing
+ "pack-gc": self.env.get("RELSTORAGE_PACK_GC"),
+ "pack-prepack-only": self.env.get("RELSTORAGE_PACK_PREPACK_ONLY"),
+ "pack-skip-prepack": self.env.get("RELSTORAGE_PACK_SKIP_PREPACK"),
+ "pack-batch-timeout": self.env.get("RELSTORAGE_PACK_BATCH_TIMEOUT"),
+ "pack-commit-busy-delay": self.env.get(
+ "RELSTORAGE_PACK_COMMIT_BUSY_DELAY",
+ ),
+
+ # Database Caching
+ "cache-prefix": self.env.get("RELSTORAGE_CACHE_PREFIX"),
+
+ # Local Caching
+ "cache-local-mb": self.env.get("RELSTORAGE_CACHE_LOCAL_MB"),
+ "cache-local-object-max": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_OBJECT_MAX",
+ ),
+ "cache-local-compression": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_COMPRESSION",
+ ),
+ "cache-delta-size-limit": self.env.get(
+ "RELSTORAGE_CACHE_DELTA_SIZE_LIMIT",
+ ),
+
+ # Persistent Local Caching
+ "cache-local-dir": self.env.get("RELSTORAGE_CACHE_LOCAL_DIR"),
+
+ # Deprecated Options
+ # ...
+ }
+
+ return "\n ".join(adapter_options + [
+ "{} {}".format(x[0], x[1].strip()) for x in settings.items() if x[1]
+ ])
+
+ def buildout(self):
+ """ Buildout from environment variables
+ """
+ # Already configured
+ if os.path.exists(self.custom_conf):
+ return
+
+ findlinks = self.env.get("FIND_LINKS", "").strip().split()
+
+ eggs = self.env.get("PLONE_ADDONS",
+ self.env.get("ADDONS", "")).strip().split()
+
+ zcml = self.env.get("PLONE_ZCML",
+ self.env.get("ZCML", "")).strip().split()
+
+ develop = self.env.get("PLONE_DEVELOP",
+ self.env.get("DEVELOP", "")).strip().split()
+
+ site = self.env.get("PLONE_SITE",
+ self.env.get("SITE", "")).strip()
+
+ profiles = self.env.get("PLONE_PROFILES",
+ self.env.get("PROFILES", "")).strip().split()
+
+ versions = self.env.get("PLONE_VERSIONS",
+ self.env.get("VERSIONS", "")).strip().split()
+
+ file_logging = self.env.get("FILE_LOGGING")
+
+ sources = self.env.get("SOURCES", "").strip()
+ sources = sources and [x.strip() for x in sources.split(",")]
+
+ relstorage = self.relstorage_conf()
+
+ buildout_extends = ((develop or sources)
+ and ["develop.cfg"] or ["buildout.cfg"])
+ extra_extends = self.env.get("BUILDOUT_EXTENDS", "").strip().split()
+ buildout_extends.extend(extra_extends)
+
+ # If profiles not provided. Install ADDONS :default profiles
+ if not profiles:
+ for egg in eggs:
+ base = egg.split("=")[0]
+ profiles.append("%s:default" % base)
+
+ enabled = bool(site)
+ if not (
+ eggs or zcml or relstorage or develop or enabled or extra_extends or file_logging
+ ):
+ return
+
+ buildout = BUILDOUT_TEMPLATE.format(
+ buildout_extends="\n\t".join(buildout_extends),
+ findlinks="\n\t".join(findlinks),
+ eggs="\n\t".join(eggs),
+ zcml="\n\t".join(zcml),
+ develop="\n\t".join(develop),
+ profiles="\n\t".join(profiles),
+ versions="\n".join(versions),
+ site=site or "Plone",
+ enabled=enabled,
+ )
+
+ # If we need to create a plonesite and we have a zeo setup
+ # configure collective.recipe.plonesite properly
+ server = self.env.get("ZEO_ADDRESS", None)
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+
+ if server:
+ buildout += ZEO_INSTANCE_TEMPLATE.format(zeoaddress=server,
+ shared_blob_dir=shared_blob_dir)
+
+ # Add RelStorage configuration if needed
+ if relstorage:
+ buildout += RELSTORAGE_TEMPLATE.format(relstorage=relstorage)
+
+ # Add file logging configuration if needed
+ if file_logging:
+ buildout += FILE_LOGGING_INSTANCE
+
+ # Add sources configuration if needed
+ if sources:
+ buildout += SOURCES_TEMPLATE.format(sources="\n".join(sources))
+
+ with open(self.custom_conf, 'w') as cfile:
+ cfile.write(buildout)
+
+ def setup(self, **kwargs):
+ self.buildout()
+ self.cors()
+ self.zeoclient()
+ self.zeopack()
+ self.zeoserver()
+
+ __call__ = setup
+
+ZEO_TEMPLATE = """
+
+ read-only {read_only}
+ read-only-fallback {zeo_client_read_only_fallback}
+ blob-dir /data/blobstorage
+ shared-blob-dir {shared_blob_dir}
+ server {zeo_address}
+ storage {zeo_storage}
+ name zeostorage
+ var /plone/instance/parts/instance/var
+ cache-size {zeo_client_cache_size}
+
+""".strip()
+
+CORS_TEMPLATE = """
+
+
+
+
+"""
+
+BUILDOUT_TEMPLATE = """
+[buildout]
+extends = {buildout_extends}
+find-links += {findlinks}
+develop += {develop}
+eggs += {eggs}
+zcml += {zcml}
+
+[plonesite]
+enabled = {enabled}
+site-id = {site}
+profiles += {profiles}
+
+[versions]
+{versions}
+"""
+
+ZEO_INSTANCE_TEMPLATE = """
+
+[instance]
+zeo-client = true
+zeo-address = {zeoaddress}
+shared-blob = {shared_blob_dir}
+http-fast-listen = off
+"""
+
+RELSTORAGE_TEMPLATE = """
+
+[instance]
+rel-storage =
+ {relstorage}
+"""
+
+SOURCES_TEMPLATE = """
+
+[sources]
+{sources}
+"""
+
+FILE_LOGGING_INSTANCE = """
+
+[instance]
+event-log-handler = FileHandler
+event-log-args = ('${buildout:var-dir}/log/instance.log', 'a')
+access-log-handler = FileHandler
+access-log-args = ('${buildout:var-dir}/log/instance-access.log', 'a')
+"""
+
+def initialize():
+ """ Configure Plone instance as ZEO Client
+ """
+ environment = Environment()
+ environment.setup()
+
+if __name__ == "__main__":
+ initialize()
diff --git a/5.2/5.2.14/python37/Dockerfile b/5.2/5.2.14/python37/Dockerfile
new file mode 100644
index 0000000..eebe0f9
--- /dev/null
+++ b/5.2/5.2.14/python37/Dockerfile
@@ -0,0 +1,50 @@
+FROM python:3.7-slim-buster
+
+ENV PIP=22.2.2 \
+ ZC_BUILDOUT=3.0.1 \
+ SETUPTOOLS=65.7.0 \
+ WHEEL=0.38.4 \
+ PLONE_MAJOR=5.2 \
+ PLONE_VERSION=5.2.13 \
+ PLONE_VERSION_RELEASE=Plone-5.2.13-UnifiedInstaller-1.0 \
+ PLONE_MD5=12c037fae9413385149e8677f8457b84
+
+RUN useradd --system -m -d /plone -U -u 500 plone \
+ && mkdir -p /plone/instance/ /data/filestorage /data/blobstorage
+
+COPY buildout.cfg /plone/instance/
+
+RUN buildDeps="default-libmysqlclient-dev dpkg-dev gcc libbz2-dev libc6-dev libffi-dev libjpeg62-turbo-dev libldap2-dev libopenjp2-7-dev libpcre3-dev libpq-dev libsasl2-dev libssl-dev libtiff5-dev libxml2-dev libxslt1-dev wget zlib1g-dev" \
+ && runDeps="default-libmysqlclient-dev git gosu libjpeg62 libopenjp2-7 libpq5 libtiff5 libxml2 libxslt1.1 lynx netcat poppler-utils rsync wv" \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends $buildDeps \
+ && wget -O Plone.tgz https://launchpad.net/plone/$PLONE_MAJOR/$PLONE_VERSION/+download/$PLONE_VERSION_RELEASE.tgz \
+ && echo "$PLONE_MD5 Plone.tgz" | md5sum -c - \
+ && tar -xzf Plone.tgz \
+ && cp -rv ./$PLONE_VERSION_RELEASE/base_skeleton/* /plone/instance/ \
+ && cp -v ./$PLONE_VERSION_RELEASE/buildout_templates/buildout.cfg /plone/instance/buildout-base.cfg \
+ && pip install pip==$PIP setuptools==$SETUPTOOLS zc.buildout==$ZC_BUILDOUT wheel==$WHEEL \
+ && cd /plone/instance \
+ && buildout \
+ && ln -s /data/filestorage/ /plone/instance/var/filestorage \
+ && ln -s /data/blobstorage /plone/instance/var/blobstorage \
+ && find /data -not -user plone -exec chown plone:plone {} \+ \
+ && find /plone -not -user plone -exec chown plone:plone {} \+ \
+ && rm -rf /Plone* \
+ && apt-get purge -y --auto-remove $buildDeps \
+ && apt-get install -y --no-install-recommends $runDeps \
+ && rm -rf /var/lib/apt/lists/* \
+ && rm -rf /plone/buildout-cache/downloads/*
+
+VOLUME /data
+
+COPY docker-initialize.py docker-entrypoint.sh /
+
+EXPOSE 8080
+WORKDIR /plone/instance
+
+HEALTHCHECK --interval=1m --timeout=5s --start-period=1m \
+ CMD nc -z -w5 127.0.0.1 8080 || exit 1
+
+ENTRYPOINT ["/docker-entrypoint.sh"]
+CMD ["start"]
diff --git a/5.2/5.2.14/python37/buildout.cfg b/5.2/5.2.14/python37/buildout.cfg
new file mode 100644
index 0000000..02ca654
--- /dev/null
+++ b/5.2/5.2.14/python37/buildout.cfg
@@ -0,0 +1,106 @@
+[buildout]
+extends =
+ buildout-base.cfg
+
+index = https://pypi.org/simple/
+
+extensions =
+effective-user = plone
+buildout-user = plone
+var-dir=/data
+user=admin:admin
+parts +=
+ zeo
+ mrbob
+ plonesite
+
+eggs +=
+ RelStorage[mysql,postgresql,oracle]
+ pas.plugins.ldap
+
+[client1]
+recipe =
+
+[instance_base]
+resources = ${buildout:directory}/resources
+
+[zeo]
+<= zeoserver_base
+recipe = plone.recipe.zeoserver
+zeo-address = 8080
+
+[instance]
+zcml-additional =
+
+
+
+event-log-handler = StreamHandler
+event-log-args = (sys.stderr,)
+access-log-handler = StreamHandler
+access-log-args = (sys.stdout,)
+
+# Requires gcc, thus install it on image build
+[mrbob]
+recipe = zc.recipe.egg
+eggs =
+ mr.bob
+ bobtemplates.plone
+
+[plonesite]
+recipe = collective.recipe.plonesite
+instance = instance
+site-id = Plone
+profiles-initial = Products.CMFPlone:dependencies
+profiles =
+ plonetheme.barceloneta:default
+ plone.app.caching:default
+ plone.app.contenttypes:plone-content
+ plone.restapi:default
+upgrade-portal = False
+upgrade-all-profiles = False
+enabled = False
+
+[versions]
+setuptools =
+zc.buildout =
+
+plone.restapi = 8.43.1
+plone.rest = 3.0.0
+
+RelStorage = 3.4.5
+argparse = 1.4.0
+bda.cache = 1.3.0
+bobtemplates.plone = 5.2.2
+case-conversion = 2.1.0
+collective.checkdocs = 0.2
+collective.recipe.plonesite = 1.12.0
+cx-Oracle = 8.3.0
+isort = 5.11.5
+mr.bob = 1.0.0
+mysqlclient = 2.1.1
+node = 1.2.1
+node.ext.ldap = 1.2
+node.ext.ugm = 1.1
+odict = 1.9.0
+pas.plugins.ldap = 1.8.2
+passlib = 1.7.4
+perfmetrics = 3.3.0
+plumber = 1.7
+psycopg2 = 2.9.3
+pyasn1 = 0.5.0
+pyasn1-modules = 0.3.0
+python-ldap = 3.4.2
+python-memcached = 1.59
+regex = 2023.6.3
+yafowil = 3.1.0
+yafowil.plone = 4.0.0a5
+yafowil.widget.array = 1.7
+yafowil.widget.dict = 1.8
+yafowil.yaml = 2.0
diff --git a/5.2/5.2.14/python37/docker-entrypoint.sh b/5.2/5.2.14/python37/docker-entrypoint.sh
new file mode 100755
index 0000000..ecf7f76
--- /dev/null
+++ b/5.2/5.2.14/python37/docker-entrypoint.sh
@@ -0,0 +1,41 @@
+#!/bin/bash
+set -e
+
+COMMANDS="adduser debug fg foreground help kill logreopen logtail reopen_transcript run show status stop wait"
+START="console start restart"
+
+# Fixing permissions for external /data volumes
+mkdir -p /data/blobstorage /data/cache /data/filestorage /data/instance /data/log /data/zeoserver
+mkdir -p /plone/instance/src
+find /data -not -user plone -exec chown plone:plone {} \+
+find /plone -not -user plone -exec chown plone:plone {} \+
+
+# Initializing from environment variables
+gosu plone python /docker-initialize.py
+
+if [ -e "custom.cfg" ]; then
+ if [ ! -e "bin/develop" ]; then
+ buildout -c custom.cfg
+ find /data -not -user plone -exec chown plone:plone {} \+
+ find /plone -not -user plone -exec chown plone:plone {} \+
+ gosu plone python /docker-initialize.py
+ fi
+fi
+
+# ZEO Server
+if [[ "$1" == "zeo"* ]]; then
+ exec gosu plone bin/$1 fg
+fi
+
+# Plone instance start
+if [[ $START == *"$1"* ]]; then
+ exec gosu plone bin/instance console
+fi
+
+# Plone instance helpers
+if [[ $COMMANDS == *"$1"* ]]; then
+ exec gosu plone bin/instance "$@"
+fi
+
+# Custom
+exec "$@"
diff --git a/5.2/5.2.14/python37/docker-initialize.py b/5.2/5.2.14/python37/docker-initialize.py
new file mode 100755
index 0000000..99ec331
--- /dev/null
+++ b/5.2/5.2.14/python37/docker-initialize.py
@@ -0,0 +1,381 @@
+#!/usr/local/bin/python
+
+import re
+import os
+
+class Environment(object):
+ """ Configure container via environment variables
+ """
+ def __init__(self, env=os.environ,
+ zope_conf="/plone/instance/parts/instance/etc/zope.conf",
+ custom_conf="/plone/instance/custom.cfg",
+ zeopack_conf="/plone/instance/bin/zeopack",
+ zeoserver_conf="/plone/instance/parts/zeoserver/etc/zeo.conf",
+ cors_conf="/plone/instance/parts/instance/etc/package-includes/999-additional-overrides.zcml"
+ ):
+ self.env = env
+ self.zope_conf = zope_conf
+ self.custom_conf = custom_conf
+ self.zeopack_conf = zeopack_conf
+ self.zeoserver_conf = zeoserver_conf
+ self.cors_conf = cors_conf
+
+ def zeoclient(self):
+ """ ZEO Client
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ config = ""
+ with open(self.zope_conf, "r") as cfile:
+ config = cfile.read()
+
+ # Already initialized
+ if "" not in config:
+ return
+
+ read_only = self.env.get("ZEO_READ_ONLY", "false")
+ zeo_ro_fallback = self.env.get("ZEO_CLIENT_READ_ONLY_FALLBACK", "false")
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+ zeo_storage=self.env.get("ZEO_STORAGE", "1")
+ zeo_client_cache_size=self.env.get("ZEO_CLIENT_CACHE_SIZE", "128MB")
+ zeo_conf = ZEO_TEMPLATE.format(
+ zeo_address=server,
+ read_only=read_only,
+ zeo_client_read_only_fallback=zeo_ro_fallback,
+ shared_blob_dir=shared_blob_dir,
+ zeo_storage=zeo_storage,
+ zeo_client_cache_size=zeo_client_cache_size
+ )
+
+ pattern = re.compile(r".+", re.DOTALL)
+ config = re.sub(pattern, zeo_conf, config)
+
+ with open(self.zope_conf, "w") as cfile:
+ cfile.write(config)
+
+ def zeopack(self):
+ """ ZEO Pack
+ """
+ server = self.env.get("ZEO_ADDRESS", None)
+ if not server:
+ return
+
+ if ":" in server:
+ host, port = server.split(":")
+ else:
+ host, port = (server, "8100")
+
+ with open(self.zeopack_conf, 'r') as cfile:
+ text = cfile.read()
+ text = text.replace('address = "8100"', 'address = "%s"' % server)
+ text = text.replace('host = "127.0.0.1"', 'host = "%s"' % host)
+ text = text.replace('port = "8100"', 'port = "%s"' % port)
+
+ with open(self.zeopack_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def zeoserver(self):
+ """ ZEO Server
+ """
+ pack_keep_old = self.env.get("ZEO_PACK_KEEP_OLD", '')
+ if pack_keep_old.lower() in ("false", "no", "0", "n", "f"):
+ with open(self.zeoserver_conf, 'r') as cfile:
+ text = cfile.read()
+ if 'pack-keep-old' not in text:
+ text = text.replace(
+ '',
+ ' pack-keep-old false\n'
+ )
+
+ with open(self.zeoserver_conf, 'w') as cfile:
+ cfile.write(text)
+
+ def cors(self):
+ """ Configure CORS Policies
+ """
+ if not [e for e in self.env if e.startswith("CORS_")]:
+ return
+
+ allow_origin = self.env.get("CORS_ALLOW_ORIGIN",
+ "http://localhost:3000,http://127.0.0.1:3000")
+ allow_methods = self.env.get("CORS_ALLOW_METHODS",
+ "DELETE,GET,OPTIONS,PATCH,POST,PUT")
+ allow_credentials = self.env.get("CORS_ALLOW_CREDENTIALS", "true")
+ expose_headers = self.env.get("CORS_EXPOSE_HEADERS",
+ "Content-Length,X-My-Header")
+ allow_headers = self.env.get("CORS_ALLOW_HEADERS",
+ "Accept,Authorization,Content-Type,X-Custom-Header,Lock-Token")
+ max_age = self.env.get("CORS_MAX_AGE", "3600")
+ cors_conf = CORS_TEMPLATE.format(
+ allow_origin=allow_origin,
+ allow_methods=allow_methods,
+ allow_credentials=allow_credentials,
+ expose_headers=expose_headers,
+ allow_headers=allow_headers,
+ max_age=max_age
+ )
+ with open(self.cors_conf, "w") as cfile:
+ cfile.write(cors_conf)
+
+ def relstorage_conf(self):
+ """ RelStorage configuration from environment variables
+ """
+ if not [e for e in self.env if e.startswith("RELSTORAGE_")]:
+ return ""
+
+ # Database specific adapter options
+ # https://relstorage.readthedocs.io/en/latest/supported-databases.html
+ adapter_options = self.env.get(
+ "RELSTORAGE_ADAPTER_OPTIONS",
+ "",
+ ).strip().split(",")
+
+ settings = {
+ # General Settings
+ "name": self.env.get("RELSTORAGE_NAME"),
+ "read-only": self.env.get("RELSTORAGE_READ_ONLY"),
+ "keep-history": self.env.get("RELSTORAGE_KEEP_HISTORY"),
+ "commit-lock-timeout": self.env.get(
+ "RELSTORAGE_COMMIT_LOCK_TIMEOUT",
+ ),
+ "commit-lock-id": self.env.get("RELSTORAGE_COMMIT_LOCK_ID"),
+ "create-schema": self.env.get("RELSTORAGE_CREATE_SCHEMA"),
+
+ # Blobs
+ "blob-dir": self.env.get("RELSTORAGE_BLOB_DIR",
+ "/plone/instance/var/blobstorage"),
+ "shared-blob-dir": self.env.get("RELSTORAGE_SHARED_BLOB_DIR"),
+ "blob-cache-size": self.env.get("RELSTORAGE_BLOB_CACHE_SIZE"),
+ "blob-cache-size-check": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK",
+ ),
+ "blob-cache-size-check-external": self.env.get(
+ "RELSTORAGE_BLOB_CACHE_SIZE_CHECK_EXTERNAL",
+ ),
+ "blob-chunk-size": self.env.get("RELSTORAGE_BLOB_CHUNK_SIZE"),
+
+ # Replication
+ "replica-conf": self.env.get("RELSTORAGE_REPLICA_CONF"),
+ "ro-replica-conf": self.env.get("RELSTORAGE_RO_REPLICA_CONF"),
+ "replica-timeout": self.env.get("RELSTORAGE_REPLICA_TIMEOUT"),
+ "revert-when-stale": self.env.get("RELSTORAGE_REVERT_WHEN_STALE"),
+
+ # GC and Packing
+ "pack-gc": self.env.get("RELSTORAGE_PACK_GC"),
+ "pack-prepack-only": self.env.get("RELSTORAGE_PACK_PREPACK_ONLY"),
+ "pack-skip-prepack": self.env.get("RELSTORAGE_PACK_SKIP_PREPACK"),
+ "pack-batch-timeout": self.env.get("RELSTORAGE_PACK_BATCH_TIMEOUT"),
+ "pack-commit-busy-delay": self.env.get(
+ "RELSTORAGE_PACK_COMMIT_BUSY_DELAY",
+ ),
+
+ # Database Caching
+ "cache-prefix": self.env.get("RELSTORAGE_CACHE_PREFIX"),
+
+ # Local Caching
+ "cache-local-mb": self.env.get("RELSTORAGE_CACHE_LOCAL_MB"),
+ "cache-local-object-max": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_OBJECT_MAX",
+ ),
+ "cache-local-compression": self.env.get(
+ "RELSTORAGE_CACHE_LOCAL_COMPRESSION",
+ ),
+ "cache-delta-size-limit": self.env.get(
+ "RELSTORAGE_CACHE_DELTA_SIZE_LIMIT",
+ ),
+
+ # Persistent Local Caching
+ "cache-local-dir": self.env.get("RELSTORAGE_CACHE_LOCAL_DIR"),
+
+ # Deprecated Options
+ # ...
+ }
+
+ return "\n ".join(adapter_options + [
+ "{} {}".format(x[0], x[1].strip()) for x in settings.items() if x[1]
+ ])
+
+ def buildout(self):
+ """ Buildout from environment variables
+ """
+ # Already configured
+ if os.path.exists(self.custom_conf):
+ return
+
+ findlinks = self.env.get("FIND_LINKS", "").strip().split()
+
+ eggs = self.env.get("PLONE_ADDONS",
+ self.env.get("ADDONS", "")).strip().split()
+
+ zcml = self.env.get("PLONE_ZCML",
+ self.env.get("ZCML", "")).strip().split()
+
+ develop = self.env.get("PLONE_DEVELOP",
+ self.env.get("DEVELOP", "")).strip().split()
+
+ site = self.env.get("PLONE_SITE",
+ self.env.get("SITE", "")).strip()
+
+ profiles = self.env.get("PLONE_PROFILES",
+ self.env.get("PROFILES", "")).strip().split()
+
+ versions = self.env.get("PLONE_VERSIONS",
+ self.env.get("VERSIONS", "")).strip().split()
+
+ file_logging = self.env.get("FILE_LOGGING")
+
+ sources = self.env.get("SOURCES", "").strip()
+ sources = sources and [x.strip() for x in sources.split(",")]
+
+ relstorage = self.relstorage_conf()
+
+ buildout_extends = ((develop or sources)
+ and ["develop.cfg"] or ["buildout.cfg"])
+ extra_extends = self.env.get("BUILDOUT_EXTENDS", "").strip().split()
+ buildout_extends.extend(extra_extends)
+
+ # If profiles not provided. Install ADDONS :default profiles
+ if not profiles:
+ for egg in eggs:
+ base = egg.split("=")[0]
+ profiles.append("%s:default" % base)
+
+ enabled = bool(site)
+ if not (
+ eggs or zcml or relstorage or develop or enabled or extra_extends or file_logging
+ ):
+ return
+
+ buildout = BUILDOUT_TEMPLATE.format(
+ buildout_extends="\n\t".join(buildout_extends),
+ findlinks="\n\t".join(findlinks),
+ eggs="\n\t".join(eggs),
+ zcml="\n\t".join(zcml),
+ develop="\n\t".join(develop),
+ profiles="\n\t".join(profiles),
+ versions="\n".join(versions),
+ site=site or "Plone",
+ enabled=enabled,
+ )
+
+ # If we need to create a plonesite and we have a zeo setup
+ # configure collective.recipe.plonesite properly
+ server = self.env.get("ZEO_ADDRESS", None)
+ shared_blob_dir=self.env.get("ZEO_SHARED_BLOB_DIR", "off")
+ if server:
+ buildout += ZEO_INSTANCE_TEMPLATE.format(zeoaddress=server,
+ shared_blob_dir=shared_blob_dir)
+
+ # Add RelStorage configuration if needed
+ if relstorage:
+ buildout += RELSTORAGE_TEMPLATE.format(relstorage=relstorage)
+
+ # Add file logging configuration if needed
+ if file_logging:
+ buildout += FILE_LOGGING_INSTANCE
+
+ # Add sources configuration if needed
+ if sources:
+ buildout += SOURCES_TEMPLATE.format(sources="\n".join(sources))
+
+ with open(self.custom_conf, 'w') as cfile:
+ cfile.write(buildout)
+
+ def setup(self, **kwargs):
+ self.buildout()
+ self.cors()
+ self.zeoclient()
+ self.zeopack()
+ self.zeoserver()
+
+ __call__ = setup
+
+ZEO_TEMPLATE = """
+
+ read-only {read_only}
+ read-only-fallback {zeo_client_read_only_fallback}
+ blob-dir /data/blobstorage
+ shared-blob-dir {shared_blob_dir}
+ server {zeo_address}
+ storage {zeo_storage}
+ name zeostorage
+ var /plone/instance/parts/instance/var
+ cache-size {zeo_client_cache_size}
+
+""".strip()
+
+CORS_TEMPLATE = """
+
+
+
+
+"""
+
+BUILDOUT_TEMPLATE = """
+[buildout]
+extends = {buildout_extends}
+find-links += {findlinks}
+develop += {develop}
+eggs += {eggs}
+zcml += {zcml}
+
+[plonesite]
+enabled = {enabled}
+site-id = {site}
+profiles += {profiles}
+
+[versions]
+{versions}
+"""
+
+ZEO_INSTANCE_TEMPLATE = """
+
+[instance]
+zeo-client = true
+zeo-address = {zeoaddress}
+shared-blob = {shared_blob_dir}
+http-fast-listen = off
+"""
+
+RELSTORAGE_TEMPLATE = """
+
+[instance]
+rel-storage =
+ {relstorage}
+"""
+
+SOURCES_TEMPLATE = """
+
+[sources]
+{sources}
+"""
+
+FILE_LOGGING_INSTANCE = """
+
+[instance]
+event-log-handler = FileHandler
+event-log-args = ('${buildout:var-dir}/log/instance.log', 'a')
+access-log-handler = FileHandler
+access-log-args = ('${buildout:var-dir}/log/instance-access.log', 'a')
+"""
+
+def initialize():
+ """ Configure Plone instance as ZEO Client
+ """
+ environment = Environment()
+ environment.setup()
+
+if __name__ == "__main__":
+ initialize()