Skip to content

Commit

Permalink
Merge pull request #305 from pobtastic/172-add-networks
Browse files Browse the repository at this point in the history
#172: Additional argument to use specific docker network
  • Loading branch information
chadlwilson authored Dec 6, 2024
2 parents 6824859 + d9946d0 commit 737b6dd
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 9 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ apply from: "https://raw.githubusercontent.com/gocd/gocd-plugin-gradle-task-help

gocdPlugin {
id = 'cd.go.contrib.elastic-agent.docker'
pluginVersion = '3.3.0'
pluginVersion = '3.4.0'
goCdVersion = '21.4.0'
name = 'Docker Elastic Agent Plugin'
description = 'Docker Based Elastic Agent Plugins for GoCD'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public static DockerContainer create(CreateAgentRequest request, PluginSettings
}

final String hostConfig = request.properties().get("Hosts");
final String networks = request.properties().get("Networks");
final String reservedMemory = request.properties().get("ReservedMemory");
final String maxMemory = request.properties().get("MaxMemory");
final String cpus = request.properties().get("Cpus");
Expand All @@ -142,6 +143,12 @@ public static DockerContainer create(CreateAgentRequest request, PluginSettings
if (volumeMounts != null) {
hostBuilder.appendBinds(Util.splitIntoLinesAndTrimSpaces(volumeMounts));
}
if (networks != null) {
String networkMode = Networks.firstMatching(networks, docker.listNetworks());
if (networkMode != null) {
hostBuilder.networkMode(networkMode);
}
}

ContainerConfig containerConfig = containerConfigBuilder
.image(imageName)
Expand All @@ -159,6 +166,11 @@ public static DockerContainer create(CreateAgentRequest request, PluginSettings
LOG.debug("Created container " + containerName);
consoleLogAppender.accept(String.format("Starting container: %s", containerName));
docker.startContainer(containerName);
Collection<String> additionalNetworks = Networks.getAdditionalNetworks(networks);
for (String network : additionalNetworks) {
docker.connectToNetwork(container.id(), network);
consoleLogAppender.accept(String.format("Connected container %s to additional network: %s", containerName, network));
}
consoleLogAppender.accept(String.format("Started container: %s", containerName));
LOG.debug("container " + containerName + " started");
return new DockerContainer(id, containerName, request.jobIdentifier(), containerInfo.created(), request.properties(), request.environment());
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/cd/go/contrib/elasticagents/docker/Networks.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cd.go.contrib.elasticagents.docker;

import static cd.go.contrib.elasticagents.docker.utils.Util.splitIntoLinesAndTrimSpaces;
import static org.apache.commons.lang.StringUtils.isBlank;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import com.spotify.docker.client.messages.Network;

public class Networks {

private Networks() {}

public static String firstMatching(String networkConfig, List<Network> dockerNetworks) {
if (isBlank(networkConfig)) {
return null;
}

final List<String> networkEntries = splitIntoLinesAndTrimSpaces(networkConfig);

final Collection<String> missingNetworks = networkEntries
.stream()
.filter(networkEntry -> dockerNetworks.stream().noneMatch(network -> network.name().equals(networkEntry)))
.collect(Collectors.toList());

if (!missingNetworks.isEmpty()) {
throw new RuntimeException(String.format("Networks %s do not exist.", missingNetworks));
}

return networkEntries.get(0);
}

public static Collection<String> getAdditionalNetworks(String networkConfig) {
if (isBlank(networkConfig)) {
return Collections.emptyList();
}

final List<String> networkEntries = splitIntoLinesAndTrimSpaces(networkConfig);

return networkEntries.isEmpty() ? networkEntries : networkEntries.subList(1, networkEntries.size());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ public class GetProfileMetadataExecutor implements RequestExecutor {
public static final Metadata MAX_MEMORY = new MemoryMetadata("MaxMemory");
public static final Metadata CPUS = new CpusMetadata("Cpus");
public static final Metadata MOUNTS = new Metadata("Mounts");
public static final Metadata NETWORKS = new Metadata("Networks", false, false);
public static final Metadata HOSTS = new HostMetadata();
public static final Metadata PRIVILEGED = new Metadata("Privileged", false, false);

Expand All @@ -49,6 +50,7 @@ public class GetProfileMetadataExecutor implements RequestExecutor {
FIELDS.add(MAX_MEMORY);
FIELDS.add(CPUS);
FIELDS.add(MOUNTS);
FIELDS.add(NETWORKS);
FIELDS.add(HOSTS);
FIELDS.add(PRIVILEGED);
}
Expand Down
10 changes: 4 additions & 6 deletions src/main/java/cd/go/contrib/elasticagents/docker/utils/Util.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@
import java.io.StringReader;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Properties;
import java.util.*;
import java.util.stream.Collectors;

import static org.apache.commons.lang.StringUtils.isBlank;

Expand Down Expand Up @@ -62,12 +60,12 @@ public static String pluginId() {
}
}

public static Collection<String> splitIntoLinesAndTrimSpaces(String lines) {
public static List<String> splitIntoLinesAndTrimSpaces(String lines) {
if (isBlank(lines)) {
return Collections.emptyList();
}

return Collections2.transform(Arrays.asList(lines.split("[\r\n]+")), String::trim);
return Arrays.stream(lines.split("[\r\n]+")).map(String::trim).collect(Collectors.toList());
}

public static String readableSize(long size) {
Expand Down
8 changes: 7 additions & 1 deletion src/main/resources/profile.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@

<div class="form_item_block">
<label ng-class="{'is-invalid-label': GOINPUTNAME[Image].$error.server}">Docker image:<span class='asterix'>*</span></label>
<input ng-class="{'is-invalid-input': GOINPUTNAME[Image].$error.server}" type="text" ng-model="Image" ng-required="true" placeholder="gocd/gocd-agent-wolfi:v24.1.0"/>
<input ng-class="{'is-invalid-input': GOINPUTNAME[Image].$error.server}" type="text" ng-model="Image" ng-required="true" placeholder="gocd/gocd-agent-wolfi:v24.4.0"/>
<span class="form_error form-error" ng-class="{'is-visible': GOINPUTNAME[Image].$error.server}" ng-show="GOINPUTNAME[Image].$error.server">{{GOINPUTNAME[Image].$error.server}}</span>
</div>

Expand Down Expand Up @@ -94,6 +94,12 @@
<span class="form_error form-error" ng-class="{'is-visible': GOINPUTNAME[Mounts].$error.server}" ng-show="GOINPUTNAME[Mounts].$error.server">{{GOINPUTNAME[Mounts].$error.server}}</span>
</div>

<div class="form_item_block">
<label ng-class="{'is-invalid-label': GOINPUTNAME[Networks].$error.server}">Network attachments <small>(Enter one network name per line. Leave empty to use the default network)</small></label>
<textarea ng-class="{'is-invalid-input': GOINPUTNAME[Networks].$error.server}" type="text" ng-model="Networks" ng-required="true" rows="3" placeholder="gocd-net&#x000A;other-net"></textarea>
<span class="form_error form-error" ng-class="{'is-visible': GOINPUTNAME[Networks].$error.server}" ng-show="GOINPUTNAME[Networks].$error.server">{{GOINPUTNAME[Networks].$error.server}}</span>
</div>

<div class="row">
<div class="columns end">
<label ng-class="{'is-invalid-label': GOINPUTNAME[Hosts].$error.server}">Extra Host entries <small>(Enter one host entry per line)</small></label>
Expand Down
60 changes: 60 additions & 0 deletions src/test/java/cd/go/contrib/elasticagents/docker/NetworksTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package cd.go.contrib.elasticagents.docker;

import com.spotify.docker.client.messages.Network;

import org.junit.jupiter.api.Test;

import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class NetworksTest {

@Test
public void shouldReturnNullWhenNetworkConfigIsNotProvided() {
assertNull(Networks.firstMatching(null, Collections.emptyList()));
assertNull(Networks.firstMatching("", Collections.emptyList()));
}

@Test
public void shouldReturnFirstNetworkFromString() {
Network network = mock(Network.class);
when(network.name()).thenReturn("gocd-net");
when(network.id()).thenReturn("network-id-1");

List<Network> networks = new ArrayList<>();
networks.add(network);

String result = Networks.firstMatching("gocd-net", networks);

assertNotNull(result);
assertEquals("gocd-net", result);
}

@Test
public void shouldThrowExceptionWhenNetworkDoesNotExist() {
RuntimeException exception = assertThrows(RuntimeException.class, () -> {
Networks.firstMatching("gocd-net", Collections.emptyList());
});

assertEquals("Networks [gocd-net] do not exist.", exception.getMessage());
}

@Test
public void shouldReturnEmptyListForAdditionalNetworksWhenOnlyOneNetwork() {
assertTrue(Networks.getAdditionalNetworks("single-network").isEmpty());
}

@Test
public void shouldReturnAdditionalNetworksWhenMultipleNetworksProvided() {
String networkConfig = "network1\nnetwork2\nnetwork3";
var additionalNetworks = Networks.getAdditionalNetworks(networkConfig);

assertEquals(2, additionalNetworks.size());
assertTrue(additionalNetworks.contains("network2"));
assertTrue(additionalNetworks.contains("network3"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,13 @@ public void assertJsonStructure() throws Exception {
" }\n" +
" },\n" +
" {\n" +
" \"key\": \"Networks\",\n" +
" \"metadata\": {\n" +
" \"required\": false,\n" +
" \"secure\": false\n" +
" }\n" +
" },\n" +
" {\n" +
" \"key\": \"Hosts\",\n" +
" \"metadata\": {\n" +
" \"required\": false,\n" +
Expand All @@ -115,4 +122,4 @@ public void assertJsonStructure() throws Exception {
JSONAssert.assertEquals(expectedJSON, response.responseBody(), true);
}

}
}

0 comments on commit 737b6dd

Please # to comment.