Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix mustache workaround only taking top level keys into account #84

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-and-publish-container-image.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ jobs:
use-black: false
use-mypy: false
use-isort: false
extra-pycodestyle-options: --max-line-length=120
- name: Log in to the container registry
uses: docker/login-action@327cd5a69de6c009b9ce71bce8395f28e651bf99
with:
Expand Down
23 changes: 10 additions & 13 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,22 @@ ENV PYTHONUNBUFFERED=1
FROM base AS builder
# we want always the latest version of fetched apk packages
# hadolint ignore=DL3018
RUN apk add --no-cache build-base openssl-dev glibc-dev posix-libc-utils libffi-dev \
python-3.12 python3-dev py3.12-pip && \
RUN apk add --no-cache build-base posix-libc-utils && \
apk add --no-cache python-3.12 python3-dev py3.12-pip && \
mkdir /install
WORKDIR /install
COPY requirements.txt requirements.txt
# we want always the latest version of fetched pip packages
# hadolint ignore=DL3013
RUN pip3 install --no-cache-dir -U pip setuptools wheel && \
pip3 install --no-cache-dir --prefix=/install --no-warn-script-location -r ./requirements.txt

FROM builder AS native-builder
# we want always the latest version of fetched apk packages
# hadolint ignore=DL3018
RUN apk add --no-cache ccache patchelf
COPY src/ /src/
RUN python -m venv /venv && \
/venv/bin/pip install --no-cache-dir -U pip nuitka setuptools wheel && \
/venv/bin/pip install --no-cache-dir --no-warn-script-location -r ./requirements.txt && \
/venv/bin/python -m nuitka --onefile /src/harbor.py && \
COPY requirements.txt requirements.txt

# use latest version of pyinstaller
# hadolint ignore=DL3013
RUN pip install --no-cache-dir -U pyinstaller && \
pip install --no-cache-dir --no-warn-script-location -r ./requirements.txt && \
pyinstaller --onefile /src/harbor.py && \
pwd && \

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 25 & 26 not needed besides for debugging

ls -lha

Expand All @@ -39,4 +36,4 @@ RUN python3 -m unittest discover -v -s .
# hadolint ignore=DL3007
FROM cgr.dev/chainguard/wolfi-base:latest
USER nonroot
COPY --from=native-builder /install/harbor.bin /usr/local/harbor
COPY --from=native-builder /install/dist/harbor /usr/local/harbor
seekermarcel marked this conversation as resolved.
Show resolved Hide resolved
61 changes: 32 additions & 29 deletions src/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,36 +70,22 @@ def get_member_id(members: [ProjectMemberEntity], username: str) -> int | None:


async def fill_template(client, path: str, logger) -> str:
"""Takes the path to a template file and returns its content with the
replaced ids
"""
"""Reads a template file, replaces placeholders with fetched IDs, and returns the updated content."""
with open(path, 'r') as file:
content = file.read()
placeholders = re.findall(
r'{{[ ]*(?:project|registry):[A-z,0-9,.,\-,_]+[ ]*}}', content
)
logger.info("Found id templates", extra={"placeholders": placeholders})
placeholders = [
placeholder.replace('{{', '').replace(' ', '').replace('}}', '')
for placeholder in placeholders
]
replacements = {}
for placeholder in placeholders:
placeholder_type, placeholder_value = placeholder.split(':')
replacement_value = await fetch_id(
client, placeholder_type, placeholder_value
)
# The mustache specification, which the chevron library builds
# on top of, does not allow for dots in keys. Instead, keys with
# dots are meant to reference nested objects. In order to have
# the right objects to reference, nested objects / dictionaries
# are created for keys with dots.
last_part = str(replacement_value)
for part in reversed(placeholder.split('.')):
last_part = {part: last_part}
replacements = replacements | last_part
config = chevron.render(content, replacements)
return config
config = file.read()

placeholders = re.findall(r'{{\s*(?:project|registry):[\w.\-_]+\s*}}', config)
logger.info("Found id templates", extra={"placeholders": placeholders})

replacements = {}
for placeholder in (p.strip(" {}") for p in placeholders):
placeholder_type, placeholder_value = placeholder.split(':')
replacement_value = await fetch_id(client, placeholder_type, placeholder_value)

# Create nested dictionary structure for replacements
insert_into_dict(replacements, placeholder.split('.') + [str(replacement_value)])

return chevron.render(config, replacements)


async def fetch_id(
Expand All @@ -120,3 +106,20 @@ async def fetch_id(
registry = registries[0]
registry_id = registry.id
return registry_id


def insert_into_dict(d: dict, parts: [str]) -> None:
"""Inserts nested keys and value into a dictionary.

>>> d = {}
>>> insert_into_dict(d, ["a", "b", 1])
>>> d
{"a": {"b": 1}}
>>> insert_into_dict(d, ["a", "c", 2])
>>> d
{"a": {"b": 1, c: "2"}}
"""
*keys, last_key, value = parts
for key in keys:
d = d.setdefault(key, {})
d[last_key] = value