From e4f24bf3a6bea922897bda7ee2066c339e5aaeaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=84=8C=E1=85=A1=E1=86=BC=E1=84=89=E1=85=A5=E1=86=AB?= =?UTF-8?q?=E1=84=8B=E1=85=A2?= Date: Fri, 8 Sep 2023 10:43:51 +0900 Subject: [PATCH] =?UTF-8?q?1.=20Tube=20On/Off=20=EC=A0=9C=EC=96=B4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=202.=20k8s=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EA=B4=80=EB=A0=A8=20=ED=8C=8C=EC=9D=BC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- k8s/command/docker-build-push.sh | 4 ++ k8s/control-center-management-k8s.yml | 3 ++ k8s/deploy.yaml | 42 +++++++++++++++++++ k8s/svc.yaml | 15 +++++++ rest/api.http | 16 +++++++ .../application/DefaultTubeService.java | 21 ++++------ .../application/TubeService.java | 3 +- .../presentation/TubeController.java | 7 +++- .../exception/ExceptionResponse.java | 25 +++++++++++ .../RestControllerExceptionHandler.java | 33 +++++++++++++++ 10 files changed, 153 insertions(+), 16 deletions(-) create mode 100644 k8s/command/docker-build-push.sh create mode 100644 k8s/control-center-management-k8s.yml create mode 100644 k8s/deploy.yaml create mode 100644 k8s/svc.yaml create mode 100644 rest/api.http create mode 100644 src/main/java/inc/sdt/controlcentermanagement/presentation/exception/ExceptionResponse.java create mode 100644 src/main/java/inc/sdt/controlcentermanagement/presentation/exception/RestControllerExceptionHandler.java diff --git a/k8s/command/docker-build-push.sh b/k8s/command/docker-build-push.sh new file mode 100644 index 0000000..a583e26 --- /dev/null +++ b/k8s/command/docker-build-push.sh @@ -0,0 +1,4 @@ +aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com +docker build --platform linux/amd64 -t control-center-management ../../ +docker tag control-center-management:latest 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.1 +docker push 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.1 \ No newline at end of file diff --git a/k8s/control-center-management-k8s.yml b/k8s/control-center-management-k8s.yml new file mode 100644 index 0000000..0a3451d --- /dev/null +++ b/k8s/control-center-management-k8s.yml @@ -0,0 +1,3 @@ +SERVER_PORT: 8087 +MONGODB_URL: mongodb://sdt:251327@13.209.39.139:27017/awexomeray?authSource=admin +DEPLOYER_ENDPOINT: http://device-deployer.sdt-cloud.svc.cluster.local:8085 diff --git a/k8s/deploy.yaml b/k8s/deploy.yaml new file mode 100644 index 0000000..12c8123 --- /dev/null +++ b/k8s/deploy.yaml @@ -0,0 +1,42 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: control-center-management + namespace: sdt-cloud + labels: + name: control-center-management +spec: + selector: + matchLabels: + name: control-center-management + replicas: 1 + template: + metadata: + labels: + name: control-center-management + spec: + imagePullSecrets: + - name: regcred + containers: + - name: control-center-management + image: 003960268191.dkr.ecr.ap-northeast-2.amazonaws.com/sdt-cloud/control-center-management:0.0.1 + imagePullPolicy: Always + ports: + - containerPort: 8087 + env: + - name: SPRING_PROFILES_ACTIVE + value: "k8s" + - name: SERVER_PORT + value: "8087" + - name: MONGODB_URL + value: "mongodb://sdt:251327@mongo-db.database.svc.cluster.local/awexomeray?authSource=admin" + - name: DEPLOYER_ENDPOINT + value: "http://device-deployer.sdt-cloud.svc.cluster.local:8085" + - name: IAM_AMQP_HOST + value: "rabbitmq.sdt-cloud.svc.cluster.local" + - name: IAM_AMQP_PORT + value: "5672" + - name: IAM_AMQP_CREDENTIALS_USERNAME + value: "sdt" + - name: IAM_AMQP_CREDENTIALS_PASSWORD + value: "251327" diff --git a/k8s/svc.yaml b/k8s/svc.yaml new file mode 100644 index 0000000..da473be --- /dev/null +++ b/k8s/svc.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: control-center-management + namespace: sdt-cloud +spec: + ports: + - port: 8087 + targetPort: 8087 + protocol: TCP + name: control-center-management + nodePort: 30870 + type: NodePort + selector: + name: control-center-management \ No newline at end of file diff --git a/rest/api.http b/rest/api.http new file mode 100644 index 0000000..ef26b28 --- /dev/null +++ b/rest/api.http @@ -0,0 +1,16 @@ +### ON/OFF 제어 +#PATCH http://13.209.39.139:30870/chamber/1/tube/toggle +PATCH http://localhost:8087/chamber/1/tube/toggle +Content-Type: application/json +Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJvcmdhbml6YXRpb25JZCI6ImQxZGJlYWExLWY5ZTUtNGE4OC1hMWM4LTYzMWQ4NTMyOWJmYyIsInJvbGVzIjpbIlJPTEVfQURNSU5JU1RSQVRPUiJdLCJpZCI6IjcyYTUxZDUwLTYwMDEtNDAwYy04NjNmLWZlOGU2OGE1MGExMCIsInN1YiI6InNhLmphbmdAc2R0LmluYyIsImlhdCI6MTY5NDEzNjg4OCwiZXhwIjoxNjk0MTQwNDg4fQ.likh7Ix7p4Yf2iwankLG71VGrgCDzQzhn9Z7QJK0blg + +{ + "command" : "OFF", + "assetCode" : "NODEQ-TEST-1", + "slotNumber" : "1-1", + "tube": [ + {"code": "1"}, {"code": "3"}, {"code": "11"}, {"code": "16"} + ] +} + +//{"command": "ON"} \ No newline at end of file diff --git a/src/main/java/inc/sdt/controlcentermanagement/application/DefaultTubeService.java b/src/main/java/inc/sdt/controlcentermanagement/application/DefaultTubeService.java index 369db73..a5c0433 100644 --- a/src/main/java/inc/sdt/controlcentermanagement/application/DefaultTubeService.java +++ b/src/main/java/inc/sdt/controlcentermanagement/application/DefaultTubeService.java @@ -1,10 +1,7 @@ package inc.sdt.controlcentermanagement.application; import com.fasterxml.jackson.core.type.TypeReference; -import inc.sdt.controlcentermanagement.domain.CommandType; -import inc.sdt.controlcentermanagement.domain.DeployRequest; -import inc.sdt.controlcentermanagement.domain.Slot; -import inc.sdt.controlcentermanagement.domain.Tube; +import inc.sdt.controlcentermanagement.domain.*; import inc.sdt.controlcentermanagement.infrastructure.resttemplate.RestTemplateRequestHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -45,7 +42,7 @@ class DefaultTubeService implements TubeService { log.info("[controlByTubeCode] request: {}", request); Map tubeMap = new LinkedHashMap<>(); for (Tube tube : request.getTube()) { - Map tubeOffsetMap = this.tubeOffset(request); + Map tubeOffsetMap = this.tubeOffset(); String offsetKey = request.getSlotNumber().substring(request.getSlotNumber().length() - 1); int tubeOffset = tubeOffsetMap.getOrDefault(offsetKey, 1); int tubeKey = Integer.parseInt(tube.getCode()) + tubeOffset; @@ -64,10 +61,9 @@ class DefaultTubeService implements TubeService { } @Override - public void controlAll(String authorization, Slot request) { - log.info("[controlAll] request: {}", request); + public void controlAll(String authorization, List slots, Command command) { + log.info("[controlAll] chamberNumber: {}, command: {}", slots.get(0).getChamberNumber(), command); - List slots = this.get(request.getChamberNumber()); Map>> resultMap = new LinkedHashMap<>(); for (Slot slot : slots) { String assetCode = slot.getAssetCode(); @@ -78,12 +74,11 @@ class DefaultTubeService implements TubeService { Map slotMap = assetMap.computeIfAbsent(slotNumber, k -> new HashMap<>()); for (Tube tube : tubes) { - Map tubeOffsetMap = this.tubeOffset(request); + Map tubeOffsetMap = this.tubeOffset(); String offsetKey = slotNumber.substring(slotNumber.length() - 1); int tubeOffset = tubeOffsetMap.getOrDefault(offsetKey, 1); int offsetResult = Integer.parseInt(tube.getCode()) + tubeOffset; - - slotMap.put(String.valueOf(offsetResult), String.valueOf(request.getCommand().ordinal())); + slotMap.put(String.valueOf(offsetResult), String.valueOf(command.ordinal())); } } @@ -100,9 +95,7 @@ class DefaultTubeService implements TubeService { })); } - private Map tubeOffset(Slot request) { - log.info("[tubeOffset] request: {}", request); - + private Map tubeOffset() { int offset = 0; Map tubeOffsetMap = new HashMap<>(); for (int i = 1; i <= 8; i++) { diff --git a/src/main/java/inc/sdt/controlcentermanagement/application/TubeService.java b/src/main/java/inc/sdt/controlcentermanagement/application/TubeService.java index 03ab0e5..a05a0f9 100644 --- a/src/main/java/inc/sdt/controlcentermanagement/application/TubeService.java +++ b/src/main/java/inc/sdt/controlcentermanagement/application/TubeService.java @@ -1,5 +1,6 @@ package inc.sdt.controlcentermanagement.application; +import inc.sdt.controlcentermanagement.domain.Command; import inc.sdt.controlcentermanagement.domain.Slot; import java.util.List; @@ -10,5 +11,5 @@ import java.util.List; public interface TubeService { List get(String chamberNumber); void controlByTubeCode(String authorization, Slot request); - void controlAll(String authorization, Slot request); + void controlAll(String authorization, List slots, Command command); } diff --git a/src/main/java/inc/sdt/controlcentermanagement/presentation/TubeController.java b/src/main/java/inc/sdt/controlcentermanagement/presentation/TubeController.java index 8ddbd9f..a58f5fe 100644 --- a/src/main/java/inc/sdt/controlcentermanagement/presentation/TubeController.java +++ b/src/main/java/inc/sdt/controlcentermanagement/presentation/TubeController.java @@ -8,6 +8,9 @@ import org.slf4j.LoggerFactory; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; +import java.util.List; +import java.util.NoSuchElementException; + /** * @author sunae.jang (sa.jang@sdt.inc) */ @@ -26,11 +29,13 @@ public class TubeController { @PatchMapping("/chamber/{chamberNumber}/tube/toggle") public void toggle(@RequestHeader("Authorization") String authorization, @PathVariable String chamberNumber, @RequestBody Slot slot) { log.info("[toggle] chamberNumber: {}, slot: {}", chamberNumber, slot); + List slots = tubeService.get(chamberNumber); + if (slots.isEmpty()) throw new NoSuchElementException(chamberNumber); slot.setChamberNumber(chamberNumber); if (slot.getTube() != null) { tubeService.controlByTubeCode(authorization, slot); } else { - tubeService.controlAll(authorization, slot); + tubeService.controlAll(authorization, slots, slot.getCommand()); } } } diff --git a/src/main/java/inc/sdt/controlcentermanagement/presentation/exception/ExceptionResponse.java b/src/main/java/inc/sdt/controlcentermanagement/presentation/exception/ExceptionResponse.java new file mode 100644 index 0000000..423726c --- /dev/null +++ b/src/main/java/inc/sdt/controlcentermanagement/presentation/exception/ExceptionResponse.java @@ -0,0 +1,25 @@ +package inc.sdt.controlcentermanagement.presentation.exception; + +import org.springframework.http.HttpStatus; + +import java.time.LocalDateTime; +import java.time.ZoneOffset; + +record ExceptionResponse(int code, String error, String message, long timestamp) { + public static Builder builder(HttpStatus httpStatus) { + return new Builder(httpStatus); + } + + public static class Builder { + private HttpStatus httpStatus; + + private Builder(HttpStatus httpStatus) { + this.httpStatus = httpStatus; + } + + public ExceptionResponse build(String message) { + final long timeStamp = LocalDateTime.now().toInstant(ZoneOffset.UTC).toEpochMilli(); + return new ExceptionResponse(this.httpStatus.value(), this.httpStatus.getReasonPhrase(), message, timeStamp); + } + } +} diff --git a/src/main/java/inc/sdt/controlcentermanagement/presentation/exception/RestControllerExceptionHandler.java b/src/main/java/inc/sdt/controlcentermanagement/presentation/exception/RestControllerExceptionHandler.java new file mode 100644 index 0000000..46b58ec --- /dev/null +++ b/src/main/java/inc/sdt/controlcentermanagement/presentation/exception/RestControllerExceptionHandler.java @@ -0,0 +1,33 @@ +package inc.sdt.controlcentermanagement.presentation.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import java.util.NoSuchElementException; + +@RestControllerAdvice +class RestControllerExceptionHandler { + + @ExceptionHandler + @ResponseStatus(HttpStatus.BAD_REQUEST) + ExceptionResponse handleIllegalArgumentException(IllegalArgumentException e) { + return ExceptionResponse.builder(HttpStatus.BAD_REQUEST) + .build(e.getMessage()); + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + @ResponseStatus(HttpStatus.BAD_REQUEST) + ExceptionResponse handleMethodArgumentNotValidException(MethodArgumentNotValidException e) { + return ExceptionResponse.builder(HttpStatus.BAD_REQUEST) + .build(e.getBindingResult().getAllErrors().get(0).getDefaultMessage()); + } + @ExceptionHandler + @ResponseStatus(HttpStatus.NOT_FOUND) + ExceptionResponse handleNoSuchElementException(NoSuchElementException e) { + return ExceptionResponse.builder(HttpStatus.NOT_FOUND) + .build(e.getMessage() + " does not exist."); + } +}