Remove rest extension, renaming, delay
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/push-image Pipeline was successful

This commit is contained in:
Ryan Harg 2024-12-03 09:31:52 +01:00
parent 8a25ac45bb
commit 523936efb4
18 changed files with 73 additions and 75 deletions

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>de.rpr</groupId> <groupId>de.rpr</groupId>
<artifactId>ddnsclient</artifactId> <artifactId>ddnsclient</artifactId>
@ -50,11 +51,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>
<artifactId>quarkus-rest</artifactId> <artifactId>quarkus-jackson</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-rest-jackson</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.quarkus</groupId> <groupId>io.quarkus</groupId>

View file

@ -3,17 +3,11 @@ package de.rpr.ddnsclient;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import de.rpr.ddnsclient.model.Config; import de.rpr.ddnsclient.model.Config;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.ws.rs.Produces; import jakarta.enterprise.inject.Produces;
import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.text.MessageFormat;
import java.util.Properties;
public class AppConfig { public class AppConfig {
@ -27,14 +21,4 @@ public class AppConfig {
return objectMapper.readValue(configFile, Config.class); return objectMapper.readValue(configFile, Config.class);
} }
@Produces
@ApplicationScoped
public DirContext dirContext(
@ConfigProperty(name = "ddnsclient.dns.resolver", defaultValue = "9.9.9.9") String dnsServer)
throws NamingException {
Properties env = new Properties();
env.setProperty(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.dns.DnsContextFactory");
env.setProperty(Context.PROVIDER_URL, MessageFormat.format("dns://{0}", dnsServer));
return new InitialDirContext(env);
}
} }

View file

