I'm using the "Locable Resources Plugin" together with the Jenkins multipipeline functionality:
lock('my-resource-name') {
}
I have a situation where I need to lock a resource in one pipeline and unlock it in another. I have workarounds, but I would prefer using the lock plugin, if possible.
I imagagine something like this
lock("my-resource-name")
.....
unlock("my-resource-name)
I'm implementing canary releases, and there are three different paths through my pipeline (I considered other solutions, like pausing the pipeline with the input plugin - providing me with more is out of scope for this question).
I would like to lock/halt the pipeline while the canary is evaluated, and then, when the promotion or rollback is done, unlock it again.
Omitting the body for the lock
statement just gives me java.lang.IllegalStateException: There is no body to invoke
The lock step limits the number of builds running concurrently in a section of your Pipeline while the milestone step ensures that older builds of a job will not overwrite a newer build. Concurrent builds of the same job do not always run at the same rate.
The lock can be done this way
import org.jenkins.plugins.lockableresources.LockableResource
import org.jenkins.plugins.lockableresources.LockableResourcesManager
...
LockableResourcesManager lockableResourcesManager = LockableResourcesManager.get()
LockableResource lockableResource = lockableResourcesManager.fromName(resourceName)
// if the resource doesn't exists, create it
if (lockableResource == null) {
lockableResourcesManager.createResource(resourceName)
lockableResource = lockableResourcesManager.fromName(resourceName)
}
// wait until lock is successful
waitUntil { lockableResourcesManager.lock([lockableResource].toSet(), currentBuild.rawBuild, null) }
The unlock is much simpler because you know the resource exists (if it doesn't there is no reason to try to unlock it)
LockableResourcesManager lockableResourcesManager = LockableResourcesManager.get()
LockableResource lockableResource = lockableResourcesManager.fromName(resourceName)
// do not pass currentBuild.rawBuild as in your case is not the build that locked this resource
// so I am passing null instead
lockableResourcesManager.unlock([lockableResource], null)
Note that I used to test this org.6wind.jenkins:lockable-resources:2.7
, the implementation details may vary depending on the version used.
<dependency>
<groupId>org.6wind.jenkins</groupId>
<artifactId>lockable-resources</artifactId>
<version>2.7</version>
<scope>provided</scope>
</dependency>
One way of doing it is this:
curl -XGET https://your-jenkins/lockable-resources/reserve?resource=myresource
curl -XGET https://your-jenkins/lockable-resources/unreserve?resource=myresource
The GET is not a mistake, it really is GET.
To wait for a lock
lock("my-resource-name") {}
I also know Jenkins support something called "milestones" apparently is something used to communicate between builds. But I have no idea if it can be used to solve this problem in any meaningful way.
from LockableResourcesManager get each lock, then foreach lock do if lock.getName matches then do lock.reset() to release the lock
e.g. some groovy to find locked locks not owned by any builds and clean them up:
print "START\n"
def all_lockable_resources = org.jenkins.plugins.lockableresources.LockableResourcesManager.get().resources
all_lockable_resources.each { r->
if (r.isLocked() || r.isReserved()) {
println "Lock " + r + " is locked or reserved by " + r.getBuild() + " B CARSE " + r.getLockCause()
b = r.getBuild()
if (b) {
if (b.isBuilding()) { println "build:" + b + " is building" }
if (b.getResult().equals(null)) { println "build:" + b + " result is not in yet" }
if ( ! b.isBuilding() && ! b.getResult().equals(null)) {
println "build:" + b + " is not building and result is " + b.getResult() + " yet the lock " + r + " is locked."
println "ACTION RELEASE LOCK " + r
println "getLockCause:" + r.getLockCause()
println "getDescription:" + r.getDescription()
println "getReservedBy:" + r.getReservedBy()
println "isReserved:" + r.isReserved()
println "isLocked:" + r.isLocked()
println "isQueued:" + r.isQueued()
//release the lock
r.reset()
println "getLockCause:" + r.getLockCause()
println "getDescription:" + r.getDescription()
println "getReservedBy:" + r.getReservedBy()
println "isReserved:" + r.isReserved()
println "isLocked:" + r.isLocked()
println "isQueued:" + r.isQueued()
}
}
}
}
API: http://javadoc.jenkins.io/plugin/lockable-resources/org/jenkins/plugins/lockableresources/LockableResource.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With