Skip to content

Commit ea58a4b

Browse files
authored
Merge pull request #605 from mageddo/develop
Develop Merge
2 parents 7e3973e + de22177 commit ea58a4b

File tree

9 files changed

+267
-11
lines changed

9 files changed

+267
-11
lines changed

Diff for: RELEASE-NOTES.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
## 3.32.3
2+
* Ignoring containers which fails to inspect. #599
3+
14
## 3.32.2
25
* Exposing Stub Solver domain config, see the docs. #545
36

@@ -31,7 +34,7 @@
3134

3235
## 3.30.0
3336
* Module to beans which need to initialize on app startup, different of StartupEvent,
34-
Eager are not coupled to DPS logic.
37+
Eager are not coupled to DPS logic.
3538

3639
## 3.29.0
3740
* Implementing an IntTest which can validate the happy path of all DPS solvers,

Diff for: gradle.properties

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
version=3.32.2-snapshot
1+
version=3.32.3-snapshot

Diff for: src/main/java/com/mageddo/dnsproxyserver/docker/dataprovider/ContainerFacade.java

+5
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.github.dockerjava.api.model.Container;
55

66
import java.util.List;
7+
import java.util.stream.Stream;
78

89
public interface ContainerFacade {
910

@@ -12,4 +13,8 @@ public interface ContainerFacade {
1213
List<Container> findActiveContainers();
1314

1415
InspectContainerResponse inspect(String id);
16+
17+
InspectContainerResponse safeInspect(String id);
18+
19+
Stream<InspectContainerResponse> inspectFilteringValidContainers(List<Container> containers);
1520
}

Diff for: src/main/java/com/mageddo/dnsproxyserver/docker/dataprovider/ContainerFacadeDefault.java

+25
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import com.github.dockerjava.api.DockerClient;
44
import com.github.dockerjava.api.command.InspectContainerResponse;
5+
import com.github.dockerjava.api.exception.NotFoundException;
56
import com.github.dockerjava.api.model.Container;
67
import com.mageddo.dnsproxyserver.docker.application.Containers;
78
import lombok.RequiredArgsConstructor;
@@ -12,6 +13,8 @@
1213
import javax.inject.Singleton;
1314
import java.util.Collections;
1415
import java.util.List;
16+
import java.util.Objects;
17+
import java.util.stream.Stream;
1518

1619
@Slf4j
1720
@Default
@@ -47,4 +50,26 @@ public List<Container> findActiveContainers() {
4750
public InspectContainerResponse inspect(String id) {
4851
return this.dockerClient.inspectContainerCmd(id).exec();
4952
}
53+
54+
@Override
55+
public InspectContainerResponse safeInspect(String id) {
56+
try {
57+
return this.inspect(id);
58+
} catch (NotFoundException e) {
59+
log.warn("status=container-not-found, action=inspect-container, containerId={}", id);
60+
} catch (Exception e) {
61+
log.warn("status=unexpected-exception, action=inspect-container, containerId={}, msg={}", id, e.getMessage(), e);
62+
}
63+
return null;
64+
}
65+
66+
@Override
67+
public Stream<InspectContainerResponse> inspectFilteringValidContainers(List<Container> containers) {
68+
return containers
69+
.stream()
70+
.map(com.github.dockerjava.api.model.Container::getId)
71+
.map(this::safeInspect)
72+
.filter(Objects::nonNull)
73+
;
74+
}
5075
}

Diff for: src/main/java/com/mageddo/dnsproxyserver/solver/docker/dataprovider/ContainerDAODefault.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ public class ContainerDAODefault implements ContainerDAO {
2626

2727
@Override
2828
public List<Container> findActiveContainersMatching(HostnameQuery query) {
29-
return this.containerFacade.findActiveContainers()
30-
.stream()
31-
.map(it -> this.containerFacade.inspect(it.getId()))
29+
final var containersToFilter = this.containerFacade.findActiveContainers();
30+
return this.containerFacade.inspectFilteringValidContainers(containersToFilter)
3231
.filter(ContainerHostnameMatcher.buildPredicate(query))
3332
.map(ContainerMapper::of)
3433
.toList();

Diff for: src/main/java/com/mageddo/dnsproxyserver/solver/docker/dataprovider/DpsContainerDAODefault.java

+1-3
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,8 @@ public Container findDPSContainer() {
5252
} else {
5353
log.debug("dpsContainersFound={}", containers.size());
5454
}
55-
return containers
56-
.stream()
55+
return this.containerFacade.inspectFilteringValidContainers(containers)
5756
.findFirst()
58-
.map(it -> this.containerFacade.inspect(it.getId()))
5957
.map(ContainerMapper::of)
6058
.orElse(null);
6159
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
package com.mageddo.dnsproxyserver.docker.dataprovider;
2+
3+
import com.github.dockerjava.api.DockerClient;
4+
import com.github.dockerjava.api.model.Container;
5+
import org.junit.jupiter.api.BeforeEach;
6+
import org.junit.jupiter.api.Test;
7+
import org.junit.jupiter.api.extension.ExtendWith;
8+
import org.mockito.junit.jupiter.MockitoExtension;
9+
import testing.templates.docker.ContainerTemplates;
10+
import testing.templates.docker.DockerClientTemplates;
11+
import testing.templates.docker.InspectContainerResponseTemplates;
12+
13+
import java.util.ArrayList;
14+
15+
import static org.junit.jupiter.api.Assertions.assertEquals;
16+
import static org.junit.jupiter.api.Assertions.assertNull;
17+
import static org.mockito.Mockito.doReturn;
18+
import static org.mockito.Mockito.spy;
19+
20+
@ExtendWith(MockitoExtension.class)
21+
class ContainerFacadeDefaultCompTest {
22+
23+
ContainerFacadeDefault dao;
24+
25+
DockerClient dockerClient;
26+
27+
@BeforeEach
28+
void before(){
29+
this.dockerClient = DockerClientTemplates.buildSpy();
30+
this.dao = spy(new ContainerFacadeDefault(this.dockerClient));
31+
}
32+
33+
@Test
34+
void mustFindContainerById(){
35+
// arrange
36+
final var mockReturn = new ArrayList<Container>();
37+
mockReturn.add(ContainerTemplates.buildDpsContainer());
38+
mockReturn.add(ContainerTemplates.buildRegularContainerCoffeeMakerCheckout());
39+
40+
final var containerId = mockReturn.get(0).getId();
41+
42+
final var inspectContainerCmd = this.dockerClient.listContainersCmd();
43+
doReturn(mockReturn)
44+
.when(inspectContainerCmd)
45+
.exec()
46+
;
47+
48+
// act
49+
final var container = this.dao.findById(containerId);
50+
51+
// assert
52+
assertEquals(mockReturn.get(0), container);
53+
}
54+
55+
@Test
56+
void mustReturnNullWhenFindContainerByIdNotFound(){
57+
// arrange
58+
final var mockReturn = new ArrayList<Container>();
59+
60+
final var containerId = "abc123";
61+
62+
final var listContainerCmd = this.dockerClient.listContainersCmd();
63+
doReturn(mockReturn)
64+
.when(listContainerCmd)
65+
.exec()
66+
;
67+
68+
// act
69+
final var container = this.dao.findById(containerId);
70+
71+
// assert
72+
assertNull(container);
73+
}
74+
75+
@Test
76+
void mustListActiveContainers(){
77+
// arrange
78+
final var expected = new ArrayList<Container>();
79+
expected.add(ContainerTemplates.buildRegularContainerCoffeeMakerCheckout());
80+
81+
final var listContainerCmd = this.dockerClient.listContainersCmd();
82+
doReturn(expected)
83+
.when(listContainerCmd)
84+
.exec()
85+
;
86+
87+
// act
88+
final var findActiveContainersResponse = this.dao.findActiveContainers();
89+
90+
// assert
91+
assertEquals(expected, findActiveContainersResponse);
92+
}
93+
94+
@Test
95+
void mustInspectContainerById(){
96+
// arrange
97+
final var expected = InspectContainerResponseTemplates.ngixWithDefaultBridgeNetworkOnly();
98+
final var containerId = expected.getId();
99+
100+
final var inspectContainerCmd = this.dockerClient.inspectContainerCmd(containerId);
101+
doReturn(expected)
102+
.when(inspectContainerCmd)
103+
.exec()
104+
;
105+
106+
// act
107+
final var inspectResponse = this.dao.inspect(containerId);
108+
109+
// assert
110+
assertEquals(expected, inspectResponse);
111+
}
112+
113+
114+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package com.mageddo.dnsproxyserver.docker.dataprovider;
2+
3+
import com.github.dockerjava.api.exception.NotFoundException;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.api.extension.ExtendWith;
6+
import org.mockito.InjectMocks;
7+
import org.mockito.Spy;
8+
import org.mockito.junit.jupiter.MockitoExtension;
9+
import testing.templates.docker.ContainerTemplates;
10+
import testing.templates.docker.InspectContainerResponseTemplates;
11+
12+
import java.util.List;
13+
14+
import static org.junit.jupiter.api.Assertions.assertEquals;
15+
import static org.junit.jupiter.api.Assertions.assertNull;
16+
import static org.mockito.Mockito.doReturn;
17+
import static org.mockito.Mockito.doThrow;
18+
19+
@ExtendWith(MockitoExtension.class)
20+
class ContainerFacadeDefaultTest {
21+
22+
@Spy
23+
@InjectMocks
24+
ContainerFacadeDefault facade;
25+
26+
@Test
27+
void mustNotThrowErrorWhenInspectContainerGetNotFound() {
28+
// arrange
29+
final var containerId = "a39bba9a8bab2899";
30+
31+
doThrow(new NotFoundException("Container not found"))
32+
.when(this.facade).inspect(containerId)
33+
;
34+
35+
// act
36+
final var container = this.facade.safeInspect(containerId);
37+
38+
// assert
39+
assertNull(container);
40+
}
41+
42+
@Test
43+
void mustNotThrowErrorWhenInspectContainerFails() {
44+
// arrange
45+
final var containerId = "a39bba9a8bab28aa";
46+
47+
doThrow(new NullPointerException("Unexpected failure"))
48+
.when(this.facade).inspect(containerId)
49+
;
50+
51+
// act
52+
final var container = this.facade.safeInspect(containerId);
53+
54+
// assert
55+
assertNull(container);
56+
}
57+
58+
@Test
59+
void mustFilterNullContainerInspections() {
60+
final var c1 = ContainerTemplates.buildRegularContainerCoffeeMakerCheckout();
61+
final var c2 = ContainerTemplates.buildDpsContainer();
62+
final var containers = List.of(c1, c2);
63+
64+
doReturn(InspectContainerResponseTemplates.withDpsLabel())
65+
.when(this.facade).safeInspect(c1.getId())
66+
;
67+
68+
doReturn(null)
69+
.when(this.facade).safeInspect(c2.getId())
70+
;
71+
72+
final var filtered = this.facade.inspectFilteringValidContainers(containers)
73+
.toList();
74+
75+
assertEquals(1, filtered.size());
76+
}
77+
}

Diff for: src/test/java/testing/mocks/DockerClientStub.java

+38-3
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,60 @@
33
import com.github.dockerjava.api.DockerClientDelegate;
44
import com.github.dockerjava.api.command.ConnectToNetworkCmd;
55
import com.github.dockerjava.api.command.DockerCmdSyncExec;
6+
import com.github.dockerjava.api.command.InspectContainerCmd;
7+
import com.github.dockerjava.api.command.ListContainersCmd;
68
import com.github.dockerjava.core.command.ConnectToNetworkCmdImpl;
9+
import com.github.dockerjava.core.command.InspectContainerCmdImpl;
10+
import com.github.dockerjava.core.command.ListContainersCmdImpl;
711
import lombok.Getter;
812

13+
import javax.annotation.Nonnull;
14+
15+
import java.util.HashMap;
16+
import java.util.Map;
17+
918
import static org.mockito.Mockito.mock;
1019
import static org.mockito.Mockito.spy;
1120

1221
@Getter
1322
public class DockerClientStub extends DockerClientDelegate {
1423

1524
private final ConnectToNetworkCmd connectToNetworkCmd;
16-
private final DockerCmdSyncExec<?, Void> execution;
25+
private final ListContainersCmd listContainersCmd;
26+
private final Map<String, InspectContainerCmd> inspectContainerCmdMap;
27+
28+
private final DockerCmdSyncExec<ConnectToNetworkCmd, Void> connectToNetworkExecution;
29+
private final ListContainersCmd.Exec listContainersExecution;
30+
private final InspectContainerCmd.Exec inspectContainerExecution;
1731

1832
public DockerClientStub() {
19-
this.execution = mock(DockerCmdSyncExec.class);
20-
this.connectToNetworkCmd = spy(new ConnectToNetworkCmdImpl((DockerCmdSyncExec<ConnectToNetworkCmd, Void>) this.execution));
33+
this.connectToNetworkExecution = mock(DockerCmdSyncExec.class);
34+
this.listContainersExecution = mock(ListContainersCmd.Exec.class);
35+
this.inspectContainerExecution = mock(InspectContainerCmd.Exec.class);
36+
37+
this.connectToNetworkCmd = spy(new ConnectToNetworkCmdImpl(this.connectToNetworkExecution));
38+
this.listContainersCmd = spy(new ListContainersCmdImpl(this.listContainersExecution));
39+
this.inspectContainerCmdMap = new HashMap<>();
2140
}
2241

2342
@Override
2443
public ConnectToNetworkCmd connectToNetworkCmd() {
2544
return this.connectToNetworkCmd;
2645
}
46+
47+
@Override
48+
public ListContainersCmd listContainersCmd() {
49+
return this.listContainersCmd;
50+
}
51+
52+
@Override
53+
public InspectContainerCmd inspectContainerCmd(@Nonnull String containerId) {
54+
if (this.inspectContainerCmdMap.containsKey(containerId)) {
55+
return this.inspectContainerCmdMap.get(containerId);
56+
} else {
57+
final var inspectCmd = spy(new InspectContainerCmdImpl(this.inspectContainerExecution, containerId));
58+
inspectContainerCmdMap.put(containerId, inspectCmd);
59+
return inspectCmd;
60+
}
61+
}
2762
}

0 commit comments

Comments
 (0)