Skip to content

Commit 4539e25

Browse files
authored
Merge pull request #5 from obeone:code_documentation
docs: improve comments, docstrings, and user guidance throughout codebase
2 parents 0e39b68 + 50bdb3c commit 4539e25

File tree

7 files changed

+248
-165
lines changed

7 files changed

+248
-165
lines changed

.github/workflows/build-and-publish.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
permissions:
1717
contents: read
1818
packages: write
19-
id-token: write # For cosign
19+
id-token: write # Permission for cosign signing
2020

2121
steps:
2222
- name: Checkout code
@@ -30,24 +30,29 @@ jobs:
3030

3131
- name: Determine tags
3232
run: |
33+
# Initialize tags with latest tags for GitHub Container Registry and Docker Hub
3334
TAGS="ghcr.io/obeone/multi-registry-cache:latest,docker.io/obeoneorg/multi-registry-cache:latest"
3435
36+
# If this is a release event, add version-specific tags
3537
if [[ "${{ github.event_name }}" == "release" ]]; then
3638
VERSION=${{ github.event.release.tag_name }}
3739
VERSION=${VERSION#v} # Remove 'v' prefix if present
3840
MAJOR=$(echo $VERSION | cut -d. -f1)
3941
MINOR=$(echo $VERSION | cut -d. -f2)
4042
PATCH=$(echo $VERSION | cut -d. -f3)
4143
44+
# Add version tags for GitHub Container Registry
4245
TAGS="$TAGS,ghcr.io/obeone/multi-registry-cache:v$VERSION,ghcr.io/obeone/multi-registry-cache:$VERSION"
4346
TAGS="$TAGS,ghcr.io/obeone/multi-registry-cache:v$MAJOR.$MINOR,ghcr.io/obeone/multi-registry-cache:$MAJOR.$MINOR"
4447
TAGS="$TAGS,ghcr.io/obeone/multi-registry-cache:v$MAJOR,ghcr.io/obeone/multi-registry-cache:$MAJOR"
4548
49+
# Add version tags for Docker Hub
4650
TAGS="$TAGS,docker.io/obeoneorg/multi-registry-cache:v$VERSION,docker.io/obeoneorg/multi-registry-cache:$VERSION"
4751
TAGS="$TAGS,docker.io/obeoneorg/multi-registry-cache:v$MAJOR.$MINOR,docker.io/obeoneorg/multi-registry-cache:$MAJOR.$MINOR"
4852
TAGS="$TAGS,docker.io/obeoneorg/multi-registry-cache:v$MAJOR,docker.io/obeoneorg/multi-registry-cache:$MAJOR"
4953
fi
5054
55+
# Export tags as environment variable for later steps
5156
echo "DOCKER_TAGS=$TAGS" >> $GITHUB_ENV
5257
5358
- name: Log in to GitHub Container Registry
@@ -85,6 +90,7 @@ jobs:
8590
- name: Sign the container image with cosign
8691
if: github.event_name == 'push' && github.ref == 'refs/heads/main' || github.event_name == 'release'
8792
run: |
93+
# Sign each tag with cosign using the image digest
8894
for tag in $(echo $DOCKER_TAGS | tr ',' '\n'); do
8995
cosign sign --yes $tag@${DIGEST}
9096
done

CONFIG.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -187,16 +187,16 @@ registry:
187187

188188
#### Automatic
189189

190-
- Run `python setup.py` and fine-tune settings in `config.yaml`after that.
191-
- And run `python generate.py` to generate all files in `compose` directory.
190+
- Run `python setup.py` and fine-tune settings in `config.yaml` afterwards.
191+
- Then run `python generate.py` to generate all files in the `compose` directory.
192192

193193
#### Manual
194194

195195
1. Copy `config.sample.yaml` to `config.yaml`.
196196
2. Fill in your registry credentials and other settings.
197-
3. Set everything else (especially hosts)
198-
4. Execute `python generate.py` to generate all files in `compose` directory.
199-
5. Go in that directory (`cd compose`)
197+
3. Set everything else (especially hosts).
198+
4. Execute `python generate.py` to generate all files in the `compose` directory.
199+
5. Go into that directory (`cd compose`).
200200
6. Run `docker compose up -d` to start the services.
201201

202202
By following these steps, you can configure and run your multi-registry environment with Traefik and Redis caching, simplifying the management of multiple container registries.

docker/Dockerfile

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,45 @@
11
# syntax=docker/dockerfile:1
2-
3-
# Start the build stage for creating wheels
2+
#
3+
# Dockerfile for building and running the Python application.
4+
# It uses a multi-stage build to create wheel files for dependencies
5+
# in a full Python environment, then installs them in a slim Python image
6+
# to reduce the final image size.
7+
#
8+
# Stage 1: Build wheels for dependencies
49
FROM python:3.12 AS wheel
510

6-
# Set the working directory
11+
# Set the working directory inside the container
712
WORKDIR /app
813

914
# Copy the requirements file to the working directory
1015
COPY requirements.txt .
1116

12-
# Install wheel and create wheel files for the requirements
17+
# Install wheel package and build wheel files for all dependencies listed in requirements.txt
1318
RUN --mount=type=cache,target=/root/.cache/pip \
1419
pip install wheel && \
1520
pip wheel --exists-action i -r requirements.txt --wheel-dir /root/.cache/wheel
1621

17-
# Start the final image using a slimmer version of Python
22+
# Stage 2: Create the final image with a slim Python base
1823
FROM python:3.12-slim
1924

25+
# Environment variable to indicate running inside Docker
2026
ENV IN_DOCKER=1
2127

22-
# Set the working directory
28+
# Set the working directory inside the container
2329
WORKDIR /app
2430

2531
# Copy the requirements file to the working directory
2632
COPY requirements.txt .
2733

28-
# Install the dependencies from the wheel files created in the previous stage
34+
# Install dependencies from the pre-built wheel files from the previous stage
2935
RUN --mount=type=bind,from=wheel,source=/root/.cache/wheel,dst=/root/.cache/wheel \
3036
pip install --no-index --find-links=/root/.cache/wheel -r requirements.txt
3137

32-
# Copy the entire application code to the working directory
38+
# Copy the entire application code into the container
3339
COPY . .
3440

35-
# Copy the entrypoint script and set the appropriate permissions
41+
# Copy the entrypoint script and set executable permissions
3642
COPY --chmod=777 docker/entrypoint.sh /
3743

38-
# Specify the entrypoint for the container
44+
# Set the entrypoint for the container
3945
ENTRYPOINT [ "/entrypoint.sh" ]

docker/entrypoint.sh

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,27 @@
11
#!/usr/bin/env bash
22

3+
# Entrypoint script for Docker container
4+
# This script checks the first argument and executes the corresponding Python script or command.
5+
# Usage:
6+
# ./entrypoint.sh setup [args] - Runs python setup.py with the given arguments
7+
# ./entrypoint.sh generate [args] - Runs python generate.py with the given arguments
8+
# ./entrypoint.sh [command] - Executes the given command
9+
10+
# Check if the first argument is empty
11+
if [ -z "$1" ]; then
12+
echo "No command provided. Exiting."
13+
exit 1
14+
fi
15+
316
if [ "$1" == "setup" ]; then
417
shift
18+
# Execute setup.py with remaining arguments
519
exec python setup.py "$@"
620
elif [ "$1" == "generate" ]; then
721
shift
22+
# Execute generate.py with remaining arguments
823
exec python generate.py "$@"
924
else
25+
# Execute the provided command as is
1026
exec "$@"
1127
fi

functions.py

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -36,56 +36,63 @@ def interpolate_strings(obj, variables):
3636
return obj
3737

3838

39-
def create_docker_service(registry, custom={}):
40-
"""Creates a docker service for the registry.
41-
39+
def create_docker_service(registry, custom=None):
40+
"""
41+
Creates a docker service for the registry.
42+
4243
Args:
4344
registry (dict): A dictionary containing the registry information.
44-
custom (dict): A dictionary of customizations to apply to the
45-
docker service.
45+
custom (dict, optional): A dictionary of customizations to apply to the
46+
docker service. Defaults to None.
47+
4648
Returns:
4749
dict: The docker service.
4850
"""
49-
obj = {
50-
}
51+
if custom is None:
52+
custom = {}
53+
54+
obj = {}
5155
obj.update(custom)
5256

5357
console.print(Text("Docker service created for the registry", style="green"))
5458
return interpolate_strings(obj, registry)
5559

5660

57-
def create_traefik_router(registry, custom={}):
61+
def create_traefik_router(registry, custom=None):
5862
"""
5963
Creates a Traefik router object for a given registry.
6064
6165
Args:
6266
registry (str): The name of the registry.
63-
custom (dict, optional): A dictionary of custom router properties. Defaults to {}.
67+
custom (dict, optional): A dictionary of custom router properties. Defaults to None.
6468
6569
Returns:
6670
dict: A dictionary representing the Traefik router object.
6771
"""
68-
obj = {
69-
}
70-
72+
if custom is None:
73+
custom = {}
74+
75+
obj = {}
7176
obj.update(custom)
7277

7378
console.print(Text("Traefik router object created", style="green"))
7479
return interpolate_strings(obj, registry)
7580

76-
def create_traefik_service(registry, custom={}):
81+
def create_traefik_service(registry, custom=None):
7782
"""
7883
Creates a Traefik service object with a load balancer configuration that points to the specified registry.
7984
8085
Args:
8186
registry (str): The URL of the registry to point the load balancer to.
82-
custom (dict, optional): A dictionary of custom configuration options to add to the service object. Defaults to {}.
87+
custom (dict, optional): A dictionary of custom configuration options to add to the service object. Defaults to None.
8388
8489
Returns:
8590
dict: A Traefik service object with the specified load balancer configuration.
8691
"""
87-
obj = {
88-
}
92+
if custom is None:
93+
custom = {}
94+
95+
obj = {}
8996
obj.update(custom)
9097

9198
console.print(Text("Traefik service object created", style="green"))
@@ -118,8 +125,11 @@ def create_registry_config(config, registry, db):
118125

119126
interpolated = interpolate_strings(config, registry)
120127

121-
if 'redis' in interpolated:
122-
interpolated['redis']['db'] = int(db)
128+
if isinstance(interpolated, dict) and 'redis' in interpolated:
129+
# Ensure 'redis' is a dictionary before setting 'db'
130+
redis_config = interpolated.get('redis')
131+
if isinstance(redis_config, dict):
132+
redis_config['db'] = int(db)
123133

124134
console.print(Text("Registry configuration created", style="green"))
125135
return interpolated
@@ -156,8 +166,9 @@ def write_http_secret():
156166
"""
157167
Write the HTTP secret to the .env file if it does not exist or if REGISTRY_HTTP_SECRET is not already set.
158168
"""
159-
if not os.path.exists('compose/.env') or 'REGISTRY_HTTP_SECRET' not in open('compose/.env').read():
160-
with open('compose/.env', 'a') as env_file:
169+
env_path = 'compose/.env'
170+
if not os.path.exists(env_path) or 'REGISTRY_HTTP_SECRET' not in open(env_path).read():
171+
with open(env_path, 'a') as env_file:
161172
env_file.write(f"REGISTRY_HTTP_SECRET={secrets.token_hex(32)}\n")
162173
console.print(Text("HTTP secret written to .env file", style="green"))
163174
else:

generate.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
"""
2-
This module sets up a multi-registry environment by creating configuration files
3-
for Docker Compose, registry and Traefik.
2+
This module sets up a multi-registry environment by creating configuration files
3+
for Docker Compose, registry, and Traefik.
44
See the README.md file for more information.
5+
6+
Usage:
7+
Run this script to generate configuration files based on the config.yaml.
58
"""
69
import os
710
import yaml
@@ -11,7 +14,7 @@
1114
import copy
1215

1316

14-
# Load config
17+
# Load configuration from config.yaml file
1518
try:
1619
with open('config.yaml', 'r', encoding='UTF-8') as file:
1720
base_config = yaml.safe_load(file)
@@ -20,6 +23,7 @@
2023
console.print(Text("Error: config.yaml not found", style="bold red"))
2124
raise
2225

26+
# Extract configuration sections from the loaded config
2327
try:
2428
registries = base_config['registries']
2529
docker_config = base_config['docker']['baseConfig']
@@ -31,26 +35,29 @@
3135
console.print(Text(f"Error: Missing key in config file - {e}", style="bold red"))
3236
raise
3337

34-
# Create a compose directory to store the configuration files
38+
# Create a compose directory to store the configuration files if it does not exist
3539
if not os.path.exists('compose'):
3640
os.mkdir('compose')
3741
os.mkdir('compose/acme')
3842
console.print(Text("Compose directory created", style="bold green"))
3943
else:
4044
console.print(Text("Compose directory already exists", style="bold yellow"))
4145

42-
# Adding services to docker-compose and routers to traefik
46+
# Initialize Redis database count for registries
4347
count_redis_db = 0
48+
49+
# Iterate over each registry to create configuration files and update docker and traefik configs
4450
for registry in registries:
4551
name = registry['name']
4652

47-
# Creating registry configuration file
53+
# Create registry configuration file
4854
try:
49-
# Retrocompatibility with old config files without type field
55+
# Retrocompatibility with old config files without 'type' field
5056
if 'type' not in registry:
5157
registry['type'] = 'cache'
5258
console.print(Text(f"No type specified for registry {name}, defaulting to cache", style="bold yellow"))
5359

60+
# Deep copy base registry config and create specific config for this registry
5461
registry_config_copy = copy.deepcopy(registry_config)
5562
registry_config_file = functions.create_registry_config(registry_config_copy, registry, count_redis_db)
5663
functions.write_yaml_file(f'compose/{name}.yaml', registry_config_file)
@@ -59,15 +66,15 @@
5966
console.print(Text(f"Error creating registry configuration file for {name}: {e}", style="bold red"))
6067
raise
6168

62-
# Unsset password before interpolate variables
69+
# Unset password before interpolating variables to avoid leaking sensitive data
6370
try:
6471
if 'password' in registry:
6572
registry.pop('password')
6673
except KeyError:
6774
console.print(Text(f"Error: Missing 'password' key in registry configuration for {name}", style="bold red"))
6875
raise
6976

70-
# Creating docker-compose and traefik configuration
77+
# Create docker-compose and traefik configuration entries for this registry
7178
try:
7279
docker_config['services'][name] = functions.create_docker_service(registry, docker_perregistry['compose'])
7380
traefik_config['http']['routers'][name] = functions.create_traefik_router(registry, traefik_perregistry['router'])
@@ -77,12 +84,15 @@
7784
console.print(Text(f"Error creating docker-compose and traefik configuration for {name}: {e}", style="bold red"))
7885
raise
7986

87+
# Increment Redis database count for next registry
8088
count_redis_db += 1
8189

90+
# Write final configuration files and handle deprecated docker-compose.yml file
8291
try:
8392
functions.write_yaml_file('compose/compose.yaml', docker_config)
8493
functions.write_yaml_file('compose/traefik.yaml', traefik_config)
8594
functions.write_to_file('compose/redis.conf', f'databases {count_redis_db}')
95+
8696
# If docker-compose.yml exists, ask for confirmation before removing it
8797
docker_compose_path = 'compose/docker-compose.yml'
8898
if os.path.exists(docker_compose_path):
@@ -93,10 +103,10 @@
93103
console.print(Text("Existing docker-compose.yml file removed", style="bold blue"))
94104
else:
95105
console.print(Text("docker-compose.yml file not removed", style="bold yellow"))
96-
97-
106+
107+
# Write HTTP secret file
98108
functions.write_http_secret()
99-
109+
100110
console.print(Text("Configuration files written successfully", style="bold green"))
101111
except Exception as e:
102112
console.print(Text(f"Error writing configuration files: {e}", style="bold red"))

0 commit comments

Comments
 (0)