summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java78
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java1
-rw-r--r--docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java3
-rw-r--r--docker-api/src/main/resources/configdefinitions/docker.def2
-rw-r--r--docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImplTest.java48
-rw-r--r--node-admin/src/main/application/services.xml1
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/DockerAdminComponent.java4
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetAclResponse.java2
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetNodesResponse.java3
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/UpdateNodeAttributesRequestBody.java2
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java28
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslator.java38
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddresses.java130
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesImpl.java19
-rw-r--r--node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPVersion.java22
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java5
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslatorTest.java36
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java5
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java3
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesMock.java33
-rw-r--r--node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesTest.java79
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeAclResponse.java26
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-config-server.json32
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-docker-host.json13
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-tenant-node.json23
25 files changed, 439 insertions, 197 deletions
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java
index 485de99082b..260e2da7c59 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImpl.java
@@ -21,6 +21,7 @@ import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
+import java.util.stream.Stream;
class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
private final DockerClient docker;
@@ -32,13 +33,14 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
private final List<String> environmentAssignments = new ArrayList<>();
private final List<String> volumeBindSpecs = new ArrayList<>();
private final List<Ulimit> ulimits = new ArrayList<>();
+ private final Set<Capability> addCapabilities = new HashSet<>();
+ private final Set<Capability> dropCapabilities = new HashSet<>();
private Optional<String> networkMode = Optional.empty();
private Optional<String> ipv4Address = Optional.empty();
private Optional<String> ipv6Address = Optional.empty();
private Optional<String[]> entrypoint = Optional.empty();
- private Set<Capability> addCapabilities = new HashSet<>();
- private Set<Capability> dropCapabilities = new HashSet<>();
+ private boolean privileged = false;
CreateContainerCommandImpl(DockerClient docker,
DockerImage dockerImage,
@@ -60,8 +62,7 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
}
public Docker.CreateContainerCommand withManagedBy(String manager) {
- labels.put(DockerImpl.LABEL_NAME_MANAGEDBY, manager);
- return this;
+ return withLabel(DockerImpl.LABEL_NAME_MANAGEDBY, manager);
}
@Override
@@ -77,6 +78,12 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
}
@Override
+ public Docker.CreateContainerCommand withPrivileged(boolean privileged) {
+ this.privileged = privileged;
+ return this;
+ }
+
+ @Override
public Docker.CreateContainerCommand withUlimit(String name, int softLimit, int hardLimit) {
ulimits.add(new Ulimit(name, softLimit, hardLimit));
return this;
@@ -84,6 +91,7 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
@Override
public Docker.CreateContainerCommand withEntrypoint(String... entrypoint) {
+ if (entrypoint.length < 1) throw new IllegalArgumentException("Entrypoint must contain at least 1 element");
this.entrypoint = Optional.of(entrypoint);
return this;
}
@@ -142,7 +150,8 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
.withBinds(volumeBinds)
.withUlimits(ulimits)
.withCapAdd(new ArrayList<>(addCapabilities))
- .withCapDrop(new ArrayList<>(dropCapabilities));
+ .withCapDrop(new ArrayList<>(dropCapabilities))
+ .withPrivileged(privileged);
networkMode
.filter(mode -> ! mode.toLowerCase().equals("host"))
@@ -156,15 +165,19 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
return containerCmd;
}
- /** Maps ("--env", {"A", "B", "C"}) to "--env A --env B --env C ". */
+ /** Maps ("--env", {"A", "B", "C"}) to "--env A --env B --env C" */
private String toRepeatedOption(String option, List<String> optionValues) {
- StringBuilder builder = new StringBuilder();
- optionValues.forEach(optionValue -> builder.append(option).append(" ").append(optionValue).append(" "));
- return builder.toString();
+ return optionValues.stream()
+ .map(optionValue -> option + " " + optionValue)
+ .collect(Collectors.joining(" "));
+ }
+
+ private String toOptionalOption(String option, Optional<String> value) {
+ return value.map(o -> option + " " + o).orElse("");
}
- private String toOptionalOption(String option, Optional<?> value) {
- return value.isPresent() ? option + " " + value.get() + " " : "";
+ private String toFlagOption(String option, boolean value) {
+ return value ? option : "";
}
/** Make toString() print the equivalent arguments to 'docker run' */
@@ -175,24 +188,31 @@ class CreateContainerCommandImpl implements Docker.CreateContainerCommand {
List<String> ulimitList = ulimits.stream()
.map(ulimit -> ulimit.getName() + "=" + ulimit.getSoft() + ":" + ulimit.getHard())
.collect(Collectors.toList());
- List<String> addCapabilitiesList = addCapabilities.stream().map(Enum<Capability>::toString).collect(Collectors.toList());
- List<String> dropCapabilitiesList = dropCapabilities.stream().map(Enum<Capability>::toString).collect(Collectors.toList());
-
- return "--name " + containerName.asString() + " "
- + "--hostname " + hostName + " "
- + "--cpu-shares " + containerResources.cpuShares + " "
- + "--memory " + containerResources.memoryBytes + " "
- + toRepeatedOption("--label", labelList)
- + toRepeatedOption("--ulimit", ulimitList)
- + toRepeatedOption("--env", environmentAssignments)
- + toRepeatedOption("--volume", volumeBindSpecs)
- + toRepeatedOption("--cap-add", addCapabilitiesList)
- + toRepeatedOption("--cap-drop", dropCapabilitiesList)
- + toOptionalOption("--net", networkMode)
- + toOptionalOption("--ip", ipv4Address)
- + toOptionalOption("--ip6", ipv6Address)
- + toOptionalOption("--entrypoint", entrypoint)
- + dockerImage.asString();
+ List<String> addCapabilitiesList = addCapabilities.stream().map(Enum<Capability>::toString).sorted().collect(Collectors.toList());
+ List<String> dropCapabilitiesList = dropCapabilities.stream().map(Enum<Capability>::toString).sorted().collect(Collectors.toList());
+ Optional<String> entrypointExecuteable = entrypoint.map(args -> args[0]);
+ String entrypointArgs = entrypoint.map(Stream::of).orElseGet(Stream::empty)
+ .skip(1)
+ .collect(Collectors.joining(" "));
+
+ return String.join(" ",
+ "--name " + containerName.asString(),
+ "--hostname " + hostName,
+ "--cpu-shares " + containerResources.cpuShares,
+ "--memory " + containerResources.memoryBytes,
+ toRepeatedOption("--label", labelList),
+ toRepeatedOption("--ulimit", ulimitList),
+ toRepeatedOption("--env", environmentAssignments),
+ toRepeatedOption("--volume", volumeBindSpecs),
+ toRepeatedOption("--cap-add", addCapabilitiesList),
+ toRepeatedOption("--cap-drop", dropCapabilitiesList),
+ toOptionalOption("--net", networkMode),
+ toOptionalOption("--ip", ipv4Address),
+ toOptionalOption("--ip6", ipv6Address),
+ toOptionalOption("--entrypoint", entrypointExecuteable),
+ toFlagOption("--privileged", privileged),
+ dockerImage.asString(),
+ entrypointArgs);
}
/**
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
index 2039d0adfc9..36fc1446bea 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/Docker.java
@@ -27,6 +27,7 @@ public interface Docker {
CreateContainerCommand withManagedBy(String manager);
CreateContainerCommand withAddCapability(String capabilityName);
CreateContainerCommand withDropCapability(String capabilityName);
+ CreateContainerCommand withPrivileged(boolean privileged);
void create();
}
diff --git a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
index f6588512e2d..805b1e69d45 100644
--- a/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
+++ b/docker-api/src/main/java/com/yahoo/vespa/hosted/dockerapi/DockerImpl.java
@@ -200,7 +200,8 @@ public class DockerImpl implements Docker {
@Override
public CreateContainerCommand createContainerCommand(DockerImage image, ContainerResources containerResources,
ContainerName name, String hostName) {
- return new CreateContainerCommandImpl(dockerClient, image, containerResources, name, hostName);
+ return new CreateContainerCommandImpl(dockerClient, image, containerResources, name, hostName)
+ .withPrivileged(config.runContainersInPrivileged());
}
@Override
diff --git a/docker-api/src/main/resources/configdefinitions/docker.def b/docker-api/src/main/resources/configdefinitions/docker.def
index 83fee05dff6..7be8d85e0a9 100644
--- a/docker-api/src/main/resources/configdefinitions/docker.def
+++ b/docker-api/src/main/resources/configdefinitions/docker.def
@@ -13,3 +13,5 @@ isRunningLocally bool default = false
imageGCMinTimeToLiveMinutes int default = 45
networkNATed bool default = false
+
+runContainersInPrivileged bool default = false
diff --git a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImplTest.java b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImplTest.java
index aa455cfc0f2..0d8701ac43c 100644
--- a/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImplTest.java
+++ b/docker-api/src/test/java/com/yahoo/vespa/hosted/dockerapi/CreateContainerCommandImplTest.java
@@ -4,6 +4,8 @@ package com.yahoo.vespa.hosted.dockerapi;
import org.junit.Test;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
import java.util.Optional;
import java.util.stream.Stream;
@@ -12,6 +14,52 @@ import static org.junit.Assert.assertEquals;
public class CreateContainerCommandImplTest {
@Test
+ public void testToString() throws UnknownHostException {
+ DockerImage dockerImage = new DockerImage("docker.registry.domain.tld/my/image:1.2.3");
+ ContainerResources containerResources = new ContainerResources(100, 1024);
+ String hostname = "docker-1.region.domain.tld";
+ ContainerName containerName = ContainerName.fromHostname(hostname);
+
+ Docker.CreateContainerCommand createContainerCommand = new CreateContainerCommandImpl(
+ null, dockerImage, containerResources, containerName, hostname)
+ .withLabel("my-label", "test-label")
+ .withUlimit("nofile", 1, 2)
+ .withUlimit("nproc", 10, 20)
+ .withEnvironment("env1", "val1")
+ .withEnvironment("env2", "val2")
+ .withVolume("vol1", "/host/vol1")
+ .withAddCapability("SYS_PTRACE")
+ .withAddCapability("SYS_ADMIN")
+ .withDropCapability("NET_ADMIN")
+ .withNetworkMode("bridge")
+ .withIpAddress(InetAddress.getByName("10.0.0.1"))
+ .withIpAddress(InetAddress.getByName("::1"))
+ .withEntrypoint("/path/to/program", "arg1", "arg2")
+ .withPrivileged(true);
+
+ assertEquals("--name docker-1 " +
+ "--hostname docker-1.region.domain.tld " +
+ "--cpu-shares 100 " +
+ "--memory 1024 " +
+ "--label my-label=test-label " +
+ "--ulimit nofile=1:2 " +
+ "--ulimit nproc=10:20 " +
+ "--env env1=val1 " +
+ "--env env2=val2 " +
+ "--volume vol1:/host/vol1 " +
+ "--cap-add SYS_ADMIN " +
+ "--cap-add SYS_PTRACE " +
+ "--cap-drop NET_ADMIN " +
+ "--net bridge " +
+ "--ip 10.0.0.1 " +
+ "--ip6 0:0:0:0:0:0:0:1 " +
+ "--entrypoint /path/to/program " +
+ "--privileged docker.registry.domain.tld/my/image:1.2.3 " +
+ "arg1 " +
+ "arg2", createContainerCommand.toString());
+ }
+
+ @Test
public void generateMacAddressTest() {
String[][] addresses = {
{"test123.host.yahoo.com", null, "abcd:1234::1", "ee:ae:a9:de:ad:c2"},
diff --git a/node-admin/src/main/application/services.xml b/node-admin/src/main/application/services.xml
index f2f9e46c5b8..afe2888c5ef 100644
--- a/node-admin/src/main/application/services.xml
+++ b/node-admin/src/main/application/services.xml
@@ -13,6 +13,7 @@
<config name="vespa.hosted.dockerapi.docker">
<uri>unix:///var/run/docker.sock</uri>
+ <runContainersInPrivileged>true</runContainersInPrivileged>
</config>
<preprocess:include file="variant.xml" required="false"/>
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/DockerAdminComponent.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/DockerAdminComponent.java
index 89f52a39fbb..a93d77d07bd 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/DockerAdminComponent.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/component/DockerAdminComponent.java
@@ -18,6 +18,7 @@ import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminStateUpdaterImpl;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgent;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgentImpl;
import com.yahoo.vespa.hosted.node.admin.provider.NodeAdminStateUpdater;
+import com.yahoo.vespa.hosted.node.admin.task.util.network.IPAddressesImpl;
import java.time.Clock;
import java.time.Duration;
@@ -93,7 +94,8 @@ public class DockerAdminComponent implements AdminComponent {
DockerOperations dockerOperations = new DockerOperationsImpl(
docker,
environment.get(),
- processExecuter);
+ processExecuter,
+ new IPAddressesImpl());
StorageMaintainer storageMaintainer = new StorageMaintainer(
dockerOperations,
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetAclResponse.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetAclResponse.java
index b7762cf6aa9..7000170ca4c 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetAclResponse.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetAclResponse.java
@@ -29,6 +29,7 @@ public class GetAclResponse {
this.trustedNetworks = trustedNetworks == null ? Collections.emptyList() : trustedNetworks;
}
+ @JsonIgnoreProperties(ignoreUnknown = true)
public static class Node {
@JsonProperty("hostname")
@@ -49,6 +50,7 @@ public class GetAclResponse {
}
}
+ @JsonIgnoreProperties(ignoreUnknown = true)
public static class Network {
@JsonProperty("network")
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetNodesResponse.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetNodesResponse.java
index 783ce89ad5c..d1eda3c2d45 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetNodesResponse.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/GetNodesResponse.java
@@ -119,7 +119,7 @@ public class GetNodesResponse {
+ " }";
}
-
+ @JsonIgnoreProperties(ignoreUnknown = true)
public static class Owner {
public final String tenant;
public final String application;
@@ -143,6 +143,7 @@ public class GetNodesResponse {
}
}
+ @JsonIgnoreProperties(ignoreUnknown = true)
public static class Membership {
public final String clusterType;
public final String clusterId;
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/UpdateNodeAttributesRequestBody.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/UpdateNodeAttributesRequestBody.java
index 28605bc3a8d..305d7d386de 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/UpdateNodeAttributesRequestBody.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/configserver/noderepository/bindings/UpdateNodeAttributesRequestBody.java
@@ -1,6 +1,7 @@
// Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.node.admin.configserver.noderepository.bindings;
+import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAttributes;
@@ -16,6 +17,7 @@ import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAttributes;
* @author bakksjo
*/
@JsonInclude(JsonInclude.Include.NON_NULL)
+@JsonIgnoreProperties(ignoreUnknown = true)
public class UpdateNodeAttributesRequestBody {
public Long currentRestartGeneration;
public Long currentRebootGeneration;
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java
index 1b5507eb534..b9cea1cd5da 100644
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImpl.java
@@ -18,9 +18,11 @@ import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
import com.yahoo.vespa.hosted.node.admin.ContainerNodeSpec;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
import com.yahoo.vespa.hosted.node.admin.maintenance.acl.iptables.NATCommand;
+import com.yahoo.vespa.hosted.node.admin.task.util.network.IPAddresses;
import com.yahoo.vespa.hosted.node.admin.util.PrefixLogger;
import java.io.IOException;
+import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.URI;
@@ -43,7 +45,8 @@ public class DockerOperationsImpl implements DockerOperations {
private static final String MANAGER_NAME = "node-admin";
- private static final String LOCAL_IPV6_PREFIX = "fd00::";
+ private static final String IPV6_NPT_PREFIX = "fd00::";
+ private static final String IPV4_NPT_PREFIX = "172.17.0.0";
private static final String DOCKER_CUSTOM_BRIDGE_NETWORK_NAME = "vespa-bridge";
private final Docker docker;
@@ -51,11 +54,13 @@ public class DockerOperationsImpl implements DockerOperations {
private final ProcessExecuter processExecuter;
private final String nodeProgram;
private Map<Path, Boolean> directoriesToMount;
+ private final IPAddresses retriever;
- public DockerOperationsImpl(Docker docker, Environment environment, ProcessExecuter processExecuter) {
+ public DockerOperationsImpl(Docker docker, Environment environment, ProcessExecuter processExecuter, IPAddresses retriever) {
this.docker = docker;
this.environment = environment;
this.processExecuter = processExecuter;
+ this.retriever = retriever;
this.nodeProgram = environment.pathInNodeUnderVespaHome("bin/vespa-nodectl").toString();
this.directoriesToMount = getDirectoriesToMount(environment);
@@ -91,10 +96,21 @@ public class DockerOperationsImpl implements DockerOperations {
command.withNetworkMode(DockerImpl.DOCKER_CUSTOM_MACVLAN_NETWORK_NAME);
command.withVolume("/etc/hosts", "/etc/hosts"); // TODO This is probably not necessary - review later
} else {
- command.withIpAddress(NetworkPrefixTranslator.translate(
- nodeInetAddress,
- InetAddress.getByName(LOCAL_IPV6_PREFIX),
- 64));
+ // IPv6 - Assume always valid
+ Inet6Address ipV6Address = this.retriever.getIPv6Address(nodeSpec.hostname).orElseThrow(
+ () -> new RuntimeException("Unable to find a valid IPv6 address. Missing an AAAA DNS entry?"));
+ InetAddress ipV6Prefix = InetAddress.getByName(IPV6_NPT_PREFIX);
+ InetAddress ipV6Local = IPAddresses.prefixTranslate(ipV6Address, ipV6Prefix, 8);
+ command.withIpAddress(ipV6Local);
+
+ // IPv4 - Only present for some containers
+ Optional<Inet4Address> ipV4Address = this.retriever.getIPv4Address(nodeSpec.hostname);
+ if (ipV4Address.isPresent()) {
+ InetAddress ipV4Prefix = InetAddress.getByName(IPV4_NPT_PREFIX);
+ InetAddress ipV4Local = IPAddresses.prefixTranslate(ipV4Address.get(), ipV4Prefix, 2);
+ command.withIpAddress(ipV4Local);
+ }
+
command.withNetworkMode(DOCKER_CUSTOM_BRIDGE_NETWORK_NAME);
}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslator.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslator.java
deleted file mode 100644
index a52dedb90e5..00000000000
--- a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslator.java
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-/**
- * @author smorgrav
- */
-package com.yahoo.vespa.hosted.node.admin.docker;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-class NetworkPrefixTranslator {
-
- /**
- * For NPTed networks we want to find the private address from a public.
- *
- * @param address The original address to translate
- * @param prefix The prefix address
- * @param subnetSize in bits - e.g a /64 subnet equals 64 bits
- * @return The translated address
- */
- static Inet6Address translate(InetAddress address, InetAddress prefix, int subnetSize) {
-
- byte[] originalAddress = address.getAddress();
- byte[] prefixAddress = prefix.getAddress();
- byte[] translatedAddress = new byte[16];
-
- for (int i = 0; i < 16; i++) {
- translatedAddress[i] = i < subnetSize / 8 ? prefixAddress[i] : originalAddress[i];
- }
-
- try {
- return (Inet6Address) InetAddress.getByAddress(address.getHostName(), translatedAddress);
- } catch (UnknownHostException e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddresses.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddresses.java
new file mode 100644
index 00000000000..a49c4e1fbf6
--- /dev/null
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddresses.java
@@ -0,0 +1,130 @@
+package com.yahoo.vespa.hosted.node.admin.task.util.network;
+
+import com.google.common.net.InetAddresses;
+
+import java.net.Inet4Address;
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * IP addresses - IP utilities to retrieve and manipulate addresses for docker host and docker containers in a
+ * multi-home environment.
+ *
+ * The assumption is that DNS is the source of truth for which address are assigned to the host and which
+ * that belongs to the containers. Only one address should be assigned to each.
+ *
+ * The behavior with respect to site-local addresses are distinct for IPv4 and IPv6. For IPv4 we choose
+ * the site-local address (assume the public is a NAT address not assigned to the host interface (the typical aws setup)).
+ *
+ * For IPv6 we disregard any site-local addresses (these are normally not in DNS anyway).
+ *
+ * This class also provides some utilities for prefix translation.
+ *
+ * @author smorgrav
+ */
+public interface IPAddresses {
+
+ InetAddress[] getAddresses(String hostname);
+
+ default List<String> getAddresses(String hostname, IPVersion ipVersion) {
+ return Stream.of(getAddresses(hostname))
+ .filter(inetAddress -> isOfType(inetAddress, ipVersion))
+ .map(InetAddresses::toAddrString)
+ .collect(Collectors.toList());
+ }
+
+ /**
+ * Get the IPv6 address for the host if any.
+ *
+ * @throws RuntimeException if multiple addresses are found
+ * @return An optional string representation of the IP address (RFC 5952 compact format)
+ */
+ default Optional<Inet6Address> getIPv6Address(String hostname) {
+ List<InetAddress> ipv6addresses = Stream.of(getAddresses(hostname))
+ .filter(inetAddress -> inetAddress instanceof Inet6Address)
+ .filter(inetAddress -> !inetAddress.isLinkLocalAddress())
+ .filter(inetAddress -> !inetAddress.isSiteLocalAddress())
+ .collect(Collectors.toList());
+
+ if (ipv6addresses.isEmpty()) {
+ return Optional.empty();
+ }
+
+ if (ipv6addresses.size() > 1) {
+ String addresses =
+ ipv6addresses.stream().map(InetAddresses::toAddrString).collect(Collectors.joining(","));
+ throw new RuntimeException(
+ String.format(
+ "Multiple IPv6 addresses found: %s. Perhaps a missing DNS entry or multiple AAAA records in DNS?",
+ addresses));
+ }
+
+ return Optional.of((Inet6Address)ipv6addresses.get(0));
+ }
+
+ /**
+ * Get the IPv4 address for the host if any.
+ *
+ * @throws RuntimeException if multiple site-local addresses are found
+ * @return An optional string representation of the IP address
+ */
+ default Optional<Inet4Address> getIPv4Address(String hostname) {
+ InetAddress[] allAddresses = getAddresses(hostname);
+
+ List<InetAddress> ipv4Addresses = Stream.of(allAddresses)
+ .filter(inetAddress -> inetAddress instanceof Inet4Address)
+ .collect(Collectors.toList());
+
+ if (ipv4Addresses.size() == 1) return Optional.of((Inet4Address)ipv4Addresses.get(0));
+
+ if (ipv4Addresses.isEmpty()) {
+ Optional.empty();
+ }
+
+ List<InetAddress> siteLocalIPv4Addresses = Stream.of(allAddresses)
+ .filter(inetAddress -> inetAddress instanceof Inet4Address)
+ .filter(InetAddress::isSiteLocalAddress)
+ .collect(Collectors.toList());
+
+ if (siteLocalIPv4Addresses.size() == 1) return Optional.of((Inet4Address)siteLocalIPv4Addresses.get(0));
+
+ String addresses =
+ ipv4Addresses.stream().map(InetAddresses::toAddrString).collect(Collectors.joining(","));
+ throw new RuntimeException(
+ String.format(
+ "Multiple IPv4 addresses found: %s. Perhaps a missing DNS entry or multiple A records in DNS?",
+ addresses));
+ }
+
+ static boolean isOfType(InetAddress address, IPVersion ipVersion) {
+ if (ipVersion.equals(IPVersion.IPv4) && address instanceof Inet4Address) return true;
+ if (ipVersion.equals(IPVersion.IPv6) && address instanceof Inet6Address) return true;
+ return false;
+ }
+
+ /**
+ * For NPTed networks we want to find the private address from a public.
+ *
+ * @param address The original address to translate
+ * @param prefix The prefix address
+ * @param subnetSizeInBytes in bits - e.g a /64 subnet equals 8 bytes
+ * @return The translated address
+ */
+ static InetAddress prefixTranslate(InetAddress address, InetAddress prefix, int subnetSizeInBytes) {
+ return prefixTranslate(address.getAddress(), prefix.getAddress(), subnetSizeInBytes);
+ }
+
+ static InetAddress prefixTranslate(byte[] address, byte[] prefix, int nofBytes) {
+ System.arraycopy(prefix, 0, address, 0, nofBytes);
+ try {
+ return InetAddress.getByAddress(address);
+ } catch (UnknownHostException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesImpl.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesImpl.java
new file mode 100644
index 00000000000..9ae7181abe9
--- /dev/null
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesImpl.java
@@ -0,0 +1,19 @@
+package com.yahoo.vespa.hosted.node.admin.task.util.network;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @author smorgrav
+ */
+public class IPAddressesImpl implements IPAddresses {
+
+ @Override
+ public InetAddress[] getAddresses(String hostname) {
+ try {
+ return InetAddress.getAllByName(hostname);
+ } catch (UnknownHostException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPVersion.java b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPVersion.java
new file mode 100644
index 00000000000..f03f1a57f81
--- /dev/null
+++ b/node-admin/src/main/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPVersion.java
@@ -0,0 +1,22 @@
+package com.yahoo.vespa.hosted.node.admin.task.util.network;
+
+/**
+ * Strong type IPv4 and IPv6 with the respective iptables executable.
+ *
+ * @author smorgrav
+ */
+enum IPVersion {
+
+ IPv6("ip6tables"),
+ IPv4("iptables");
+
+ IPVersion(String exec) {
+ this.exec = exec;
+ }
+
+ private String exec;
+
+ String exec() {
+ return exec;
+ }
+}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java
index e2db9743412..a07bd4e0e91 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/DockerOperationsImplTest.java
@@ -9,6 +9,7 @@ import com.yahoo.vespa.hosted.dockerapi.Docker;
import com.yahoo.vespa.hosted.dockerapi.DockerImage;
import com.yahoo.vespa.hosted.dockerapi.ProcessResult;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
+import com.yahoo.vespa.hosted.node.admin.task.util.network.IPAddressesMock;
import org.junit.Test;
import org.mockito.InOrder;
@@ -34,7 +35,9 @@ public class DockerOperationsImplTest {
.build();
private final Docker docker = mock(Docker.class);
private final ProcessExecuter processExecuter = mock(ProcessExecuter.class);
- private final DockerOperationsImpl dockerOperations = new DockerOperationsImpl(docker, environment, processExecuter);
+ private final IPAddressesMock addressesMock = new IPAddressesMock();
+ private final DockerOperationsImpl dockerOperations
+ = new DockerOperationsImpl(docker, environment, processExecuter, addressesMock);
@Test
public void processResultFromNodeProgramWhenSuccess() throws Exception {
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslatorTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslatorTest.java
deleted file mode 100644
index 96afe685a61..00000000000
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/docker/NetworkPrefixTranslatorTest.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright 2018 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
-/**
- * @author smorgrav
- */
-package com.yahoo.vespa.hosted.node.admin.docker;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-import java.net.Inet6Address;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
-
-public class NetworkPrefixTranslatorTest {
-
- @Test
- public void translator_with_valid_parameters() throws UnknownHostException {
-
- // Test simplest possible address
- Inet6Address original = (Inet6Address)InetAddress.getByName("2001:db8::1");
- Inet6Address prefix = (Inet6Address)InetAddress.getByName("fd00::");
- Inet6Address translated = NetworkPrefixTranslator.translate(original, prefix, 64);
- Assert.assertEquals("fd00:0:0:0:0:0:0:1", translated.getHostAddress());
-
-
- // Test an actual aws address we use
- original = (Inet6Address)InetAddress.getByName("2600:1f16:f34:5300:ccc6:1703:b7c2:369d");
- translated = NetworkPrefixTranslator.translate(original, prefix, 64);
- Assert.assertEquals("fd00:0:0:0:ccc6:1703:b7c2:369d", translated.getHostAddress());
-
- // Test different subnet size
- translated = NetworkPrefixTranslator.translate(original, prefix, 48);
- Assert.assertEquals("fd00:0:0:5300:ccc6:1703:b7c2:369d", translated.getHostAddress());
- }
-}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
index 6c9df440826..c183a7ba306 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerMock.java
@@ -221,6 +221,11 @@ public class DockerMock implements Docker {
}
@Override
+ public CreateContainerCommand withPrivileged(boolean privileged) {
+ return this;
+ }
+
+ @Override
public void create() {
}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java
index 2968c1737a8..ba176305173 100644
--- a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/integrationTests/DockerTester.java
@@ -15,6 +15,7 @@ import com.yahoo.vespa.hosted.node.admin.nodeadmin.NodeAdminStateUpdaterImpl;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgent;
import com.yahoo.vespa.hosted.node.admin.nodeagent.NodeAgentImpl;
import com.yahoo.vespa.hosted.node.admin.component.Environment;
+import com.yahoo.vespa.hosted.node.admin.task.util.network.IPAddressesImpl;
import com.yahoo.vespa.hosted.node.admin.util.InetAddressResolver;
import com.yahoo.vespa.hosted.node.admin.component.PathResolver;
@@ -65,7 +66,7 @@ public class DockerTester implements AutoCloseable {
.pathResolver(new PathResolver(pathToVespaHome, Paths.get("/tmp"), Paths.get("/tmp")))
.build();
Clock clock = Clock.systemUTC();
- DockerOperations dockerOperations = new DockerOperationsImpl(dockerMock, environment, null);
+ DockerOperations dockerOperations = new DockerOperationsImpl(dockerMock, environment, null, new IPAddressesImpl());
StorageMaintainerMock storageMaintainer = new StorageMaintainerMock(dockerOperations, null, environment, callOrderVerifier, clock);
AclMaintainer aclMaintainer = mock(AclMaintainer.class);
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesMock.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesMock.java
new file mode 100644
index 00000000000..c799ee5eaca
--- /dev/null
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesMock.java
@@ -0,0 +1,33 @@
+package com.yahoo.vespa.hosted.node.admin.task.util.network;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author smorgrav
+ */
+public class IPAddressesMock implements IPAddresses {
+
+ Map<String, List<InetAddress>> otherAddresses = new HashMap<>();
+
+ IPAddressesMock addAddress(String hostname, String ip) {
+ List<InetAddress> addresses = otherAddresses.getOrDefault(hostname, new ArrayList<>());
+ try {
+ addresses.add(InetAddress.getByName(ip));
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ }
+ otherAddresses.put(hostname, addresses);
+ return this;
+ }
+
+ @Override
+ public InetAddress[] getAddresses(String hostname) {
+ List<InetAddress> addresses = otherAddresses.get(hostname);
+ return addresses.toArray(new InetAddress[addresses.size()]);
+ }
+}
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesTest.java
new file mode 100644
index 00000000000..71f02364afa
--- /dev/null
+++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/network/IPAddressesTest.java
@@ -0,0 +1,79 @@
+package com.yahoo.vespa.hosted.node.admin.task.util.network;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.net.Inet6Address;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * @author smorgrav
+ */
+public class IPAddressesTest {
+
+ private final IPAddressesMock mock = new IPAddressesMock();
+
+ @Test
+ public void choose_sitelocal_ipv4_over_public() {
+ mock.addAddress("localhost", "38.3.4.2")
+ .addAddress("localhost", "10.0.2.2")
+ .addAddress("localhost", "fe80::1")
+ .addAddress("localhost", "2001::1");
+
+ Assert.assertTrue(equals("10.0.2.2", mock.getIPv4Address("localhost").get()));
+ }
+
+ @Test
+ public void choose_ipv6_public_over_local() {
+ mock.addAddress("localhost", "38.3.4.2")
+ .addAddress("localhost", "10.0.2.2")
+ .addAddress("localhost", "fe80::1")
+ .addAddress("localhost", "2001::1");
+
+ Assert.assertTrue(equals("2001::1", mock.getIPv6Address("localhost").get()));
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void throws_when_multiple_ipv6_addresses() {
+ mock.addAddress("localhost", "2001::1")
+ .addAddress("localhost", "2001::2");
+ mock.getIPv6Address("localhost");
+ }
+
+ @Test(expected = RuntimeException.class)
+ public void throws_when_multiple_private_ipv4_addresses() {
+ mock.addAddress("localhost", "38.3.4.2")
+ .addAddress("localhost", "10.0.2.2")
+ .addAddress("localhost", "10.0.2.3");
+ mock.getIPv4Address("localhost");
+ }
+
+ @Test
+ public void translator_with_valid_parameters() throws UnknownHostException {
+
+ // Test simplest possible address
+ Inet6Address original = (Inet6Address) InetAddress.getByName("2001:db8::1");
+ Inet6Address prefix = (Inet6Address) InetAddress.getByName("fd00::");
+ InetAddress translated = IPAddresses.prefixTranslate(original, prefix, 8);
+ Assert.assertEquals("fd00:0:0:0:0:0:0:1", translated.getHostAddress());
+
+
+ // Test an actual aws address we use
+ original = (Inet6Address) InetAddress.getByName("2600:1f16:f34:5300:ccc6:1703:b7c2:369d");
+ translated = IPAddresses.prefixTranslate(original, prefix, 8);
+ Assert.assertEquals("fd00:0:0:0:ccc6:1703:b7c2:369d", translated.getHostAddress());
+
+ // Test different subnet size
+ translated = IPAddresses.prefixTranslate(original, prefix, 6);
+ Assert.assertEquals("fd00:0:0:5300:ccc6:1703:b7c2:369d", translated.getHostAddress());
+ }
+
+ boolean equals(String a, InetAddress b) {
+ try {
+ return InetAddress.getByName(a).equals(b);
+ } catch (UnknownHostException e) {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeAclResponse.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeAclResponse.java
index 65b727ad0dd..2a4f37151de 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeAclResponse.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/restapi/v2/NodeAclResponse.java
@@ -7,13 +7,12 @@ import com.yahoo.slime.Cursor;
import com.yahoo.slime.Slime;
import com.yahoo.vespa.config.SlimeUtils;
import com.yahoo.vespa.hosted.provision.Node;
-import com.yahoo.vespa.hosted.provision.NodeRepository;
import com.yahoo.vespa.hosted.provision.node.NodeAcl;
+import com.yahoo.vespa.hosted.provision.NodeRepository;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
-import java.util.Set;
/**
* @author mpolden
@@ -37,35 +36,36 @@ public class NodeAclResponse extends HttpResponse {
toSlime(hostname, root);
}
+ private static String baseName(String path) {
+ return new File(path).getName();
+ }
+
private void toSlime(String hostname, Cursor object) {
Node node = nodeRepository.getNode(hostname)
.orElseGet(() -> nodeRepository.getConfigNode(hostname)
.orElseThrow(() -> new NotFoundException("No node with hostname '" + hostname + "'")));
Cursor trustedNodesArray = object.setArray("trustedNodes");
- nodeRepository.getNodeAcls(node, aclsForChildren).forEach(nodeAcl -> toSlime(nodeAcl, trustedNodesArray));
+ nodeRepository.getNodeAcls(node, aclsForChildren).forEach(nodeAcl -> toTrustedNodeSlime(nodeAcl, trustedNodesArray));
Cursor trustedNetworksArray = object.setArray("trustedNetworks");
- nodeRepository.getNodeAcls(node, aclsForChildren).forEach(nodeAcl -> toSlime(nodeAcl.trustedNetworks(),
- nodeAcl.node(),
- trustedNetworksArray));
+ nodeRepository.getNodeAcls(node, aclsForChildren).forEach(nodeAcl -> toTrustedNetworkSlime(nodeAcl, trustedNetworksArray));
}
- private void toSlime(NodeAcl nodeAcl, Cursor array) {
+ private void toTrustedNodeSlime(NodeAcl nodeAcl, Cursor array) {
nodeAcl.trustedNodes().forEach(node -> node.ipAddresses().forEach(ipAddress -> {
Cursor object = array.addObject();
object.setString("hostname", node.hostname());
- object.setString("type", node.type().name());
object.setString("ipAddress", ipAddress);
object.setString("trustedBy", nodeAcl.node().hostname());
}));
}
- private void toSlime(Set<String> trustedNetworks, Node trustedBy, Cursor array) {
- trustedNetworks.forEach(network -> {
+ private void toTrustedNetworkSlime(NodeAcl nodeAcl, Cursor array) {
+ nodeAcl.trustedNetworks().forEach(network -> {
Cursor object = array.addObject();
object.setString("network", network);
- object.setString("trustedBy", trustedBy.hostname());
+ object.setString("trustedBy", nodeAcl.node().hostname());
});
}
@@ -78,8 +78,4 @@ public class NodeAclResponse extends HttpResponse {
public String getContentType() {
return "application/json";
}
-
- private static String baseName(String path) {
- return new File(path).getName();
- }
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-config-server.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-config-server.json
index 775d33a3a19..af925e9f94e 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-config-server.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-config-server.json
@@ -2,193 +2,161 @@
"trustedNodes": [
{
"hostname": "cfg1",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "cfg1"
},
{
"hostname": "cfg2",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "cfg1"
},
{
"hostname": "cfg3",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost1.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost1.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost2.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost2.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost3.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost3.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost4.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost4.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost5.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "dockerhost5.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host1.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host1.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host10.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host10.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host2.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host2.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host3.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host3.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host4.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host4.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host5.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host5.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host55.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host55.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host6.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host6.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "host7.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "cfg1"
},
{
"hostname": "host7.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "cfg1"
},
{
"hostname": "test-container-1",
- "type": "tenant",
"ipAddress": "::2",
"trustedBy": "cfg1"
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-docker-host.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-docker-host.json
index f13730ba066..195edac7cce 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-docker-host.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-docker-host.json
@@ -2,79 +2,66 @@
"trustedNodes": [
{
"hostname": "cfg1",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "cfg2",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "cfg3",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost1.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost1.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost2.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost2.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost3.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost3.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost4.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost4.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost5.yahoo.com",
- "type": "host",
"ipAddress": "::1",
"trustedBy": "dockerhost1.yahoo.com"
},
{
"hostname": "dockerhost5.yahoo.com",
- "type": "host",
"ipAddress": "127.0.0.1",
"trustedBy": "dockerhost1.yahoo.com"
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-tenant-node.json b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-tenant-node.json
index b2184c9d825..eb7a6ba61bb 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-tenant-node.json
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/restapi/v2/responses/acl-tenant-node.json
@@ -2,139 +2,116 @@
"trustedNodes": [
{
"hostname": "cfg1",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "cfg2",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "cfg3",
- "type": "config",
"ipAddress": "(ignore)",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "foo.yahoo.com",
- "type": "tenant",
"ipAddress": "(ignore)",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host1.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host1.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host10.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host10.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host2.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host2.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host3.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host3.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host4.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host4.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host5.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host5.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host55.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host55.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host6.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host6.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host7.yahoo.com",
- "type": "tenant",
"ipAddress": "::1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "host7.yahoo.com",
- "type": "tenant",
"ipAddress": "127.0.0.1",
"trustedBy": "foo.yahoo.com"
},
{
"hostname": "test-container-1",
- "type": "tenant",
"ipAddress": "::2",
"trustedBy": "foo.yahoo.com"
}