@ -5,6 +5,8 @@ import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import java.util.concurrent.TimeUnit;
@ApplicationScoped @ApplicationScoped
public class Schedule { public class Schedule {
@ -17,7 +19,7 @@ public class Schedule {
this.updater = updater; this.updater = updater;
} }
@Scheduled(every = "${ddnsclient.interval:5m}") @Scheduled(every = "${ddnsclient.interval:5m}", delay = 5, delayUnit = TimeUnit.SECONDS)
void run() { void run() {
log.debug("Starting run()"); log.debug("Starting run()");
updater.run(); updater.run();

View file

@ -4,9 +4,9 @@ import de.rpr.ddnsclient.dyndns.DynDns;
import de.rpr.ddnsclient.dyndns.DyndnsProviderRegistry; import de.rpr.ddnsclient.dyndns.DyndnsProviderRegistry;
import de.rpr.ddnsclient.lookup.DnsResolver; import de.rpr.ddnsclient.lookup.DnsResolver;
import de.rpr.ddnsclient.lookup.PublicIpLookup; import de.rpr.ddnsclient.lookup.PublicIpLookup;
import de.rpr.ddnsclient.model.Addresses;
import de.rpr.ddnsclient.model.Config; import de.rpr.ddnsclient.model.Config;
import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.DyndnsAuth;
import de.rpr.ddnsclient.model.IPs;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
@ -51,7 +51,7 @@ public class Updater {
throw new IllegalStateException("Missing configuration"); throw new IllegalStateException("Missing configuration");
} }
IPs publicIps = publicIpLookup.get(); Addresses publicIps = publicIpLookup.get();
log.debugf("Public ips - v4: %s, v6: %s", publicIps.v4(), publicIps.v6()); log.debugf("Public ips - v4: %s, v6: %s", publicIps.v4(), publicIps.v6());
config.forEach(cfg -> { config.forEach(cfg -> {
@ -64,7 +64,7 @@ public class Updater {
log.debugf("Handling %s.", cfg.hostname()); log.debugf("Handling %s.", cfg.hostname());
IPs registeredIps = dnsResolver.resolve(cfg.hostname()); Addresses registeredIps = dnsResolver.resolve(cfg.hostname());
log.debugf("Registered ips - v4: %s, v6: %s", registeredIps.v4(), registeredIps.v6()); log.debugf("Registered ips - v4: %s, v6: %s", registeredIps.v4(), registeredIps.v6());
if (!publicIps.equals(registeredIps)) { if (!publicIps.equals(registeredIps)) {

View file

@ -1,7 +1,7 @@
package de.rpr.ddnsclient.dyndns; package de.rpr.ddnsclient.dyndns;
import de.rpr.ddnsclient.model.Addresses;
import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.DyndnsAuth;
import de.rpr.ddnsclient.model.IPs;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -26,7 +26,7 @@ public class Ddnss implements DynDns {
return "ddnss"; return "ddnss";
} }
public void update(String hostname, IPs currentIps, DyndnsAuth auth) { public void update(String hostname, Addresses currentIps, DyndnsAuth auth) {
log.tracef("Updating ddnss hostname %s", hostname); log.tracef("Updating ddnss hostname %s", hostname);
try (HttpClient http = httpClientFactory.create()) { try (HttpClient http = httpClientFactory.create()) {
@ -41,7 +41,7 @@ public class Ddnss implements DynDns {
} }
} }
private String getUpdateUrl(String hostname, IPs currentIps, String token) { private String getUpdateUrl(String hostname, Addresses currentIps, String token) {
if (currentIps.v4().isPresent() && currentIps.v6().isPresent()) { if (currentIps.v4().isPresent() && currentIps.v6().isPresent()) {
return MessageFormat.format("https://ddnss.de/upd.php?key={0}&host={1}&ip={2}&ip6={3}", token, hostname, currentIps.v4().get(), currentIps.v6().get()); return MessageFormat.format("https://ddnss.de/upd.php?key={0}&host={1}&ip={2}&ip6={3}", token, hostname, currentIps.v4().get(), currentIps.v6().get());
} else if (currentIps.v4().isPresent()) { } else if (currentIps.v4().isPresent()) {

View file

@ -1,7 +1,7 @@
package de.rpr.ddnsclient.dyndns; package de.rpr.ddnsclient.dyndns;
import de.rpr.ddnsclient.model.Addresses;
import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.DyndnsAuth;
import de.rpr.ddnsclient.model.IPs;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -27,7 +27,7 @@ public class DuckDNS implements DynDns {
} }
@Override @Override
public void update(String hostname, IPs currentIps, DyndnsAuth auth) { public void update(String hostname, Addresses currentIps, DyndnsAuth auth) {
log.tracef("Updating duckdns hostname %s", hostname); log.tracef("Updating duckdns hostname %s", hostname);
try (HttpClient http = httpClientFactory.create()) { try (HttpClient http = httpClientFactory.create()) {
@ -44,7 +44,7 @@ public class DuckDNS implements DynDns {
} }
} }
private String getUpdateUrl(String hostname, IPs currentIps, String token) { private String getUpdateUrl(String hostname, Addresses currentIps, String token) {
if (currentIps.v4().isPresent() && currentIps.v6().isPresent()) { if (currentIps.v4().isPresent() && currentIps.v6().isPresent()) {
return MessageFormat.format("https://www.duckdns.org/update?domains={0}&token={1}&ip={2}&ipv6={3}", hostname, token, currentIps.v4().get(), currentIps.v6().get()); return MessageFormat.format("https://www.duckdns.org/update?domains={0}&token={1}&ip={2}&ipv6={3}", hostname, token, currentIps.v4().get(), currentIps.v6().get());
} else if (currentIps.v4().isPresent()) { } else if (currentIps.v4().isPresent()) {

View file

@ -1,7 +1,7 @@
package de.rpr.ddnsclient.dyndns; package de.rpr.ddnsclient.dyndns;
import de.rpr.ddnsclient.model.Addresses;
import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.DyndnsAuth;
import de.rpr.ddnsclient.model.IPs;
import java.net.URI; import java.net.URI;
import java.net.http.HttpRequest; import java.net.http.HttpRequest;
@ -10,7 +10,7 @@ public interface DynDns {
String name(); String name();
void update(String hostname, IPs currentIps, DyndnsAuth auth); void update(String hostname, Addresses currentIps, DyndnsAuth auth);
default HttpRequest getRequest(String updateUrl) { default HttpRequest getRequest(String updateUrl) {
return HttpRequest.newBuilder() return HttpRequest.newBuilder()

View file

@ -1,6 +1,6 @@
package de.rpr.ddnsclient.lookup; package de.rpr.ddnsclient.lookup;
import de.rpr.ddnsclient.model.IPs; import de.rpr.ddnsclient.model.Addresses;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import org.eclipse.microprofile.config.inject.ConfigProperty; import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -21,10 +21,10 @@ public class DnsJava implements DnsResolver {
} }
@Override @Override
public IPs resolve(String hostname) { public Addresses resolve(String hostname) {
Optional<String> v4 = getIp(hostname, RecordType.A); Optional<String> v4 = getIp(hostname, RecordType.A);
Optional<String> v6 = getIp(hostname, RecordType.AAAA); Optional<String> v6 = getIp(hostname, RecordType.AAAA);
return new IPs(v4, v6); return new Addresses(v4, v6);
} }
private Optional<String> getIp(String hostname, RecordType type) { private Optional<String> getIp(String hostname, RecordType type) {

View file

@ -1,7 +1,7 @@
package de.rpr.ddnsclient.lookup; package de.rpr.ddnsclient.lookup;
import de.rpr.ddnsclient.model.IPs; import de.rpr.ddnsclient.model.Addresses;
public interface DnsResolver { public interface DnsResolver {
IPs resolve(String hostname); Addresses resolve(String hostname);
} }

View file

@ -1,6 +1,6 @@
package de.rpr.ddnsclient.lookup; package de.rpr.ddnsclient.lookup;
import de.rpr.ddnsclient.model.IPs; import de.rpr.ddnsclient.model.Addresses;
import io.quarkus.runtime.StartupEvent; import io.quarkus.runtime.StartupEvent;
import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes; import jakarta.enterprise.event.Observes;
@ -38,7 +38,7 @@ public class PublicIpLookup {
} }
} }
public IPs get() { public Addresses get() {
log.trace("Retrieving public ips."); log.trace("Retrieving public ips.");
try { try {
@ -47,7 +47,7 @@ public class PublicIpLookup {
Optional<String> v4 = getIp(provider, CurlProcessFactory.IpClass.V4); Optional<String> v4 = getIp(provider, CurlProcessFactory.IpClass.V4);
Optional<String> v6 = getIp(provider, CurlProcessFactory.IpClass.V6); Optional<String> v6 = getIp(provider, CurlProcessFactory.IpClass.V6);
return new IPs(v4, v6); return new Addresses(v4, v6);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View file

@ -0,0 +1,26 @@
package de.rpr.ddnsclient.model;
import java.text.MessageFormat;
import java.util.Optional;
public record Addresses(Optional<String> v4, Optional<String> v6) {
public Addresses(String v4, String v6) {
this(Optional.ofNullable(v4), Optional.ofNullable(v6));
}
@SuppressWarnings("OptionalIsPresent")
@Override
public String toString() {
if (v4.isPresent() && v6.isPresent()) {
return MessageFormat.format("v4: {0}, v6: {1}", v4.get(), v6.get());
} else if (v4.isPresent()) {
return MessageFormat.format("v4: {0}, v6: empty", v4.get());
} else if (v6.isPresent()) {
return MessageFormat.format("v4: empty, v6: {0}", v6.get());
} else {
return "v4: empty, v6: empty";
}
}
}

View file

@ -1,11 +0,0 @@
package de.rpr.ddnsclient.model;
import java.util.Optional;
public record IPs(Optional<String> v4, Optional<String> v6) {
public IPs(String v4, String v6) {
this(Optional.ofNullable(v4), Optional.ofNullable(v6));
}
}

View file

@ -1,4 +1,4 @@
quarkus.banner.path=logo-rubifont.txt quarkus.banner.path=logo-rubifont.txt
quarkus.log.level=INFO quarkus.log.level=INFO
quarkus.log.category."de.rpr.ddnsclient".min-level=TRACE quarkus.log.category."de.rpr.ddnsclient".min-level=TRACE
quarkus.log.category."de.rpr.ddnsclient".level=${DDNS_LOG_LEVEL:INFO} quarkus.log.category."de.rpr.ddnsclient".level=${DDNS_LOG_LEVEL:DEBUG}

View file

@ -5,9 +5,9 @@ import de.rpr.ddnsclient.dyndns.DynDns;
import de.rpr.ddnsclient.dyndns.DyndnsProviderRegistry; import de.rpr.ddnsclient.dyndns.DyndnsProviderRegistry;
import de.rpr.ddnsclient.lookup.DnsResolver; import de.rpr.ddnsclient.lookup.DnsResolver;
import de.rpr.ddnsclient.lookup.PublicIpLookup; import de.rpr.ddnsclient.lookup.PublicIpLookup;
import de.rpr.ddnsclient.model.Addresses;
import de.rpr.ddnsclient.model.Config; import de.rpr.ddnsclient.model.Config;
import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.DyndnsAuth;
import de.rpr.ddnsclient.model.IPs;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
@ -46,7 +46,7 @@ class UpdaterTest {
@Test @Test
void should_process_all_config_entries() { void should_process_all_config_entries() {
IPs ips = new IPs("ipv4", "ipv6"); Addresses ips = new Addresses("ipv4", "ipv6");
when(publicIpLookup.get()).thenReturn(ips); when(publicIpLookup.get()).thenReturn(ips);
when(dnsResolver.resolve(any())).thenReturn(ips); when(dnsResolver.resolve(any())).thenReturn(ips);
@ -69,7 +69,7 @@ class UpdaterTest {
@Test @Test
void should_not_trigger_dyndns_update_if_ips_match() { void should_not_trigger_dyndns_update_if_ips_match() {
IPs ips = new IPs("ipv4", "ipv6"); Addresses ips = new Addresses("ipv4", "ipv6");
when(publicIpLookup.get()).thenReturn(ips); when(publicIpLookup.get()).thenReturn(ips);
when(dnsResolver.resolve("example.org")).thenReturn(ips); when(dnsResolver.resolve("example.org")).thenReturn(ips);
@ -88,9 +88,9 @@ class UpdaterTest {
when(dyndnsProviderRegistry.get("ddnss")).thenReturn(ddnss); when(dyndnsProviderRegistry.get("ddnss")).thenReturn(ddnss);
IPs publicIps = new IPs("ipv4", "ipv6"); Addresses publicIps = new Addresses("ipv4", "ipv6");
when(publicIpLookup.get()).thenReturn(publicIps); when(publicIpLookup.get()).thenReturn(publicIps);
when(dnsResolver.resolve("example.org")).thenReturn(new IPs("registered_ipv4", "registered_ipv6")); when(dnsResolver.resolve("example.org")).thenReturn(new Addresses("registered_ipv4", "registered_ipv6"));
Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, ddnssConfig, backoff); Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, ddnssConfig, backoff);
updater.run(); updater.run();
@ -109,9 +109,9 @@ class UpdaterTest {
when(dyndnsProviderRegistry.get("ddnss")).thenReturn(ddnss); when(dyndnsProviderRegistry.get("ddnss")).thenReturn(ddnss);
IPs publicIps = new IPs("ipv4", "ipv6"); Addresses publicIps = new Addresses("ipv4", "ipv6");
when(publicIpLookup.get()).thenReturn(publicIps); when(publicIpLookup.get()).thenReturn(publicIps);
when(dnsResolver.resolve("example.org")).thenReturn(new IPs("registered_ipv4", "registered_ipv6")); when(dnsResolver.resolve("example.org")).thenReturn(new Addresses("registered_ipv4", "registered_ipv6"));
Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, ddnssConfig, backoff); Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, ddnssConfig, backoff);
updater.run(); updater.run();

View file

@ -1,7 +1,7 @@
package de.rpr.ddnsclient.dyndns; package de.rpr.ddnsclient.dyndns;
import de.rpr.ddnsclient.model.Addresses;
import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.DyndnsAuth;
import de.rpr.ddnsclient.model.IPs;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
@ -42,7 +42,7 @@ class DdnssTest {
ddnss.update( ddnss.update(
"example.com", "example.com",
new IPs("ipv4", "ipv6"), new Addresses("ipv4", "ipv6"),
new DyndnsAuth(null, null, "token") new DyndnsAuth(null, null, "token")
); );
@ -66,7 +66,7 @@ class DdnssTest {
dynDns.update( dynDns.update(
"example.com", "example.com",
new IPs("ipv4", null), new Addresses("ipv4", null),
new DyndnsAuth(null, null, "token") new DyndnsAuth(null, null, "token")
); );
@ -87,7 +87,7 @@ class DdnssTest {
dynDns.update( dynDns.update(
"example.com", "example.com",
new IPs(null, "ipv6"), new Addresses(null, "ipv6"),
new DyndnsAuth(null, null, "token") new DyndnsAuth(null, null, "token")
); );

View file

@ -1,7 +1,7 @@
package de.rpr.ddnsclient.dyndns; package de.rpr.ddnsclient.dyndns;
import de.rpr.ddnsclient.model.Addresses;
import de.rpr.ddnsclient.model.DyndnsAuth; import de.rpr.ddnsclient.model.DyndnsAuth;
import de.rpr.ddnsclient.model.IPs;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor; import org.mockito.ArgumentCaptor;
@ -42,7 +42,7 @@ class DuckDNSTest {
dynDns.update( dynDns.update(
"example.com", "example.com",
new IPs("ipv4", "ipv6"), new Addresses("ipv4", "ipv6"),
new DyndnsAuth(null, null, "token") new DyndnsAuth(null, null, "token")
); );
@ -66,7 +66,7 @@ class DuckDNSTest {
dynDns.update( dynDns.update(
"example.com", "example.com",
new IPs("ipv4", null), new Addresses("ipv4", null),
new DyndnsAuth(null, null, "token") new DyndnsAuth(null, null, "token")
); );
@ -87,7 +87,7 @@ class DuckDNSTest {
dynDns.update( dynDns.update(
"example.com", "example.com",
new IPs(null, "ipv6"), new Addresses(null, "ipv6"),
new DyndnsAuth(null, null, "token") new DyndnsAuth(null, null, "token")
); );

View file

@ -1,6 +1,6 @@
package de.rpr.ddnsclient.lookup; package de.rpr.ddnsclient.lookup;
import de.rpr.ddnsclient.model.IPs; import de.rpr.ddnsclient.model.Addresses;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -9,7 +9,7 @@ class DnsJavaTest {
@Test @Test
void test() { void test() {
IPs result = new DnsJava("9.9.9.9").resolve("example.com"); Addresses result = new DnsJava("9.9.9.9").resolve("example.com");
assertThat(result.v4()).isPresent(); assertThat(result.v4()).isPresent();
assertThat(result.v6()).isPresent(); assertThat(result.v6()).isPresent();
} }

View file

@ -1,6 +1,6 @@
package de.rpr.ddnsclient.lookup; package de.rpr.ddnsclient.lookup;
import de.rpr.ddnsclient.model.IPs; import de.rpr.ddnsclient.model.Addresses;
import io.quarkus.runtime.StartupEvent; import io.quarkus.runtime.StartupEvent;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.assertj.core.api.Assertions; import org.assertj.core.api.Assertions;
@ -53,9 +53,9 @@ class PublicIpLookupTest {
PublicIpLookup lookup = new PublicIpLookup(curlProcessFactory, Optional.of("ifconfig.me")); PublicIpLookup lookup = new PublicIpLookup(curlProcessFactory, Optional.of("ifconfig.me"));
lookup.onStart(new StartupEvent()); lookup.onStart(new StartupEvent());
IPs result = lookup.get(); Addresses result = lookup.get();
assertThat(result).isEqualTo(new IPs("ipv4", "ipv6")); assertThat(result).isEqualTo(new Addresses("ipv4", "ipv6"));
ArgumentCaptor<String> providerCaptor = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> providerCaptor = ArgumentCaptor.forClass(String.class);
verify(curlProcessFactory, times(2)).create(providerCaptor.capture(), any()); verify(curlProcessFactory, times(2)).create(providerCaptor.capture(), any());