package io.vertx.servicediscovery.docker;
import com.github.dockerjava.api.model.Container;
import com.github.dockerjava.api.model.ContainerPort;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.servicediscovery.Record;
import io.vertx.servicediscovery.spi.ServiceType;
import io.vertx.servicediscovery.types.HttpEndpoint;
import io.vertx.servicediscovery.types.HttpLocation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class DockerService {
private final String name;
private final String host;
private String containerId;
private List<String> containerNames;
private List<Record> records = new ArrayList<>();
public DockerService(Container container, String host) {
this.host = host;
containerId = container.getId();
containerNames = Arrays.stream(container.getNames()).collect(Collectors.toList());
if (!containerNames.isEmpty()) {
name = containerNames.get(0);
} else {
name = containerId;
}
for (ContainerPort port : container.getPorts()) {
Record record = createRecord(container, port);
if (record != null) {
records.add(record);
}
}
}
public List<Record> records() {
return records;
}
public String name() {
return name;
}
public List<String> names() {
return containerNames;
}
public String id() {
return containerId;
}
public Record createRecord(Container container, ContainerPort port) {
Record record = new Record()
.setName(name);
Map<String, String> labels = container.getLabels();
if (labels != null) {
for (Map.Entry<String, String> entry : labels.entrySet()) {
record.getMetadata().put(entry.getKey(), entry.getValue());
}
}
JsonArray names = new JsonArray();
containerNames.forEach(names::add);
record.getMetadata().put("docker.names", names);
record.getMetadata().put("docker.name", name);
record.getMetadata().put("docker.id", containerId);
String type = labels != null ? labels.get("service.type") : ServiceType.UNKNOWN;
if (type == null) {
type = ServiceType.UNKNOWN;
}
switch (type) {
case "http-endpoint":
return manageHttpService(record, port, labels);
default:
return manageUnknownService(record, port);
}
}
private Record manageUnknownService(Record record, ContainerPort port) {
if (port.getPublicPort() == null || port.getPublicPort() == 0) {
return null;
}
JsonObject location = new JsonObject();
location.put("port", port.getPublicPort());
location.put("internal-port", port.getPrivatePort());
location.put("type", port.getType());
location.put("ip", host);
return record.setLocation(location).setType(ServiceType.UNKNOWN);
}
private static Record manageHttpService(Record record, ContainerPort port, Map<String, String> labels) {
if (port.getPublicPort() == null || port.getPublicPort() == 0) {
return null;
}
record.setType(HttpEndpoint.TYPE);
HttpLocation location = new HttpLocation()
.setHost(port.getIp())
.setPort(port.getPublicPort());
if (isTrue(labels, "ssl") || port.getPrivatePort() == 443) {
location.setSsl(true);
}
return record.setLocation(location.toJson());
}
private static boolean isTrue(Map<String, String> labels, String key) {
return labels != null && "true".equalsIgnoreCase(labels.get(key));
}
}