Skip to content

Commit

Permalink
Avoid dynamic-plugins writing conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
gazarenkov committed Jan 29, 2025
1 parent 53c59b8 commit c419211
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 0 deletions.
33 changes: 33 additions & 0 deletions docker/install-dynamic-plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
import subprocess
import base64
import binascii
import atexit
import time

# This script is used to install dynamic plugins in the Backstage application,
# and is available in the container image to be called at container initialization,
# for example in an init container when using Kubernetes.
Expand Down Expand Up @@ -181,8 +184,38 @@ def verify_package_integrity(plugin: dict, archive: str, working_directory: str)
if hash_digest != output.decode('utf-8').strip():
raise InstallException(f'{package}: The hash of the downloaded package {output.decode("utf-8").strip()} does not match the provided integrity hash {hash_digest} provided in the configuration file')

# Create the lock file, so that other instances of the script will wait for this one to finish
def create_lock(lock_file_path):
while True:
try:
with open(lock_file_path, 'x'):
print(f"======= Created lock file: {lock_file_path}")
return
except FileExistsError:
wait_for_lock_release(lock_file_path)

# Remove the lock file
def remove_lock(lock_file_path):
os.remove(lock_file_path)
print(f"======= Removed lock file: {lock_file_path}")

# Wait for the lock file to be released
def wait_for_lock_release(lock_file_path):
print("======= Waiting for lock release...")
while True:
if not os.path.exists(lock_file_path):
break
time.sleep(1)
print("======= Lock released.")

def main():

dynamicPluginsRoot = sys.argv[1]

lock_file_path = os.path.join(dynamicPluginsRoot, 'install-dynamic-plugins.lock')
atexit.register(remove_lock, lock_file_path)
create_lock(lock_file_path)

maxEntrySize = int(os.environ.get('MAX_ENTRY_SIZE', 20000000))
skipIntegrityCheck = os.environ.get("SKIP_INTEGRITY_CHECK", "").lower() == "true"

Expand Down
4 changes: 4 additions & 0 deletions docs/dynamic-plugins/installing-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,7 @@ When using RHDH Helm Chart you can just name the Secret using following pattern
When using the Operator ....

//TODO

### Storage of Dynamic Plugins

The directory where dynamic plugins are located is mounted as a volume to the _install-dynamic-plugins_ init container and the _backstage-backend_ container. The _install-dynamic-plugins_ init container is responsible for downloading and extracting the plugins into this directory. Depending on the deployment method, the directory is mounted as an ephemeral or persistent volume. In the latter case, the volume can be shared between several Pods, and the plugins installation script is also responsible for downloading and extracting the plugins only once, avoiding conflicts.

0 comments on commit c419211

Please sign in to comment.