Skip to content

Commit dfe4cd8

Browse files
openshift-cherrypick-robotgazarenkovrm3l
authored
[release-1.4] feat: avoid dynamic-plugins writing conflicts (#2351)
* Avoid dynamic-plugins writing conflicts * add SIGTERM handling * add manual lock remove doc * Update docker/install-dynamic-plugins.py Co-authored-by: Armel Soro <[email protected]> * Fix link to aap-backend plugin This was deprecated in janus-idp/backstage-plugins#2628 --------- Co-authored-by: gazarenkov <[email protected]> Co-authored-by: Armel Soro <[email protected]> Co-authored-by: Armel Soro <[email protected]>
1 parent e9f462b commit dfe4cd8

File tree

3 files changed

+52
-1
lines changed

3 files changed

+52
-1
lines changed

docker/install-dynamic-plugins.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525
import subprocess
2626
import base64
2727
import binascii
28+
import atexit
29+
import time
30+
import signal
31+
2832
# This script is used to install dynamic plugins in the Backstage application,
2933
# and is available in the container image to be called at container initialization,
3034
# for example in an init container when using Kubernetes.
@@ -181,8 +185,39 @@ def verify_package_integrity(plugin: dict, archive: str, working_directory: str)
181185
if hash_digest != output.decode('utf-8').strip():
182186
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')
183187

188+
# Create the lock file, so that other instances of the script will wait for this one to finish
189+
def create_lock(lock_file_path):
190+
while True:
191+
try:
192+
with open(lock_file_path, 'x'):
193+
print(f"======= Created lock file: {lock_file_path}")
194+
return
195+
except FileExistsError:
196+
wait_for_lock_release(lock_file_path)
197+
198+
# Remove the lock file
199+
def remove_lock(lock_file_path):
200+
os.remove(lock_file_path)
201+
print(f"======= Removed lock file: {lock_file_path}")
202+
203+
# Wait for the lock file to be released
204+
def wait_for_lock_release(lock_file_path):
205+
print("======= Waiting for lock release...", flush=True)
206+
while True:
207+
if not os.path.exists(lock_file_path):
208+
break
209+
time.sleep(1)
210+
print("======= Lock released.")
211+
184212
def main():
213+
185214
dynamicPluginsRoot = sys.argv[1]
215+
216+
lock_file_path = os.path.join(dynamicPluginsRoot, 'install-dynamic-plugins.lock')
217+
atexit.register(remove_lock, lock_file_path)
218+
signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(0))
219+
create_lock(lock_file_path)
220+
186221
maxEntrySize = int(os.environ.get('MAX_ENTRY_SIZE', 20000000))
187222
skipIntegrityCheck = os.environ.get("SKIP_INTEGRITY_CHECK", "").lower() == "true"
188223

docs/dynamic-plugins/export-derived-package.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ If you are developing your own plugin that is going to be used as a dynamic plug
4343
To be compatible with the showcase dynamic plugin support, and used as dynamic plugins, existing plugins must be based on, or compatible with, the new backend system, as well as rebuilt with a dedicated CLI command.
4444

4545
The new backend system standard entry point (created using `createBackendPlugin()` or `createBackendModule()`) should be exported as the default export of either the main package or of an `alpha` package (if the new backend support is still provided as `alpha` APIs). This doesn't add any additional requirement on top of the standard plugin development guidelines of the new backend system.
46-
For a practical example of a dynamic plugin entry point built upon the new backend system, please refer to the [Janus plugins repository](https://github.com/janus-idp/backstage-plugins/blob/main/plugins/aap-backend/src/module.ts#L25).
46+
For a practical example of a dynamic plugin entry point built upon the new backend system, please refer to the [Janus plugins repository](https://github.com/janus-idp/backstage-plugins/blob/release-1.4/plugins/aap-backend/src/module.ts#L25).
4747

4848
The dynamic export mechanism identifies private, non-backstage dependencies, and sets the `bundleDependencies` field in the `package.json` file for them, so that the dynamic plugin package can be published as a self-contained package, along with its private dependencies bundled in a private `node_modules` folder.
4949

docs/dynamic-plugins/installing-plugins.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,19 @@ When using RHDH Helm Chart you can just name the Secret using following pattern
119119
When using the Operator ....
120120

121121
//TODO
122+
123+
### Storage of Dynamic Plugins
124+
125+
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.
126+
127+
**Important Note:** If _install-dynamic-plugins_ init container was killed with SIGKILL signal (for example in a case of OOM) the script is not able to remove the lock file and the next time the Pod starts, it will be waiting for the lock release. You can see the following message in the logs for all the Pods:
128+
129+
```console
130+
oc logs -n <namespace-name> -f backstage-<backstage-name>-<pod-suffix> -c install-dynamic-plugins
131+
======= Waiting for lock release...
132+
```
133+
In such a case, you can delete the lock file manually from any of the Pods:
134+
135+
```console
136+
oc exec -n <namespace-name> deploy/backstage-<backstage-name> -c install-dynamic-plugins -- rm -f /dynamic-plugins-root/dynamic-plugins.lock
137+
```

0 commit comments

Comments
 (0)