==============
Stormlock
==============
|status| |version|
.. |status| image:: https://github.com/tmccombs/stormlock/workflows/Main/badge.svg
:alt: Build Status
:target: https://github.com/tmccombs/stormlock/actions
.. |version| image:: https://img.shields.io/pypi/v/stormlock
:alt: Version
:target: https://pypi.org/project/stormlock/
.. note:: Stormlock is beta quality and not ready for production use.
Stormlock is a simple centralized locking system primarily intended for human operators (although it may also be useful in some
simple scripting scenarios).
The basic idea is that you acquire a lock by running a command, which gives you a "lease id". That lease id can then be used to
release the lock, or extend its duration. All locks are given a duration after which they are automatically released. The lock is
stored in a backend, which is generally some kind of database.
The intended use case is where you have some kind of operation which happens somewhat infrequently across a distributed system,
and you want to ensure multiple operators don't perform the operation at the same time. For example, this could be used to make sure
to prevent simultaneous attempts to apply infrastructure-as-code changes, database patches, etc. to the same system by different
operators.
This is **not** intended as a general purpose lock. It is designed with the assumption that locks can be held for a long time without
problems (hours or even days), and that the TTL for the lock doesn't need granularity better than a second. Furthermore, the availability
of the lock is a function of the availability of the backend it uses.
Concepts
--------
resource
A unique resource that is protected by a lock. The resource name is used as the key for storing
the lock in the backend.
principal
Who is holding the lock. When a lock is held, an identifier for the principal is stored in the
backend so that it is easy to see who currently has the lock.
backend
Some form of database which stores the state of the lock. Multiple backends are supported, and
it is possible to implement your own plugin to support additional backends.
ttl
Time to live. How long a lease on a lock should live before expiring. Renewing a lease sets
a new time to live.
lease
A handle on an actively held lock. You hold the lock for a resource from the time you acquire
a lease to the time you release it, or the lease expires. Only one lease can exist for a
resource at a time.
lease id
A unique, opaque identifier for a lease. This id is needed to perform operations on a lease,
such as releasing it and renewing it. This id helps ensure multiple leases are not held
for the same resource at the same time.
Configuration
-------------
By default, `stormlock` searches for a configuration file in the following locations (in order):
#. `.stormlock.cfg` in the current directory
#. `$XDG_CONFIG_HOME/stormlock.cfg` (with a default of `XDG_CONFIG_HOME=$HOME/.config`)
#. `$HOME/.stormlock.cfg`
The configuration file is an INI-style config file that looks like this:
.. code-block:: ini
# Default section is used for default configuration for locks.
# If a configuration isn't specified in a more specific section it falls back
# to values in here.
[default]
# ttl is the maximum time a lock can be held without renewing
ttl = 1 days
# principal is an identifier of who is holding the lock
principal = me@example.com
# specify which backend to use
backend = etcd
# Specify configuration for a specific lock
[special]
ttl = 30 minutes
backend = redis
# Backend sections have configuration specific to the backend
[backend.etcd]
host = etcd.example.com
[backend.redis]
url = redis://example.com:6379
Usage
-----
The `stormlock` command can be used to operate on locks using the configuration described above.
The supported operations are:
stormlock acquire [--ttl=\ *TTL*\ ] *RESOURCE*
Attempt to acquire a lease on *RESOURCE*. If successful prints the lease id. Otherwise exit
with an error code.
stormlock release *RESOURCE* *LEASE_ID*
Release the given lease for the given resource. The lease id should be ther result of calling
``stormlock acquire``.
stormlock renew [--ttl=\ *TTL*\ ] *RESOURCE* *LEASE_ID*
Attempt to renew the given lease on the given resource. If the lease is no longer the
active lease for the resource, returns an error code.
stormlock current [--id-only] *RESOURCE*
Retrieve information about the current lease on a resource, if any.
If a lease is active returns a line containing the principal, time the lease was created,
and the lase id seperated by tabs. If ``--id-only`` is passed, only the lease id is printed.
If no lease is active an error message is printed and an error code is returned.
stormlock is-held *RESOURCE* *LEASE_ID*
Test if a lease is currently active. Returns a 0 status code if it is, otherwise returns a
non-zero status code.
A specific configuration file can be specified by either supplying a file with the ``-c`` or
``--config`` options, or with the ``STORMLOCK_CONFIG`` environment variable.
Backends
--------
The currently supported backends are:
* Etcd
* Renewing a lock always uses the same TTL as the original acquisition
* Redis
* DynamoDB
* PostgreSQL
It's also possible to implement your own backend by implementing the ``stormlock.Backend`` interface and registering the class in the
``stormlock.backends`` entry point in python.
Raw data
{
"_id": null,
"home_page": "https://github.com/tmccombs/stormlock",
"name": "stormlock",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.9",
"maintainer_email": null,
"keywords": "lock, cli",
"author": "Thayne McCombs",
"author_email": "astrothayne@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/b8/54/47cbf31879ed04fa4b244ca2834f176e9d9402b9b5218aac0f535b896953/stormlock-0.4.1.tar.gz",
"platform": null,
"description": "==============\nStormlock\n==============\n\n|status| |version|\n\n.. |status| image:: https://github.com/tmccombs/stormlock/workflows/Main/badge.svg\n :alt: Build Status\n :target: https://github.com/tmccombs/stormlock/actions\n.. |version| image:: https://img.shields.io/pypi/v/stormlock\n :alt: Version\n :target: https://pypi.org/project/stormlock/\n\n.. note:: Stormlock is beta quality and not ready for production use.\n\nStormlock is a simple centralized locking system primarily intended for human operators (although it may also be useful in some\nsimple scripting scenarios).\n\nThe basic idea is that you acquire a lock by running a command, which gives you a \"lease id\". That lease id can then be used to\nrelease the lock, or extend its duration. All locks are given a duration after which they are automatically released. The lock is\nstored in a backend, which is generally some kind of database.\n\nThe intended use case is where you have some kind of operation which happens somewhat infrequently across a distributed system,\nand you want to ensure multiple operators don't perform the operation at the same time. For example, this could be used to make sure\nto prevent simultaneous attempts to apply infrastructure-as-code changes, database patches, etc. to the same system by different\noperators.\n\nThis is **not** intended as a general purpose lock. It is designed with the assumption that locks can be held for a long time without\nproblems (hours or even days), and that the TTL for the lock doesn't need granularity better than a second. Furthermore, the availability\nof the lock is a function of the availability of the backend it uses.\n\nConcepts\n--------\n\nresource\n A unique resource that is protected by a lock. The resource name is used as the key for storing\n the lock in the backend.\nprincipal\n Who is holding the lock. When a lock is held, an identifier for the principal is stored in the\n backend so that it is easy to see who currently has the lock.\nbackend\n Some form of database which stores the state of the lock. Multiple backends are supported, and\n it is possible to implement your own plugin to support additional backends.\nttl\n Time to live. How long a lease on a lock should live before expiring. Renewing a lease sets\n a new time to live.\nlease\n A handle on an actively held lock. You hold the lock for a resource from the time you acquire\n a lease to the time you release it, or the lease expires. Only one lease can exist for a\n resource at a time.\nlease id\n A unique, opaque identifier for a lease. This id is needed to perform operations on a lease,\n such as releasing it and renewing it. This id helps ensure multiple leases are not held\n for the same resource at the same time.\n\nConfiguration\n-------------\n\nBy default, `stormlock` searches for a configuration file in the following locations (in order):\n\n#. `.stormlock.cfg` in the current directory\n#. `$XDG_CONFIG_HOME/stormlock.cfg` (with a default of `XDG_CONFIG_HOME=$HOME/.config`)\n#. `$HOME/.stormlock.cfg`\n\nThe configuration file is an INI-style config file that looks like this:\n\n.. code-block:: ini\n\n # Default section is used for default configuration for locks.\n # If a configuration isn't specified in a more specific section it falls back\n # to values in here.\n [default]\n # ttl is the maximum time a lock can be held without renewing\n ttl = 1 days\n # principal is an identifier of who is holding the lock\n principal = me@example.com\n # specify which backend to use\n backend = etcd\n\n # Specify configuration for a specific lock\n [special]\n ttl = 30 minutes\n backend = redis\n\n # Backend sections have configuration specific to the backend\n [backend.etcd]\n host = etcd.example.com\n\n [backend.redis]\n url = redis://example.com:6379\n\nUsage\n-----\n\nThe `stormlock` command can be used to operate on locks using the configuration described above.\n\nThe supported operations are:\n\nstormlock acquire [--ttl=\\ *TTL*\\ ] *RESOURCE*\n Attempt to acquire a lease on *RESOURCE*. If successful prints the lease id. Otherwise exit\n with an error code.\nstormlock release *RESOURCE* *LEASE_ID*\n Release the given lease for the given resource. The lease id should be ther result of calling\n ``stormlock acquire``.\nstormlock renew [--ttl=\\ *TTL*\\ ] *RESOURCE* *LEASE_ID*\n Attempt to renew the given lease on the given resource. If the lease is no longer the\n active lease for the resource, returns an error code.\nstormlock current [--id-only] *RESOURCE*\n Retrieve information about the current lease on a resource, if any.\n\n If a lease is active returns a line containing the principal, time the lease was created,\n and the lase id seperated by tabs. If ``--id-only`` is passed, only the lease id is printed.\n\n If no lease is active an error message is printed and an error code is returned.\nstormlock is-held *RESOURCE* *LEASE_ID*\n Test if a lease is currently active. Returns a 0 status code if it is, otherwise returns a\n non-zero status code.\n\nA specific configuration file can be specified by either supplying a file with the ``-c`` or\n``--config`` options, or with the ``STORMLOCK_CONFIG`` environment variable.\n\nBackends\n--------\n\nThe currently supported backends are:\n\n* Etcd\n * Renewing a lock always uses the same TTL as the original acquisition\n* Redis\n* DynamoDB\n* PostgreSQL\n\nIt's also possible to implement your own backend by implementing the ``stormlock.Backend`` interface and registering the class in the\n``stormlock.backends`` entry point in python.\n",
"bugtrack_url": null,
"license": null,
"summary": "Simple distributed lock with support for multiple backends",
"version": "0.4.1",
"project_urls": {
"Homepage": "https://github.com/tmccombs/stormlock",
"Repository": "https://github.com/tmccombs/stormlock"
},
"split_keywords": [
"lock",
" cli"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "52b9342e8609b37de218b2d55d2e954c6312cd31248f92ef2cabb515d0a57310",
"md5": "fcd8f2ea39868b41c55c827105e62f3c",
"sha256": "0100bc28dc8b1857ecec1e415bd552e5f86990b5602334d4bd0739bee13aecf9"
},
"downloads": -1,
"filename": "stormlock-0.4.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "fcd8f2ea39868b41c55c827105e62f3c",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.9",
"size": 39083,
"upload_time": "2024-10-28T08:19:26",
"upload_time_iso_8601": "2024-10-28T08:19:26.000418Z",
"url": "https://files.pythonhosted.org/packages/52/b9/342e8609b37de218b2d55d2e954c6312cd31248f92ef2cabb515d0a57310/stormlock-0.4.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "b85447cbf31879ed04fa4b244ca2834f176e9d9402b9b5218aac0f535b896953",
"md5": "49cf7eb06b63ab0250c9a8808e1bbffd",
"sha256": "ab235b60065dbc198c352a44b814ff28543811f7c115f6069369dc499930fdbf"
},
"downloads": -1,
"filename": "stormlock-0.4.1.tar.gz",
"has_sig": false,
"md5_digest": "49cf7eb06b63ab0250c9a8808e1bbffd",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.9",
"size": 34478,
"upload_time": "2024-10-28T08:19:27",
"upload_time_iso_8601": "2024-10-28T08:19:27.489838Z",
"url": "https://files.pythonhosted.org/packages/b8/54/47cbf31879ed04fa4b244ca2834f176e9d9402b9b5218aac0f535b896953/stormlock-0.4.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-28 08:19:27",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tmccombs",
"github_project": "stormlock",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "stormlock"
}