https://github.com/jenkinsci/lockable-resources-plugin
Lock resources against concurrent use
https://github.com/jenkinsci/lockable-resources-plugin
jenkins-plugin pipeline
Last synced: 5 months ago
JSON representation
Lock resources against concurrent use
- Host: GitHub
- URL: https://github.com/jenkinsci/lockable-resources-plugin
- Owner: jenkinsci
- License: mit
- Created: 2013-12-11T12:23:19.000Z (almost 12 years ago)
- Default Branch: master
- Last Pushed: 2025-05-05T20:49:58.000Z (5 months ago)
- Last Synced: 2025-05-05T21:48:53.645Z (5 months ago)
- Topics: jenkins-plugin, pipeline
- Language: Java
- Homepage: https://plugins.jenkins.io/lockable-resources
- Size: 1.92 MB
- Stars: 90
- Watchers: 109
- Forks: 190
- Open Issues: 117
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.old.md
- Contributing: CONTRIBUTING.md
- License: LICENSE.txt
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# Jenkins Lockable Resources Plugin
[](https://plugins.jenkins.io/lockable-resources)
[](https://github.com/jenkinsci/lockable-resources-plugin/releases/latest)
[](https://plugins.jenkins.io/lockable-resources)
[](https://ci.jenkins.io/job/Plugins/job/lockable-resources-plugin/job/master/)
[](https://github.com/jenkinsci/lockable-resources-plugin/blob/master/LICENSE.txt)
[](https://github.com/jenkinsci/lockable-resources-plugin)
[](https://jenkins.crowdin.com/lockable-resources-plugin)
[](https://gitter.im/jenkinsci/lockable-resources?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)This plugin allows defining lockable resources (such as printers, phones,
computers, etc.) that can be used by builds. If a build requires a resource
which is already locked, it will wait for the resource to be free.----
## Support“Open source” does not mean “includes free support”
You can support the contributor and buy him a coffee.
[](https://www.buymeacoffee.com/mpokornyetm)
Every second invested in an open-source project is a second you can't invest in your own family / friends / hobby.
That`s the reason, why supporting the contributors is so important.Thx very much for supporting us.
----
## Usage
### Adding lockable resources
1. In *Manage Jenkins* > *Configure System* go to **Lockable Resources
Manager**
2. Select *Add Lockable Resource*Each lockable resource has the following properties:
- **Name** - A mandatory name (not containing spaces!) for this particular resource, i.e.
`DK_Printer_ColorA3_2342`
- **Description** - Optional verbose description of this particular resource,
i.e. `Printers in the Danish Office`
- **Labels** - Optional space-delimited list of Labels (A label can not containing spaces) used to
identify a pool of resources. i.e. `DK_Printers_Office Country:DK device:printer`,
`DK_Printer_Production`, `DK_Printer_Engineering`
- **Reserved by** - Optional reserved / locked cause. If non-empty,
the resource will be unavailable for jobs. i.e. `All printers are currently not available due to maintenance.`
This option is still possible, but we recommend to use the page `/lockable-resources/`A resource is always the one thing that is locked (or free or reserved).
It exists once and has an unique name (if we take the hardware example, this may be `office_printer_14`).
Every resource can have multiple labels (the printer could be labeled `dot-matrix-printer`, `in-office-printer`, `a4-printer`, etc.).
All resources with the same label form a "pool", so if you try to lock an `a4-printer`, one of the resources with the label `a4-printer` will be locked when it is available.
If all resources with the label `a4-printer` are in use, your job waits until one is available.
This is similar to nodes and node labels.### Using a resource in a freestyle job
When configuring the job, select **This build requires lockable resources**.
Please see the help item for each field for details.### Using a resource in a pipeline job
When the `lock` step is used in a Pipeline, if the resource to be locked isn't
already defined in the Jenkins global configuration, an ephemeral resource is
used: These resources only exist as long as any running build is referencing
them.Examples:
#### Acquire lock
Example for scripted pipeline:
```groovy
echo 'Starting'
lock('my-resource-name') {
echo 'Do something here that requires unique access to the resource'
// any other build will wait until the one locking the resource leaves this block
}
echo 'Finish'```
Example for declarative pipeline:
```groovy
pipeline {
agent anystages {
stage("Build") {
steps {
lock(label: 'printer', quantity: 1, resource : null) {
echo 'printer locked'
}
}
}
}
}
```Setting `quantity` to `null`, `0` or a smaller number, all available resources of that label are locked at once.
#### Take first position in queue
```groovy
lock(resource: 'staging-server', inversePrecedence: true) {
node {
servers.deploy 'staging'
}
input message: "Does ${jettyUrl}staging/ look good?"
}
```> It is not allowed to mixed **inversePrecedence** and **priority**.
start time | job | resource | inversePrecedence
------ |--- |--- |---
00:01 | j1 | resource1 | false
00:02 | j2 | resource1 | false
00:03 | j3 | resource1 | true
00:04 | j4 | resource1 | false
00:05 | j5 | resource1 | true
00:06 | j6 | resource1 | falseResulting lock order: j1 -> j5 -> j3 -> j2 -> j4 -> j6
#### lock (queue) priority
```groovy
lock(resource: 'staging-server', priority: 10) {
node {
servers.deploy 'staging'
}
input message: "Does ${jettyUrl}staging/ look good?"
}
```start time | job | resource | priority
------ |--- |--- |---
00:01 | j1 | resource1 | 0
00:02 | j2 | resource1 |
00:03 | j3 | resource1 | -1
00:04 | j4 | resource1 | 10
00:05 | j5 | resource1 | -2
00:06 | j6 | resource1 | 100Resulting lock order: j1 -> j6 -> j4 -> j2 -> j3 -> j5
#### Resolve a variable configured with the resource name and properties
```groovy
lock(label: 'some_resource', variable: 'LOCKED_RESOURCE') {
echo env.LOCKED_RESOURCE
echo env.LOCKED_RESOURCE0_PROP_ABC
}
```When multiple locks are acquired, each will be assigned to a numbered variable:
```groovy
lock(label: 'some_resource', variable: 'LOCKED_RESOURCE', quantity: 2) {
// comma separated names of all acquired locks
echo env.LOCKED_RESOURCE// first lock
echo env.LOCKED_RESOURCE0
echo env.LOCKED_RESOURCE0_PROP_ABC// second lock
echo env.LOCKED_RESOURCE1
echo env.LOCKED_RESOURCE1_PROP_ABC
}
```#### Skip executing the block if there is a queue
```groovy
lock(resource: 'some_resource', skipIfLocked: true) {
echo 'Do something now or never!'
}
```Detailed documentation can be found as part of the
[Pipeline Steps](https://jenkins.io/doc/pipeline/steps/lockable-resources/)
documentation.### Jenkins label parser allows sophisticated filtering
The plugin uses the Jenkins-internal label parser for filtering lockable resources. A full list of supported operators and syntax examples can be found in the [official documentation](https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#node-allocate-node).
```groovy
lock(label: 'labelA && labelB', variable : 'someVar') {
echo 'labelA && labelB acquired by: ' + env.someVar;
}lock(label: 'labelA || labelB', variable : 'someVar') {
echo 'labelA || labelB acquired by: ' + env.someVar;
}lock(label: 'labelA || labelB || labelC', variable : 'someVar', quantity : 100) {
echo 'labelA || labelB || labelC acquired by: ' + env.someVar;
}
```#### Multiple resource lock
```groovy
lock(label: 'label1', extra: [[resource: 'resource1']]) {
echo 'Do something now or never!'
}
echo 'Finish'
``````groovy
lock(
variable: 'var',
extra: [
[resource: 'resource4'],
[resource: 'resource2'],
[label: 'label1', quantity: 2]
]
) {
def lockedResources = env.var.split(',').sort()
echo "Resources locked: ${lockedResources}"
}
echo 'Finish'
```More examples are [here](src/doc/examples/readme.md).
----
## Node mirroring
Lockable resources plugin allow to mirror nodes (agents) into lockable resources. This eliminate effort by re-creating resources on every node change.
That means when you create new node, it will be also created new lockable-resource with the same name. When the node has been deleted, lockable-resource will be deleted too.
Following properties are mirrored:
- name.
- labels. Please note, that labels still contains node-name self.
- description.To allow this behavior start jenkins with option `-Dorg.jenkins.plugins.lockableresources.ENABLE_NODE_MIRROR=true` or run this groovy code.
```groovy
System.setProperty("org.jenkins.plugins.lockableresources.ENABLE_NODE_MIRROR", "true");
```> *Note:* When the node has been deleted, during the lockable-resource is locked / reserved / queued, then the lockable-resource will be NOT deleted.
----
## Improve performance
To be safe thread over all jobs and resources, need to be all operations synchronized.
This might lead to slow down your jobs. The jenkins self, has low CPU usage, but your jobs are very slow. Why?The most time are spend to write the lockable-resources states into local file system. This is important to get the correct state after Jenkins reboots.
To eliminate this saving time has been added a property *DISABLE_SAVE*.
+ The best way is to use it with JCaC plugin. So you are sure, you have still correct
resources on Jenkins start.
+ When you set pipeline durability level to *PERFORMANCE_OPTIMIZED*, it makes also sense to set this property to true.> *Note:* Keep in mind, that you will lost all your manual changes!
> *Note:* This option is experimental. It has been tested in many scenarios, but no body know.
To allow this behavior start jenkins with option `-Dorg.jenkins.plugins.lockableresources.DISABLE_SAVE=true` or run this groovy code.
```groovy
System.setProperty("org.jenkins.plugins.lockableresources.DISABLE_SAVE", "true");
```## Detailed lock cause
Tle plugin step lock() will inform you in the build log detailed block cause. The size of cause depends on count of ordered resources and size of current queue. To eliminate big unreadable logs we limited the size. To see all cause change the properties as follow:
```groovy
System.setProperty("org.jenkins.plugins.lockableresources.PRINT_BLOCKED_RESOURCE", "-1");
System.setProperty("org.jenkins.plugins.lockableresources.PRINT_QUEUE_INFO", "-1");
```*PRINT_BLOCKED_RESOURCE* means how many of ordered resources are printed. Per default 2.
*PRINT_QUEUE_INFO* how many queue items are printed. Per default 2.0 means disabled
-1 means all / unlimited.## Configuration as Code
This plugin can be configured via
[Configuration-as-Code](https://github.com/jenkinsci/configuration-as-code-plugin).### Example configuration
```yml
unclassified:
lockableResourcesManager:
declaredResources:
- name: "S7_1200_1"
description: "S7 PLC model 1200"
labels: "plc:S7 model:1200"
reservedBy: "Reserved due maintenance window"
- name: "S7_1200_2"
labels: "plc:S7 model:1200"
- name: "Resource-with-properties"
properties:
- name: "Property-A"
value: "Value"
```Properties *description*, *labels* and *reservedBy* are optional.
----
## lockable-resources overview
The page `/lockable-resources/` provides an overview over all lockable-resources.
### Resources
Provides an status overview over all resources and actions to change resource status.
Name | Permission | Description
-----|------------|------------
Reserve | RESERVE | Reserves an available resource for currently logged user indefinitely (until that person, or some explicit scripted action, decides to release the resource).
Unreserve | RESERVE | Un-reserves a resource that may be reserved by some person already. The user can unreserve only own resource. Administrator can unreserve any resource.
Unlock | UNLOCK | Unlocks a resource that may be or not be locked by some job (or reserved by some user) already.
Steal lock | STEAL | Reserves a resource that may be or not be locked by some job (or reserved by some user) already. Giving it away to currently logged user indefinitely (until that person, or some explicit scripted action, later decides to release the resource).
Reassign | STEAL | Reserves a resource that may be or not be reserved by some person already. Giving it away to currently logged user indefinitely (until that person, or some explicit scripted action, decides to release the resource).
Reset | UNLOCK | Reset a resource that may be reserved, locked or queued.
Note | RESERVE | Add or edit resource note.### Labels
Provides an overview over all lockable-resources labels.
> *Note:* Please keep in mind, that lockable-resource-label is not the same as node-label!
### Queue
Provides an overview over currently queued requests.
A request is queued by the pipeline step `lock()`. When the requested resource(s) is currently in use (not free), then any new request for this resource will be added into the queue.A resource may be requested by:
- name, such as in `lock('ABC') { ... }`
- label, such as in `lock(label : 'COFFEE_MACHINE')`> *Note:* Please keep in mind that groovy expressions are currently supported only in free-style jobs. Free-style jobs do not update this queue and therefore can not be shown in this view.
> *Note:* An empty value in the column 'Requested at' means that this build has been started in an older plugin version - [1117.v157231b_03882](https://github.com/jenkinsci/lockable-resources-plugin/releases/tag/1117.v157231b_03882) and early. In this case we cannot recognize the timestamp.
----
## Upgrading from 1102.vde5663d777cf
Due an [issue](https://github.com/jenkinsci/lockable-resources-plugin/issues/434) **is not possible anymore to read resource-labels** from the config file org.jenkins.plugins.lockableresources.LockableResourcesManager.xml, **which is generated in the release** [1102.vde5663d777cf](https://github.com/jenkinsci/lockable-resources-plugin/releases/tag/1102.vde5663d777cf)
This issue does not **effect** instances configured by [Configuration-as-Code](https://github.com/jenkinsci/configuration-as-code-plugin) plugin.
A possible solution is to remove the `` tags from your `org.jenkins.plugins.lockableresources.LockableResourcesManager.xml` config file manually, before you upgrade to new version (Keep in mind that a backup is still good idea).
Example:
change this one
```xml
tests-integration-installation
```
to
```xml
tests-integration-installation
```
----
## Changelog
- See [GitHub Releases](https://github.com/jenkinsci/lockable-resources-plugin/releases)
for recent versions.
- See the [old changelog](CHANGELOG.old.md) for versions 2.5 and older.----
## Report an Issue
Please report issues and enhancements through the [Jenkins issue tracker in GitHub](https://github.com/jenkinsci/lockable-resources-plugin/issues/new/choose)
----
## Contributing
Contributions are welcome, please
refer to the separate [CONTRIBUTING](CONTRIBUTING.md) document
for details on how to proceed!
Join [Gitter channel](https://gitter.im/jenkinsci/lockable-resources) to discuss your ideas with the community.----
## License
All source code is licensed under the MIT license.
See [LICENSE](LICENSE.txt)