diff --git a/infrastructure/istio/config/23-mtls-authz-policies.yaml b/infrastructure/istio/config/23-mtls-authz-policies.yaml index fd7b41d7d..9c85bb02e 100644 --- a/infrastructure/istio/config/23-mtls-authz-policies.yaml +++ b/infrastructure/istio/config/23-mtls-authz-policies.yaml @@ -51,6 +51,23 @@ spec: --- apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy +metadata: + name: hc-kafka-authz + namespace: hc-kafka +spec: + action: ALLOW + selector: + matchLabels: + app.kubernetes.io/name: kafka + app.kubernetes.io/instance: hc-kafka + rules: + - from: + - source: + principals: + - cluster.local/ns/hc-track/sa/track +--- +apiVersion: security.istio.io/v1beta1 +kind: AuthorizationPolicy metadata: name: keycloak-authz namespace: hc-keycloak diff --git a/infrastructure/kubernetes/helmfile.d/00-namespaces.yaml b/infrastructure/kubernetes/helmfile.d/00-namespaces.yaml index e94b9ab3a..3213fbcf7 100644 --- a/infrastructure/kubernetes/helmfile.d/00-namespaces.yaml +++ b/infrastructure/kubernetes/helmfile.d/00-namespaces.yaml @@ -90,6 +90,26 @@ releases: "kuma.io/mesh": "default" {{- end }} spec: + - apiVersion: v1 + kind: Namespace + metadata: + name: hc-kafka + {{- if eq .Environment.Name "istio" }} + labels: + "istio-injection": "enabled" + {{- end }} + {{- if eq .Environment.Name "linkerd" }} + annotations: + "linkerd.io/inject": "enabled" + "config.linkerd.io/trace-collector": "linkerd-collector.linkerd:55678" + "config.alpha.linkerd.io/trace-collector-service-account": "linkerd-collector" + {{- end }} + {{- if eq .Environment.Name "kuma" }} + annotations: + "kuma.io/sidecar-injection": "enabled" + "kuma.io/mesh": "default" + {{- end }} + spec: - apiVersion: v1 kind: Namespace metadata: diff --git a/infrastructure/kubernetes/helmfile.d/15-kafka.yaml b/infrastructure/kubernetes/helmfile.d/15-kafka.yaml new file mode 100644 index 000000000..f61331414 --- /dev/null +++ b/infrastructure/kubernetes/helmfile.d/15-kafka.yaml @@ -0,0 +1,16 @@ +bases: + - environments.yaml + +repositories: + - name: bitnami-archive-full-index + url: https://raw.githubusercontent.com/bitnami/charts/archive-full-index/bitnami + +releases: + - name: hc-kafka + namespace: hc-kafka + labels: + service: hc-kafka + chart: bitnami-archive-full-index/kafka + version: 25.3.1 + values: + - ./values/kafka-values.yaml.gotmpl diff --git a/infrastructure/kubernetes/helmfile.d/values/kafka-values.yaml.gotmpl b/infrastructure/kubernetes/helmfile.d/values/kafka-values.yaml.gotmpl new file mode 100644 index 000000000..363909523 --- /dev/null +++ b/infrastructure/kubernetes/helmfile.d/values/kafka-values.yaml.gotmpl @@ -0,0 +1,15 @@ +controller: + replicaCount: 1 +kraft: + # generated with: uuidgen | tr -d '-' | base64 | cut -b 1-22 + clusterId: "ZDQ2MzI3MWEwNmIwNGMyMT" +sasl: + interbroker: + password: "kafka" + controller: + password: "kafka" + client: + users: + - "track" + passwords: + - "track" diff --git a/infrastructure/kubernetes/helmfile.d/values/track-values.yaml.gotmpl b/infrastructure/kubernetes/helmfile.d/values/track-values.yaml.gotmpl index 45a2ca2e0..1e7fa8d66 100644 --- a/infrastructure/kubernetes/helmfile.d/values/track-values.yaml.gotmpl +++ b/infrastructure/kubernetes/helmfile.d/values/track-values.yaml.gotmpl @@ -17,9 +17,10 @@ image: pullPolicy: Always ## habitcentric track service configuration - -{{- if (eq .Environment.Name "traefik-mesh") }} extraEnv: + - name: KAFKA_BOOTSTRAP_SERVERS + value: hc-kafka.hc-kafka.svc.cluster.local:9092 +{{- if (eq .Environment.Name "traefik-mesh") }} - name: MANAGEMENT_ZIPKIN_TRACING_ENDPOINT value: http://jaeger-collector.traefik-mesh.svc.cluster.local:9411 {{- end }} diff --git a/services/track/build.gradle b/services/track/build.gradle index 85147ad22..91a62507a 100644 --- a/services/track/build.gradle +++ b/services/track/build.gradle @@ -98,6 +98,7 @@ dependencies { // Spring Modulith implementation "org.springframework.modulith:spring-modulith-starter-core" implementation "org.springframework.modulith:spring-modulith-starter-jpa" + implementation "org.springframework.modulith:spring-modulith-events-kafka" intTestImplementation "org.springframework.modulith:spring-modulith-starter-test" implementation 'io.micrometer:micrometer-tracing-bridge-otel' diff --git a/services/track/docker-compose.yml b/services/track/docker-compose.yml index bce20e4f3..aafb5cf5c 100644 --- a/services/track/docker-compose.yml +++ b/services/track/docker-compose.yml @@ -8,3 +8,26 @@ services: environment: POSTGRESQL_PASSWORD: postgres POSTGRESQL_PORT_NUMBER: 10002 + + kafka: + image: 'bitnami/kafka:latest' + ports: + - 9094:9094 + environment: + - KAFKA_CFG_NODE_ID=0 + - KAFKA_CFG_PROCESS_ROLES=controller,broker + - KAFKA_CFG_LISTENERS=PLAINTEXT://:9092,CONTROLLER://:9093,EXTERNAL://:9094 + - KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=CONTROLLER:PLAINTEXT,PLAINTEXT:SASL_PLAINTEXT,EXTERNAL:SASL_PLAINTEXT + - KAFKA_CFG_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,EXTERNAL://localhost:9094 + - KAFKA_CFG_CONTROLLER_QUORUM_VOTERS=0@kafka:9093 + - KAFKA_CFG_CONTROLLER_LISTENER_NAMES=CONTROLLER + - KAFKA_CLIENT_USERS=track + - KAFKA_CLIENT_PASSWORDS=track + + kafka-ui: + container_name: kafka-ui + image: provectuslabs/kafka-ui:latest + ports: + - 8080:8080 + environment: + DYNAMIC_CONFIG_ENABLED: 'true' diff --git a/services/track/src/main/java/de/codecentric/habitcentric/track/habit/HabitTracking.java b/services/track/src/main/java/de/codecentric/habitcentric/track/habit/HabitTracking.java index 641a7f0c9..3970c563a 100644 --- a/services/track/src/main/java/de/codecentric/habitcentric/track/habit/HabitTracking.java +++ b/services/track/src/main/java/de/codecentric/habitcentric/track/habit/HabitTracking.java @@ -18,6 +18,7 @@ import lombok.Setter; import lombok.ToString; import org.springframework.data.domain.AbstractAggregateRoot; +import org.springframework.modulith.events.Externalized; @Entity @AllArgsConstructor @@ -55,5 +56,10 @@ public static class Id implements Serializable { @NotNull private LocalDate trackDate; } - public record Created(String userId, Long habitId, LocalDate trackDate) {} + @Externalized("habit-tracked::#{#this.getId()}") + public record Created(String userId, Long habitId, LocalDate trackDate) { + public String getId() { + return userId + "-" + habitId; + } + } } diff --git a/services/track/src/main/resources/application.yml b/services/track/src/main/resources/application.yml index e8a847ac0..6caabb3ab 100644 --- a/services/track/src/main/resources/application.yml +++ b/services/track/src/main/resources/application.yml @@ -25,6 +25,15 @@ spring: lob: # https://github.com/spring-projects/spring-boot/issues/12007#issuecomment-370774241 non_contextual_creation: true + + kafka: + client-id: track + bootstrap-servers: ${KAFKA_BOOTSTRAP_SERVERS:localhost:9094} + properties: + "security.protocol": SASL_PLAINTEXT + "sasl.mechanism": PLAIN + "sasl.jaas.config": 'org.apache.kafka.common.security.plain.PlainLoginModule required username="${KAFKA_USER:track}" password="${KAFKA_PASSWORD:track}";' + server: port: 9002 error: diff --git a/services/track/track-request.http b/services/track/track-request.http new file mode 100644 index 000000000..0d36b404c --- /dev/null +++ b/services/track/track-request.http @@ -0,0 +1,7 @@ +PUT localhost:9002/track/users/12345/habits/1 +Content-Type: application/json + +[ + "2021-01-01", + "2021-01-02" +]