From 638b7433a716d3f90c980d503ebe19995b5c7b0a Mon Sep 17 00:00:00 2001 From: Richard Kosegi Date: Fri, 21 Oct 2022 09:11:20 +0200 Subject: [PATCH] Serialize access to HetznerCloudResourceManager#createServer() As reported in #57, there is small window of oportunity for race condition during server creation. Primary IP allocation and server creation are two separate API calls that can't be done atomically. By serializing access to this method, this could be further mitigated as HetznerCloud instance is using same instance of HetznerCloudResourceManager during its lifecycle. This fix won't prevent problems done externally. Closes #57 --- .../jenkins/plugins/hetzner/HetznerCloudResourceManager.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/cloud/dnation/jenkins/plugins/hetzner/HetznerCloudResourceManager.java b/src/main/java/cloud/dnation/jenkins/plugins/hetzner/HetznerCloudResourceManager.java index a67a326..0b65e06 100644 --- a/src/main/java/cloud/dnation/jenkins/plugins/hetzner/HetznerCloudResourceManager.java +++ b/src/main/java/cloud/dnation/jenkins/plugins/hetzner/HetznerCloudResourceManager.java @@ -54,6 +54,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.function.Function; import java.util.stream.Collectors; @@ -68,6 +69,7 @@ public class HetznerCloudResourceManager { @NonNull private final String credentialsId; + private final ReentrantReadWriteLock lock = new ReentrantReadWriteLock(); public static HetznerCloudResourceManager create(String credentialsId) { return new HetznerCloudResourceManager(credentialsId); @@ -222,6 +224,7 @@ public HetznerServerInfo refreshServerInfo(HetznerServerInfo info) { */ public HetznerServerInfo createServer(HetznerServerAgent agent) { try { + lock.writeLock().lock(); final SshKeyDetail sshKey = getOrCreateSshKey(agent.getTemplate()); final String imageId; //check if image is label expression @@ -271,6 +274,8 @@ public HetznerServerInfo createServer(HetznerServerAgent agent) { return info; } catch (IOException e) { throw new IllegalStateException(e); + } finally { + lock.writeLock().unlock(); } }