diff --git a/.env b/.env new file mode 100644 index 0000000..91f491f --- /dev/null +++ b/.env @@ -0,0 +1,15 @@ +POSTGRES_DB: monitoring_db +POSTGRES_USER: adminMonitoring +POSTGRES_PASSWORD: monitoringDbApp +POSTGRES_PORT=5353 +POSTGRES_HOST=db + +REDIS_HOST=redis +REDIS_PORT=6379 + +SERVER_PORT=8080 + +MAIL_HOST_PROD=postfix-production +MAIL_PORT_PROD=25 +MAIL_USERNAME_PROD=noreply@nocopy.com +SMTP_PASSWORD_PROD=nocopy!nocopy! \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d9be650 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,14 @@ +FROM gradle:8.14.2-jdk21 AS build + +WORKDIR /app +COPY . . +RUN gradle --no-daemon clean bootJar -x test + +FROM eclipse-temurin:21-jre + +WORKDIR /app +COPY --from=build /app/build/libs/*.jar app.jar + +EXPOSE 8083 + +CMD ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/build.gradle b/build.gradle index 00044d1..39f5a43 100644 --- a/build.gradle +++ b/build.gradle @@ -1,11 +1,12 @@ plugins { id 'java' - id 'org.springframework.boot' version '4.0.6' + id 'org.springframework.boot' version '3.5.6' id 'io.spring.dependency-management' version '1.1.7' } group = 'ru.no-copy' version = '0.0.1-SNAPSHOT' +description = 'monitoring' java { toolchain { @@ -13,16 +14,25 @@ java { } } +configurations { + compileOnly { + extendsFrom annotationProcessor + } +} + repositories { mavenCentral() } dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' + implementation 'org.springframework.boot:spring-boot-starter' + implementation 'org.springframework.kafka:spring-kafka' implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-validation' + annotationProcessor 'org.projectlombok:lombok' implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6' developmentOnly 'org.springframework.boot:spring-boot-devtools' runtimeOnly 'org.postgresql:postgresql' diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..88f083e --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,71 @@ +version: '3.9' + +services: + db: + image: postgres:17.7 + container_name: monitoring-db + environment: + POSTGRES_DB: monitoring_db + POSTGRES_USER: adminMonitoring + POSTGRES_PASSWORD: monitoringDbApp + volumes: + - postgres_data:/var/lib/postgresql/data + ports: + - "5353:5432" + restart: unless-stopped + + monitoring: + build: . + container_name: monitoring-backend + ports: + - "${SERVER_PORT:-8083}:${SERVER_PORT:-8083}" + environment: + SPRING_PROFILES_ACTIVE: prod + POSTGRES_HOST: db + POSTGRES_PORT: 5432 + POSTGRES_DB: monitoring_db + POSTGRES_USER: adminMonitoring + POSTGRES_PASSWORD: monitoringDbApp + SERVER_PORT: ${SERVER_PORT:-8083} + SPRING_KAFKA_BOOTSTRAP_SERVERS: kafka:9092 + depends_on: + - db + restart: unless-stopped + + kafka: + image: apache/kafka:latest + container_name: kafka + ports: + - "9092:9092" + environment: + KAFKA_NODE_ID: 1 + KAFKA_PROCESS_ROLES: 'broker,controller' + KAFKA_CONTROLLER_QUORUM_VOTERS: '1@kafka:9093' + KAFKA_LISTENERS: 'PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093' + KAFKA_ADVERTISED_LISTENERS: 'PLAINTEXT://kafka:9092' + KAFKA_CONTROLLER_LISTENER_NAMES: 'CONTROLLER' + KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: 'CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT' + KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true' + KAFKA_DELETE_TOPIC_ENABLE: 'true' + KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 + KAFKA_DEFAULT_REPLICATION_FACTOR: 1 + KAFKA_MIN_INSYNC_REPLICAS: 1 + volumes: + - kafka_data:/var/lib/kafka/data + + kafka-ui: + image: provectuslabs/kafka-ui:latest + container_name: kafka-ui + ports: + - "8010:8080" + environment: + DYNAMIC_CONFIG_ENABLED: 'true' + KAFKA_CLUSTERS_0_NAME: 'local-cluster' + KAFKA_CLUSTERS_0_BOOTSTRAPSERVERS: 'kafka:9092' + depends_on: + - kafka + + +volumes: + kafka_data: + postgres_data: \ No newline at end of file diff --git a/src/main/java/ru/no_copy/monitoring/MonitoringApplication.java b/src/main/java/ru/no_copy/monitoring/MonitoringApplication.java index c1eff16..99618c6 100644 --- a/src/main/java/ru/no_copy/monitoring/MonitoringApplication.java +++ b/src/main/java/ru/no_copy/monitoring/MonitoringApplication.java @@ -2,6 +2,7 @@ package ru.no_copy.monitoring; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.scheduling.annotation.EnableScheduling; @SpringBootApplication public class MonitoringApplication { diff --git a/src/main/java/ru/no_copy/monitoring/controller/HealthCheckController.java b/src/main/java/ru/no_copy/monitoring/controller/HealthCheckController.java new file mode 100644 index 0000000..cad81f7 --- /dev/null +++ b/src/main/java/ru/no_copy/monitoring/controller/HealthCheckController.java @@ -0,0 +1,17 @@ +package ru.no_copy.monitoring.controller; + +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@RestController("/api/monitoring") +public class HealthCheckController { + + @GetMapping + public ResponseEntity> healthCheck() { + + return ResponseEntity.ok().body(Map.of("status","ok")); + } +} diff --git a/src/main/java/ru/no_copy/monitoring/kafka/MonitoringCommandListener.java b/src/main/java/ru/no_copy/monitoring/kafka/MonitoringCommandListener.java new file mode 100644 index 0000000..3639460 --- /dev/null +++ b/src/main/java/ru/no_copy/monitoring/kafka/MonitoringCommandListener.java @@ -0,0 +1,30 @@ +package ru.no_copy.monitoring.kafka; + +import org.springframework.kafka.annotation.KafkaListener; +import org.springframework.kafka.core.KafkaTemplate; +import org.springframework.stereotype.Component; +import ru.no_copy.monitoring.service.MonitoringService; + +import java.util.concurrent.CompletableFuture; + +@Component +public class MonitoringCommandListener { + private final KafkaTemplate kafkaTemplate; + + private final MonitoringService monitoringService; + + + public MonitoringCommandListener(KafkaTemplate kafkaTemplate, MonitoringService monitoringService) { + this.kafkaTemplate = kafkaTemplate; + this.monitoringService = monitoringService; + } + + @KafkaListener(topics = "monitoring-commands", groupId = "monitoring-service") + public void handleCommand(String commandMessage) { + CompletableFuture.runAsync(() -> { + String result = monitoringService.execute(commandMessage); + //TODO + kafkaTemplate.send("monitoring-results", result); + }); + } +} diff --git a/src/main/java/ru/no_copy/monitoring/service/MonitoringService.java b/src/main/java/ru/no_copy/monitoring/service/MonitoringService.java new file mode 100644 index 0000000..de5a876 --- /dev/null +++ b/src/main/java/ru/no_copy/monitoring/service/MonitoringService.java @@ -0,0 +1,10 @@ +package ru.no_copy.monitoring.service; + +import org.springframework.stereotype.Service; + +@Service +public class MonitoringService { + public String execute(String command) { + return "{\"status\": \"ok\", \"data\": \"...\"}"; + } +} diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index ee1e996..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -spring.application.name=monitoring diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml new file mode 100644 index 0000000..ab74f62 --- /dev/null +++ b/src/main/resources/application.yaml @@ -0,0 +1,40 @@ +spring: + kafka: + bootstrap-servers: kafka:9092 + consumer: + group-id: monitoring-service + key-deserializer: org.apache.kafka.common.serialization.StringDeserializer + value-deserializer: org.apache.kafka.common.serialization.StringDeserializer + producer: + key-serializer: org.apache.kafka.common.serialization.StringSerializer + value-serializer: org.apache.kafka.common.serialization.StringSerializer + + cloud: + compatibility-verifier: + enabled: false + + datasource: + url: jdbc:postgresql://${POSTGRES_HOST:db}:${POSTGRES_PORT:5432}/${POSTGRES_DB:monitoring_db} + username: ${POSTGRES_USER:adminMonitoring} + password: ${POSTGRES_PASSWORD:monitoringDbApp} + + jpa: + hibernate: + ddl-auto: update + properties: + hibernate: + dialect: org.hibernate.dialect.PostgreSQLDialect + format_sql: true + +server: + port: ${SERVER_PORT:8083} + +app: + internal-api-key: "tljzkXiEYF1klSHuG2hPZKjx6EsBX8RQP6UrzMdQanSKbRYuHuOBwrXejZkn7V4FICvIahoDmYD2hjNBPw61NFbGIt4scOzwZpyCiXEa1YKLAeJSPso4S43LIZlKjO4S" + +jwt: + secret: Z29nb3Bvd2VycmFuZ2VydHVtYmF5YW1iZjMyNDIyMjh3aW5lcndpbmVy + expiration: 3600000 + +nocopy-dashboard: + url: http://172.17.0.1:3001 \ No newline at end of file