Rework dyndns provider registry and add tests
All checks were successful
ci/woodpecker/push/build Pipeline was successful

This commit is contained in:
Ryan Harg 2024-11-27 14:11:56 +01:00
parent 98f1a855f7
commit fcac4fb75b
5 changed files with 74 additions and 43 deletions

View file

@ -1,7 +1,7 @@
package de.rpr.ddnsclient; package de.rpr.ddnsclient;
import de.rpr.ddnsclient.dyndns.DynDns; import de.rpr.ddnsclient.dyndns.DynDns;
import de.rpr.ddnsclient.dyndns.DynDnsRouter; 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.Config; import de.rpr.ddnsclient.model.Config;
@ -16,14 +16,13 @@ import java.time.Duration;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.Optional;
@ApplicationScoped @ApplicationScoped
public class Updater { public class Updater {
private static final Logger log = Logger.getLogger(Updater.class); private static final Logger log = Logger.getLogger(Updater.class);
private final DynDnsRouter dynDnsRouter; private final DyndnsProviderRegistry dyndnsProviderRegistry;
private final PublicIpLookup publicIpLookup; private final PublicIpLookup publicIpLookup;
private final DnsResolver dnsResolver; private final DnsResolver dnsResolver;
private final Duration backoff; private final Duration backoff;
@ -33,12 +32,12 @@ public class Updater {
private final Map<String, LocalDateTime> updateMap = new HashMap<>(); private final Map<String, LocalDateTime> updateMap = new HashMap<>();
@Inject @Inject
public Updater(DynDnsRouter dynDnsRouter, public Updater(DyndnsProviderRegistry dyndnsProviderRegistry,
PublicIpLookup publicIpLookup, PublicIpLookup publicIpLookup,
DnsResolver dnsResolver, DnsResolver dnsResolver,
Config config, Config config,
@ConfigProperty(name = "ddnsclient.backoff-duration", defaultValue = "300s") Duration backoff) { @ConfigProperty(name = "ddnsclient.backoff-duration", defaultValue = "300s") Duration backoff) {
this.dynDnsRouter = dynDnsRouter; this.dyndnsProviderRegistry = dyndnsProviderRegistry;
this.publicIpLookup = publicIpLookup; this.publicIpLookup = publicIpLookup;
this.dnsResolver = dnsResolver; this.dnsResolver = dnsResolver;
this.config = config; this.config = config;
@ -70,7 +69,7 @@ public class Updater {
if (!publicIps.equals(registeredIps)) { if (!publicIps.equals(registeredIps)) {
log.tracef("IPs changed, updating..."); log.tracef("IPs changed, updating...");
DynDns dynDns = dynDnsRouter.get(cfg.provider()); DynDns dynDns = dyndnsProviderRegistry.get(cfg.provider());
dynDns.update(cfg.hostname(), publicIps, new DyndnsAuth(null, null, cfg.token())); dynDns.update(cfg.hostname(), publicIps, new DyndnsAuth(null, null, cfg.token()));
updateMap.put(cfg.hostname(), LocalDateTime.now()); updateMap.put(cfg.hostname(), LocalDateTime.now());
} else { } else {

View file

@ -1,27 +0,0 @@
package de.rpr.ddnsclient.dyndns;
import de.rpr.ddnsclient.model.DyndnsAuth;
import io.quarkus.arc.All;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.List;
@ApplicationScoped
public class DynDnsRouter {
private final List<DynDns> dynDnsList;
@SuppressWarnings("CdiInjectionPointsInspection")
@Inject
public DynDnsRouter(@All List<DynDns> dynDnsList) {
this.dynDnsList = dynDnsList;
}
public DynDns get(String name) {
return dynDnsList.stream()
.filter(it -> it.name().equals(name))
.findFirst()
.orElseThrow(() -> new IllegalStateException("Unknown DynDns provider"));
}
}

View file

@ -0,0 +1,30 @@
package de.rpr.ddnsclient.dyndns;
import io.quarkus.arc.All;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@ApplicationScoped
public class DyndnsProviderRegistry {
private final Map<String, DynDns> dynDnsMap;
@SuppressWarnings("CdiInjectionPointsInspection")
public DyndnsProviderRegistry(@All List<DynDns> dynDnsList) {
if (dynDnsList == null || dynDnsList.isEmpty()) {
throw new IllegalStateException("No dyndns services implemented1");
}
this.dynDnsMap = dynDnsList.stream().collect(Collectors.toMap(DynDns::name, dynDns -> dynDns));
}
public DynDns get(String name) {
if (!dynDnsMap.containsKey(name)) {
throw new IllegalStateException("Unknown DynDns provider");
}
return dynDnsMap.get(name);
}
}

View file

@ -2,7 +2,7 @@ package de.rpr.ddnsclient;
import de.rpr.ddnsclient.dyndns.Ddnss; import de.rpr.ddnsclient.dyndns.Ddnss;
import de.rpr.ddnsclient.dyndns.DynDns; import de.rpr.ddnsclient.dyndns.DynDns;
import de.rpr.ddnsclient.dyndns.DynDnsRouter; 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.Config; import de.rpr.ddnsclient.model.Config;
@ -25,7 +25,7 @@ import static org.mockito.Mockito.*;
class UpdaterTest { class UpdaterTest {
@Mock @Mock
DynDnsRouter dynDnsRouter; DyndnsProviderRegistry dyndnsProviderRegistry;
@Mock @Mock
PublicIpLookup publicIpLookup; PublicIpLookup publicIpLookup;
@Mock @Mock
@ -40,7 +40,7 @@ class UpdaterTest {
@Test @Test
void should_throw_exception_if_config_is_empty() { void should_throw_exception_if_config_is_empty() {
Config config = new Config(); Config config = new Config();
Updater updater = new Updater(dynDnsRouter, publicIpLookup, dnsResolver, config, backoff); Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, config, backoff);
Assertions.assertThrows(IllegalStateException.class, updater::run); Assertions.assertThrows(IllegalStateException.class, updater::run);
} }
@ -56,7 +56,7 @@ class UpdaterTest {
add(new Value("ddnss", "host2.example.org", null, null, "token")); add(new Value("ddnss", "host2.example.org", null, null, "token"));
}}; }};
Updater updater = new Updater(dynDnsRouter, publicIpLookup, dnsResolver, multipleConfigEntries, backoff); Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, multipleConfigEntries, backoff);
updater.run(); updater.run();
ArgumentCaptor<String> hostnameCaptor = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> hostnameCaptor = ArgumentCaptor.forClass(String.class);
@ -74,10 +74,10 @@ class UpdaterTest {
when(publicIpLookup.get()).thenReturn(ips); when(publicIpLookup.get()).thenReturn(ips);
when(dnsResolver.resolve("example.org")).thenReturn(ips); when(dnsResolver.resolve("example.org")).thenReturn(ips);
Updater updater = new Updater(dynDnsRouter, publicIpLookup, dnsResolver, ddnssConfig, backoff); Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, ddnssConfig, backoff);
updater.run(); updater.run();
verify(dynDnsRouter, never()).get(any()); verify(dyndnsProviderRegistry, never()).get(any());
} }
@ -86,13 +86,13 @@ class UpdaterTest {
DynDns ddnss = mock(Ddnss.class); DynDns ddnss = mock(Ddnss.class);
when(dynDnsRouter.get("ddnss")).thenReturn(ddnss); when(dyndnsProviderRegistry.get("ddnss")).thenReturn(ddnss);
IPs publicIps = new IPs("ipv4", "ipv6"); IPs publicIps = new IPs("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 IPs("registered_ipv4", "registered_ipv6"));
Updater updater = new Updater(dynDnsRouter, publicIpLookup, dnsResolver, ddnssConfig, backoff); Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, ddnssConfig, backoff);
updater.run(); updater.run();
verify(ddnss).update( verify(ddnss).update(
@ -107,13 +107,13 @@ class UpdaterTest {
DynDns ddnss = mock(Ddnss.class); DynDns ddnss = mock(Ddnss.class);
when(dynDnsRouter.get("ddnss")).thenReturn(ddnss); when(dyndnsProviderRegistry.get("ddnss")).thenReturn(ddnss);
IPs publicIps = new IPs("ipv4", "ipv6"); IPs publicIps = new IPs("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 IPs("registered_ipv4", "registered_ipv6"));
Updater updater = new Updater(dynDnsRouter, publicIpLookup, dnsResolver, ddnssConfig, backoff); Updater updater = new Updater(dyndnsProviderRegistry, publicIpLookup, dnsResolver, ddnssConfig, backoff);
updater.run(); updater.run();
updater.run(); updater.run();

View file

@ -0,0 +1,29 @@
package de.rpr.ddnsclient.dyndns;
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
class DyndnsProviderRegistryTest {
@Test
void empty_dyndns_list_should_throw_exception() {
assertThatExceptionOfType(IllegalStateException.class)
.isThrownBy(() -> new DyndnsProviderRegistry(List.of()));
}
@Test
void existing_dyndns_provider_should_be_returned() {
DyndnsProviderRegistry registry = new DyndnsProviderRegistry(List.of(new Ddnss()));
assertThat(registry.get("ddnss")).isNotNull();
}
@Test
void unknown_dyndns_provider_should_throw_exception() {
DyndnsProviderRegistry registry = new DyndnsProviderRegistry(List.of(new Ddnss()));
assertThatExceptionOfType(IllegalStateException.class).isThrownBy(() -> registry.get("unknown"));
}
}