diff --git a/src/main/java/com/litoralregas/openvpn/deployment/Deployment.java b/src/main/java/com/litoralregas/openvpn/deployment/Deployment.java new file mode 100644 index 0000000..959f6a4 --- /dev/null +++ b/src/main/java/com/litoralregas/openvpn/deployment/Deployment.java @@ -0,0 +1,113 @@ +package com.litoralregas.openvpn.deployment; + +import com.litoralregas.openvpn.router.Router; +import jakarta.persistence.*; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Entity +@Table(name = "deployments") +public class Deployment { + + @Id + private UUID id; + + @ManyToOne + @JoinColumn(name = "router_id", nullable = false) + private Router router; + + @Enumerated(EnumType.STRING) + private DeploymentAction action; + + @Enumerated(EnumType.STRING) + private DeploymentStatus status; + + private LocalDateTime startedAt; + private LocalDateTime finishedAt; + + @Column(columnDefinition = "TEXT") + private String stdout; + + @Column(columnDefinition = "TEXT") + private String stderr; + + private LocalDateTime createdAt; + + public Deployment() { + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public Router getRouter() { + return router; + } + + public void setRouter(Router router) { + this.router = router; + } + + public DeploymentAction getAction() { + return action; + } + + public void setAction(DeploymentAction action) { + this.action = action; + } + + public DeploymentStatus getStatus() { + return status; + } + + public void setStatus(DeploymentStatus status) { + this.status = status; + } + + public LocalDateTime getStartedAt() { + return startedAt; + } + + public void setStartedAt(LocalDateTime startedAt) { + this.startedAt = startedAt; + } + + public LocalDateTime getFinishedAt() { + return finishedAt; + } + + public void setFinishedAt(LocalDateTime finishedAt) { + this.finishedAt = finishedAt; + } + + public String getStdout() { + return stdout; + } + + public void setStdout(String stdout) { + this.stdout = stdout; + } + + public String getStderr() { + return stderr; + } + + public void setStderr(String stderr) { + this.stderr = stderr; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + // getters and setters +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/openvpn/deployment/DeploymentAction.java b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentAction.java new file mode 100644 index 0000000..f168907 --- /dev/null +++ b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentAction.java @@ -0,0 +1,6 @@ +package com.litoralregas.openvpn.deployment; + +public enum DeploymentAction { + PROVISION, + REMOVE +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/openvpn/deployment/DeploymentRepository.java b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentRepository.java new file mode 100644 index 0000000..94620af --- /dev/null +++ b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentRepository.java @@ -0,0 +1,8 @@ +package com.litoralregas.openvpn.deployment; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.UUID; + +public interface DeploymentRepository extends JpaRepository { +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/openvpn/deployment/DeploymentService.java b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentService.java new file mode 100644 index 0000000..370eca9 --- /dev/null +++ b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentService.java @@ -0,0 +1,46 @@ +package com.litoralregas.openvpn.deployment; + +import com.litoralregas.openvpn.router.Router; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.UUID; + +@Service +public class DeploymentService { + + private final DeploymentRepository repository; + + public DeploymentService(DeploymentRepository repository) { + this.repository = repository; + } + + public Deployment startDeployment(Router router, DeploymentAction action) { + Deployment deployment = new Deployment(); + + deployment.setId(UUID.randomUUID()); + deployment.setRouter(router); + deployment.setAction(action); + deployment.setStatus(DeploymentStatus.RUNNING); + deployment.setStartedAt(LocalDateTime.now()); + deployment.setCreatedAt(LocalDateTime.now()); + + return repository.save(deployment); + } + + public Deployment finishSuccess(Deployment deployment, String stdout) { + deployment.setStatus(DeploymentStatus.SUCCESS); + deployment.setFinishedAt(LocalDateTime.now()); + deployment.setStdout(stdout); + + return repository.save(deployment); + } + + public Deployment finishFailure(Deployment deployment, String stderr) { + deployment.setStatus(DeploymentStatus.FAILED); + deployment.setFinishedAt(LocalDateTime.now()); + deployment.setStderr(stderr); + + return repository.save(deployment); + } +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/openvpn/deployment/DeploymentStatus.java b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentStatus.java new file mode 100644 index 0000000..9a936a0 --- /dev/null +++ b/src/main/java/com/litoralregas/openvpn/deployment/DeploymentStatus.java @@ -0,0 +1,7 @@ +package com.litoralregas.openvpn.deployment; + +public enum DeploymentStatus { + RUNNING, + SUCCESS, + FAILED +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/openvpn/router/RouterController.java b/src/main/java/com/litoralregas/openvpn/router/RouterController.java index 12af938..638f2ac 100644 --- a/src/main/java/com/litoralregas/openvpn/router/RouterController.java +++ b/src/main/java/com/litoralregas/openvpn/router/RouterController.java @@ -1,5 +1,7 @@ package com.litoralregas.openvpn.router; +import com.litoralregas.openvpn.deployment.DeploymentAction; +import com.litoralregas.openvpn.deployment.DeploymentService; import jakarta.validation.Valid; import org.springframework.web.bind.annotation.*; @@ -11,9 +13,11 @@ import java.util.UUID; public class RouterController { private final RouterService service; + private final DeploymentService deploymentService; - public RouterController(RouterService service) { + public RouterController(RouterService service, DeploymentService deploymentService) { this.service = service; + this.deploymentService = deploymentService; } @GetMapping @@ -43,4 +47,16 @@ public class RouterController { public void delete(@PathVariable UUID id) { service.delete(id); } + + @PostMapping("/{id}/provision") + public String provision(@PathVariable UUID id) { + Router router = service.findById(id); + + var deployment = deploymentService.startDeployment(router, DeploymentAction.PROVISION); + + // simulate success + deploymentService.finishSuccess(deployment, "Provision completed"); + + return "Provision simulated"; + } } \ No newline at end of file diff --git a/src/main/resources/db/migration/V4__deployments_table.sql b/src/main/resources/db/migration/V4__deployments_table.sql new file mode 100644 index 0000000..2f5c16f --- /dev/null +++ b/src/main/resources/db/migration/V4__deployments_table.sql @@ -0,0 +1,20 @@ +CREATE TABLE deployments ( + id UUID PRIMARY KEY, + + router_id UUID NOT NULL, + action VARCHAR(50) NOT NULL, + status VARCHAR(50) NOT NULL, + + started_at TIMESTAMP, + finished_at TIMESTAMP, + + stdout TEXT, + stderr TEXT, + + created_at TIMESTAMP NOT NULL DEFAULT now(), + + CONSTRAINT fk_deployments_router + FOREIGN KEY (router_id) + REFERENCES routers (id) + ON DELETE CASCADE +); \ No newline at end of file