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
|
enabled = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ext {
|
||||||
|
jjwtVersion = "0.11.5"
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
@ -26,6 +30,9 @@ dependencies {
|
||||||
implementation("org.springframework.boot:spring-boot-starter-amqp")
|
implementation("org.springframework.boot:spring-boot-starter-amqp")
|
||||||
implementation("org.springframework.boot:spring-boot-starter-web")
|
implementation("org.springframework.boot:spring-boot-starter-web")
|
||||||
implementation("org.springframework.integration:spring-integration-mqtt")
|
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")
|
runtimeOnly("org.postgresql:postgresql")
|
||||||
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
|
annotationProcessor "org.springframework.boot:spring-boot-configuration-processor"
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package inc.sdt.blokworks.devicedeployer;
|
package inc.sdt.blokworks.devicedeployer;
|
||||||
|
|
||||||
|
import inc.sdt.blokworks.devicedeployer.presentation.rest.RestTemplateResponseErrorHandler;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
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
|
@SpringBootApplication
|
||||||
public class DeviceDeployerApplication {
|
public class DeviceDeployerApplication {
|
||||||
|
@ -10,4 +14,11 @@ public class DeviceDeployerApplication {
|
||||||
SpringApplication.run(DeviceDeployerApplication.class, args);
|
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.core.JsonProcessingException;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
import inc.sdt.blokworks.devicedeployer.domain.*;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
|
||||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
||||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.OutboundMessagePayload;
|
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.IMqttClient;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttException;
|
import org.eclipse.paho.client.mqttv3.MqttException;
|
||||||
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
import org.eclipse.paho.client.mqttv3.MqttMessage;
|
||||||
|
@ -18,59 +14,67 @@ import org.springframework.data.domain.Page;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class DefaultDeployerService implements DeployerService{
|
public class DefaultDeployerService implements DeployerService{
|
||||||
private final Logger log;
|
private final Logger log;
|
||||||
private final IMqttClient mqttClient;
|
private final IMqttClient mqttClient;
|
||||||
private final ObjectMapper objectMapper;
|
private final ObjectMapper objectMapper;
|
||||||
private final DeployerRepositoryDelegate deployerRepositoryDelegate;
|
private final DeployerRepositoryDelegate deployerRepositoryDelegate;
|
||||||
private String requestId;
|
private final DeployRequestRepositoryDelegate requestRepositoryDelegate;
|
||||||
|
|
||||||
public DefaultDeployerService(IMqttClient mqttClient,
|
public DefaultDeployerService(IMqttClient mqttClient,
|
||||||
ObjectMapper objectMapper,
|
ObjectMapper objectMapper,
|
||||||
DeployerRepositoryDelegate deployerRepositoryDelegate) {
|
DeployerRepositoryDelegate deployerRepositoryDelegate,
|
||||||
|
DeployRequestRepositoryDelegate requestRepositoryDelegate) {
|
||||||
this.log = LoggerFactory.getLogger(this.getClass());
|
this.log = LoggerFactory.getLogger(this.getClass());
|
||||||
this.mqttClient = mqttClient;
|
this.mqttClient = mqttClient;
|
||||||
this.objectMapper = objectMapper;
|
this.objectMapper = objectMapper;
|
||||||
this.deployerRepositoryDelegate = deployerRepositoryDelegate;
|
this.deployerRepositoryDelegate = deployerRepositoryDelegate;
|
||||||
|
this.requestRepositoryDelegate = requestRepositoryDelegate;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void publish(OutboundMessage deployMessage, String assetCode) {
|
public void publish(OutboundMessage outboundMessage) {
|
||||||
log.info("[publish]");
|
log.info("[publish] outboundMessage = {}", outboundMessage);
|
||||||
try {
|
try {
|
||||||
OutboundMessagePayload payload = new OutboundMessagePayload(
|
OutboundMessagePayload payload = new OutboundMessagePayload(
|
||||||
deployMessage.getUrl(),
|
outboundMessage.getCommandInfo(),
|
||||||
deployMessage.getName(),
|
outboundMessage.getCommandType(),
|
||||||
deployMessage.getCommand(),
|
outboundMessage.getSubCommandType(),
|
||||||
deployMessage.getEnv(),
|
outboundMessage.getAssetCode(),
|
||||||
OperationType.DEPLOY,
|
outboundMessage.getRequestId()
|
||||||
deployMessage.getRequestId()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
byte[] bytes = objectMapper.writeValueAsBytes(payload);
|
byte[] bytes = objectMapper.writeValueAsBytes(payload);
|
||||||
MqttMessage message = new MqttMessage();
|
MqttMessage message = new MqttMessage();
|
||||||
message.setPayload(bytes);
|
message.setPayload(bytes);
|
||||||
|
|
||||||
mqttClient.publish("/assets/"+assetCode+"/apps/deploy", message);
|
mqttClient.publish("/device-control/"+outboundMessage.getAssetCode(), message);
|
||||||
requestId = deployMessage.getRequestId();
|
log.info("[publish] payload = {}", payload);
|
||||||
log.info("[publish] message = {}", message);
|
|
||||||
}catch (JsonProcessingException | MqttException e) {
|
}catch (JsonProcessingException | MqttException e) {
|
||||||
throw new IllegalArgumentException();
|
throw new IllegalArgumentException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DeployRequest save(DeployRequest deployRequest) {
|
||||||
|
log.info("[save] deployRequest = {}", deployRequest);
|
||||||
|
requestRepositoryDelegate.save(deployRequest);
|
||||||
|
return deployRequest;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Mono<Void> apply(InboundDeployMessagePayload payload) {
|
public Mono<Void> apply(InboundDeployMessagePayload payload) {
|
||||||
log.info("[apply] inboundDeployMessagePayload = {}", payload);
|
log.info("[apply] payload = {}", payload);
|
||||||
// 배포된 앱 정보 저장
|
Optional<DeployRequest> deployRequest = requestRepositoryDelegate.findByRequestId(payload.requestId());
|
||||||
// request Id 판별
|
if(deployRequest.isPresent()) {
|
||||||
if(requestId.equals(payload.requestId())) {
|
|
||||||
return Mono.just(payload)
|
return Mono.just(payload)
|
||||||
.doOnNext(deployerRepositoryDelegate)
|
.doOnNext(deployerRepositoryDelegate)
|
||||||
.then();
|
.then();
|
||||||
}else {
|
}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;
|
package inc.sdt.blokworks.devicedeployer.application;
|
||||||
|
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
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.domain.OutboundMessage;
|
||||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
@ -9,6 +10,7 @@ import reactor.core.publisher.Mono;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
public interface DeployerService extends Function<InboundDeployMessagePayload, Mono<Void>> {
|
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);
|
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 {
|
public class AssetApp {
|
||||||
private String assetCode;
|
private String assetCode;
|
||||||
private String name;
|
private String name;
|
||||||
private Long size;
|
private int size;
|
||||||
|
private int pid;
|
||||||
|
private String message;
|
||||||
private Long releaseAt;
|
private Long releaseAt;
|
||||||
private Long updatedAt;
|
private Long updatedAt;
|
||||||
|
private Status status;
|
||||||
|
|
||||||
protected AssetApp() {}
|
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.assetCode = assetCode;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
|
this.pid = pid;
|
||||||
|
this.message = message;
|
||||||
this.releaseAt = releaseAt;
|
this.releaseAt = releaseAt;
|
||||||
this.updatedAt = updatedAt;
|
this.updatedAt = updatedAt;
|
||||||
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getAssetCode() {
|
public String getAssetCode() {
|
||||||
|
@ -25,10 +31,18 @@ public class AssetApp {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Long getSize() {
|
public int getSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getPid() {
|
||||||
|
return pid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMessage() {
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
|
||||||
public Long getReleaseAt() {
|
public Long getReleaseAt() {
|
||||||
return releaseAt;
|
return releaseAt;
|
||||||
}
|
}
|
||||||
|
@ -37,14 +51,21 @@ public class AssetApp {
|
||||||
return updatedAt;
|
return updatedAt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Status getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AssetApp{" +
|
return "AssetApp{" +
|
||||||
"assetCode='" + assetCode + '\'' +
|
"assetCode='" + assetCode + '\'' +
|
||||||
", name='" + name + '\'' +
|
", name='" + name + '\'' +
|
||||||
", size=" + size +
|
", size=" + size +
|
||||||
|
", pid=" + pid +
|
||||||
|
", message='" + message + '\'' +
|
||||||
", releaseAt=" + releaseAt +
|
", releaseAt=" + releaseAt +
|
||||||
", updatedAt=" + updatedAt +
|
", updatedAt=" + updatedAt +
|
||||||
|
", status=" + status +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,9 +76,12 @@ public class AssetApp {
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private String assetCode;
|
private String assetCode;
|
||||||
private String name;
|
private String name;
|
||||||
private Long size;
|
private int size;
|
||||||
|
private int pid;
|
||||||
|
private String message;
|
||||||
private Long releasedAt;
|
private Long releasedAt;
|
||||||
private Long updatedAt;
|
private Long updatedAt;
|
||||||
|
private Status status;
|
||||||
|
|
||||||
public Builder assetCode(String assetCode) {
|
public Builder assetCode(String assetCode) {
|
||||||
this.assetCode = assetCode;
|
this.assetCode = assetCode;
|
||||||
|
@ -69,11 +93,21 @@ public class AssetApp {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder size(Long size) {
|
public Builder size(int size) {
|
||||||
this.size = size;
|
this.size = size;
|
||||||
return this;
|
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) {
|
public Builder releasedAt(Long releasedAt) {
|
||||||
this.releasedAt = releasedAt;
|
this.releasedAt = releasedAt;
|
||||||
return this;
|
return this;
|
||||||
|
@ -84,13 +118,21 @@ public class AssetApp {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder status(Status status) {
|
||||||
|
this.status = status;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public AssetApp build() {
|
public AssetApp build() {
|
||||||
AssetApp assetApp = new AssetApp();
|
AssetApp assetApp = new AssetApp();
|
||||||
assetApp.assetCode = this.assetCode;
|
assetApp.assetCode = this.assetCode;
|
||||||
assetApp.name = this.name;
|
assetApp.name = this.name;
|
||||||
assetApp.size = this.size;
|
assetApp.size = this.size;
|
||||||
|
assetApp.pid = this.pid;
|
||||||
|
assetApp.message = this.message;
|
||||||
assetApp.releaseAt = this.releasedAt;
|
assetApp.releaseAt = this.releasedAt;
|
||||||
assetApp.updatedAt = this.updatedAt;
|
assetApp.updatedAt = this.updatedAt;
|
||||||
|
assetApp.status = this.status;
|
||||||
return assetApp;
|
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;
|
package inc.sdt.blokworks.devicedeployer.domain;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class OutboundMessage {
|
public class OutboundMessage {
|
||||||
private String url;
|
private String url;
|
||||||
private String name;
|
private String fileType;
|
||||||
private HashMap<String, String> env;
|
private String assetCode;
|
||||||
|
private String appName; // 사용자가 정한 파일 이름
|
||||||
|
private String name; // stackbase 에 저장된 파일 이름
|
||||||
|
private String image;
|
||||||
|
private LinkedHashMap<String, Object> options;
|
||||||
private String command;
|
private String command;
|
||||||
private OperationType operationType;
|
|
||||||
private String requestId;
|
private String requestId;
|
||||||
|
private CommandType commandType;
|
||||||
|
private SubCommandType subCommandType;
|
||||||
|
private LinkedHashMap<String, String> parameters;
|
||||||
|
private LinkedHashMap<String, Object> commandInfo;
|
||||||
|
|
||||||
protected OutboundMessage() {}
|
protected OutboundMessage() {}
|
||||||
|
|
||||||
|
@ -17,22 +23,38 @@ public class OutboundMessage {
|
||||||
return url;
|
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() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HashMap<String, String> getEnv() {
|
public String getImage() {
|
||||||
return env;
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedHashMap<String, Object> getOptions() {
|
||||||
|
return options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCommand() {
|
public String getCommand() {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OperationType getOperationType() {
|
|
||||||
return operationType;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRequestId(String requestId) {
|
public void setRequestId(String requestId) {
|
||||||
this.requestId = requestId;
|
this.requestId = requestId;
|
||||||
}
|
}
|
||||||
|
@ -41,15 +63,42 @@ public class OutboundMessage {
|
||||||
return requestId;
|
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
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "AssetApp{" +
|
return "OutboundMessage{" +
|
||||||
"url='" + url + '\'' +
|
"url='" + url + '\'' +
|
||||||
|
", fileType='" + fileType + '\'' +
|
||||||
|
", assetCode='" + assetCode + '\'' +
|
||||||
|
", appName='" + appName + '\'' +
|
||||||
", name='" + name + '\'' +
|
", name='" + name + '\'' +
|
||||||
", env=" + env +
|
", image='" + image + '\'' +
|
||||||
|
", options=" + options +
|
||||||
", command='" + command + '\'' +
|
", command='" + command + '\'' +
|
||||||
", operationType=" + operationType +
|
|
||||||
", requestId='" + requestId + '\'' +
|
", requestId='" + requestId + '\'' +
|
||||||
|
", commandType=" + commandType +
|
||||||
|
", subCommandType=" + subCommandType +
|
||||||
|
", parameters=" + parameters +
|
||||||
|
", commandInfo=" + commandInfo +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,24 +108,51 @@ public class OutboundMessage {
|
||||||
|
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private String url;
|
private String url;
|
||||||
|
private String fileType;
|
||||||
|
private String assetCode;
|
||||||
|
private String appName;
|
||||||
private String name;
|
private String name;
|
||||||
private HashMap<String, String> env;
|
private String image;
|
||||||
|
private LinkedHashMap<String, Object> options;
|
||||||
private String command;
|
private String command;
|
||||||
private OperationType operationType;
|
|
||||||
private String requestId;
|
private String requestId;
|
||||||
|
private CommandType commandType;
|
||||||
|
private SubCommandType subCommandType;
|
||||||
|
private LinkedHashMap<String, String> parameters;
|
||||||
|
private LinkedHashMap<String, Object> commandInfo;
|
||||||
|
|
||||||
public Builder url(String url) {
|
public Builder url(String url) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
return this;
|
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) {
|
public Builder name(String name) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder env(HashMap<String, String> env) {
|
public Builder image(String image) {
|
||||||
this.env = env;
|
this.image = image;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder options(LinkedHashMap<String, Object> options) {
|
||||||
|
this.options = options;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,24 +161,46 @@ public class OutboundMessage {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder operationType(OperationType operationType) {
|
public Builder requestId(String requestId) {
|
||||||
this.operationType = operationType;
|
this.requestId = requestId;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder requestId(String requestId) {
|
public Builder commandType(CommandType commandType) {
|
||||||
this.requestId = requestId;
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public OutboundMessage build() {
|
public OutboundMessage build() {
|
||||||
OutboundMessage deployMessage = new OutboundMessage();
|
OutboundMessage deployMessage = new OutboundMessage();
|
||||||
deployMessage.url = this.url;
|
deployMessage.url = this.url;
|
||||||
|
deployMessage.fileType = this.fileType;
|
||||||
|
deployMessage.assetCode = this.assetCode;
|
||||||
|
deployMessage.appName = this.appName;
|
||||||
deployMessage.name = this.name;
|
deployMessage.name = this.name;
|
||||||
deployMessage.env = this.env;
|
deployMessage.image = this.image;
|
||||||
|
deployMessage.options = this.options;
|
||||||
deployMessage.command = this.command;
|
deployMessage.command = this.command;
|
||||||
deployMessage.operationType = this.operationType;
|
|
||||||
deployMessage.requestId = this.requestId;
|
deployMessage.requestId = this.requestId;
|
||||||
|
deployMessage.commandType = this.commandType;
|
||||||
|
deployMessage.subCommandType = this.subCommandType;
|
||||||
|
deployMessage.parameters = this.parameters;
|
||||||
|
deployMessage.commandInfo = this.commandInfo;
|
||||||
return deployMessage;
|
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;
|
package inc.sdt.blokworks.devicedeployer.domain;
|
||||||
|
|
||||||
public enum Status {
|
public record Status(
|
||||||
success,
|
int succeed,
|
||||||
fail
|
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;
|
package inc.sdt.blokworks.devicedeployer.infrastructure.mqtt;
|
||||||
|
|
||||||
|
import inc.sdt.blokworks.devicedeployer.domain.Result;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
||||||
|
|
||||||
public record InboundDeployMessagePayload(
|
public record InboundDeployMessagePayload(
|
||||||
Status status,
|
|
||||||
String assetCode,
|
String assetCode,
|
||||||
String name,
|
String deviceType,
|
||||||
Long size,
|
Status status,
|
||||||
Long releasedAt,
|
Result result,
|
||||||
Long updatedAt,
|
|
||||||
String requestId
|
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;
|
package inc.sdt.blokworks.devicedeployer.infrastructure.mqtt;
|
||||||
|
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
import inc.sdt.blokworks.devicedeployer.domain.CommandType;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.Port;
|
import inc.sdt.blokworks.devicedeployer.domain.SubCommandType;
|
||||||
import inc.sdt.blokworks.devicedeployer.presentation.PortResource;
|
|
||||||
import inc.sdt.blokworks.devicedeployer.presentation.PortResourceConverter;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public record OutboundMessagePayload(
|
public record OutboundMessagePayload(
|
||||||
String url,
|
HashMap<String, Object> cmdInfo,
|
||||||
String name,
|
CommandType cmdType,
|
||||||
String command,
|
SubCommandType subCmdType,
|
||||||
HashMap<String, String> env,
|
String assetCode,
|
||||||
OperationType operationType,
|
|
||||||
String requestId
|
String requestId
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package inc.sdt.blokworks.devicedeployer.infrastructure.relational;
|
||||||
|
|
||||||
import jakarta.persistence.*;
|
import jakarta.persistence.*;
|
||||||
|
|
||||||
import java.sql.Timestamp;
|
|
||||||
|
|
||||||
@Entity(name = "asset_app")
|
@Entity(name = "asset_app")
|
||||||
class AssetAppEntity {
|
class AssetAppEntity {
|
||||||
@Id
|
@Id
|
||||||
|
@ -15,20 +13,35 @@ class AssetAppEntity {
|
||||||
@Column(name = "app_name", length = 255)
|
@Column(name = "app_name", length = 255)
|
||||||
private String name;
|
private String name;
|
||||||
@Column(name = "size")
|
@Column(name = "size")
|
||||||
private Long size;
|
private int size;
|
||||||
@Column(name = "released_at")
|
@Column(name = "released_at")
|
||||||
private Long releasedAt;
|
private Long releasedAt;
|
||||||
@Column(name = "updated_at")
|
@Column(name = "updated_at")
|
||||||
private Long updatedAt;
|
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() {}
|
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.assetCode = assetCode;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.releasedAt = releasedAt;
|
this.releasedAt = releasedAt;
|
||||||
this.updatedAt = updatedAt;
|
this.updatedAt = updatedAt;
|
||||||
|
this.pid = pid;
|
||||||
|
this.succeed = succeed;
|
||||||
|
this.statusCode = statusCode;
|
||||||
|
this.message = message;
|
||||||
|
this.errorMessage = errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
|
@ -43,7 +56,7 @@ class AssetAppEntity {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getSize() {
|
public int getSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -55,5 +68,23 @@ class AssetAppEntity {
|
||||||
return updatedAt;
|
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.application.DeployerRepositoryDelegate;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
||||||
|
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
||||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundDeployMessagePayload;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -23,6 +24,7 @@ public class AssetAppRelationalRepository implements DeployerRepositoryDelegate
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(InboundDeployMessagePayload inboundDeployMessagePayload) {
|
public void accept(InboundDeployMessagePayload inboundDeployMessagePayload) {
|
||||||
|
log.info("[accept] payload = {}", inboundDeployMessagePayload);
|
||||||
this.save(this.fromMessage(inboundDeployMessagePayload));
|
this.save(this.fromMessage(inboundDeployMessagePayload));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,7 +51,12 @@ public class AssetAppRelationalRepository implements DeployerRepositoryDelegate
|
||||||
assetApp.getName(),
|
assetApp.getName(),
|
||||||
assetApp.getSize(),
|
assetApp.getSize(),
|
||||||
assetApp.getReleaseAt(),
|
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())
|
.assetCode(entity.getAssetCode())
|
||||||
.name(entity.getName())
|
.name(entity.getName())
|
||||||
.size(entity.getSize())
|
.size(entity.getSize())
|
||||||
|
.pid(entity.getPid())
|
||||||
|
.message(entity.getMessage())
|
||||||
.releasedAt(entity.getReleasedAt())
|
.releasedAt(entity.getReleasedAt())
|
||||||
.updatedAt(entity.getUpdatedAt())
|
.updatedAt(entity.getUpdatedAt())
|
||||||
|
.status(new Status(entity.getSucceed(), entity.getStatusCode(), entity.getErrorMessage()))
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private AssetApp fromMessage(InboundDeployMessagePayload payload) {
|
private AssetApp fromMessage(InboundDeployMessagePayload payload) {
|
||||||
return AssetApp.builder()
|
return AssetApp.builder()
|
||||||
.assetCode(payload.assetCode())
|
.assetCode(payload.assetCode())
|
||||||
.name(payload.name())
|
.name(payload.result().name())
|
||||||
.size(payload.size())
|
.size(payload.result().size())
|
||||||
.releasedAt(payload.releasedAt())
|
.pid(payload.result().pid())
|
||||||
.updatedAt(payload.updatedAt())
|
.message(payload.result().message())
|
||||||
|
.releasedAt(payload.result().releasedAt())
|
||||||
|
.updatedAt(payload.result().updatedAt())
|
||||||
|
.status(payload.status())
|
||||||
.build();
|
.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;
|
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||||
|
|
||||||
|
import inc.sdt.blokworks.devicedeployer.domain.Status;
|
||||||
|
|
||||||
record AssetAppResource(
|
record AssetAppResource(
|
||||||
String assetCode,
|
String assetCode,
|
||||||
String name,
|
String name,
|
||||||
Long size,
|
int size,
|
||||||
|
int pid,
|
||||||
|
String message,
|
||||||
Long releaseAt,
|
Long releaseAt,
|
||||||
Long updatedAt
|
Long updatedAt,
|
||||||
|
Status status
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,23 +6,16 @@ import org.springframework.stereotype.Component;
|
||||||
@Component
|
@Component
|
||||||
public class AssetAppResourceConverter {
|
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) {
|
public AssetAppResource toResource(AssetApp assetApp) {
|
||||||
return new AssetAppResource(
|
return new AssetAppResource(
|
||||||
assetApp.getAssetCode(),
|
assetApp.getAssetCode(),
|
||||||
assetApp.getName(),
|
assetApp.getName(),
|
||||||
assetApp.getSize(),
|
assetApp.getSize(),
|
||||||
|
assetApp.getPid(),
|
||||||
|
assetApp.getMessage(),
|
||||||
assetApp.getReleaseAt(),
|
assetApp.getReleaseAt(),
|
||||||
assetApp.getUpdatedAt()
|
assetApp.getUpdatedAt(),
|
||||||
|
assetApp.getStatus()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
package inc.sdt.blokworks.devicedeployer.presentation;
|
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.DeployerService;
|
||||||
import inc.sdt.blokworks.devicedeployer.application.ProcessService;
|
import inc.sdt.blokworks.devicedeployer.domain.*;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.AssetApp;
|
import inc.sdt.blokworks.devicedeployer.infrastructure.amqp.ResourceMapping;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.OperationType;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.Process;
|
|
||||||
import jakarta.servlet.http.HttpSession;
|
|
||||||
import jakarta.validation.Valid;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.data.domain.Page;
|
import org.springframework.data.domain.Page;
|
||||||
|
@ -22,36 +19,68 @@ public class DeployerController {
|
||||||
private final DeployerService deployerService;
|
private final DeployerService deployerService;
|
||||||
private final OutboundMessageResourceConverter outboundMessageResourceConverter;
|
private final OutboundMessageResourceConverter outboundMessageResourceConverter;
|
||||||
private final AssetAppResourceConverter assetAppResourceConverter;
|
private final AssetAppResourceConverter assetAppResourceConverter;
|
||||||
|
private final CommandInvoker commandInvoker;
|
||||||
|
private final GiteaApiRequestHandler giteaApiRequestHandler;
|
||||||
|
|
||||||
public DeployerController(DeployerService deployerService,
|
public DeployerController(DeployerService deployerService,
|
||||||
OutboundMessageResourceConverter outboundMessageResourceConverter,
|
OutboundMessageResourceConverter outboundMessageResourceConverter,
|
||||||
AssetAppResourceConverter assetAppResourceConverter) {
|
AssetAppResourceConverter assetAppResourceConverter,
|
||||||
|
CommandInvoker commandInvoker,
|
||||||
|
GiteaApiRequestHandler giteaApiRequestHandler) {
|
||||||
this.log = LoggerFactory.getLogger(this.getClass());
|
this.log = LoggerFactory.getLogger(this.getClass());
|
||||||
this.deployerService = deployerService;
|
this.deployerService = deployerService;
|
||||||
this.outboundMessageResourceConverter = outboundMessageResourceConverter;
|
this.outboundMessageResourceConverter = outboundMessageResourceConverter;
|
||||||
this.assetAppResourceConverter = assetAppResourceConverter;
|
this.assetAppResourceConverter = assetAppResourceConverter;
|
||||||
|
this.commandInvoker = commandInvoker;
|
||||||
|
this.giteaApiRequestHandler = giteaApiRequestHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 앱 배포 명령
|
* 앱 배포 명령
|
||||||
* @param assetCode 자산 코드
|
* @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")
|
@PostMapping("/assets/{assetCode}/apps")
|
||||||
public void deploy(@PathVariable String assetCode,
|
public void deploy(@PathVariable String assetCode,
|
||||||
@Valid @RequestBody OutboundMessageResource assetAppResource) {
|
@RequestBody OutboundMessageResource resource,
|
||||||
log.info("[deploy] assetCode = {}, assetAppResource = {}", assetCode, assetAppResource);
|
HttpServletRequest httpServletRequest) {
|
||||||
|
log.info("[deploy] assetCode = {}, resource = {}", assetCode, resource);
|
||||||
|
String authorization = httpServletRequest.getHeader("Authorization");
|
||||||
String requestId = UUID.randomUUID().toString();
|
String requestId = UUID.randomUUID().toString();
|
||||||
OutboundMessage outboundMessage = outboundMessageResourceConverter.fromResource(assetAppResource);
|
|
||||||
|
OutboundMessage outboundMessage = outboundMessageResourceConverter.fromResource(resource);
|
||||||
outboundMessage.setRequestId(requestId);
|
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 자산 코드
|
* @param assetCode 자산 코드
|
||||||
*/
|
*/
|
||||||
|
@ResourceMapping(name = "Get_Asset_App", method = "GET", uri = "/assets/{code}/apps", description = "배포된 앱 정보 조회")
|
||||||
@ResponseStatus(HttpStatus.OK)
|
@ResponseStatus(HttpStatus.OK)
|
||||||
@GetMapping("/assets/{assetCode}/apps")
|
@GetMapping("/assets/{assetCode}/apps")
|
||||||
public PageableResponse<AssetAppResource> get(@PathVariable String assetCode,
|
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;
|
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||||
|
|
||||||
import inc.sdt.blokworks.devicedeployer.application.DeployerService;
|
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.InboundDeployMessagePayload;
|
||||||
import inc.sdt.blokworks.devicedeployer.infrastructure.mqtt.InboundProcessMessagePayload;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.integration.annotation.MessageEndpoint;
|
import org.springframework.integration.annotation.MessageEndpoint;
|
||||||
import org.springframework.integration.annotation.ServiceActivator;
|
import org.springframework.integration.annotation.ServiceActivator;
|
||||||
import org.springframework.integration.mqtt.support.MqttHeaders;
|
|
||||||
import org.springframework.messaging.Message;
|
import org.springframework.messaging.Message;
|
||||||
|
|
||||||
@MessageEndpoint
|
@MessageEndpoint
|
||||||
public class MqttMessageHandler {
|
public class MqttMessageHandler {
|
||||||
private final Logger log;
|
private final Logger log;
|
||||||
private final DeployerService deployerService;
|
private final DeployerService deployerService;
|
||||||
private final ProcessService processService;
|
|
||||||
private final MqttMessageConverter<InboundDeployMessagePayload> deployMessagePayloadConverter;
|
private final MqttMessageConverter<InboundDeployMessagePayload> deployMessagePayloadConverter;
|
||||||
private final MqttMessageConverter<InboundProcessMessagePayload> processMessagePayloadConverter;
|
|
||||||
|
|
||||||
public MqttMessageHandler(DeployerService deployerService,
|
public MqttMessageHandler(DeployerService deployerService,
|
||||||
ProcessService processService,
|
MqttMessageConverter<InboundDeployMessagePayload> deployMessagePayloadConverter) {
|
||||||
MqttMessageConverter<InboundDeployMessagePayload> deployMessagePayloadConverter,
|
|
||||||
MqttMessageConverter<InboundProcessMessagePayload> processMessagePayloadConverter) {
|
|
||||||
this.log = LoggerFactory.getLogger(this.getClass());
|
this.log = LoggerFactory.getLogger(this.getClass());
|
||||||
this.deployerService = deployerService;
|
this.deployerService = deployerService;
|
||||||
this.processService = processService;
|
|
||||||
this.deployMessagePayloadConverter = deployMessagePayloadConverter;
|
this.deployMessagePayloadConverter = deployMessagePayloadConverter;
|
||||||
this.processMessagePayloadConverter = processMessagePayloadConverter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ServiceActivator(inputChannel = "mqttInboundChannel")
|
@ServiceActivator(inputChannel = "mqttInboundChannel")
|
||||||
void handleMessage(Message<String> message) {
|
void handleMessage(Message<String> message) {
|
||||||
log.info("[handleMessage] message={}", message);
|
log.info("[handleMessage] message={}", message);
|
||||||
|
|
||||||
if(!message.getPayload().contains("pid")) {
|
deployMessagePayloadConverter.convertFromByte(message.getPayload(), InboundDeployMessagePayload.class)
|
||||||
String topic = String.valueOf(message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC));
|
.map(p -> new InboundDeployMessagePayload(
|
||||||
String id = topic.split("/")[4];
|
p.assetCode(),
|
||||||
|
p.deviceType(),
|
||||||
log.info("[handleMessage] topic = {}, id = {}", topic, id);
|
p.status(),
|
||||||
|
p.result(),
|
||||||
deployMessagePayloadConverter.convertFromByte(message.getPayload(), InboundDeployMessagePayload.class)
|
p.requestId()
|
||||||
.map(p -> new InboundDeployMessagePayload(
|
))
|
||||||
p.status(),
|
.flatMap(deployerService)
|
||||||
p.assetCode(),
|
.subscribe();
|
||||||
p.name(),
|
|
||||||
p.size(),
|
|
||||||
p.releasedAt(),
|
|
||||||
p.updatedAt(),
|
|
||||||
id))
|
|
||||||
.flatMap(deployerService)
|
|
||||||
.subscribe();
|
|
||||||
}else {
|
|
||||||
processMessagePayloadConverter.convertFromByte(message.getPayload(), InboundProcessMessagePayload.class)
|
|
||||||
.flatMap(processService)
|
|
||||||
.subscribe();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,21 @@
|
||||||
package inc.sdt.blokworks.devicedeployer.presentation;
|
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(
|
record OutboundMessageResource(
|
||||||
@NotNull
|
|
||||||
String url,
|
String url,
|
||||||
@NotNull
|
String fileType,
|
||||||
String name,
|
String appName, // 사용자가 정한 파일 이름
|
||||||
|
String name, // stackbase 에 저장된 파일 이름
|
||||||
|
String image,
|
||||||
String command,
|
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;
|
package inc.sdt.blokworks.devicedeployer.presentation;
|
||||||
|
|
||||||
|
import inc.sdt.blokworks.devicedeployer.domain.CommandType;
|
||||||
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
import inc.sdt.blokworks.devicedeployer.domain.OutboundMessage;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class OutboundMessageResourceConverter {
|
public class OutboundMessageResourceConverter {
|
||||||
|
|
||||||
public OutboundMessageResource toResource(OutboundMessage outboundMessage) {
|
|
||||||
return new OutboundMessageResource(
|
|
||||||
outboundMessage.getUrl(),
|
|
||||||
outboundMessage.getName(),
|
|
||||||
outboundMessage.getCommand(),
|
|
||||||
outboundMessage.getEnv()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OutboundMessage fromResource(OutboundMessageResource resource) {
|
public OutboundMessage fromResource(OutboundMessageResource resource) {
|
||||||
return OutboundMessage.builder()
|
return OutboundMessage.builder()
|
||||||
.url(resource.url())
|
.url(resource.url())
|
||||||
|
.fileType(resource.fileType())
|
||||||
|
.appName(resource.appName())
|
||||||
.name(resource.name())
|
.name(resource.name())
|
||||||
|
.image(resource.image())
|
||||||
.command(resource.command())
|
.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();
|
.build();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,21 +25,21 @@ class PageableResourceImpl implements PageableResource {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTotalElements() {
|
public long getTotalElements() {
|
||||||
return 0;
|
return totalElements;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getTotalPages() {
|
public int getTotalPages() {
|
||||||
return 0;
|
return totalPages;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getSize() {
|
public int getSize() {
|
||||||
return 0;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getPage() {
|
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) {
|
public ErrorResponse handleConflictException(Exception exception) {
|
||||||
return new ErrorResponse(HttpStatus.CONFLICT, exception.getMessage());
|
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:
|
iam:
|
||||||
enabled: ${IAM_REGISTER_ENABLED}
|
enabled: ${IAM_REGISTER_ENABLED}
|
||||||
amqp:
|
amqp:
|
||||||
|
@ -6,4 +26,8 @@ iam:
|
||||||
username: ${IAM_AMQP_CREDENTIALS_USERNAME}
|
username: ${IAM_AMQP_CREDENTIALS_USERNAME}
|
||||||
password: ${IAM_AMQP_CREDENTIALS_PASSWORD}
|
password: ${IAM_AMQP_CREDENTIALS_PASSWORD}
|
||||||
exchange: ${IAM_AMQP_EXCHANGE}
|
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:
|
inbound:
|
||||||
mqtt:
|
mqtt:
|
||||||
url: tcp://localhost:1883
|
url: tcp://localhost:1883
|
||||||
|
#url: tcp://13.209.39.139:32259
|
||||||
username: sdt
|
username: sdt
|
||||||
password: 251327
|
password: 251327
|
||||||
topics:
|
topics:
|
||||||
- /assets/+/command-req/+
|
- /device-control/+/result
|
||||||
- /assets/+/apps/process
|
|
||||||
|
stackbase:
|
||||||
|
api:
|
||||||
|
host: https://sdt-site-bucket.s3.ap-northeast-2.amazonaws.com/app/
|
|
@ -5,12 +5,20 @@ spring:
|
||||||
name: device-deployer
|
name: device-deployer
|
||||||
datasource:
|
datasource:
|
||||||
driver-class-name: org.postgresql.Driver
|
driver-class-name: org.postgresql.Driver
|
||||||
|
application:
|
||||||
|
security:
|
||||||
|
jwt:
|
||||||
|
secret-key: D3KJ3G92IWW3W3QWZLU416IN4T9AFYEWM84P5HKHRFEA8C4I1HWALFXGP2HYD87Q
|
||||||
|
|
||||||
inbound:
|
inbound:
|
||||||
mqtt:
|
mqtt:
|
||||||
url: tcp://192.168.1.162:32102
|
url: tcp://13.209.39.139:32259
|
||||||
username: sdt
|
username: sdt
|
||||||
password: 251327
|
password: 251327
|
||||||
topics:
|
topics:
|
||||||
- /assets/+/command-req/+
|
- /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