pyrelukko 0.10.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyrelukko-0.10.0/.gitlab-ci.yml +128 -0
- pyrelukko-0.10.0/.readthedocs.yaml +22 -0
- pyrelukko-0.10.0/LICENSE +21 -0
- pyrelukko-0.10.0/PKG-INFO +198 -0
- pyrelukko-0.10.0/README.md +175 -0
- pyrelukko-0.10.0/cicd/run_publish.sh +11 -0
- pyrelukko-0.10.0/cicd/run_pylint.sh +11 -0
- pyrelukko-0.10.0/cicd/run_pytest.sh +11 -0
- pyrelukko-0.10.0/cicd/run_shellcheck.sh +11 -0
- pyrelukko-0.10.0/cicd/tox_docs_pages.sh +18 -0
- pyrelukko-0.10.0/cicd/tox_publish.sh +27 -0
- pyrelukko-0.10.0/cicd/tox_shellcheck.sh +14 -0
- pyrelukko-0.10.0/docs/_static/favicon.ico +0 -0
- pyrelukko-0.10.0/docs/apidocs/modules.rst +10 -0
- pyrelukko-0.10.0/docs/apidocs/pyrelukko.decorators.rst +10 -0
- pyrelukko-0.10.0/docs/apidocs/pyrelukko.pyrelukko.rst +10 -0
- pyrelukko-0.10.0/docs/apidocs/pyrelukko.rst +20 -0
- pyrelukko-0.10.0/docs/apidocs/pyrelukko.testcontainers.rst +10 -0
- pyrelukko-0.10.0/docs/conf.py +90 -0
- pyrelukko-0.10.0/docs/index.md +9 -0
- pyrelukko-0.10.0/pyproject.toml +151 -0
- pyrelukko-0.10.0/src/pyrelukko/__init__.py +5 -0
- pyrelukko-0.10.0/src/pyrelukko/decorators.py +91 -0
- pyrelukko-0.10.0/src/pyrelukko/pyrelukko.py +691 -0
- pyrelukko-0.10.0/src/pyrelukko/testcontainers.py +138 -0
- pyrelukko-0.10.0/src/pyrelukko/version.py +2 -0
- pyrelukko-0.10.0/tests/cert/5d868fca.0 +1 -0
- pyrelukko-0.10.0/tests/cert/README.md +11 -0
- pyrelukko-0.10.0/tests/cert/relukko.crt +18 -0
- pyrelukko-0.10.0/tests/cert/relukko.csr +16 -0
- pyrelukko-0.10.0/tests/cert/relukko.key +28 -0
- pyrelukko-0.10.0/tests/cert/rootCA.crt +19 -0
- pyrelukko-0.10.0/tests/cert/rootCA.der +0 -0
- pyrelukko-0.10.0/tests/cert/rootCA.key +28 -0
- pyrelukko-0.10.0/tests/cert/rootCA.srl +1 -0
- pyrelukko-0.10.0/tests/conftest.py +85 -0
- pyrelukko-0.10.0/tests/test_relukko.py +719 -0
- pyrelukko-0.10.0/tests/test_skip_relukko.py +48 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
variables:
|
|
2
|
+
FF_TIMESTAMPS: true
|
|
3
|
+
RUN_PYLINT:
|
|
4
|
+
description: Used in rules, if "true" and web triggered run pylint.
|
|
5
|
+
value: "false"
|
|
6
|
+
options:
|
|
7
|
+
- "false"
|
|
8
|
+
- "true"
|
|
9
|
+
RUN_PYTEST:
|
|
10
|
+
description: Used in rules, if "true" and web triggered run the pytests.
|
|
11
|
+
value: "false"
|
|
12
|
+
options:
|
|
13
|
+
- "false"
|
|
14
|
+
- "true"
|
|
15
|
+
RELUKKO_HOSTNAME: relukko
|
|
16
|
+
RELUKKO_BIND_PORT: 3000
|
|
17
|
+
RELUKKO_API_KEY: "somerandomkey"
|
|
18
|
+
POSTGRES_USER: relukko
|
|
19
|
+
POSTGRES_PASSWORD: okkuler
|
|
20
|
+
POSTGRES_DB: relukko
|
|
21
|
+
POSTGRES_HOSTNAME: postgres
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
run-pylint:
|
|
25
|
+
stage: test
|
|
26
|
+
image: "registry.gitlab.com/relukko/py-tox-images/py-3.14-tox"
|
|
27
|
+
rules:
|
|
28
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
29
|
+
changes:
|
|
30
|
+
- src/**/*.py
|
|
31
|
+
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
32
|
+
changes:
|
|
33
|
+
- src/**/*.py
|
|
34
|
+
- if: $CI_PIPELINE_SOURCE == "web" && $RUN_PYLINT == "true"
|
|
35
|
+
when: always
|
|
36
|
+
before_script:
|
|
37
|
+
- echo "Running PyLint."
|
|
38
|
+
script:
|
|
39
|
+
- ./cicd/run_pylint.sh
|
|
40
|
+
artifacts:
|
|
41
|
+
when: always
|
|
42
|
+
expire_in: 2 week
|
|
43
|
+
paths:
|
|
44
|
+
- pylint.out.*
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
run-pytest:
|
|
48
|
+
stage: test
|
|
49
|
+
services:
|
|
50
|
+
- name: postgres:17
|
|
51
|
+
alias: postgres
|
|
52
|
+
- name: registry.gitlab.com/relukko/relukko:latest
|
|
53
|
+
alias: relukko
|
|
54
|
+
variables:
|
|
55
|
+
DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}"
|
|
56
|
+
RELUKKO_USER: "relukko"
|
|
57
|
+
RELUKKO_PASSWORD: "relukko"
|
|
58
|
+
RELUKKO_BIND_ADDR: "0.0.0.0"
|
|
59
|
+
HEALTHCHECK_TCP_PORT: "${RELUKKO_BIND_PORT}"
|
|
60
|
+
variables:
|
|
61
|
+
FF_NETWORK_PER_BUILD: 1
|
|
62
|
+
CI_HAS_RELUKKO: true
|
|
63
|
+
CI_RELUKKO_BASE_URL: "http://${RELUKKO_HOSTNAME}:${RELUKKO_BIND_PORT}"
|
|
64
|
+
CI_RELUKKO_API_KEY: "${RELUKKO_API_KEY}"
|
|
65
|
+
parallel:
|
|
66
|
+
matrix:
|
|
67
|
+
- PIPELINE_PY_VERSION: ['3.11', '3.12', '3.13', '3.14']
|
|
68
|
+
image: "registry.gitlab.com/relukko/py-tox-images/py-$PIPELINE_PY_VERSION-tox"
|
|
69
|
+
rules:
|
|
70
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
71
|
+
changes:
|
|
72
|
+
- src/**/*.py
|
|
73
|
+
- tests/test_*.py
|
|
74
|
+
- tests/conftest.py
|
|
75
|
+
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
76
|
+
changes:
|
|
77
|
+
- src/**/*.py
|
|
78
|
+
- tests/test_*.py
|
|
79
|
+
- tests/conftest.py
|
|
80
|
+
- if: $CI_PIPELINE_SOURCE == "web" && $RUN_PYTEST == "true"
|
|
81
|
+
when: always
|
|
82
|
+
before_script:
|
|
83
|
+
- echo "Running PyTest."
|
|
84
|
+
script:
|
|
85
|
+
- ./cicd/run_pytest.sh
|
|
86
|
+
artifacts:
|
|
87
|
+
when: always
|
|
88
|
+
expire_in: 2 week
|
|
89
|
+
paths:
|
|
90
|
+
- pytest-junit*.xml
|
|
91
|
+
- log*.html
|
|
92
|
+
- output*.xml
|
|
93
|
+
- xunit*.xml
|
|
94
|
+
reports:
|
|
95
|
+
junit:
|
|
96
|
+
- pytest-junit*.xml
|
|
97
|
+
- xunit*.xml
|
|
98
|
+
|
|
99
|
+
run-shellcheck:
|
|
100
|
+
stage: test
|
|
101
|
+
image: "registry.gitlab.com/relukko/py-tox-images/py-3.14-tox"
|
|
102
|
+
rules:
|
|
103
|
+
- if: $CI_PIPELINE_SOURCE == "merge_request_event" && $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
|
|
104
|
+
changes:
|
|
105
|
+
- cicd/*.sh
|
|
106
|
+
- if: $CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
|
|
107
|
+
changes:
|
|
108
|
+
- cicd/*.sh
|
|
109
|
+
before_script:
|
|
110
|
+
- echo "Running ShellCheck."
|
|
111
|
+
script:
|
|
112
|
+
- ./cicd/run_shellcheck.sh
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
publish:
|
|
116
|
+
stage: deploy
|
|
117
|
+
image: "registry.gitlab.com/relukko/py-tox-images/py-3.14-tox"
|
|
118
|
+
environment: publish
|
|
119
|
+
rules:
|
|
120
|
+
- if: $CI_COMMIT_TAG =~ /^v[0-9]+\.[0-9]+\.[0-9]+$/ && $CI_PIPELINE_SOURCE == "push"
|
|
121
|
+
id_tokens:
|
|
122
|
+
PYPI_ID_TOKEN:
|
|
123
|
+
aud: pypi
|
|
124
|
+
before_script:
|
|
125
|
+
- echo "Publishing to PyPi..."
|
|
126
|
+
script:
|
|
127
|
+
- ./cicd/run_publish.sh
|
|
128
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Read the Docs configuration file
|
|
2
|
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
3
|
+
|
|
4
|
+
# Required
|
|
5
|
+
version: 2
|
|
6
|
+
|
|
7
|
+
# Set the OS, Python version, and other tools you might need
|
|
8
|
+
build:
|
|
9
|
+
os: ubuntu-24.04
|
|
10
|
+
tools:
|
|
11
|
+
python: "3.13"
|
|
12
|
+
jobs:
|
|
13
|
+
install:
|
|
14
|
+
# Since the install step is overridden, pip is no longer updated automatically.
|
|
15
|
+
- pip install --upgrade pip
|
|
16
|
+
- pip install .
|
|
17
|
+
- pip install --group 'docs'
|
|
18
|
+
- pip install --group 'test'
|
|
19
|
+
|
|
20
|
+
# Build documentation in the "docs/" directory with Sphinx
|
|
21
|
+
sphinx:
|
|
22
|
+
configuration: docs/conf.py
|
pyrelukko-0.10.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Reto Zingg <g.d0b3rm4n@gmail.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pyrelukko
|
|
3
|
+
Version: 0.10.0
|
|
4
|
+
Summary: The client library for Relukko can be found in module
|
|
5
|
+
Author-email: Reto Zingg <g.d0b3rm4n@gmail.com>
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Topic :: Internet :: WWW/HTTP
|
|
12
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
License-File: LICENSE
|
|
18
|
+
Requires-Dist: requests >=2.32.5
|
|
19
|
+
Requires-Dist: websockets >= 15.0
|
|
20
|
+
Project-URL: Homepage, https://gitlab.com/relukko/pyrelukko
|
|
21
|
+
Project-URL: Issues, https://gitlab.com/relukko/pyrelukko/-/issues
|
|
22
|
+
|
|
23
|
+
# PyRelukko
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+

|
|
27
|
+

|
|
28
|
+

|
|
29
|
+

|
|
30
|
+

|
|
31
|
+

|
|
32
|
+

|
|
33
|
+

|
|
34
|
+

|
|
35
|
+

|
|
36
|
+

|
|
37
|
+

|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
**PyRelukko** is the official Python client library for the
|
|
42
|
+
[Relukko](https://gitlab.com/relukko/relukko) resource-locking backend. It
|
|
43
|
+
provides a simple, distributed locking mechanism for coordinating access to
|
|
44
|
+
shared resources across multiple Python processes or services.
|
|
45
|
+
|
|
46
|
+
Relukko is intentionally lightweight: it is designed for **collaborative
|
|
47
|
+
environments**. The system assumes clients behave cooperatively, and by design
|
|
48
|
+
it does **not** enforce protection against misbehaving clients.
|
|
49
|
+
|
|
50
|
+
## Documentation
|
|
51
|
+
|
|
52
|
+
Full API documentation can be found at:
|
|
53
|
+
|
|
54
|
+
👉 [https://pyrelukko.readthedocs.io](https://pyrelukko.readthedocs.io)
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
* **Simple, Pythonic API** for acquiring and releasing locks.
|
|
61
|
+
* **Centralized lock management** via the
|
|
62
|
+
[Relukko](https://gitlab.com/relukko/relukko) backend.
|
|
63
|
+
* **Lightweight and dependency-minimal**.
|
|
64
|
+
* **Useful for distributed systems, CI pipelines,
|
|
65
|
+
automated testing and shared-resource orchestration**.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Important Design Note
|
|
70
|
+
|
|
71
|
+
Relukko and PyRelukko are built for *trusted*, *collaborative* clients.
|
|
72
|
+
|
|
73
|
+
### ⚠️ No client-side trust guarantees
|
|
74
|
+
|
|
75
|
+
A client that connects to the Relukko backend **can forcibly release any
|
|
76
|
+
lock**, including those owned by another client. There is **no protection**
|
|
77
|
+
against malicious manipulation of locks.
|
|
78
|
+
|
|
79
|
+
This is an intentional design decision to keep the system simple and
|
|
80
|
+
lightweight.
|
|
81
|
+
|
|
82
|
+
If you require secure, adversarial-resistant locking, you should consider using
|
|
83
|
+
a system built upon consensus algorithms (e.g., etcd, Consul, Zookeeper).
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Ecosystem
|
|
88
|
+
|
|
89
|
+
The Relukko ecosystem consists of the following components:
|
|
90
|
+
|
|
91
|
+
### 1. **Relukko Backend (Rust)**
|
|
92
|
+
|
|
93
|
+
The backend is responsible for storing and arbitrating lock states.
|
|
94
|
+
|
|
95
|
+
Repository: [https://gitlab.com/relukko/relukko](https://gitlab.com/relukko/relukko)
|
|
96
|
+
|
|
97
|
+
### 2. **PyRelukko Client (Python)**
|
|
98
|
+
|
|
99
|
+
This Python package communicates with the backend, providing user-friendly
|
|
100
|
+
locking primitives.
|
|
101
|
+
|
|
102
|
+
Repository: [https://gitlab.com/relukko/pyrelukko](https://gitlab.com/relukko/pyrelukko)
|
|
103
|
+
|
|
104
|
+
👉 [https://pyrelukko.readthedocs.io](https://pyrelukko.readthedocs.io)
|
|
105
|
+
|
|
106
|
+
### 3. **Robotframework-Relukko (Python)**
|
|
107
|
+
|
|
108
|
+
Robot Framework keyword library that enables acquiring and releasing locks
|
|
109
|
+
directly from Robot Framework test suites.
|
|
110
|
+
Depends on **PyRelukko**.
|
|
111
|
+
|
|
112
|
+
Repository: [https://gitlab.com/relukko/robotframework-relukko](https://gitlab.com/relukko/robotframework-relukko)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Installation
|
|
117
|
+
|
|
118
|
+
Install via pip:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
pip install pyrelukko
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Requires Python **3.11+**.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Quick Start
|
|
129
|
+
|
|
130
|
+
### Basic Example
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
from pyrelukko import RelukkoClient
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
relukko = RelukkoClient(
|
|
137
|
+
base_url="http://localhost:3000",
|
|
138
|
+
api_key="api-key",
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
lock = relukko.acquire_relukko("LockName", "Creator", 300)
|
|
142
|
+
lock_id = lock.get('id')
|
|
143
|
+
|
|
144
|
+
# Perform work while holding the lock
|
|
145
|
+
|
|
146
|
+
relukko.delete_relukko(lock_id)
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## When to Use PyRelukko
|
|
152
|
+
|
|
153
|
+
PyRelukko is ideal for:
|
|
154
|
+
|
|
155
|
+
* Distributed test harnesses
|
|
156
|
+
* CI/CD job coordination
|
|
157
|
+
* Server orchestration scripts
|
|
158
|
+
* Managing exclusive access to hardware devices or simulation environments
|
|
159
|
+
* Any cooperative environment where multiple workers need a shared mutex
|
|
160
|
+
|
|
161
|
+
It is **not** designed for untrusted environments or where mutual exclusion
|
|
162
|
+
must be strongly enforced.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
## Limitations
|
|
167
|
+
|
|
168
|
+
* ❗ **A malicious or buggy client can release locks it doesn’t own.**
|
|
169
|
+
* ❗ No cryptographic guarantees or client identity.
|
|
170
|
+
* ❗ Requires a running Relukko backend server.
|
|
171
|
+
* ❗ Not fault-tolerant like consensus-based systems.
|
|
172
|
+
|
|
173
|
+
These limitations are **intentional**, in exchange for simplicity and minimal
|
|
174
|
+
overhead.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Running the Backend
|
|
179
|
+
|
|
180
|
+
The backend is written in Rust and provides a simple HTTP API.
|
|
181
|
+
See the backend repository for instructions:
|
|
182
|
+
|
|
183
|
+
👉 [https://gitlab.com/relukko/relukko](https://gitlab.com/relukko/relukko)
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Contributing
|
|
188
|
+
|
|
189
|
+
Contributions to both the Python client and Rust backend are welcome! Feel
|
|
190
|
+
free to open issues or merge requests in the relevant GitLab repository.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## License
|
|
195
|
+
|
|
196
|
+
MIT License.
|
|
197
|
+
See `LICENSE` for details.
|
|
198
|
+
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# PyRelukko
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+

|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+

|
|
9
|
+

|
|
10
|
+

|
|
11
|
+

|
|
12
|
+

|
|
13
|
+

|
|
14
|
+

|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
**PyRelukko** is the official Python client library for the
|
|
20
|
+
[Relukko](https://gitlab.com/relukko/relukko) resource-locking backend. It
|
|
21
|
+
provides a simple, distributed locking mechanism for coordinating access to
|
|
22
|
+
shared resources across multiple Python processes or services.
|
|
23
|
+
|
|
24
|
+
Relukko is intentionally lightweight: it is designed for **collaborative
|
|
25
|
+
environments**. The system assumes clients behave cooperatively, and by design
|
|
26
|
+
it does **not** enforce protection against misbehaving clients.
|
|
27
|
+
|
|
28
|
+
## Documentation
|
|
29
|
+
|
|
30
|
+
Full API documentation can be found at:
|
|
31
|
+
|
|
32
|
+
👉 [https://pyrelukko.readthedocs.io](https://pyrelukko.readthedocs.io)
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Features
|
|
37
|
+
|
|
38
|
+
* **Simple, Pythonic API** for acquiring and releasing locks.
|
|
39
|
+
* **Centralized lock management** via the
|
|
40
|
+
[Relukko](https://gitlab.com/relukko/relukko) backend.
|
|
41
|
+
* **Lightweight and dependency-minimal**.
|
|
42
|
+
* **Useful for distributed systems, CI pipelines,
|
|
43
|
+
automated testing and shared-resource orchestration**.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Important Design Note
|
|
48
|
+
|
|
49
|
+
Relukko and PyRelukko are built for *trusted*, *collaborative* clients.
|
|
50
|
+
|
|
51
|
+
### ⚠️ No client-side trust guarantees
|
|
52
|
+
|
|
53
|
+
A client that connects to the Relukko backend **can forcibly release any
|
|
54
|
+
lock**, including those owned by another client. There is **no protection**
|
|
55
|
+
against malicious manipulation of locks.
|
|
56
|
+
|
|
57
|
+
This is an intentional design decision to keep the system simple and
|
|
58
|
+
lightweight.
|
|
59
|
+
|
|
60
|
+
If you require secure, adversarial-resistant locking, you should consider using
|
|
61
|
+
a system built upon consensus algorithms (e.g., etcd, Consul, Zookeeper).
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Ecosystem
|
|
66
|
+
|
|
67
|
+
The Relukko ecosystem consists of the following components:
|
|
68
|
+
|
|
69
|
+
### 1. **Relukko Backend (Rust)**
|
|
70
|
+
|
|
71
|
+
The backend is responsible for storing and arbitrating lock states.
|
|
72
|
+
|
|
73
|
+
Repository: [https://gitlab.com/relukko/relukko](https://gitlab.com/relukko/relukko)
|
|
74
|
+
|
|
75
|
+
### 2. **PyRelukko Client (Python)**
|
|
76
|
+
|
|
77
|
+
This Python package communicates with the backend, providing user-friendly
|
|
78
|
+
locking primitives.
|
|
79
|
+
|
|
80
|
+
Repository: [https://gitlab.com/relukko/pyrelukko](https://gitlab.com/relukko/pyrelukko)
|
|
81
|
+
|
|
82
|
+
👉 [https://pyrelukko.readthedocs.io](https://pyrelukko.readthedocs.io)
|
|
83
|
+
|
|
84
|
+
### 3. **Robotframework-Relukko (Python)**
|
|
85
|
+
|
|
86
|
+
Robot Framework keyword library that enables acquiring and releasing locks
|
|
87
|
+
directly from Robot Framework test suites.
|
|
88
|
+
Depends on **PyRelukko**.
|
|
89
|
+
|
|
90
|
+
Repository: [https://gitlab.com/relukko/robotframework-relukko](https://gitlab.com/relukko/robotframework-relukko)
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Installation
|
|
95
|
+
|
|
96
|
+
Install via pip:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
pip install pyrelukko
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Requires Python **3.11+**.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Quick Start
|
|
107
|
+
|
|
108
|
+
### Basic Example
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from pyrelukko import RelukkoClient
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
relukko = RelukkoClient(
|
|
115
|
+
base_url="http://localhost:3000",
|
|
116
|
+
api_key="api-key",
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
lock = relukko.acquire_relukko("LockName", "Creator", 300)
|
|
120
|
+
lock_id = lock.get('id')
|
|
121
|
+
|
|
122
|
+
# Perform work while holding the lock
|
|
123
|
+
|
|
124
|
+
relukko.delete_relukko(lock_id)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## When to Use PyRelukko
|
|
130
|
+
|
|
131
|
+
PyRelukko is ideal for:
|
|
132
|
+
|
|
133
|
+
* Distributed test harnesses
|
|
134
|
+
* CI/CD job coordination
|
|
135
|
+
* Server orchestration scripts
|
|
136
|
+
* Managing exclusive access to hardware devices or simulation environments
|
|
137
|
+
* Any cooperative environment where multiple workers need a shared mutex
|
|
138
|
+
|
|
139
|
+
It is **not** designed for untrusted environments or where mutual exclusion
|
|
140
|
+
must be strongly enforced.
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## Limitations
|
|
145
|
+
|
|
146
|
+
* ❗ **A malicious or buggy client can release locks it doesn’t own.**
|
|
147
|
+
* ❗ No cryptographic guarantees or client identity.
|
|
148
|
+
* ❗ Requires a running Relukko backend server.
|
|
149
|
+
* ❗ Not fault-tolerant like consensus-based systems.
|
|
150
|
+
|
|
151
|
+
These limitations are **intentional**, in exchange for simplicity and minimal
|
|
152
|
+
overhead.
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Running the Backend
|
|
157
|
+
|
|
158
|
+
The backend is written in Rust and provides a simple HTTP API.
|
|
159
|
+
See the backend repository for instructions:
|
|
160
|
+
|
|
161
|
+
👉 [https://gitlab.com/relukko/relukko](https://gitlab.com/relukko/relukko)
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
## Contributing
|
|
166
|
+
|
|
167
|
+
Contributions to both the Python client and Rust backend are welcome! Feel
|
|
168
|
+
free to open issues or merge requests in the relevant GitLab repository.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT License.
|
|
175
|
+
See `LICENSE` for details.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
4
|
+
REPO_DIR="$(readlink -f "${SCRIPT_DIR}/..")"
|
|
5
|
+
PUBLIC_DIR="${REPO_DIR}/public"
|
|
6
|
+
DOCS_DIR="${REPO_DIR}/docs"
|
|
7
|
+
|
|
8
|
+
# Main script execution
|
|
9
|
+
main() {
|
|
10
|
+
rm -rf "${PUBLIC_DIR}"
|
|
11
|
+
mkdir -p "${PUBLIC_DIR}"
|
|
12
|
+
sphinx-build --jobs auto --builder html --write-all "${DOCS_DIR}" "${PUBLIC_DIR}"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# Execute the main function
|
|
16
|
+
main
|
|
17
|
+
|
|
18
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
export FLIT_INDEX_URL="https://upload.pypi.org/legacy/"
|
|
4
|
+
export FLIT_USERNAME="__token__"
|
|
5
|
+
|
|
6
|
+
# Main script execution
|
|
7
|
+
main() {
|
|
8
|
+
echo "CI: ${CI}"
|
|
9
|
+
if [[ "${CI}" == "true" ]]; then
|
|
10
|
+
echo "Push to PyPi!"
|
|
11
|
+
# Retrieve the OIDC token from GitLab CI/CD,
|
|
12
|
+
# and exchange it for a PyPI API token
|
|
13
|
+
oidc_token=$(python -m id PYPI)
|
|
14
|
+
resp=$(curl -X POST https://pypi.org/_/oidc/mint-token \
|
|
15
|
+
-d "{\"token\":\"${oidc_token}\"}")
|
|
16
|
+
api_token=$(jq --raw-output '.token' <<< "${resp}")
|
|
17
|
+
|
|
18
|
+
FLIT_PASSWORD="${api_token}" flit publish
|
|
19
|
+
else
|
|
20
|
+
echo "Running local, will not push to PyPi!"
|
|
21
|
+
fi
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Execute the main function
|
|
25
|
+
main
|
|
26
|
+
|
|
27
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
|
|
3
|
+
SCRIPT_DIR=$(dirname "$(readlink -f "$0")")
|
|
4
|
+
REPO_DIR="$(readlink -f "${SCRIPT_DIR}/..")"
|
|
5
|
+
|
|
6
|
+
# Main script execution
|
|
7
|
+
main() {
|
|
8
|
+
shellcheck "${REPO_DIR}"/cicd/*.sh
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
# Execute the main function
|
|
12
|
+
main
|
|
13
|
+
|
|
14
|
+
# vim:set softtabstop=4 shiftwidth=4 tabstop=4 expandtab:
|
|
Binary file
|