Added docker-compose file creation with correct parameters
This commit is contained in:
parent
e8a06ae425
commit
a67a13bbd0
@ -51,6 +51,7 @@ import static org.thingsboard.server.controller.ControllerConstants.PROTOCOL;
|
|||||||
import static org.thingsboard.server.controller.ControllerConstants.PROTOCOL_PARAM_DESCRIPTION;
|
import static org.thingsboard.server.controller.ControllerConstants.PROTOCOL_PARAM_DESCRIPTION;
|
||||||
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
import static org.thingsboard.server.controller.ControllerConstants.TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.CA_ROOT_CERT_PEM;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.CA_ROOT_CERT_PEM;
|
||||||
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.DOCKER_COMPOSE_YML;
|
||||||
|
|
||||||
@RestController
|
@RestController
|
||||||
@TbCoreComponent
|
@TbCoreComponent
|
||||||
@ -89,36 +90,6 @@ public class DeviceConnectivityController extends BaseController {
|
|||||||
return deviceConnectivityService.findDevicePublishTelemetryCommands(baseUrl, device);
|
return deviceConnectivityService.findDevicePublishTelemetryCommands(baseUrl, device);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiOperation(value = "Get commands to launch gateway (getGatewayLaunchCommands)",
|
|
||||||
notes = "Fetch the list of commands for different operation systems to launch a gateway using docker." +
|
|
||||||
TENANT_OR_CUSTOMER_AUTHORITY_PARAGRAPH)
|
|
||||||
@ApiResponses(value = {
|
|
||||||
@ApiResponse(code = 200, message = "OK",
|
|
||||||
examples = @io.swagger.annotations.Example(
|
|
||||||
value = {
|
|
||||||
@io.swagger.annotations.ExampleProperty(
|
|
||||||
mediaType = "application/json",
|
|
||||||
value = "{\"mqtt\": {\n" +
|
|
||||||
" \"linux\": \"docker run --rm -it -v ~/.tb-gateway/logs:/thingsboard_gateway/logs -v ~/.tb-gateway/extensions:/thingsboard_gateway/extensions -v ~/.tb-gateway/config:/thingsboard_gateway/config --name tbGateway127001 -e host=localhost -e port=1883 -e accessToken=qTe5oDBHPJf0KCSKO8J3 --restart always thingsboard/tb-gateway\",\n" +
|
|
||||||
" \"windows\": \"docker run --rm -it -v %HOMEPATH%/tb-gateway/logs:/thingsboard_gateway/logs -v %HOMEPATH%/tb-gateway/extensions:/thingsboard_gateway/extensions -v %HOMEPATH%/tb-gateway/config:/thingsboard_gateway/config --name tbGateway127001 -e host=localhost -e port=1883 -e accessToken=qTe5oDBHPJf0KCSKO8J3 --restart always thingsboard/tb-gateway\"}\n" +
|
|
||||||
"}")}))})
|
|
||||||
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")
|
|
||||||
@RequestMapping(value = "/device-connectivity/gateway-launch/{deviceId}", method = RequestMethod.GET)
|
|
||||||
@ResponseBody
|
|
||||||
public JsonNode getGatewayLaunchCommands(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
|
|
||||||
@PathVariable(DEVICE_ID) String strDeviceId, HttpServletRequest request) throws ThingsboardException, URISyntaxException {
|
|
||||||
checkParameter(DEVICE_ID, strDeviceId);
|
|
||||||
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
|
|
||||||
Device device = checkDeviceId(deviceId, Operation.READ_CREDENTIALS);
|
|
||||||
|
|
||||||
if (!checkIsGateway(device)) {
|
|
||||||
throw new ThingsboardException("The device must be a gateway!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
|
|
||||||
}
|
|
||||||
|
|
||||||
String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request);
|
|
||||||
return deviceConnectivityService.findGatewayLaunchCommands(baseUrl, device);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ApiOperation(value = "Download server certificate using file path defined in device.connectivity properties (downloadServerCertificate)", notes = "Download server certificate.")
|
@ApiOperation(value = "Download server certificate using file path defined in device.connectivity properties (downloadServerCertificate)", notes = "Download server certificate.")
|
||||||
@RequestMapping(value = "/device-connectivity/{protocol}/certificate/download", method = RequestMethod.GET)
|
@RequestMapping(value = "/device-connectivity/{protocol}/certificate/download", method = RequestMethod.GET)
|
||||||
@ResponseBody
|
@ResponseBody
|
||||||
@ -136,6 +107,30 @@ public class DeviceConnectivityController extends BaseController {
|
|||||||
.body(pemCert);
|
.body(pemCert);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ApiOperation(value = "Download generated docker-compose.yml file for gateway (downloadGatewayDockerCompose)", notes = "Download generated docker-compose.yml for gateway.")
|
||||||
|
@RequestMapping(value = "/device-connectivity/gateway-launch/{deviceId}/docker-compose/download", method = RequestMethod.GET)
|
||||||
|
@ResponseBody
|
||||||
|
public ResponseEntity<org.springframework.core.io.Resource> downloadGatewayDockerCompose(@ApiParam(value = DEVICE_ID_PARAM_DESCRIPTION)
|
||||||
|
@PathVariable(DEVICE_ID) String strDeviceId, HttpServletRequest request) throws ThingsboardException, URISyntaxException, IOException {
|
||||||
|
checkParameter(DEVICE_ID, strDeviceId);
|
||||||
|
DeviceId deviceId = new DeviceId(toUUID(strDeviceId));
|
||||||
|
Device device = checkDeviceId(deviceId, Operation.READ_CREDENTIALS);
|
||||||
|
|
||||||
|
if (!checkIsGateway(device)) {
|
||||||
|
throw new ThingsboardException("The device must be a gateway!", ThingsboardErrorCode.BAD_REQUEST_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
String baseUrl = systemSecurityService.getBaseUrl(getTenantId(), getCurrentUser().getCustomerId(), request);
|
||||||
|
var dockerCompose = checkNotNull(deviceConnectivityService.createGatewayDockerComposeFile(baseUrl, device), "Failed to create docker-compose.yml file!");
|
||||||
|
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + DOCKER_COMPOSE_YML)
|
||||||
|
.header("x-filename", DOCKER_COMPOSE_YML)
|
||||||
|
.contentLength(dockerCompose.contentLength())
|
||||||
|
.contentType(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
.body(dockerCompose);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean checkIsGateway(Device device) {
|
private static boolean checkIsGateway(Device device) {
|
||||||
return device.getAdditionalInfo().has(DataConstants.GATEWAY_PARAMETER) &&
|
return device.getAdditionalInfo().has(DataConstants.GATEWAY_PARAMETER) &&
|
||||||
device.getAdditionalInfo().get(DataConstants.GATEWAY_PARAMETER).asBoolean();
|
device.getAdditionalInfo().get(DataConstants.GATEWAY_PARAMETER).asBoolean();
|
||||||
|
|||||||
@ -60,11 +60,8 @@ import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.COAPS;
|
|||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.DOCKER;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.DOCKER;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTP;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTP;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTPS;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTPS;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.LINUX;
|
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MACOS;
|
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTT;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTT;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTTS;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTTS;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.WINDOWS;
|
|
||||||
|
|
||||||
@TestPropertySource(properties = {
|
@TestPropertySource(properties = {
|
||||||
"device.connectivity.mqtts.pem_cert_file=/tmp/" + CA_ROOT_CERT_PEM
|
"device.connectivity.mqtts.pem_cert_file=/tmp/" + CA_ROOT_CERT_PEM
|
||||||
@ -294,7 +291,7 @@ public class DeviceConnectivityControllerTest extends AbstractControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFetchGatewayLaunchCommands() throws Exception {
|
public void testFetchGatewayDockerComposeFile() throws Exception {
|
||||||
String deviceName = "My device";
|
String deviceName = "My device";
|
||||||
Device device = new Device();
|
Device device = new Device();
|
||||||
device.setName(deviceName);
|
device.setName(deviceName);
|
||||||
@ -306,24 +303,50 @@ public class DeviceConnectivityControllerTest extends AbstractControllerTest {
|
|||||||
DeviceCredentials credentials =
|
DeviceCredentials credentials =
|
||||||
doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
|
doGet("/api/device/" + savedDevice.getId().getId() + "/credentials", DeviceCredentials.class);
|
||||||
|
|
||||||
JsonNode commands =
|
String commands =
|
||||||
doGetTyped("/api/device-connectivity/gateway-launch/" + savedDevice.getId().getId(), new TypeReference<>() {
|
doGet("/api/device-connectivity/gateway-launch/" + savedDevice.getId().getId() + "/docker-compose/download", String.class);
|
||||||
});
|
|
||||||
|
|
||||||
String expectedContainerName = deviceName.replace(" ", "_").replaceAll("[^A-Za-z0-9_.-]", "");
|
assertThat(commands).isEqualTo(String.format("version: '3.4'\n" +
|
||||||
|
"services:\n" +
|
||||||
JsonNode dockerMqttCommands = commands.get(MQTT);
|
" # ThingsBoard IoT Gateway Service Configuration\n" +
|
||||||
assertThat(dockerMqttCommands.get(LINUX).asText()).isEqualTo(String.format("docker run -it -v ~/.tb-gateway/logs:/thingsboard_gateway/logs -v ~/.tb-gateway/extensions:/thingsboard_gateway/extensions -v ~/.tb-gateway/config:/thingsboard_gateway/config --name " + expectedContainerName + " --network=host --add-host=host.docker.internal:host-gateway -e host=host.docker.internal -e accessToken=%s --restart always thingsboard/tb-gateway", credentials.getCredentialsId()));
|
" tb-gateway:\n" +
|
||||||
assertThat(dockerMqttCommands.get(WINDOWS).asText()).isEqualTo("docker run -it -v %HOMEDRIVE%%HOMEPATH%\\tb-gateway\\logs:/thingsboard_gateway/logs -v %HOMEDRIVE%%HOMEPATH%\\tb-gateway\\extensions:/thingsboard_gateway/extensions -v %HOMEDRIVE%%HOMEPATH%\\tb-gateway\\config:/thingsboard_gateway/config --name " + expectedContainerName + " -p 6400-6420:6400-6420 -e host=host.docker.internal -e accessToken=" + credentials.getCredentialsId() + " --restart always thingsboard/tb-gateway");
|
" image: thingsboard/tb-gateway\n" +
|
||||||
assertThat(dockerMqttCommands.get(MACOS).asText()).isEqualTo("docker run -it -v ~/.tb-gateway/logs:/thingsboard_gateway/logs -v ~/.tb-gateway/extensions:/thingsboard_gateway/extensions -v ~/.tb-gateway/config:/thingsboard_gateway/config --name " + expectedContainerName + " -p 6400-6420:6400-6420 -e host=host.docker.internal -e accessToken=" + credentials.getCredentialsId() + " --restart always thingsboard/tb-gateway");
|
" container_name: tb-gateway\n" +
|
||||||
|
" restart: always\n" +
|
||||||
JsonNode dockerMqttsCommands = commands.get(MQTTS);
|
"\n" +
|
||||||
assertThat(dockerMqttsCommands.get(LINUX).asText()).isEqualTo(String.format("curl -f -S -o ~/.tb-gateway/config/ca-root.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download && " +
|
" # Ports bindings - required by some connectors\n" +
|
||||||
"docker run -it -v ~/.tb-gateway/logs:/thingsboard_gateway/logs -v ~/.tb-gateway/extensions:/thingsboard_gateway/extensions -v ~/.tb-gateway/config:/thingsboard_gateway/config --name " + expectedContainerName + " --network=host --add-host=host.docker.internal:host-gateway -e host=host.docker.internal -e port=8883 -e accessToken=%s -e caCert=/thingsboard_gateway/config/ca-root.pem --restart always thingsboard/tb-gateway", credentials.getCredentialsId()));
|
" ports:\n" +
|
||||||
assertThat(dockerMqttsCommands.get(WINDOWS).asText()).isEqualTo("curl -f -S -o %HOMEDRIVE%%HOMEPATH%\\tb-gateway\\config\\ca-root.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download && " +
|
" - \"5000:5000\" # Comment if you don't use REST connector and change if you use another port\n" +
|
||||||
"docker run -it -v %HOMEDRIVE%%HOMEPATH%\\tb-gateway\\logs:/thingsboard_gateway/logs -v %HOMEDRIVE%%HOMEPATH%\\tb-gateway\\extensions:/thingsboard_gateway/extensions -v %HOMEDRIVE%%HOMEPATH%\\tb-gateway\\config:/thingsboard_gateway/config --name " + expectedContainerName + " -p 6400-6420:6400-6420 -e host=host.docker.internal -e port=8883 -e accessToken=" + credentials.getCredentialsId() + " -e caCert=/thingsboard_gateway/config/ca-root.pem --restart always thingsboard/tb-gateway");
|
" # Uncomment and modify the following ports based on connector usage:\n" +
|
||||||
assertThat(dockerMqttsCommands.get(MACOS).asText()).isEqualTo("curl -f -S -o ~/.tb-gateway/config/ca-root.pem http://localhost:80/api/device-connectivity/mqtts/certificate/download && " +
|
"# - \"1052:1052\" # BACnet connector\n" +
|
||||||
"docker run -it -v ~/.tb-gateway/logs:/thingsboard_gateway/logs -v ~/.tb-gateway/extensions:/thingsboard_gateway/extensions -v ~/.tb-gateway/config:/thingsboard_gateway/config --name " + expectedContainerName + " -p 6400-6420:6400-6420 -e host=host.docker.internal -e port=8883 -e accessToken=" + credentials.getCredentialsId() + " -e caCert=/thingsboard_gateway/config/ca-root.pem --restart always thingsboard/tb-gateway");
|
"# - \"5026:5026\" # Modbus TCP connector (Modbus Slave)\n" +
|
||||||
|
"# - \"50000:50000/tcp\" # Socket connector with type TCP\n" +
|
||||||
|
"# - \"50000:50000/udp\" # Socket connector with type UDP\n" +
|
||||||
|
"\n" +
|
||||||
|
" # Necessary mapping for Linux\n" +
|
||||||
|
" extra_hosts:\n" +
|
||||||
|
" - \"host.docker.internal:host-gateway\"\n" +
|
||||||
|
"\n" +
|
||||||
|
" # Environment variables\n" +
|
||||||
|
" environment:\n" +
|
||||||
|
" - host=host.docker.internal\n" +
|
||||||
|
" - port=1883\n" +
|
||||||
|
" - accessToken=" + credentials.getCredentialsId() + "\n" +
|
||||||
|
"\n" +
|
||||||
|
" # Volumes bind\n" +
|
||||||
|
" volumes:\n" +
|
||||||
|
" - tb-gw-config:/thingsboard_gateway/config\n" +
|
||||||
|
" - tb-gw-logs:/thingsboard_gateway/logs\n" +
|
||||||
|
" - tb-gw-extensions:/thingsboard_gateway/extensions\n" +
|
||||||
|
"\n" +
|
||||||
|
"# Volumes declaration for configurations, extensions and configuration\n" +
|
||||||
|
"volumes:\n" +
|
||||||
|
" tb-gw-config:\n" +
|
||||||
|
" name: tb-gw-config\n" +
|
||||||
|
" tb-gw-logs:\n" +
|
||||||
|
" name: tb-gw-logs\n" +
|
||||||
|
" tb-gw-extensions:\n" +
|
||||||
|
" name: tb-gw-extensions\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@ -25,7 +25,7 @@ public interface DeviceConnectivityService {
|
|||||||
|
|
||||||
JsonNode findDevicePublishTelemetryCommands(String baseUrl, Device device) throws URISyntaxException;
|
JsonNode findDevicePublishTelemetryCommands(String baseUrl, Device device) throws URISyntaxException;
|
||||||
|
|
||||||
JsonNode findGatewayLaunchCommands(String baseUrl, Device device) throws URISyntaxException;
|
|
||||||
|
|
||||||
Resource getPemCertFile(String protocol);
|
Resource getPemCertFile(String protocol);
|
||||||
|
|
||||||
|
Resource createGatewayDockerComposeFile(String baseUrl, Device device) throws URISyntaxException;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -59,11 +59,8 @@ import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.COAPS;
|
|||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.DOCKER;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.DOCKER;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTP;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTP;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTPS;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.HTTPS;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.LINUX;
|
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MACOS;
|
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTT;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTT;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTTS;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.MQTTS;
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.WINDOWS;
|
|
||||||
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.getHost;
|
import static org.thingsboard.server.dao.util.DeviceConnectivityUtil.getHost;
|
||||||
|
|
||||||
@Service("DeviceConnectivityDaoService")
|
@Service("DeviceConnectivityDaoService")
|
||||||
@ -131,27 +128,6 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService
|
|||||||
return commands;
|
return commands;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public JsonNode findGatewayLaunchCommands(String baseUrl, Device device) throws URISyntaxException {
|
|
||||||
DeviceId deviceId = device.getId();
|
|
||||||
log.trace("Executing findDevicePublishTelemetryCommands [{}]", deviceId);
|
|
||||||
validateId(deviceId, INCORRECT_DEVICE_ID + deviceId);
|
|
||||||
|
|
||||||
DeviceCredentials creds = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), deviceId);
|
|
||||||
String deviceName = device.getName();
|
|
||||||
|
|
||||||
ObjectNode commands = JacksonUtil.newObjectNode();
|
|
||||||
if (isEnabled(MQTT)) {
|
|
||||||
Optional.ofNullable(getGatewayDockerCommands(baseUrl, deviceName, creds, MQTT))
|
|
||||||
.ifPresent(v -> commands.set(MQTT, v));
|
|
||||||
}
|
|
||||||
if (isEnabled(MQTTS)) {
|
|
||||||
Optional.ofNullable(getGatewayDockerCommands(baseUrl, deviceName, creds, MQTTS))
|
|
||||||
.ifPresent(v -> commands.set(MQTTS, v));
|
|
||||||
}
|
|
||||||
return commands;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Resource getPemCertFile(String protocol) {
|
public Resource getPemCertFile(String protocol) {
|
||||||
return certs.computeIfAbsent(protocol, key -> {
|
return certs.computeIfAbsent(protocol, key -> {
|
||||||
@ -175,6 +151,14 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Resource createGatewayDockerComposeFile(String baseUrl, Device device) throws URISyntaxException {
|
||||||
|
String mqttType = isEnabled(MQTTS) ? MQTTS : MQTT;
|
||||||
|
DeviceConnectivityInfo properties = getConnectivity(mqttType);
|
||||||
|
DeviceCredentials creds = deviceCredentialsService.findDeviceCredentialsByDeviceId(device.getTenantId(), device.getId());
|
||||||
|
return DeviceConnectivityUtil.getGatewayDockerComposeFile(baseUrl, properties, creds, mqttType);
|
||||||
|
}
|
||||||
|
|
||||||
private DeviceConnectivityInfo getConnectivity(String protocol) {
|
private DeviceConnectivityInfo getConnectivity(String protocol) {
|
||||||
AdminSettings connectivitySettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "connectivity");
|
AdminSettings connectivitySettings = adminSettingsService.findAdminSettingsByKey(TenantId.SYS_TENANT_ID, "connectivity");
|
||||||
JsonNode connectivity;
|
JsonNode connectivity;
|
||||||
@ -300,18 +284,6 @@ public class DeviceConnectivityServiceImpl implements DeviceConnectivityService
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonNode getGatewayDockerCommands(String baseUrl, String deviceName, DeviceCredentials deviceCredentials, String mqttType) throws URISyntaxException {
|
|
||||||
ObjectNode dockerLaunchCommands = JacksonUtil.newObjectNode();
|
|
||||||
DeviceConnectivityInfo properties = getConnectivity(mqttType);
|
|
||||||
Optional.ofNullable(DeviceConnectivityUtil.getGatewayLaunchCommand(LINUX, deviceName, properties, deviceCredentials, mqttType, baseUrl))
|
|
||||||
.ifPresent(v -> dockerLaunchCommands.put(LINUX, v));
|
|
||||||
Optional.ofNullable(DeviceConnectivityUtil.getGatewayLaunchCommand(WINDOWS, deviceName, properties, deviceCredentials, mqttType, baseUrl))
|
|
||||||
.ifPresent(v -> dockerLaunchCommands.put(WINDOWS, v));
|
|
||||||
Optional.ofNullable(DeviceConnectivityUtil.getGatewayLaunchCommand(MACOS, deviceName, properties, deviceCredentials, mqttType, baseUrl))
|
|
||||||
.ifPresent(v -> dockerLaunchCommands.put(MACOS, v));
|
|
||||||
return dockerLaunchCommands.isEmpty() ? null : dockerLaunchCommands;
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getDockerMqttPublishCommand(String protocol, String baseUrl, String deviceTelemetryTopic, DeviceCredentials deviceCredentials) throws URISyntaxException {
|
private String getDockerMqttPublishCommand(String protocol, String baseUrl, String deviceTelemetryTopic, DeviceCredentials deviceCredentials) throws URISyntaxException {
|
||||||
DeviceConnectivityInfo properties = getConnectivity(protocol);
|
DeviceConnectivityInfo properties = getConnectivity(protocol);
|
||||||
String mqttHost = getHost(baseUrl, properties, protocol);
|
String mqttHost = getHost(baseUrl, properties, protocol);
|
||||||
|
|||||||
@ -15,6 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.thingsboard.server.dao.util;
|
package org.thingsboard.server.dao.util;
|
||||||
|
|
||||||
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
|
import org.springframework.core.io.Resource;
|
||||||
import org.thingsboard.common.util.JacksonUtil;
|
import org.thingsboard.common.util.JacksonUtil;
|
||||||
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
|
import org.thingsboard.server.common.data.device.credentials.BasicMqttCredentials;
|
||||||
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
import org.thingsboard.server.common.data.security.DeviceCredentials;
|
||||||
@ -25,6 +27,7 @@ import java.net.InetAddress;
|
|||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class DeviceConnectivityUtil {
|
public class DeviceConnectivityUtil {
|
||||||
@ -40,13 +43,10 @@ public class DeviceConnectivityUtil {
|
|||||||
public static final String COAP = "coap";
|
public static final String COAP = "coap";
|
||||||
public static final String COAPS = "coaps";
|
public static final String COAPS = "coaps";
|
||||||
public static final String CA_ROOT_CERT_PEM = "ca-root.pem";
|
public static final String CA_ROOT_CERT_PEM = "ca-root.pem";
|
||||||
public static final String CA_ROOT_GATEWAY_CERT_PEM_PATH = "{gatewayVolumePathPrefix}config{pathSep}" + CA_ROOT_CERT_PEM;
|
public static final String DOCKER_COMPOSE_YML = "docker-compose.yml";
|
||||||
public static final String CHECK_DOCUMENTATION = "Check documentation";
|
public static final String CHECK_DOCUMENTATION = "Check documentation";
|
||||||
public static final String JSON_EXAMPLE_PAYLOAD = "\"{temperature:25}\"";
|
public static final String JSON_EXAMPLE_PAYLOAD = "\"{temperature:25}\"";
|
||||||
public static final String DOCKER_RUN = "docker run --rm -it ";
|
public static final String DOCKER_RUN = "docker run --rm -it ";
|
||||||
public static final String GATEWAY_DOCKER_RUN = "docker run -it ";
|
|
||||||
|
|
||||||
public static final String NETWORK_HOST_PARAM = "--network=host ";
|
|
||||||
public static final String HOST_DOCKER_INTERNAL = "host.docker.internal";
|
public static final String HOST_DOCKER_INTERNAL = "host.docker.internal";
|
||||||
public static final String ADD_DOCKER_INTERNAL_HOST = "--add-host=" + HOST_DOCKER_INTERNAL + ":host-gateway ";
|
public static final String ADD_DOCKER_INTERNAL_HOST = "--add-host=" + HOST_DOCKER_INTERNAL + ":host-gateway ";
|
||||||
public static final String MQTT_IMAGE = "thingsboard/mosquitto-clients ";
|
public static final String MQTT_IMAGE = "thingsboard/mosquitto-clients ";
|
||||||
@ -94,75 +94,72 @@ public class DeviceConnectivityUtil {
|
|||||||
return command.toString();
|
return command.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getGatewayLaunchCommand(String os, String deviceName, DeviceConnectivityInfo properties, DeviceCredentials deviceCredentials, String mqttType, String baseUrl) throws URISyntaxException {
|
public static Resource getGatewayDockerComposeFile(String baseUrl, DeviceConnectivityInfo properties, DeviceCredentials deviceCredentials, String mqttType) throws URISyntaxException {
|
||||||
String host = getHost(baseUrl, properties, mqttType);
|
String host = getHost(baseUrl, properties, mqttType);
|
||||||
String port = properties.getPort().isEmpty() ? null : properties.getPort();
|
|
||||||
String gatewayVolumePathPrefix = "~/.tb-gateway/";
|
|
||||||
String pathSep = "/";
|
|
||||||
if (WINDOWS.equals(os)) {
|
|
||||||
gatewayVolumePathPrefix = "%HOMEDRIVE%%HOMEPATH%\\tb-gateway\\";
|
|
||||||
pathSep = "\\";
|
|
||||||
}
|
|
||||||
|
|
||||||
String gatewayContainerName = deviceName.replace(" ", "_").replaceAll("[^A-Za-z0-9_.-]", "");
|
|
||||||
|
|
||||||
StringBuilder command = new StringBuilder();
|
|
||||||
String caRootGatewayCertPemPath = CA_ROOT_GATEWAY_CERT_PEM_PATH
|
|
||||||
.replace("{gatewayVolumePathPrefix}", gatewayVolumePathPrefix)
|
|
||||||
.replace("{pathSep}", pathSep);
|
|
||||||
if (MQTTS.equals(mqttType)) {
|
|
||||||
command.append(getCurlPemCertCommand(baseUrl, MQTTS, caRootGatewayCertPemPath));
|
|
||||||
command.append(" && ");
|
|
||||||
}
|
|
||||||
command.append(GATEWAY_DOCKER_RUN);
|
|
||||||
command.append("-v {gatewayVolumePathPrefix}logs:/thingsboard_gateway/logs ".replace("{gatewayVolumePathPrefix}", gatewayVolumePathPrefix));
|
|
||||||
command.append("-v {gatewayVolumePathPrefix}extensions:/thingsboard_gateway/extensions ".replace("{gatewayVolumePathPrefix}", gatewayVolumePathPrefix));
|
|
||||||
command.append("-v {gatewayVolumePathPrefix}config:/thingsboard_gateway/config ".replace("{gatewayVolumePathPrefix}", gatewayVolumePathPrefix));
|
|
||||||
command.append("--name ").append(gatewayContainerName).append(" ");
|
|
||||||
if (LINUX.equals(os)) {
|
|
||||||
command.append(NETWORK_HOST_PARAM);
|
|
||||||
command.append(isLocalhost(host) ? ADD_DOCKER_INTERNAL_HOST : "");
|
|
||||||
} else {
|
|
||||||
command.append("-p 6400-6420:6400-6420 ");
|
|
||||||
}
|
|
||||||
command.append("-e host=").append(isLocalhost(host) ? HOST_DOCKER_INTERNAL : host);
|
|
||||||
if (port != null && !"1883".equals(port)) {
|
|
||||||
command.append(" -e port=").append(port);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
StringBuilder dockerComposeBuilder = new StringBuilder();
|
||||||
|
dockerComposeBuilder.append("version: '3.4'\n");
|
||||||
|
dockerComposeBuilder.append("services:\n");
|
||||||
|
dockerComposeBuilder.append(" # ThingsBoard IoT Gateway Service Configuration\n");
|
||||||
|
dockerComposeBuilder.append(" tb-gateway:\n");
|
||||||
|
dockerComposeBuilder.append(" image: thingsboard/tb-gateway\n");
|
||||||
|
dockerComposeBuilder.append(" container_name: tb-gateway\n");
|
||||||
|
dockerComposeBuilder.append(" restart: always\n");
|
||||||
|
dockerComposeBuilder.append("\n");
|
||||||
|
dockerComposeBuilder.append(" # Ports bindings - required by some connectors\n");
|
||||||
|
dockerComposeBuilder.append(" ports:\n");
|
||||||
|
dockerComposeBuilder.append(" - \"5000:5000\" # Comment if you don't use REST connector and change if you use another port\n");
|
||||||
|
dockerComposeBuilder.append(" # Uncomment and modify the following ports based on connector usage:\n");
|
||||||
|
dockerComposeBuilder.append("# - \"1052:1052\" # BACnet connector\n");
|
||||||
|
dockerComposeBuilder.append("# - \"5026:5026\" # Modbus TCP connector (Modbus Slave)\n");
|
||||||
|
dockerComposeBuilder.append("# - \"50000:50000/tcp\" # Socket connector with type TCP\n");
|
||||||
|
dockerComposeBuilder.append("# - \"50000:50000/udp\" # Socket connector with type UDP\n");
|
||||||
|
dockerComposeBuilder.append("\n");
|
||||||
|
dockerComposeBuilder.append(" # Necessary mapping for Linux\n");
|
||||||
|
dockerComposeBuilder.append(" extra_hosts:\n");
|
||||||
|
dockerComposeBuilder.append(" - \"host.docker.internal:host-gateway\"\n");
|
||||||
|
dockerComposeBuilder.append("\n");
|
||||||
|
dockerComposeBuilder.append(" # Environment variables\n");
|
||||||
|
dockerComposeBuilder.append(" environment:\n");
|
||||||
|
dockerComposeBuilder.append(" - host=").append(isLocalhost(host) ? HOST_DOCKER_INTERNAL : host).append("\n");
|
||||||
|
dockerComposeBuilder.append(" - port=1883\n");
|
||||||
switch (deviceCredentials.getCredentialsType()) {
|
switch (deviceCredentials.getCredentialsType()) {
|
||||||
case ACCESS_TOKEN:
|
case ACCESS_TOKEN:
|
||||||
command.append(" -e accessToken=").append(deviceCredentials.getCredentialsId());
|
dockerComposeBuilder.append(" - accessToken=").append(deviceCredentials.getCredentialsId()).append("\n");
|
||||||
break;
|
break;
|
||||||
case MQTT_BASIC:
|
case MQTT_BASIC:
|
||||||
BasicMqttCredentials credentials = JacksonUtil.fromString(deviceCredentials.getCredentialsValue(),
|
BasicMqttCredentials credentials = JacksonUtil.fromString(deviceCredentials.getCredentialsValue(),
|
||||||
BasicMqttCredentials.class);
|
BasicMqttCredentials.class);
|
||||||
if (credentials != null) {
|
if (credentials != null) {
|
||||||
if (credentials.getClientId() != null) {
|
if (credentials.getClientId() != null) {
|
||||||
command.append(" -e clientId=").append(credentials.getClientId());
|
dockerComposeBuilder.append(" - clientId=").append(credentials.getClientId()).append("\n");
|
||||||
}
|
}
|
||||||
if (credentials.getUserName() != null) {
|
if (credentials.getUserName() != null) {
|
||||||
command.append(" -e username=").append(credentials.getUserName());
|
dockerComposeBuilder.append(" - username=").append(credentials.getUserName()).append("\n");
|
||||||
}
|
}
|
||||||
if (credentials.getPassword() != null) {
|
if (credentials.getPassword() != null) {
|
||||||
command.append(" -e password=").append(credentials.getPassword());
|
dockerComposeBuilder.append(" - password=").append(credentials.getPassword()).append("\n");
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
dockerComposeBuilder.append("\n");
|
||||||
|
dockerComposeBuilder.append(" # Volumes bind\n");
|
||||||
|
dockerComposeBuilder.append(" volumes:\n");
|
||||||
|
dockerComposeBuilder.append(" - tb-gw-config:/thingsboard_gateway/config\n");
|
||||||
|
dockerComposeBuilder.append(" - tb-gw-logs:/thingsboard_gateway/logs\n");
|
||||||
|
dockerComposeBuilder.append(" - tb-gw-extensions:/thingsboard_gateway/extensions\n");
|
||||||
|
dockerComposeBuilder.append("\n");
|
||||||
|
dockerComposeBuilder.append("# Volumes declaration for configurations, extensions and configuration\n");
|
||||||
|
dockerComposeBuilder.append("volumes:\n");
|
||||||
|
dockerComposeBuilder.append(" tb-gw-config:\n");
|
||||||
|
dockerComposeBuilder.append(" name: tb-gw-config\n");
|
||||||
|
dockerComposeBuilder.append(" tb-gw-logs:\n");
|
||||||
|
dockerComposeBuilder.append(" name: tb-gw-logs\n");
|
||||||
|
dockerComposeBuilder.append(" tb-gw-extensions:\n");
|
||||||
|
dockerComposeBuilder.append(" name: tb-gw-extensions\n");
|
||||||
|
|
||||||
if (MQTTS.equals(mqttType)) {
|
return new ByteArrayResource(dockerComposeBuilder.toString().getBytes(StandardCharsets.UTF_8));
|
||||||
command.append(" -e caCert=/thingsboard_gateway/config/").append(CA_ROOT_CERT_PEM);
|
|
||||||
}
|
|
||||||
|
|
||||||
command.append(" --restart always");
|
|
||||||
command.append(" thingsboard/tb-gateway");
|
|
||||||
|
|
||||||
return command.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getDockerMqttPublishCommand(String protocol, String baseUrl, String host, String port, String deviceTelemetryTopic, DeviceCredentials deviceCredentials) {
|
public static String getDockerMqttPublishCommand(String protocol, String baseUrl, String host, String port, String deviceTelemetryTopic, DeviceCredentials deviceCredentials) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user