Skip to content
Snippets Groups Projects
Commit f78d7851 authored by 천 진강's avatar 천 진강
Browse files

feat: Nginx 테스트, 리로드 로직 추가, conf 파일 관련 롤백 로직 추가

parent c0d0a410
No related branches found
No related tags found
3 merge requests!15Feat/certificate,!9Feat/forwarding nginx 테스트, 리로드 / 파일 롤백,!8Feat/forwarding nginx 테스트, 리로드 / 파일 롤백
...@@ -20,7 +20,14 @@ public enum ErrorCode { ...@@ -20,7 +20,14 @@ public enum ErrorCode {
NOT_FOUND_FORWARDING(HttpStatus.BAD_REQUEST, "포트포워딩 파일이 존재하지 않습니다"), NOT_FOUND_FORWARDING(HttpStatus.BAD_REQUEST, "포트포워딩 파일이 존재하지 않습니다"),
INVALID_CONF_INPUT(HttpStatus.BAD_REQUEST, "잘못된 입력이 존재합니다"), INVALID_CONF_INPUT(HttpStatus.BAD_REQUEST, "잘못된 입력이 존재합니다"),
DUPLICATED_INSTANCE_INFO(HttpStatus.BAD_REQUEST, "중복된 인스턴스 IP와 포트입니다"), DUPLICATED_INSTANCE_INFO(HttpStatus.BAD_REQUEST, "중복된 인스턴스 IP와 포트입니다"),
DUPLICATED_SERVER_PORT(HttpStatus.BAD_REQUEST, "중복된 서버 포트입니다"); DUPLICATED_SERVER_PORT(HttpStatus.BAD_REQUEST, "중복된 서버 포트입니다"),
// Nginx
FAIL_NGINX_CONF_TEST(HttpStatus.BAD_REQUEST, "Conf 파일 테스트에 실패했습니다"),
FAIL_NGINX_CONF_RELOAD(HttpStatus.BAD_REQUEST, "Nginx 재시작에 실패했습니다"),
FAIL_DELETE_CONF(HttpStatus.BAD_REQUEST, "Conf 파일을 삭제하지 못했습니다"),
FAIL_ROLL_BACK(HttpStatus.BAD_REQUEST, "롤백 실패");
private final HttpStatus status; private final HttpStatus status;
private final String message; private final String message;
......
...@@ -7,12 +7,20 @@ import com.aolda.itda.exception.CustomException; ...@@ -7,12 +7,20 @@ import com.aolda.itda.exception.CustomException;
import com.aolda.itda.exception.ErrorCode; import com.aolda.itda.exception.ErrorCode;
import com.aolda.itda.repository.forwarding.ForwardingRepository; import com.aolda.itda.repository.forwarding.ForwardingRepository;
import com.aolda.itda.template.ForwardingTemplate; import com.aolda.itda.template.ForwardingTemplate;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.validation.ConstraintViolation; import jakarta.validation.ConstraintViolation;
import jakarta.validation.Validation; import jakarta.validation.Validation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
...@@ -21,16 +29,20 @@ import java.io.IOException; ...@@ -21,16 +29,20 @@ import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Map;
@Service @Service
@Transactional @Transactional
@RequiredArgsConstructor @RequiredArgsConstructor
@Slf4j
public class ForwardingService { public class ForwardingService {
@Value("${spring.server.base-ip}") @Value("${spring.server.base-ip}")
private String serverBaseIp; private String serverBaseIp;
private final ForwardingTemplate forwardingTemplate; private final ForwardingTemplate forwardingTemplate;
private final ForwardingRepository forwardingRepository; private final ForwardingRepository forwardingRepository;
private final RestTemplate restTemplate = new RestTemplate();
/* 포트포워딩 정보 조회 */ /* 포트포워딩 정보 조회 */
public ForwardingDTO getForwarding(Long forwardingId) { public ForwardingDTO getForwarding(Long forwardingId) {
...@@ -101,12 +113,47 @@ public class ForwardingService { ...@@ -101,12 +113,47 @@ public class ForwardingService {
bw.close(); bw.close();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
if (file.exists()) { if (file.delete()) {
file.delete(); throw new CustomException(ErrorCode.FAIL_DELETE_CONF);
} }
throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "포트포워딩 Conf 파일을 작성하지 못했습니다"); throw new CustomException(ErrorCode.FAIL_CREATE_CONF, "포트포워딩 Conf 파일을 작성하지 못했습니다");
} }
/* nginx test */
String url = "http://nginx:8081/nginx-api/test";
try {
restTemplate.getForEntity(url, String.class);
} catch (HttpServerErrorException.InternalServerError e) {
log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
if (file.delete()) {
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
} catch (Exception e) {
log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage());
if (file.delete()) {
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
}
/* nginx reload */
url = "http://nginx:8081/nginx-api/reload";
try {
restTemplate.getForEntity(url, String.class);
} catch (HttpServerErrorException.InternalServerError e) {
log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
if (file.delete()) {
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
} catch (Exception e) {
log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage());
if (file.delete()) {
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST, "(롤백 실패)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
}
} }
...@@ -140,8 +187,13 @@ public class ForwardingService { ...@@ -140,8 +187,13 @@ public class ForwardingService {
throw new CustomException(ErrorCode.NOT_FOUND_FORWARDING, "Conf 파일이 존재하지 않아 수정할 수 없습니다"); throw new CustomException(ErrorCode.NOT_FOUND_FORWARDING, "Conf 파일이 존재하지 않아 수정할 수 없습니다");
} }
Path backup;
try { try {
BufferedWriter bw = new BufferedWriter(new FileWriter(file, true)); // 예외처리 필요 backup = Files.createTempFile("temp_", ".tmp");
Files.copy(Paths.get(confPath), backup, StandardCopyOption.REPLACE_EXISTING
, StandardCopyOption.COPY_ATTRIBUTES);
BufferedWriter bw = new BufferedWriter(new FileWriter(file, false));
bw.write(content); bw.write(content);
bw.flush(); bw.flush();
bw.close(); bw.close();
...@@ -150,6 +202,59 @@ public class ForwardingService { ...@@ -150,6 +202,59 @@ public class ForwardingService {
throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "포트포워딩 Conf 파일을 수정하지 못했습니다"); throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "포트포워딩 Conf 파일을 수정하지 못했습니다");
} }
/* nginx test */
String url = "http://nginx:8081/nginx-api/test";
try {
restTemplate.getForEntity(url, String.class);
} catch (HttpServerErrorException.InternalServerError e) {
log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
try {
Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
, StandardCopyOption.COPY_ATTRIBUTES);
Files.delete(backup);
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(포트포워딩 Conf 파일 수정)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
} catch (RuntimeException e) {
log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage());
try {
Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
, StandardCopyOption.COPY_ATTRIBUTES);
Files.delete(backup);
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(포트포워딩 Conf 파일 수정)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
}
/* nginx reload */
url = "http://nginx:8081/nginx-api/reload";
try {
restTemplate.getForEntity(url, String.class);
} catch (HttpServerErrorException.InternalServerError e) {
log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
try {
Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
, StandardCopyOption.COPY_ATTRIBUTES);
Files.delete(backup);
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(포트포워딩 Conf 파일 수정)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
} catch (RuntimeException e) {
log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage());
try {
Files.copy(backup, Paths.get(confPath), StandardCopyOption.REPLACE_EXISTING
, StandardCopyOption.COPY_ATTRIBUTES);
Files.delete(backup);
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_UPDATE_CONF, "(포트포워딩 Conf 파일 수정)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
}
/* DB 정보 수정 */ /* DB 정보 수정 */
forwardingRepository.save(forwarding); forwardingRepository.save(forwarding);
} }
...@@ -161,9 +266,55 @@ public class ForwardingService { ...@@ -161,9 +266,55 @@ public class ForwardingService {
/* 파일 삭제 */ /* 파일 삭제 */
String confPath = "/data/nginx/stream/" + forwarding.getForwardingId() + ".conf"; String confPath = "/data/nginx/stream/" + forwarding.getForwardingId() + ".conf";
File file = new File(confPath); String deletePath = confPath + ".deleted";
if (!file.delete()) { try {
throw new CustomException(ErrorCode.NOT_FOUND_FORWARDING, "Conf 파일이 존재하지 않아 삭제할 수 없습니다"); Files.move(Paths.get(confPath), Paths.get(deletePath));
} catch (IOException e) {
throw new CustomException(ErrorCode.FAIL_DELETE_CONF);
}
/* nginx test */
String url = "http://nginx:8081/nginx-api/test";
try {
restTemplate.getForEntity(url, String.class);
} catch (HttpServerErrorException.InternalServerError e) {
log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
try {
Files.move(Paths.get(deletePath), Paths.get(confPath));
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(포트포워딩 Conf 삭제)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
} catch (Exception e) {
log.error("[RestClientException] {} : {}", "Nginx Conf Test (forwarding)", e.getMessage());
try {
Files.move(Paths.get(deletePath), Paths.get(confPath));
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(포트포워딩 Conf 삭제)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_TEST);
}
/* nginx reload */
url = "http://nginx:8081/nginx-api/reload";
try {
restTemplate.getForEntity(url, String.class);
} catch (HttpServerErrorException.InternalServerError e) {
log.error("[nginxApiException] {} : {}", e.getResponseBodyAsString(), e.getMessage());
try {
Files.move(Paths.get(deletePath), Paths.get(confPath));
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(포트포워딩 Conf 삭제)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
} catch (Exception e) {
log.error("[RestClientException] {} : {}", "Nginx Conf Reload (forwarding)", e.getMessage());
try {
Files.move(Paths.get(deletePath), Paths.get(confPath));
} catch (IOException e1) {
throw new CustomException(ErrorCode.FAIL_ROLL_BACK, "(포트포워딩 Conf 삭제)");
}
throw new CustomException(ErrorCode.FAIL_NGINX_CONF_RELOAD);
} }
/* DB */ /* DB */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment