Compare commits
10 Commits
9470a02ccb
...
9e722d02c4
Author | SHA1 | Date |
---|---|---|
hyunjujeong | 9e722d02c4 | |
hyunjujeong | 2aa1f0c225 | |
hyunjujeong | 15be9161f3 | |
hyunjujeong | c625560cc6 | |
hyunjujeong | 5401b6687f | |
hyunjujeong | f30f914283 | |
hyunjujeong | f9af91c688 | |
hyunjujeong | b74398813e | |
hyunjujeong | a3a7ce77cf | |
hyunjujeong | d32521e412 |
|
@ -0,0 +1,4 @@
|
|||
FROM amazoncorretto:17.0.6-al2023
|
||||
EXPOSE 8081
|
||||
ADD ./build/libs/*.jar device-deployer.jar
|
||||
ENTRYPOINT ["java", "-jar", "/device-deployer.jar"]
|
|
@ -0,0 +1,97 @@
|
|||
# [BlokWorks] Device Deployer Service #
|
||||
사용자에게 Command 를 입력받아 MQTT 를 발행하고 배포된 앱의 정보를 저장하고, 조회하는 Spring boot 기반 Java 애플리케이션입니다.
|
||||
|
||||
## 기반 기술 ##
|
||||
|
||||
---
|
||||
* Java 17
|
||||
* Spring Boot 3.1.3
|
||||
* Gradle 8.2.1
|
||||
|
||||
## 주요 의존성 ##
|
||||
|
||||
---
|
||||
* MQTT
|
||||
* PostgreSQL
|
||||
|
||||
## 빌드 ##
|
||||
|
||||
---
|
||||
|
||||
### 프로젝트 패키징 ###
|
||||
|
||||
Gradle을 사용하여 패키징합니다.
|
||||
```shell
|
||||
$ ./gradlew clean build -x test
|
||||
```
|
||||
|
||||
### 도커 빌드 ###
|
||||
|
||||
```dockerfile
|
||||
FROM amazoncorretto:17.0.6-al2023
|
||||
EXPOSE 8081
|
||||
ADD ./build/libs/*.jar device-deployer.jar
|
||||
ENTRYPOINT ["java", "-jar", "/device-deployer.jar"]
|
||||
```
|
||||
|
||||
Image Registry로 사용할 AWS ECR에 로그인을 합니다.
|
||||
```shell
|
||||
$ aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com
|
||||
```
|
||||
|
||||
패키징된 jar 파일을 Docker image로 빌드합니다.
|
||||
```shell
|
||||
$ docker build --platform linux/amd64 -t device-deployer:0.0.7-SNAPSHOT .
|
||||
$ docker tag sdt-cloud/device-deployer:0.0.7-SNAPSHOT 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/device-deployer:{{version}}
|
||||
```
|
||||
|
||||
### 이미지 업로드 ###
|
||||
|
||||
빌드 및 태깅된 Docker image를 Image Registry에 업로드 합니다.
|
||||
```shell
|
||||
$ docker push 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/device-deployer:{{version}}
|
||||
```
|
||||
|
||||
|
||||
## 구동 ##
|
||||
|
||||
---
|
||||
|
||||
### 사전 구동 애플리케이션 및 모듈 ###
|
||||
|
||||
1. MQTT 컨테이너 모듈
|
||||
- 사용자의 Command 를 Edge(Device)에게 전달하기 위한 Message Queue 입니다.
|
||||
2. PostgreSQL 컨테이너 모듈
|
||||
- 실행된 Command 의 정보를 저장하고 조회할 수 있는 RDB 입니다.
|
||||
|
||||
|
||||
### 설정 정보 ###
|
||||
설정 정보 등록은 설정 관리 애플리케이션의 POST /configuration API 를 이용합니다.
|
||||
|
||||
| 옵션 | 설명 | 필수 여부 | 기본값 |
|
||||
|:--------------------------:|:-----------------------------------:|:-----:|:---:|
|
||||
| server.port | 서버 포트 | O | - |
|
||||
| inbound.mqtt.url | MQTT 모듈의 url | O | - |
|
||||
| inbound.mqtt.username | MQTT 모듈의 username | O | - |
|
||||
| inbound.mqtt.password | MQTT 모듈의 password | O | - |
|
||||
| inbound.mqtt.topics | MQTT 모듈이 구독할 Inference 결과 데이터 topic | O | - |
|
||||
| spring.datasource.uri | PostgreSQL 모듈의 연결을 위한 URI | O | - |
|
||||
| spring.datasource.username | PostgreSQL 모듈의 username | O | - |
|
||||
| spring.datasource.pssword | PostgreSQL 모듈의 password | O | - |
|
||||
|
||||
### 배포 ###
|
||||
배포는 k8s manifest로 작성한 deploy.yaml을 이용합니다.
|
||||
Deployment 오브젝트에 반드시 명시해야 하는 설정 정보(`env`)는 아래와 같습니다.
|
||||
|
||||
| 옵션 | 설명 | 필수 여부 | 예시 |
|
||||
|:-----------------------------:|:-------------------------------------------------:|:-----:|:-----------------------------------------------------------------------------------------------------------------------------------------:|
|
||||
| SPRING_PROFILES_ACTIVE | 구동 profile | O | k8s |
|
||||
| SERVER_PORT | 애플리케이션이 등록될 포트 | O | 8085 |
|
||||
| POSTGRES_CREDENTIALS_URL | PostgreSQL의 URL | O | jdbc:postgresql://localhost:5432/blokworks |
|
||||
| POSTGRES_CREDENTIALS_USERNAME | PostgreSQL의 계정 | O | sdt |
|
||||
| POSTGRES_CREDENTIALS_PASSWORD | PostgreSQL의 비밀번호 | O | 2xxxxx |
|
||||
| IAM_AMQP_HOST | RabbitMQ의 URL | O | rabbitmq.sdt-cloud.svc.cluster.local |
|
||||
| IAM_AMQP_PORT | RabbitMQ의 포트 | O | 5672 |
|
||||
| IAM_AMQP_USERNAME | RabbitMQ에 접속할 계정 | O | guest |
|
||||
| IAM_AMQP_PASSWORD | RabbitMQ에 접속할 비밀번호 | O | guest |
|
||||
|
|
@ -15,6 +15,10 @@ jar {
|
|||
enabled = false
|
||||
}
|
||||
|
||||
ext {
|
||||
jjwtVersion = "0.11.5"
|
||||
}
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
@ -26,6 +30,9 @@ dependencies {
|
|||
implementation("org.springframework.boot:spring-boot-starter-amqp")
|
||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||
implementation("org.springframework.integration:spring-integration-mqtt")
|
||||
implementation("io.jsonwebtoken:jjwt-api:${jjwtVersion}")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-impl:${jjwtVersion}")
|
||||
runtimeOnly("io.jsonwebtoken:jjwt-jackson:${jjwtVersion}")
|
||||
runtimeOnly("org.postgresql:postgresql")
|
||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
package inc.sdt.blokworks.devicedeployer;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.rest.RestTemplateResponseErrorHandler;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DeviceDeployerApplication {
|
||||
|
@ -10,4 +14,11 @@ public class DeviceDeployerApplication {
|
|||
SpringApplication.run(DeviceDeployerApplication.class, args);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate(RestTemplateBuilder builder) {
|
||||
return builder
|
||||
.errorHandler(new RestTemplateResponseErrorHandler())
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class BashCommand implements CommandInfo{
|
||||
@Override
|
||||
public LinkedHashMap<String, Object> put(OutboundMessage message) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("cmd", message.getCommand());
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public interface CommandInfo {
|
||||
LinkedHashMap<String, Object> put(OutboundMessage message);
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class CommandInvoker {
|
||||
private final BashCommand bashCommand;
|
||||
private final SystemdCommand systemdCommand;
|
||||
private final DockerCommand dockerCommand;
|
||||
private final JsonCommand jsonCommand;
|
||||
private final DeployCommandInvoker deployCommandInvoker;
|
||||
|
||||
public CommandInvoker(BashCommand bashCommand,
|
||||
SystemdCommand systemdCommand,
|
||||
DockerCommand dockerCommand,
|
||||
JsonCommand jsonCommand,
|
||||
DeployCommandInvoker deployCommandInvoker) {
|
||||
this.bashCommand = bashCommand;
|
||||
this.systemdCommand = systemdCommand;
|
||||
this.dockerCommand = dockerCommand;
|
||||
this.jsonCommand = jsonCommand;
|
||||
this.deployCommandInvoker = deployCommandInvoker;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, Object> invoke(OutboundMessage message) {
|
||||
if(message.getCommandType() == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
switch (message.getCommandType()) {
|
||||
case bash -> {
|
||||
return bashCommand.put(message);
|
||||
}
|
||||
case systemd -> {
|
||||
return systemdCommand.put(message);
|
||||
}
|
||||
case docker -> {
|
||||
return dockerCommand.put(message);
|
||||
}
|
||||
case deploy -> {
|
||||
return deployCommandInvoker.invoke(message);
|
||||
}
|
||||
default -> {
|
||||
return jsonCommand.put(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,13 +2,9 @@ package inc.sdt.blokworks.devicedeployer.application;
|
|||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.*;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.OutboundMessagePayload;
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.exception.ConflictException;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import org.eclipse.paho.client.mqttv3.IMqttClient;
|
||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||
|
@ -18,59 +14,67 @@ import org.springframework.data.domain.Page;
|
|||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Service
|
||||
public class DefaultDeployerService implements DeployerService{
|
||||
private final Logger log;
|
||||
private final IMqttClient mqttClient;
|
||||
private final ObjectMapper objectMapper;
|
||||
private final DeployerRepositoryDelegate deployerRepositoryDelegate;
|
||||
private String requestId;
|
||||
private final DeployRequestRepositoryDelegate requestRepositoryDelegate;
|
||||
|
||||
public DefaultDeployerService(IMqttClient mqttClient,
|
||||
ObjectMapper objectMapper,
|
||||
DeployerRepositoryDelegate deployerRepositoryDelegate) {
|
||||
DeployerRepositoryDelegate deployerRepositoryDelegate,
|
||||
DeployRequestRepositoryDelegate requestRepositoryDelegate) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.mqttClient = mqttClient;
|
||||
this.objectMapper = objectMapper;
|
||||
this.deployerRepositoryDelegate = deployerRepositoryDelegate;
|
||||
this.requestRepositoryDelegate = requestRepositoryDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void publish(OutboundMessage deployMessage, String assetCode) {
|
||||
log.info("[publish]");
|
||||
public void publish(OutboundMessage outboundMessage) {
|
||||
log.info("[publish] outboundMessage = {}", outboundMessage);
|
||||
try {
|
||||
OutboundMessagePayload payload = new OutboundMessagePayload(
|
||||
deployMessage.getUrl(),
|
||||
deployMessage.getName(),
|
||||
deployMessage.getCommand(),
|
||||
deployMessage.getEnv(),
|
||||
OperationType.DEPLOY,
|
||||
deployMessage.getRequestId()
|
||||
outboundMessage.getCommandInfo(),
|
||||
outboundMessage.getCommandType(),
|
||||
outboundMessage.getSubCommandType(),
|
||||
outboundMessage.getAssetCode(),
|
||||
outboundMessage.getRequestId()
|
||||
);
|
||||
|
||||
byte[] bytes = objectMapper.writeValueAsBytes(payload);
|
||||
MqttMessage message = new MqttMessage();
|
||||
message.setPayload(bytes);
|
||||
|
||||
mqttClient.publish("/assets/"+assetCode+"/apps/deploy", message);
|
||||
requestId = deployMessage.getRequestId();
|
||||
log.info("[publish] message = {}", message);
|
||||
mqttClient.publish("/device-control/"+outboundMessage.getAssetCode(), message);
|
||||
log.info("[publish] payload = {}", payload);
|
||||
}catch (JsonProcessingException | MqttException e) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeployRequest save(DeployRequest deployRequest) {
|
||||
log.info("[save] deployRequest = {}", deployRequest);
|
||||
requestRepositoryDelegate.save(deployRequest);
|
||||
return deployRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> apply(InboundDeployMessagePayload payload) {
|
||||
log.info("[apply] inboundDeployMessagePayload = {}", payload);
|
||||
// 배포된 앱 정보 저장
|
||||
// request Id 판별
|
||||
if(requestId.equals(payload.requestId())) {
|
||||
log.info("[apply] payload = {}", payload);
|
||||
Optional<DeployRequest> deployRequest = requestRepositoryDelegate.findByRequestId(payload.requestId());
|
||||
if(deployRequest.isPresent()) {
|
||||
return Mono.just(payload)
|
||||
.doOnNext(deployerRepositoryDelegate)
|
||||
.then();
|
||||
}else {
|
||||
throw new ConflictException("This process is already exists.");
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundProcessMessagePayload;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.stereotype.Service;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
@Service
|
||||
public class DefaultProcessService implements ProcessService{
|
||||
private final Logger log;
|
||||
private final ProcessRepositoryDelegate processRepositoryDelegate;
|
||||
|
||||
public DefaultProcessService(ProcessRepositoryDelegate processRepositoryDelegate) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.processRepositoryDelegate = processRepositoryDelegate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mono<Void> apply(InboundProcessMessagePayload inboundProcessMessagePayload) {
|
||||
log.info("[apply] inboundProcessMessagePayload = {}", inboundProcessMessagePayload);
|
||||
// 프로세스 저장
|
||||
return Mono.just(inboundProcessMessagePayload)
|
||||
.doOnNext(processRepositoryDelegate)
|
||||
.then();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Process> getAll(String assetCode, int page, int size) {
|
||||
log.info("[getAll] assetCode = {}, page = {}, size = {}", assetCode, page, size);
|
||||
return processRepositoryDelegate.findAllByAssetCode(assetCode, page, size);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class DeployCommand implements CommandInfo {
|
||||
|
||||
@Override
|
||||
public LinkedHashMap<String, Object> put(OutboundMessage message) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("cmd", message.getCommand());
|
||||
map.put("appName", message.getAppName());
|
||||
map.put("name", message.getName());
|
||||
map.put("fileUrl", message.getUrl());
|
||||
map.put("fileType", message.getFileType());
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class DeployCommandInvoker {
|
||||
private final DockerCommand dockerCommand;
|
||||
private final DeployCommand deployCommand;
|
||||
private final JsonCommand jsonCommand;
|
||||
|
||||
public DeployCommandInvoker(DockerCommand dockerCommand, DeployCommand deployCommand, JsonCommand jsonCommand) {
|
||||
this.dockerCommand = dockerCommand;
|
||||
this.deployCommand = deployCommand;
|
||||
this.jsonCommand = jsonCommand;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, Object> invoke(OutboundMessage message) {
|
||||
if(message.getSubCommandType() == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
switch (message.getSubCommandType()) {
|
||||
case systemd -> {
|
||||
return deployCommand.put(message);
|
||||
}
|
||||
case docker -> {
|
||||
return dockerCommand.put(message);
|
||||
}
|
||||
default -> {
|
||||
return jsonCommand.put(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.DeployRequest;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public interface DeployRequestRepositoryDelegate {
|
||||
DeployRequest save(DeployRequest deployRequest);
|
||||
Optional<DeployRequest> findByRequestId(String requestId);
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.DeployRequest;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
@ -9,6 +10,7 @@ import reactor.core.publisher.Mono;
|
|||
import java.util.function.Function;
|
||||
|
||||
public interface DeployerService extends Function<InboundDeployMessagePayload, Mono<Void>> {
|
||||
void publish(OutboundMessage assetApp, String assetCode);
|
||||
void publish(OutboundMessage message);
|
||||
DeployRequest save(DeployRequest deployRequest);
|
||||
Page<AssetApp> getAll(String assetCode, int page, int size);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class DockerCommand implements CommandInfo {
|
||||
|
||||
@Override
|
||||
public LinkedHashMap<String, Object> put(OutboundMessage message) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("cmd", message.getCommand());
|
||||
map.put("appName", message.getAppName());
|
||||
map.put("name", message.getName()); // container 이름
|
||||
map.put("image", message.getImage());
|
||||
map.put("options", message.getOptions());
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class JsonCommand implements CommandInfo {
|
||||
@Override
|
||||
public LinkedHashMap<String, Object> put(OutboundMessage message) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("cmd", String.valueOf(message.getCommandType()));
|
||||
map.put("appName", message.getAppName());
|
||||
map.put("filename", message.getName());
|
||||
map.put("parameter", message.getParameters());
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundProcessMessagePayload;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public interface ProcessRepositoryDelegate extends Consumer<InboundProcessMessagePayload> {
|
||||
Process save(Process process);
|
||||
Page<Process> findAllByAssetCode(String assetCode, int page, int size);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundProcessMessagePayload;
|
||||
import org.springframework.data.domain.Page;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface ProcessService extends Function<InboundProcessMessagePayload, Mono<Void>> {
|
||||
Page<Process> getAll(String assetCode, int page, int size);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package inc.sdt.blokworks.devicedeployer.application;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@Component
|
||||
public class SystemdCommand implements CommandInfo {
|
||||
@Override
|
||||
public LinkedHashMap<String, Object> put(OutboundMessage message) {
|
||||
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("cmd", message.getCommand());
|
||||
map.put("service", message.getAppName());
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -3,18 +3,24 @@ package inc.sdt.blokworks.devicedeployer.domain;
|
|||
public class AssetApp {
|
||||
private String assetCode;
|
||||
private String name;
|
||||
private Long size;
|
||||
private int size;
|
||||
private int pid;
|
||||
private String message;
|
||||
private Long releaseAt;
|
||||
private Long updatedAt;
|
||||
private Status status;
|
||||
|
||||
protected AssetApp() {}
|
||||
|
||||
public AssetApp(String assetCode, String name, Long size, Long releaseAt, Long updatedAt) {
|
||||
public AssetApp(String assetCode, String name, int size, int pid, String message, Long releaseAt, Long updatedAt, Status status) {
|
||||
this.assetCode = assetCode;
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
this.pid = pid;
|
||||
this.message = message;
|
||||
this.releaseAt = releaseAt;
|
||||
this.updatedAt = updatedAt;
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public String getAssetCode() {
|
||||
|
@ -25,10 +31,18 @@ public class AssetApp {
|
|||
return name;
|
||||
}
|
||||
|
||||
public Long getSize() {
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public int getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public Long getReleaseAt() {
|
||||
return releaseAt;
|
||||
}
|
||||
|
@ -37,14 +51,21 @@ public class AssetApp {
|
|||
return updatedAt;
|
||||
}
|
||||
|
||||
public Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetApp{" +
|
||||
"assetCode='" + assetCode + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", size=" + size +
|
||||
", pid=" + pid +
|
||||
", message='" + message + '\'' +
|
||||
", releaseAt=" + releaseAt +
|
||||
", updatedAt=" + updatedAt +
|
||||
", status=" + status +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -55,9 +76,12 @@ public class AssetApp {
|
|||
public static final class Builder {
|
||||
private String assetCode;
|
||||
private String name;
|
||||
private Long size;
|
||||
private int size;
|
||||
private int pid;
|
||||
private String message;
|
||||
private Long releasedAt;
|
||||
private Long updatedAt;
|
||||
private Status status;
|
||||
|
||||
public Builder assetCode(String assetCode) {
|
||||
this.assetCode = assetCode;
|
||||
|
@ -69,11 +93,21 @@ public class AssetApp {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder size(Long size) {
|
||||
public Builder size(int size) {
|
||||
this.size = size;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder pid(int pid) {
|
||||
this.pid = pid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder message(String message) {
|
||||
this.message = message;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder releasedAt(Long releasedAt) {
|
||||
this.releasedAt = releasedAt;
|
||||
return this;
|
||||
|
@ -84,13 +118,21 @@ public class AssetApp {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder status(Status status) {
|
||||
this.status = status;
|
||||
return this;
|
||||
}
|
||||
|
||||
public AssetApp build() {
|
||||
AssetApp assetApp = new AssetApp();
|
||||
assetApp.assetCode = this.assetCode;
|
||||
assetApp.name = this.name;
|
||||
assetApp.size = this.size;
|
||||
assetApp.pid = this.pid;
|
||||
assetApp.message = this.message;
|
||||
assetApp.releaseAt = this.releasedAt;
|
||||
assetApp.updatedAt = this.updatedAt;
|
||||
assetApp.status = this.status;
|
||||
return assetApp;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public enum CommandType {
|
||||
bash,
|
||||
systemd,
|
||||
docker,
|
||||
deploy,
|
||||
json
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public class DeployRequest {
|
||||
private String requestId;
|
||||
private String assetCode;
|
||||
private String appName;
|
||||
private OperationType operationType;
|
||||
private CommandType commandType;
|
||||
private SubCommandType subCommandType;
|
||||
|
||||
protected DeployRequest() {}
|
||||
|
||||
public DeployRequest(String requestId, String assetCode, String appName, OperationType operationType, CommandType commandType, SubCommandType subCommandType) {
|
||||
this.requestId = requestId;
|
||||
this.assetCode = assetCode;
|
||||
this.appName = appName;
|
||||
this.operationType = operationType;
|
||||
this.commandType = commandType;
|
||||
this.subCommandType = subCommandType;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public String getAssetCode() {
|
||||
return assetCode;
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public OperationType getOperationType() {
|
||||
return operationType;
|
||||
}
|
||||
|
||||
public CommandType getCommandType() {
|
||||
return commandType;
|
||||
}
|
||||
|
||||
public SubCommandType getSubCommandType() {
|
||||
return subCommandType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DeployRequest{" +
|
||||
"requestId='" + requestId + '\'' +
|
||||
", assetCode='" + assetCode + '\'' +
|
||||
", appName='" + appName + '\'' +
|
||||
", operationType=" + operationType +
|
||||
", commandType=" + commandType +
|
||||
", subCommandType=" + subCommandType +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String requestId;
|
||||
private String assetCode;
|
||||
private String appName;
|
||||
private OperationType operationType;
|
||||
private CommandType commandType;
|
||||
private SubCommandType subCommandType;
|
||||
|
||||
public Builder requestId(String requestId) {
|
||||
this.requestId = requestId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder assetCode(String assetCode) {
|
||||
this.assetCode = assetCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder appName(String appName) {
|
||||
this.appName = appName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder operationType(OperationType operationType) {
|
||||
this.operationType = operationType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder commandType(CommandType commandType) {
|
||||
this.commandType = commandType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder subCommandType(SubCommandType subCommandType) {
|
||||
this.subCommandType = subCommandType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public DeployRequest build() {
|
||||
DeployRequest deployRequest = new DeployRequest();
|
||||
deployRequest.requestId = this.requestId;
|
||||
deployRequest.assetCode = this.assetCode;
|
||||
deployRequest.appName = this.appName;
|
||||
deployRequest.operationType = this.operationType;
|
||||
deployRequest.commandType = this.commandType;
|
||||
deployRequest.subCommandType = this.subCommandType;
|
||||
return deployRequest;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public enum DeviceType {
|
||||
ecn,
|
||||
nodeq
|
||||
}
|
|
@ -1,15 +1,21 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
public class OutboundMessage {
|
||||
private String url;
|
||||
private String name;
|
||||
private HashMap<String, String> env;
|
||||
private String fileType;
|
||||
private String assetCode;
|
||||
private String appName; // 사용자가 정한 파일 이름
|
||||
private String name; // stackbase 에 저장된 파일 이름
|
||||
private String image;
|
||||
private LinkedHashMap<String, Object> options;
|
||||
private String command;
|
||||
private OperationType operationType;
|
||||
private String requestId;
|
||||
private CommandType commandType;
|
||||
private SubCommandType subCommandType;
|
||||
private LinkedHashMap<String, String> parameters;
|
||||
private LinkedHashMap<String, Object> commandInfo;
|
||||
|
||||
protected OutboundMessage() {}
|
||||
|
||||
|
@ -17,22 +23,38 @@ public class OutboundMessage {
|
|||
return url;
|
||||
}
|
||||
|
||||
public String getFileType() {
|
||||
return fileType;
|
||||
}
|
||||
|
||||
public String getAssetCode() {
|
||||
return assetCode;
|
||||
}
|
||||
|
||||
public void setAssetCode(String assetCode) {
|
||||
this.assetCode = assetCode;
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public HashMap<String, String> getEnv() {
|
||||
return env;
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, Object> getOptions() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public String getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public OperationType getOperationType() {
|
||||
return operationType;
|
||||
}
|
||||
|
||||
public void setRequestId(String requestId) {
|
||||
this.requestId = requestId;
|
||||
}
|
||||
|
@ -41,15 +63,42 @@ public class OutboundMessage {
|
|||
return requestId;
|
||||
}
|
||||
|
||||
public CommandType getCommandType() {
|
||||
return commandType;
|
||||
}
|
||||
|
||||
public SubCommandType getSubCommandType() {
|
||||
return subCommandType;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, String> getParameters() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public LinkedHashMap<String, Object> getCommandInfo() {
|
||||
return commandInfo;
|
||||
}
|
||||
|
||||
public void setCommandInfo(LinkedHashMap<String, Object> commandInfo) {
|
||||
this.commandInfo = commandInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AssetApp{" +
|
||||
return "OutboundMessage{" +
|
||||
"url='" + url + '\'' +
|
||||
", fileType='" + fileType + '\'' +
|
||||
", assetCode='" + assetCode + '\'' +
|
||||
", appName='" + appName + '\'' +
|
||||
", name='" + name + '\'' +
|
||||
", env=" + env +
|
||||
", image='" + image + '\'' +
|
||||
", options=" + options +
|
||||
", command='" + command + '\'' +
|
||||
", operationType=" + operationType +
|
||||
", requestId='" + requestId + '\'' +
|
||||
", commandType=" + commandType +
|
||||
", subCommandType=" + subCommandType +
|
||||
", parameters=" + parameters +
|
||||
", commandInfo=" + commandInfo +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
@ -59,24 +108,51 @@ public class OutboundMessage {
|
|||
|
||||
public static final class Builder {
|
||||
private String url;
|
||||
private String fileType;
|
||||
private String assetCode;
|
||||
private String appName;
|
||||
private String name;
|
||||
private HashMap<String, String> env;
|
||||
private String image;
|
||||
private LinkedHashMap<String, Object> options;
|
||||
private String command;
|
||||
private OperationType operationType;
|
||||
private String requestId;
|
||||
private CommandType commandType;
|
||||
private SubCommandType subCommandType;
|
||||
private LinkedHashMap<String, String> parameters;
|
||||
private LinkedHashMap<String, Object> commandInfo;
|
||||
|
||||
public Builder url(String url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder fileType(String fileType) {
|
||||
this.fileType = fileType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder assetCode(String assetCode) {
|
||||
this.assetCode = assetCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder appName(String appName) {
|
||||
this.appName = appName;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder env(HashMap<String, String> env) {
|
||||
this.env = env;
|
||||
public Builder image(String image) {
|
||||
this.image = image;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder options(LinkedHashMap<String, Object> options) {
|
||||
this.options = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -85,24 +161,46 @@ public class OutboundMessage {
|
|||
return this;
|
||||
}
|
||||
|
||||
public Builder operationType(OperationType operationType) {
|
||||
this.operationType = operationType;
|
||||
public Builder requestId(String requestId) {
|
||||
this.requestId = requestId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder requestId(String requestId) {
|
||||
this.requestId = requestId;
|
||||
public Builder commandType(CommandType commandType) {
|
||||
this.commandType = commandType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder subCommandType(SubCommandType subCommandType) {
|
||||
this.subCommandType = subCommandType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder parameters(LinkedHashMap<String, String> parameters) {
|
||||
this.parameters = parameters;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder commandInfo(LinkedHashMap<String, Object> commandInfo) {
|
||||
this.commandInfo = commandInfo;
|
||||
return this;
|
||||
}
|
||||
|
||||
public OutboundMessage build() {
|
||||
OutboundMessage deployMessage = new OutboundMessage();
|
||||
deployMessage.url = this.url;
|
||||
deployMessage.fileType = this.fileType;
|
||||
deployMessage.assetCode = this.assetCode;
|
||||
deployMessage.appName = this.appName;
|
||||
deployMessage.name = this.name;
|
||||
deployMessage.env = this.env;
|
||||
deployMessage.image = this.image;
|
||||
deployMessage.options = this.options;
|
||||
deployMessage.command = this.command;
|
||||
deployMessage.operationType = this.operationType;
|
||||
deployMessage.requestId = this.requestId;
|
||||
deployMessage.commandType = this.commandType;
|
||||
deployMessage.subCommandType = this.subCommandType;
|
||||
deployMessage.parameters = this.parameters;
|
||||
deployMessage.commandInfo = this.commandInfo;
|
||||
return deployMessage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,63 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public class Port {
|
||||
private String protocol;
|
||||
private Integer hostPort;
|
||||
private Integer containerPort;
|
||||
|
||||
protected Port() {}
|
||||
|
||||
public String getProtocol() {
|
||||
return protocol;
|
||||
}
|
||||
|
||||
public Integer getHostPort() {
|
||||
return hostPort;
|
||||
}
|
||||
|
||||
public Integer getContainerPort() {
|
||||
return containerPort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Port{" +
|
||||
"protocol='" + protocol + '\'' +
|
||||
", hostPort=" + hostPort +
|
||||
", containerPort=" + containerPort +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String protocol;
|
||||
private Integer hostPort;
|
||||
private Integer containerPort;
|
||||
|
||||
public Builder protocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder hostPort(Integer hostPort) {
|
||||
this.hostPort = hostPort;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder containerPort(Integer containerPort) {
|
||||
this.containerPort = containerPort;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Port build() {
|
||||
Port port = new Port();
|
||||
port.protocol = this.protocol;
|
||||
port.hostPort = this.hostPort;
|
||||
port.containerPort = this.containerPort;
|
||||
return port;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,139 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public class Process {
|
||||
private String assetCode;
|
||||
private Integer pid;
|
||||
private String name;
|
||||
private Integer cpu;
|
||||
private Integer memory;
|
||||
private Integer network;
|
||||
private Long processedAt;
|
||||
private OperationType operationType;
|
||||
|
||||
protected Process() {}
|
||||
|
||||
public Process(String assetCode, Integer pid, String name, Integer cpu, Integer memory, Integer network, Long processedAt, OperationType operationType) {
|
||||
this.assetCode = assetCode;
|
||||
this.pid = pid;
|
||||
this.name = name;
|
||||
this.cpu = cpu;
|
||||
this.memory = memory;
|
||||
this.network = network;
|
||||
this.processedAt = processedAt;
|
||||
this.operationType = operationType;
|
||||
}
|
||||
|
||||
public String getAssetCode() {
|
||||
return assetCode;
|
||||
}
|
||||
|
||||
public Integer getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Integer getCpu() {
|
||||
return cpu;
|
||||
}
|
||||
|
||||
public Integer getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
public Integer getNetwork() {
|
||||
return network;
|
||||
}
|
||||
|
||||
public Long getProcessedAt() {
|
||||
return processedAt;
|
||||
}
|
||||
|
||||
public OperationType getOperationType() {
|
||||
return operationType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Process{" +
|
||||
"assetCode='" + assetCode + '\'' +
|
||||
", pid=" + pid +
|
||||
", name='" + name + '\'' +
|
||||
", cpu=" + cpu +
|
||||
", memory=" + memory +
|
||||
", network=" + network +
|
||||
", processedAt=" + processedAt +
|
||||
", operationType=" + operationType +
|
||||
'}';
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static final class Builder {
|
||||
private String assetCode;
|
||||
private Integer pid;
|
||||
private String name;
|
||||
private Integer cpu;
|
||||
private Integer memory;
|
||||
private Integer network;
|
||||
private Long processedAt;
|
||||
private OperationType operationType;
|
||||
|
||||
public Builder assetCode(String assetCode) {
|
||||
this.assetCode = assetCode;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder pid(Integer pid) {
|
||||
this.pid = pid;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder cpu(Integer cpu) {
|
||||
this.cpu = cpu;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder memory(Integer memory) {
|
||||
this.memory = memory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder network(Integer network) {
|
||||
this.network = network;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder processedAt(Long processedAt) {
|
||||
this.processedAt = processedAt;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder operationType(OperationType operationType) {
|
||||
this.operationType = operationType;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Process build() {
|
||||
Process process = new Process();
|
||||
process.assetCode = this.assetCode;
|
||||
process.pid = this.pid;
|
||||
process.name = this.name;
|
||||
process.cpu = this.cpu;
|
||||
process.memory = this.memory;
|
||||
process.network = this.network;
|
||||
process.processedAt = this.processedAt;
|
||||
process.operationType = this.operationType;
|
||||
return process;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public record Result(
|
||||
String name,
|
||||
int pid,
|
||||
int size,
|
||||
String message,
|
||||
long releasedAt,
|
||||
long updatedAt
|
||||
){}
|
|
@ -1,6 +1,7 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public enum Status {
|
||||
success,
|
||||
fail
|
||||
}
|
||||
public record Status(
|
||||
int succeed,
|
||||
int statusCode,
|
||||
String errMsg
|
||||
){}
|
|
@ -0,0 +1,7 @@
|
|||
package inc.sdt.blokworks.devicedeployer.domain;
|
||||
|
||||
public enum SubCommandType {
|
||||
systemd,
|
||||
docker,
|
||||
single
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.mqtt;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Result;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
||||
|
||||
public record InboundDeployMessagePayload(
|
||||
Status status,
|
||||
String assetCode,
|
||||
String name,
|
||||
Long size,
|
||||
Long releasedAt,
|
||||
Long updatedAt,
|
||||
String deviceType,
|
||||
Status status,
|
||||
Result result,
|
||||
String requestId
|
||||
) {
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.mqtt;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
||||
|
||||
public record InboundProcessMessagePayload(
|
||||
Status status,
|
||||
String assetCode,
|
||||
Integer pid,
|
||||
String name,
|
||||
Integer cpu,
|
||||
Integer memory,
|
||||
Integer network,
|
||||
Long processedAt
|
||||
) {
|
||||
}
|
|
@ -1,19 +1,15 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.mqtt;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Port;
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.PortResource;
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.PortResourceConverter;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.CommandType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.SubCommandType;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
|
||||
public record OutboundMessagePayload(
|
||||
String url,
|
||||
String name,
|
||||
String command,
|
||||
HashMap<String, String> env,
|
||||
OperationType operationType,
|
||||
HashMap<String, Object> cmdInfo,
|
||||
CommandType cmdType,
|
||||
SubCommandType subCmdType,
|
||||
String assetCode,
|
||||
String requestId
|
||||
) {
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@ package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
|||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Entity(name = "asset_app")
|
||||
class AssetAppEntity {
|
||||
@Id
|
||||
|
@ -15,20 +13,35 @@ class AssetAppEntity {
|
|||
@Column(name = "app_name", length = 255)
|
||||
private String name;
|
||||
@Column(name = "size")
|
||||
private Long size;
|
||||
private int size;
|
||||
@Column(name = "released_at")
|
||||
private Long releasedAt;
|
||||
@Column(name = "updated_at")
|
||||
private Long updatedAt;
|
||||
@Column(name = "pid")
|
||||
private int pid;
|
||||
@Column(name = "succeed")
|
||||
private int succeed;
|
||||
@Column(name = "statusCode")
|
||||
private int statusCode;
|
||||
@Column(name = "message", columnDefinition = "TEXT")
|
||||
private String message;
|
||||
@Column(name = "error_message", columnDefinition = "TEXT")
|
||||
private String errorMessage;
|
||||
|
||||
protected AssetAppEntity() {}
|
||||
|
||||
public AssetAppEntity(String assetCode, String name, long size, Long releasedAt, Long updatedAt) {
|
||||
public AssetAppEntity(String assetCode, String name, int size, Long releasedAt, Long updatedAt, int pid, int succeed, int statusCode, String message, String errorMessage) {
|
||||
this.assetCode = assetCode;
|
||||
this.name = name;
|
||||
this.size = size;
|
||||
this.releasedAt = releasedAt;
|
||||
this.updatedAt = updatedAt;
|
||||
this.pid = pid;
|
||||
this.succeed = succeed;
|
||||
this.statusCode = statusCode;
|
||||
this.message = message;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
|
@ -43,7 +56,7 @@ class AssetAppEntity {
|
|||
return name;
|
||||
}
|
||||
|
||||
public long getSize() {
|
||||
public int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -55,5 +68,23 @@ class AssetAppEntity {
|
|||
return updatedAt;
|
||||
}
|
||||
|
||||
public int getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
public int getSucceed() {
|
||||
return succeed;
|
||||
}
|
||||
|
||||
public int getStatusCode() {
|
||||
return statusCode;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
|||
|
||||
import inc.sdt.blokworks.devicedeployer.application.DeployerRepositoryDelegate;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -23,6 +24,7 @@ public class AssetAppRelationalRepository implements DeployerRepositoryDelegate
|
|||
|
||||
@Override
|
||||
public void accept(InboundDeployMessagePayload inboundDeployMessagePayload) {
|
||||
log.info("[accept] payload = {}", inboundDeployMessagePayload);
|
||||
this.save(this.fromMessage(inboundDeployMessagePayload));
|
||||
}
|
||||
|
||||
|
@ -49,7 +51,12 @@ public class AssetAppRelationalRepository implements DeployerRepositoryDelegate
|
|||
assetApp.getName(),
|
||||
assetApp.getSize(),
|
||||
assetApp.getReleaseAt(),
|
||||
assetApp.getUpdatedAt()
|
||||
assetApp.getUpdatedAt(),
|
||||
assetApp.getPid(),
|
||||
assetApp.getStatus().succeed(),
|
||||
assetApp.getStatus().statusCode(),
|
||||
assetApp.getMessage(),
|
||||
assetApp.getStatus().errMsg()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -58,18 +65,24 @@ public class AssetAppRelationalRepository implements DeployerRepositoryDelegate
|
|||
.assetCode(entity.getAssetCode())
|
||||
.name(entity.getName())
|
||||
.size(entity.getSize())
|
||||
.pid(entity.getPid())
|
||||
.message(entity.getMessage())
|
||||
.releasedAt(entity.getReleasedAt())
|
||||
.updatedAt(entity.getUpdatedAt())
|
||||
.status(new Status(entity.getSucceed(), entity.getStatusCode(), entity.getErrorMessage()))
|
||||
.build();
|
||||
}
|
||||
|
||||
private AssetApp fromMessage(InboundDeployMessagePayload payload) {
|
||||
return AssetApp.builder()
|
||||
.assetCode(payload.assetCode())
|
||||
.name(payload.name())
|
||||
.size(payload.size())
|
||||
.releasedAt(payload.releasedAt())
|
||||
.updatedAt(payload.updatedAt())
|
||||
.name(payload.result().name())
|
||||
.size(payload.result().size())
|
||||
.pid(payload.result().pid())
|
||||
.message(payload.result().message())
|
||||
.releasedAt(payload.result().releasedAt())
|
||||
.updatedAt(payload.result().updatedAt())
|
||||
.status(payload.status())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.CommandType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.SubCommandType;
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity(name = "deploy_request")
|
||||
public class DeployRequestEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Column(name = "id")
|
||||
private String id;
|
||||
@Column(name = "request_id")
|
||||
private String requestId;
|
||||
@Column(name = "asset_code", length = 255)
|
||||
private String assetCode;
|
||||
@Column(name = "app_name", length = 255)
|
||||
private String appName;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "operation_type", length = 255)
|
||||
private OperationType operationType;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "command_type", length = 255)
|
||||
private CommandType commandType;
|
||||
@Enumerated(EnumType.STRING)
|
||||
@Column(name = "sub_command_type", length = 255)
|
||||
private SubCommandType subCommandType;
|
||||
|
||||
protected DeployRequestEntity() {}
|
||||
|
||||
public DeployRequestEntity(String requestId, String assetCode, String appName, OperationType operationType, CommandType commandType, SubCommandType subCommandType) {
|
||||
this.requestId = requestId;
|
||||
this.assetCode = assetCode;
|
||||
this.appName = appName;
|
||||
this.operationType = operationType;
|
||||
this.commandType = commandType;
|
||||
this.subCommandType = subCommandType;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getRequestId() {
|
||||
return requestId;
|
||||
}
|
||||
|
||||
public String getAssetCode() {
|
||||
return assetCode;
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public OperationType getOperationType() {
|
||||
return operationType;
|
||||
}
|
||||
|
||||
public CommandType getCommandType() {
|
||||
return commandType;
|
||||
}
|
||||
|
||||
public SubCommandType getSubCommandType() {
|
||||
return subCommandType;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface DeployRequestJpaRepository extends JpaRepository<DeployRequestEntity, String> {
|
||||
DeployRequestEntity findByRequestId(String requestId);
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.application.DeployRequestRepositoryDelegate;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.DeployRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@Component
|
||||
public class DeployRequestRelationalRepository implements DeployRequestRepositoryDelegate {
|
||||
private final Logger log;
|
||||
private final DeployRequestJpaRepository deployRequestJpaRepository;
|
||||
|
||||
public DeployRequestRelationalRepository(DeployRequestJpaRepository deployRequestJpaRepository) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.deployRequestJpaRepository = deployRequestJpaRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeployRequest save(DeployRequest deployRequest) {
|
||||
log.info("[save] deployRequest = {}", deployRequest);
|
||||
DeployRequestEntity entity = this.toEntity(deployRequest);
|
||||
deployRequestJpaRepository.save(entity);
|
||||
return deployRequest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<DeployRequest> findByRequestId(String requestId) {
|
||||
log.info("[findByRequestId] requestId = {}", requestId);
|
||||
DeployRequestEntity entity = deployRequestJpaRepository.findByRequestId(requestId);
|
||||
return Optional.of(this.fromEntity(entity));
|
||||
}
|
||||
|
||||
private DeployRequestEntity toEntity(DeployRequest deployRequest) {
|
||||
return new DeployRequestEntity(
|
||||
deployRequest.getRequestId(),
|
||||
deployRequest.getAssetCode(),
|
||||
deployRequest.getAppName(),
|
||||
deployRequest.getOperationType(),
|
||||
deployRequest.getCommandType(),
|
||||
deployRequest.getSubCommandType()
|
||||
);
|
||||
}
|
||||
|
||||
private DeployRequest fromEntity(DeployRequestEntity entity) {
|
||||
return DeployRequest.builder()
|
||||
.requestId(entity.getRequestId())
|
||||
.assetCode(entity.getAssetCode())
|
||||
.appName(entity.getAppName())
|
||||
.operationType(entity.getOperationType())
|
||||
.commandType(entity.getCommandType())
|
||||
.subCommandType(entity.getSubCommandType())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
|
||||
@Entity(name = "app_process")
|
||||
class ProcessEntity {
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.UUID)
|
||||
@Column(name = "process_id", length = 36)
|
||||
private String id;
|
||||
@Column(name = "asset_code", length = 255)
|
||||
private String assetCode;
|
||||
@Column(name = "pid")
|
||||
private Integer pid;
|
||||
@Column(name = "app_name", length = 255)
|
||||
private String appName;
|
||||
@Column(name = "cpu")
|
||||
private Integer cpu;
|
||||
@Column(name = "memory")
|
||||
private Integer memory;
|
||||
@Column(name = "network")
|
||||
private Integer network;
|
||||
@Column(name = "processed_at")
|
||||
private Long processedAt;
|
||||
|
||||
protected ProcessEntity() {}
|
||||
|
||||
public ProcessEntity(String assetCode, Integer pid, String appName, Integer cpu, Integer memory, Integer network, Long processedAt) {
|
||||
this.assetCode = assetCode;
|
||||
this.pid = pid;
|
||||
this.appName = appName;
|
||||
this.cpu = cpu;
|
||||
this.memory = memory;
|
||||
this.network = network;
|
||||
this.processedAt = processedAt;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public String getAssetCode() {
|
||||
return assetCode;
|
||||
}
|
||||
|
||||
public Integer getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
public String getAppName() {
|
||||
return appName;
|
||||
}
|
||||
|
||||
public Integer getCpu() {
|
||||
return cpu;
|
||||
}
|
||||
|
||||
public Integer getMemory() {
|
||||
return memory;
|
||||
}
|
||||
|
||||
public Integer getNetwork() {
|
||||
return network;
|
||||
}
|
||||
|
||||
public Long getProcessedAt() {
|
||||
return processedAt;
|
||||
}
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
|
||||
public interface ProcessJpaRepository extends JpaRepository<ProcessEntity, String> {
|
||||
Page<ProcessEntity> findAllByAssetCode(String assetCode, Pageable pageable);
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.application.ProcessRepositoryDelegate;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundProcessMessagePayload;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ProcessRelationalRepository implements ProcessRepositoryDelegate {
|
||||
private final Logger log;
|
||||
private final ProcessJpaRepository processJpaRepository;
|
||||
|
||||
public ProcessRelationalRepository(ProcessJpaRepository processJpaRepository) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.processJpaRepository = processJpaRepository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(InboundProcessMessagePayload payload) {
|
||||
this.save(this.fromMessage(payload));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Process save(Process process) {
|
||||
log.info("[save] process = {}", process);
|
||||
ProcessEntity entity = this.toEntity(process);
|
||||
processJpaRepository.save(entity);
|
||||
return process;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Page<Process> findAllByAssetCode(String assetCode, int page, int size) {
|
||||
log.info("[findAllByAssetCode] assetCode = {}", assetCode);
|
||||
Pageable pageable = page < 0 ? Pageable.unpaged() : PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "processedAt"));
|
||||
return processJpaRepository.findAllByAssetCode(assetCode, pageable)
|
||||
.map(this::fromEntity);
|
||||
}
|
||||
|
||||
private ProcessEntity toEntity(Process process) {
|
||||
return new ProcessEntity(
|
||||
process.getAssetCode(),
|
||||
process.getPid(),
|
||||
process.getName(),
|
||||
process.getCpu(),
|
||||
process.getMemory(),
|
||||
process.getNetwork(),
|
||||
process.getProcessedAt()
|
||||
);
|
||||
}
|
||||
|
||||
private Process fromEntity(ProcessEntity entity) {
|
||||
return Process.builder()
|
||||
.assetCode(entity.getAssetCode())
|
||||
.pid(entity.getPid())
|
||||
.name(entity.getAppName())
|
||||
.cpu(entity.getCpu())
|
||||
.memory(entity.getMemory())
|
||||
.network(entity.getNetwork())
|
||||
.processedAt(entity.getProcessedAt())
|
||||
.build();
|
||||
}
|
||||
|
||||
private Process fromMessage(InboundProcessMessagePayload payload) {
|
||||
return Process.builder()
|
||||
.assetCode(payload.assetCode())
|
||||
.pid(payload.pid())
|
||||
.name(payload.name())
|
||||
.cpu(payload.cpu())
|
||||
.memory(payload.memory())
|
||||
.network(payload.network())
|
||||
.processedAt(payload.processedAt())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -1,10 +1,15 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
||||
|
||||
record AssetAppResource(
|
||||
String assetCode,
|
||||
String name,
|
||||
Long size,
|
||||
int size,
|
||||
int pid,
|
||||
String message,
|
||||
Long releaseAt,
|
||||
Long updatedAt
|
||||
Long updatedAt,
|
||||
Status status
|
||||
) {
|
||||
}
|
||||
|
|
|
@ -6,23 +6,16 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
public class AssetAppResourceConverter {
|
||||
|
||||
public AssetApp fromResource(AssetAppResource resource) {
|
||||
return AssetApp.builder()
|
||||
.assetCode(resource.assetCode())
|
||||
.name(resource.name())
|
||||
.size(resource.size())
|
||||
.releasedAt(resource.releaseAt())
|
||||
.updatedAt(resource.updatedAt())
|
||||
.build();
|
||||
}
|
||||
|
||||
public AssetAppResource toResource(AssetApp assetApp) {
|
||||
return new AssetAppResource(
|
||||
assetApp.getAssetCode(),
|
||||
assetApp.getName(),
|
||||
assetApp.getSize(),
|
||||
assetApp.getPid(),
|
||||
assetApp.getMessage(),
|
||||
assetApp.getReleaseAt(),
|
||||
assetApp.getUpdatedAt()
|
||||
assetApp.getUpdatedAt(),
|
||||
assetApp.getStatus()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.application.CommandInvoker;
|
||||
import inc.sdt.blokworks.devicedeployer.application.DeployerService;
|
||||
import inc.sdt.blokworks.devicedeployer.application.ProcessService;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
||||
import jakarta.servlet.http.HttpSession;
|
||||
import jakarta.validation.Valid;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.*;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.amqp.ResourceMapping;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
@ -22,36 +19,68 @@ public class DeployerController {
|
|||
private final DeployerService deployerService;
|
||||
private final OutboundMessageResourceConverter outboundMessageResourceConverter;
|
||||
private final AssetAppResourceConverter assetAppResourceConverter;
|
||||
private final CommandInvoker commandInvoker;
|
||||
private final GiteaApiRequestHandler giteaApiRequestHandler;
|
||||
|
||||
public DeployerController(DeployerService deployerService,
|
||||
OutboundMessageResourceConverter outboundMessageResourceConverter,
|
||||
AssetAppResourceConverter assetAppResourceConverter) {
|
||||
AssetAppResourceConverter assetAppResourceConverter,
|
||||
CommandInvoker commandInvoker,
|
||||
GiteaApiRequestHandler giteaApiRequestHandler) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.deployerService = deployerService;
|
||||
this.outboundMessageResourceConverter = outboundMessageResourceConverter;
|
||||
this.assetAppResourceConverter = assetAppResourceConverter;
|
||||
this.commandInvoker = commandInvoker;
|
||||
this.giteaApiRequestHandler = giteaApiRequestHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* 앱 배포 명령
|
||||
* @param assetCode 자산 코드
|
||||
* @param assetAppResource 배포하려는 앱의 정보
|
||||
* @param resource 배포하려는 앱의 정보
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.CREATED)
|
||||
@ResourceMapping(name = "Deploy_App", method = "POST", uri = "/assets/{code}/apps", description = "앱 배포 명령")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@PostMapping("/assets/{assetCode}/apps")
|
||||
public void deploy(@PathVariable String assetCode,
|
||||
@Valid @RequestBody OutboundMessageResource assetAppResource) {
|
||||
log.info("[deploy] assetCode = {}, assetAppResource = {}", assetCode, assetAppResource);
|
||||
@RequestBody OutboundMessageResource resource,
|
||||
HttpServletRequest httpServletRequest) {
|
||||
log.info("[deploy] assetCode = {}, resource = {}", assetCode, resource);
|
||||
String authorization = httpServletRequest.getHeader("Authorization");
|
||||
String requestId = UUID.randomUUID().toString();
|
||||
OutboundMessage outboundMessage = outboundMessageResourceConverter.fromResource(assetAppResource);
|
||||
|
||||
OutboundMessage outboundMessage = outboundMessageResourceConverter.fromResource(resource);
|
||||
outboundMessage.setRequestId(requestId);
|
||||
deployerService.publish(outboundMessage, assetCode);
|
||||
outboundMessage.setAssetCode(assetCode);
|
||||
outboundMessage.setCommandInfo(commandInvoker.invoke(outboundMessage));
|
||||
|
||||
if(resource.commandType() == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if(resource.commandType() == CommandType.deploy) {
|
||||
giteaApiRequestHandler.get(authorization, outboundMessage);
|
||||
}
|
||||
|
||||
DeployRequest deployRequest = DeployRequest.builder()
|
||||
.requestId(requestId)
|
||||
.assetCode(assetCode)
|
||||
.appName(outboundMessage.getName())
|
||||
.operationType(OperationType.DEPLOY)
|
||||
.commandType(resource.commandType())
|
||||
.subCommandType(resource.subCommandType())
|
||||
.build();
|
||||
|
||||
deployerService.save(deployRequest);
|
||||
deployerService.publish(outboundMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 배포된 앱 정보 조회 (페이지 조회)
|
||||
* @param assetCode 자산 코드
|
||||
*/
|
||||
@ResourceMapping(name = "Get_Asset_App", method = "GET", uri = "/assets/{code}/apps", description = "배포된 앱 정보 조회")
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@GetMapping("/assets/{assetCode}/apps")
|
||||
public PageableResponse<AssetAppResource> get(@PathVariable String assetCode,
|
||||
|
|
|
@ -0,0 +1,85 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.SubCommandType;
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.exception.NotFoundException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.*;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
@Component
|
||||
public class GiteaApiRequestHandler {
|
||||
private final Logger log;
|
||||
private final RestTemplate restTemplate;
|
||||
private final String url;
|
||||
private final List<String> extensions;
|
||||
|
||||
public GiteaApiRequestHandler(RestTemplate restTemplate,
|
||||
@Value("${stackbase.api.host}") String url) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.restTemplate = restTemplate;
|
||||
this.url = url;
|
||||
this.extensions = Arrays.asList(".py", ".jar", ".sh", ".service");
|
||||
}
|
||||
|
||||
public void get(String authorization, OutboundMessage message) {
|
||||
log.info("[get] message = {}", message);
|
||||
if(message.getSubCommandType() == null) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if(message.getSubCommandType() == SubCommandType.systemd) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Authorization", authorization);
|
||||
|
||||
try {
|
||||
download(message.getAssetCode(), message.getUrl());
|
||||
}catch (IOException e) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void download(String assetCode, String url) throws IOException {
|
||||
log.info("[download] assetCode = {}, url = {}", assetCode, url);
|
||||
byte[] bytes = restTemplate.getForObject(url, byte[].class);
|
||||
|
||||
File tempFile = File.createTempFile(assetCode+"_"+LocalDateTime.now(), ".zip");
|
||||
try(FileOutputStream fos = new FileOutputStream(tempFile)) {
|
||||
assert bytes != null;
|
||||
fos.write(bytes);
|
||||
}
|
||||
|
||||
Set<String> entries = new HashSet<>();
|
||||
try(ZipInputStream zis = new ZipInputStream(Files.newInputStream(Path.of(tempFile.getAbsolutePath())))) {
|
||||
ZipEntry zipEntry;
|
||||
while((zipEntry = zis.getNextEntry()) != null) {
|
||||
if(!zipEntry.isDirectory()) {
|
||||
for(String ext : extensions) {
|
||||
if(zipEntry.getName().contains(ext)) {
|
||||
entries.add(ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(entries.size() < 3) {
|
||||
throw new NotFoundException("Executable file not found");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,62 +1,40 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.application.DeployerService;
|
||||
import inc.sdt.blokworks.devicedeployer.application.ProcessService;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundProcessMessagePayload;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.integration.annotation.MessageEndpoint;
|
||||
import org.springframework.integration.annotation.ServiceActivator;
|
||||
import org.springframework.integration.mqtt.support.MqttHeaders;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
@MessageEndpoint
|
||||
public class MqttMessageHandler {
|
||||
private final Logger log;
|
||||
private final DeployerService deployerService;
|
||||
private final ProcessService processService;
|
||||
private final MqttMessageConverter<InboundDeployMessagePayload> deployMessagePayloadConverter;
|
||||
private final MqttMessageConverter<InboundProcessMessagePayload> processMessagePayloadConverter;
|
||||
|
||||
public MqttMessageHandler(DeployerService deployerService,
|
||||
ProcessService processService,
|
||||
MqttMessageConverter<InboundDeployMessagePayload> deployMessagePayloadConverter,
|
||||
MqttMessageConverter<InboundProcessMessagePayload> processMessagePayloadConverter) {
|
||||
MqttMessageConverter<InboundDeployMessagePayload> deployMessagePayloadConverter) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.deployerService = deployerService;
|
||||
this.processService = processService;
|
||||
this.deployMessagePayloadConverter = deployMessagePayloadConverter;
|
||||
this.processMessagePayloadConverter = processMessagePayloadConverter;
|
||||
}
|
||||
|
||||
@ServiceActivator(inputChannel = "mqttInboundChannel")
|
||||
void handleMessage(Message<String> message) {
|
||||
log.info("[handleMessage] message={}", message);
|
||||
|
||||
if(!message.getPayload().contains("pid")) {
|
||||
String topic = String.valueOf(message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
||||
String id = topic.split("/")[4];
|
||||
|
||||
log.info("[handleMessage] topic = {}, id = {}", topic, id);
|
||||
|
||||
deployMessagePayloadConverter.convertFromByte(message.getPayload(), InboundDeployMessagePayload.class)
|
||||
.map(p -> new InboundDeployMessagePayload(
|
||||
p.status(),
|
||||
p.assetCode(),
|
||||
p.name(),
|
||||
p.size(),
|
||||
p.releasedAt(),
|
||||
p.updatedAt(),
|
||||
id))
|
||||
.flatMap(deployerService)
|
||||
.subscribe();
|
||||
}else {
|
||||
processMessagePayloadConverter.convertFromByte(message.getPayload(), InboundProcessMessagePayload.class)
|
||||
.flatMap(processService)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
deployMessagePayloadConverter.convertFromByte(message.getPayload(), InboundDeployMessagePayload.class)
|
||||
.map(p -> new InboundDeployMessagePayload(
|
||||
p.assetCode(),
|
||||
p.deviceType(),
|
||||
p.status(),
|
||||
p.result(),
|
||||
p.requestId()
|
||||
))
|
||||
.flatMap(deployerService)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import org.wildfly.common.annotation.NotNull;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.CommandType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.SubCommandType;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
record OutboundMessageResource(
|
||||
@NotNull
|
||||
String url,
|
||||
@NotNull
|
||||
String name,
|
||||
String fileType,
|
||||
String appName, // 사용자가 정한 파일 이름
|
||||
String name, // stackbase 에 저장된 파일 이름
|
||||
String image,
|
||||
String command,
|
||||
HashMap<String, String> env
|
||||
CommandType commandType,
|
||||
SubCommandType subCommandType,
|
||||
LinkedHashMap<String, Object> options,
|
||||
LinkedHashMap<String, String> parameters
|
||||
) {
|
||||
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.CommandType;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Component
|
||||
public class OutboundMessageResourceConverter {
|
||||
|
||||
public OutboundMessageResource toResource(OutboundMessage outboundMessage) {
|
||||
return new OutboundMessageResource(
|
||||
outboundMessage.getUrl(),
|
||||
outboundMessage.getName(),
|
||||
outboundMessage.getCommand(),
|
||||
outboundMessage.getEnv()
|
||||
);
|
||||
}
|
||||
|
||||
public OutboundMessage fromResource(OutboundMessageResource resource) {
|
||||
return OutboundMessage.builder()
|
||||
.url(resource.url())
|
||||
.fileType(resource.fileType())
|
||||
.appName(resource.appName())
|
||||
.name(resource.name())
|
||||
.image(resource.image())
|
||||
.command(resource.command())
|
||||
.env(resource.env())
|
||||
.options(resource.options() == null ? new LinkedHashMap<>() : resource.options())
|
||||
.commandType(resource.commandType() == null ? CommandType.deploy : resource.commandType())
|
||||
.subCommandType(resource.subCommandType())
|
||||
.parameters(resource.parameters() == null ? new LinkedHashMap<>() : resource.parameters())
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,21 +25,21 @@ class PageableResourceImpl implements PageableResource {
|
|||
|
||||
@Override
|
||||
public long getTotalElements() {
|
||||
return 0;
|
||||
return totalElements;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalPages() {
|
||||
return 0;
|
||||
return totalPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 0;
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPage() {
|
||||
return 0;
|
||||
return page;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
public record PortResource(
|
||||
String protocol,
|
||||
Integer hostPort,
|
||||
Integer containerPort
|
||||
) {
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Port;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class PortResourceConverter {
|
||||
public PortResource toResource(Port port) {
|
||||
return new PortResource(
|
||||
port.getProtocol(),
|
||||
port.getHostPort(),
|
||||
port.getContainerPort()
|
||||
);
|
||||
}
|
||||
|
||||
public Port fromResource(PortResource resource) {
|
||||
return Port.builder()
|
||||
.protocol(resource.protocol())
|
||||
.hostPort(resource.hostPort())
|
||||
.containerPort(resource.containerPort())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.application.ProcessService;
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
public class ProcessController {
|
||||
private final Logger log;
|
||||
|
||||
private final ProcessService processService;
|
||||
private final ProcessResourceConverter processResourceConverter;
|
||||
|
||||
public ProcessController(ProcessService processService,
|
||||
ProcessResourceConverter processResourceConverter) {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
this.processService = processService;
|
||||
this.processResourceConverter = processResourceConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* 배포된 앱 내의 프로세스 정보 조회 (페이지 조회)
|
||||
* @param assetCode 자산 코드
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.OK)
|
||||
@GetMapping("/assets/{assetCode}/apps/process")
|
||||
public PageableResponse<ProcessResource> get(@PathVariable String assetCode,
|
||||
@RequestParam(required = false, defaultValue = "0") int page,
|
||||
@RequestParam(required = false, defaultValue = "20") int size) {
|
||||
log.info("[get] assetCode = {}, page = {}, size = {}", assetCode, page, size);
|
||||
Page<Process> process = processService.getAll(assetCode, page, size);
|
||||
return PageableResponse.from(process, processResourceConverter::toResource);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
||||
|
||||
record ProcessResource(
|
||||
String assetCode,
|
||||
Integer pid,
|
||||
String name,
|
||||
Integer cpu,
|
||||
Integer memory,
|
||||
Integer network,
|
||||
Long processedAt,
|
||||
OperationType operationType
|
||||
) {
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class ProcessResourceConverter {
|
||||
public Process fromResource(ProcessResource resource) {
|
||||
return Process.builder()
|
||||
.assetCode(resource.assetCode())
|
||||
.name(resource.name())
|
||||
.pid(resource.pid())
|
||||
.cpu(resource.cpu())
|
||||
.memory(resource.memory())
|
||||
.network(resource.network())
|
||||
.processedAt(resource.processedAt())
|
||||
.operationType(resource.operationType())
|
||||
.build();
|
||||
}
|
||||
|
||||
public ProcessResource toResource(Process process) {
|
||||
return new ProcessResource(
|
||||
process.getAssetCode(),
|
||||
process.getPid(),
|
||||
process.getName(),
|
||||
process.getCpu(),
|
||||
process.getMemory(),
|
||||
process.getNetwork(),
|
||||
process.getProcessedAt(),
|
||||
process.getOperationType()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation.configuration;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.filter.AuthorizationFilter;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.config.annotation.CorsRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@Component
|
||||
class WebConfiguration implements WebMvcConfigurer {
|
||||
private final AuthorizationFilter authorizationFilter;
|
||||
|
||||
public WebConfiguration(AuthorizationFilter authorizationFilter) {
|
||||
this.authorizationFilter = authorizationFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addCorsMappings(CorsRegistry registry) {
|
||||
registry.addMapping("/**")
|
||||
.allowedOrigins("*")
|
||||
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
|
||||
.maxAge(3600);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(authorizationFilter).addPathPatterns(
|
||||
"/assets/**"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -32,4 +32,16 @@ class ControllerAdvice {
|
|||
public ErrorResponse handleConflictException(Exception exception) {
|
||||
return new ErrorResponse(HttpStatus.CONFLICT, exception.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(NotFoundException.class)
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public ErrorResponse handleNotFoundException(Exception exception) {
|
||||
return new ErrorResponse(HttpStatus.NOT_FOUND, exception.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(UnauthorizedException.class)
|
||||
@ResponseStatus(HttpStatus.UNAUTHORIZED)
|
||||
public ErrorResponse handleUnauthorizedException(Exception exception) {
|
||||
return new ErrorResponse(HttpStatus.UNAUTHORIZED, exception.getMessage());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation.exception;
|
||||
|
||||
public class NotFoundException extends RuntimeException{
|
||||
private static final String DEFAULT_MESSAGE = "File not found";
|
||||
public NotFoundException() {
|
||||
super(DEFAULT_MESSAGE);
|
||||
}
|
||||
|
||||
public NotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation.exception;
|
||||
|
||||
public class UnauthorizedException extends RuntimeException {
|
||||
private static final String DEFAULT_MESSAGE = "Unauthorized";
|
||||
|
||||
public UnauthorizedException() {
|
||||
super(DEFAULT_MESSAGE);
|
||||
}
|
||||
|
||||
public UnauthorizedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation.filter;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.exception.UnauthorizedException;
|
||||
import io.jsonwebtoken.ExpiredJwtException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
@Component
|
||||
public class AuthorizationFilter implements HandlerInterceptor {
|
||||
private final Logger log;
|
||||
private final String secretKey;
|
||||
|
||||
public AuthorizationFilter(@Value("${application.security.jwt.secret-key}") String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
|
||||
log.info("[preHandle]");
|
||||
if(request.getHeader("Authorization") == null) {
|
||||
throw new NoSuchElementException("token does not exist.");
|
||||
}
|
||||
|
||||
String token = request.getHeader("Authorization").substring("Bearer ".length());
|
||||
|
||||
byte[] keyBytes = io.jsonwebtoken.io.Decoders.BASE64.decode(secretKey);
|
||||
javax.crypto.SecretKey secretKey = io.jsonwebtoken.security.Keys.hmacShaKeyFor(keyBytes);
|
||||
|
||||
try {
|
||||
io.jsonwebtoken.Claims claims = io.jsonwebtoken.Jwts
|
||||
.parserBuilder()
|
||||
.setSigningKey(secretKey)
|
||||
.build()
|
||||
.parseClaimsJws(token)
|
||||
.getBody();
|
||||
request.setAttribute("userId", claims.get("id").toString());
|
||||
return true;
|
||||
}catch (ExpiredJwtException e) {
|
||||
throw new UnauthorizedException("Token has expired");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package inc.sdt.blokworks.devicedeployer.presentation.rest;
|
||||
|
||||
import inc.sdt.blokworks.devicedeployer.presentation.exception.UnauthorizedException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.client.ClientHttpResponse;
|
||||
import org.springframework.web.client.DefaultResponseErrorHandler;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class RestTemplateResponseErrorHandler extends DefaultResponseErrorHandler {
|
||||
private final Logger log;
|
||||
|
||||
public RestTemplateResponseErrorHandler() {
|
||||
this.log = LoggerFactory.getLogger(this.getClass());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void handleError(ClientHttpResponse response, HttpStatusCode statusCode) throws IOException {
|
||||
log.error("[handleError] statusCode = {}, response = {}", statusCode, response);
|
||||
if(response.getStatusCode() == HttpStatus.UNAUTHORIZED) {
|
||||
throw new UnauthorizedException();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,3 +1,23 @@
|
|||
spring:
|
||||
datasource:
|
||||
url: ${POSTGRES_URL}
|
||||
username: ${POSTGRES_CREDENTIALS_USERNAME}
|
||||
password: ${POSTGRES_CREDENTIALS_PASSWORD}
|
||||
hikari:
|
||||
maximum-pool-size: 3
|
||||
jpa:
|
||||
hibernate:
|
||||
ddl-auto: update
|
||||
show-sql: false
|
||||
|
||||
inbound:
|
||||
mqtt:
|
||||
url: ${INBOUND_MQTT_URL}
|
||||
username: ${INBOUND_MQTT_CREDENTIALS_USERNAME}
|
||||
password: ${INBOUND_MQTT_CREDENTIALS_PASSWORD}
|
||||
topics:
|
||||
- /device-control/+/result
|
||||
|
||||
iam:
|
||||
enabled: ${IAM_REGISTER_ENABLED}
|
||||
amqp:
|
||||
|
@ -6,4 +26,8 @@ iam:
|
|||
username: ${IAM_AMQP_CREDENTIALS_USERNAME}
|
||||
password: ${IAM_AMQP_CREDENTIALS_PASSWORD}
|
||||
exchange: ${IAM_AMQP_EXCHANGE}
|
||||
routing-key: ${IAM_AMQP_ROUTING_KEY}
|
||||
routing-key: ${IAM_AMQP_ROUTING_KEY}
|
||||
|
||||
stackbase:
|
||||
api:
|
||||
host: https://sdt-site-bucket.s3.ap-northeast-2.amazonaws.com/app/
|
|
@ -13,8 +13,12 @@ spring:
|
|||
inbound:
|
||||
mqtt:
|
||||
url: tcp://localhost:1883
|
||||
#url: tcp://13.209.39.139:32259
|
||||
username: sdt
|
||||
password: 251327
|
||||
topics:
|
||||
- /assets/+/command-req/+
|
||||
- /assets/+/apps/process
|
||||
- /device-control/+/result
|
||||
|
||||
stackbase:
|
||||
api:
|
||||
host: https://sdt-site-bucket.s3.ap-northeast-2.amazonaws.com/app/
|
|
@ -5,12 +5,20 @@ spring:
|
|||
name: device-deployer
|
||||
datasource:
|
||||
driver-class-name: org.postgresql.Driver
|
||||
application:
|
||||
security:
|
||||
jwt:
|
||||
secret-key: D3KJ3G92IWW3W3QWZLU416IN4T9AFYEWM84P5HKHRFEA8C4I1HWALFXGP2HYD87Q
|
||||
|
||||
inbound:
|
||||
mqtt:
|
||||
url: tcp://192.168.1.162:32102
|
||||
url: tcp://13.209.39.139:32259
|
||||
username: sdt
|
||||
password: 251327
|
||||
topics:
|
||||
- /assets/+/command-req/+
|
||||
- /assets/+/apps/process
|
||||
- /assets/+/apps/process
|
||||
|
||||
stackbase:
|
||||
api:
|
||||
host: https://sdt-site-bucket.s3.ap-northeast-2.amazonaws.com/app/
|
Loading…
Reference in New Issue