Skip to content

Commit

Permalink
Devsetting: workflow + readme
Browse files Browse the repository at this point in the history
Lagt til flere tester og fikset issue med deserializer for InternTilstand
  • Loading branch information
robertkittilsen committed Oct 7, 2024
1 parent ad884c6 commit be2a0f7
Show file tree
Hide file tree
Showing 5 changed files with 270 additions and 4 deletions.
104 changes: 104 additions & 0 deletions .github/workflows/bekreftelse-utgang.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
name: Bekreftelse Utgang

on:
push:
branches:
- main
- dev/*
paths:
- 'apps/bekreftelse-utgang/**'
- 'lib/**'
- 'domain/**'
- '.github/workflows/bekreftelse-utgang.yaml'
- 'gradle/**'
- 'settings.gradle.kts'
- 'gradle.properties'
- 'gradlew'
- 'gradlew.bat'

env:
MODULE: bekreftelse-utgang
IMAGE: europe-north1-docker.pkg.dev/${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}/paw/paw-arbeidssoekerregisteret-bekreftelse-utgang
jobs:
build:
name: Build
permissions:
contents: read
id-token: write
packages: write
runs-on: ubuntu-latest
outputs:
image: ${{ steps.docker-build-push.outputs.image }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Java
uses: actions/setup-java@v4
with:
java-version: 21
distribution: temurin
cache: gradle
- name: Set version
run: echo "VERSION=$(date +'%y.%m.%d').${{ github.run_number }}-${{ github.run_attempt }}" >> $GITHUB_ENV
- name: Login GAR
uses: nais/login@v0
with:
project_id: ${{ vars.NAIS_MANAGEMENT_PROJECT_ID }}
identity_provider: ${{ secrets.NAIS_WORKLOAD_IDENTITY_PROVIDER }}
team: paw
- name: Build and push image with Gradle
id: docker-build-push
working-directory: ./
env:
ORG_GRADLE_PROJECT_githubPassword: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "image=${{ env.IMAGE }}:${{ env.VERSION }}" >> $GITHUB_OUTPUT
echo -Pversion=${{ env.VERSION }} -Pimage=${{ env.IMAGE }} :apps:${{ env.MODULE }}:build :apps:${{ env.MODULE }}:jib
./gradlew -Pversion=${{ env.VERSION }} -Pimage=${{ env.IMAGE }} :apps:${{ env.MODULE }}:build :apps:${{ env.MODULE }}:jib
echo "DIGEST=$(cat ./apps/${{ env.MODULE }}/build/jib-image.digest)" >> $GITHUB_ENV
- name: Attest and sign image
uses: nais/[email protected]
env:
TRIVY_JAVA_DB_REPOSITORY: "public.ecr.aws/aquasecurity/trivy-java-db:1"
with:
image_ref: ${{ env.IMAGE }}@${{ env.DIGEST }}

deploy-dev:
if: github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/dev')
name: Deploy to dev-gcp
needs:
- build
permissions:
contents: read
id-token: write
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Deploy to GCP
uses: nais/deploy/actions/deploy@v2
env:
CLUSTER: dev-gcp
RESOURCE: ./apps/${{ env.MODULE }}/nais/nais-dev.yaml
VAR: image=${{ needs.build.outputs.image }}

# deploy-prod:
# if: github.ref == 'refs/heads/main'
# name: Deploy to prod-gcp
# needs:
# - build
# - deploy-dev
# permissions:
# contents: read
# id-token: write
# runs-on: ubuntu-latest
# steps:
# - name: Checkout
# uses: actions/checkout@v4
# - name: Deploy to GCP
# uses: nais/deploy/actions/deploy@v2
# env:
# TEAM: paw
# CLUSTER: prod-gcp
# RESOURCE: ./apps/${{ env.MODULE }}/nais/nais-prod.yaml
# VAR: image=${{ needs.build.outputs.image }}
8 changes: 8 additions & 0 deletions apps/bekreftelse-utgang/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# paw-arbeidssoekerregisteret-bekreftelse-utgang

## Beskrivelse
Denne appen er ansvarlig for avslutting av arbeidssøkerperioder når bekreftelse grace periode er utløpt
eller bruker svarer "nei" på bekreftelse spørsmål "Vil du fortsatt være registrert som arbeidssøker?".

Appen lytter på events fra topic `paw.arbeidssoker-bekreftelse-hendelseslogg-beta-v2`
og sender `Avsluttet` hendelser til `paw.arbeidssoker-hendelseslogg-v1` for `RegisterGracePeriodeUtloept`- og `BaOmAaAvsluttePeriode`-hendelser.
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
package no.nav.paw.bekreftelseutgang.tilstand

import com.fasterxml.jackson.core.JsonParser
import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonDeserializer
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.module.SimpleModule
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.registerKotlinModule
import no.nav.paw.bekreftelse.internehendelser.BekreftelseHendelse
import no.nav.paw.bekreftelse.internehendelser.BekreftelseHendelseDeserializer
import org.apache.kafka.common.serialization.Deserializer
import org.apache.kafka.common.serialization.Serde
import org.apache.kafka.common.serialization.Serializer
Expand Down Expand Up @@ -31,4 +37,13 @@ object InternTilstandDeserializer : Deserializer<InternTilstand> {

private val internTilstandObjectMapper = ObjectMapper()
.registerKotlinModule()
.registerModules(JavaTimeModule())
.registerModules(SimpleModule().addDeserializer(BekreftelseHendelse::class.java,
BekreftelseHendelseJsonDeserializer
))
.registerModules(JavaTimeModule())

object BekreftelseHendelseJsonDeserializer : JsonDeserializer<BekreftelseHendelse>() {
override fun deserialize(parser: JsonParser, context: DeserializationContext): BekreftelseHendelse =
BekreftelseHendelseDeserializer.deserializeNode(context.readTree(parser))
}

Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import no.nav.paw.arbeidssoekerregisteret.testdata.kafkaKeyContext
import no.nav.paw.arbeidssoekerregisteret.testdata.mainavro.metadata
import no.nav.paw.arbeidssoekerregisteret.testdata.mainavro.periode
import no.nav.paw.arbeidssokerregisteret.intern.v1.Avsluttet
import no.nav.paw.bekreftelse.internehendelser.BaOmAaAvsluttePeriode
import no.nav.paw.bekreftelse.internehendelser.RegisterGracePeriodeUtloept
import no.nav.paw.bekreftelseutgang.tilstand.InternTilstand
import no.nav.paw.bekreftelseutgang.tilstand.StateStore
import java.time.Duration
import java.time.Instant
import java.util.*

Expand All @@ -34,8 +38,138 @@ class BekreftelseUtgangTopologyTest : FreeSpec({
}
}
}

"BekreftelseHendelse 'BaOmAaAvsluttePeriode' med tilhørende identitetsnummer i state sender 'Avsluttet' hendelse" {
with(ApplicationTestContext(initialWallClockTime = startTime)) {
with(kafkaKeyContext()) {
val (id, key, periode) = periode(identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime))
periodeTopic.pipeInput(key, periode)

val baOmAaAvslutteHendelse = baOmAaAvslutteHendelse(periodeId = periode.id, arbeidssoekerId = id)
bekreftelseHendelseLoggTopic.pipeInput(key, baOmAaAvslutteHendelse)

hendelseLoggTopicOut.isEmpty shouldBe false
val kv = hendelseLoggTopicOut.readKeyValue()
kv.key shouldBe key
kv.value.shouldBeInstanceOf<Avsluttet>()
}
}
}

"BekreftelseHendelse 'RegisterGracePeriodeUtloept' uten tilhørende identitetsnummer i state sender ikke 'Avsluttet' hendelse før identitetsnummer er satt" {
with(ApplicationTestContext(initialWallClockTime = startTime)) {
with(kafkaKeyContext()) {
val (id, key, periode) = periode(identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime))

val graceperiodeUtloeptHendelse = graceperiodeUtloeptHendelse(periodeId = periode.id, arbeidssoekerId = id)
bekreftelseHendelseLoggTopic.pipeInput(key, graceperiodeUtloeptHendelse)

hendelseLoggTopicOut.isEmpty shouldBe true

periodeTopic.pipeInput(key, periode)

hendelseLoggTopicOut.isEmpty shouldBe false
val kv = hendelseLoggTopicOut.readKeyValue()
kv.key shouldBe key
kv.value.shouldBeInstanceOf<Avsluttet>()
}
}
}

"Periode with identitetsnummer but without corresponding BekreftelseHendelse does not send 'Avsluttet' event" {
with(ApplicationTestContext(initialWallClockTime = startTime)) {
with(kafkaKeyContext()) {
val (_, key, periode) = periode(identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime))
periodeTopic.pipeInput(key, periode)

// No BekreftelseHendelse is sent yet, only Periode.
hendelseLoggTopicOut.isEmpty shouldBe true
}
}
}

"Avsluttet periode removes state and does not send 'Avsluttet' hendelse" {
with(ApplicationTestContext(initialWallClockTime = startTime)) {
with(kafkaKeyContext()) {
val (_, key, periode) = periode(identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime))
periodeTopic.pipeInput(key, periode)

hendelseLoggTopicOut.isEmpty shouldBe true

val (_, key2, periode2) = periode(periodeId = periode.id, identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime), avsluttetMetadata = metadata(tidspunkt = startTime.plus(Duration.ofDays(2))))
periodeTopic.pipeInput(key2, periode2)

hendelseLoggTopicOut.isEmpty shouldBe true

val stateStore: StateStore = testDriver.getKeyValueStore(applicationConfig.kafkaTopology.stateStoreName)
stateStore.get(periode.id) shouldBe null
}
}
}

"BekreftelseHendelse without identitetsnummer in state does not send 'Avsluttet' hendelse" {
with(ApplicationTestContext(initialWallClockTime = startTime)) {
with(kafkaKeyContext()) {
val (id, key) = periode(identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime))

val graceperiodeUtloeptHendelse = graceperiodeUtloeptHendelse(periodeId = UUID.randomUUID(), arbeidssoekerId = id)
bekreftelseHendelseLoggTopic.pipeInput(key, graceperiodeUtloeptHendelse)

hendelseLoggTopicOut.isEmpty shouldBe true
}
}
}

"State is updated with BekreftelseHendelse" {
with(ApplicationTestContext(initialWallClockTime = startTime)) {
with(kafkaKeyContext()) {
val (id, key, periode) = periode(identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime))
periodeTopic.pipeInput(key, periode)

val graceperiodeUtloeptHendelse = graceperiodeUtloeptHendelse(periodeId = periode.id, arbeidssoekerId = id)
bekreftelseHendelseLoggTopic.pipeInput(key, graceperiodeUtloeptHendelse)

val stateStore: StateStore = testDriver.getKeyValueStore(applicationConfig.kafkaTopology.stateStoreName)
val currentState = stateStore[periode.id]
currentState shouldBe InternTilstand(identitetsnummer = identitetsnummer, bekreftelseHendelse = graceperiodeUtloeptHendelse)

hendelseLoggTopicOut.isEmpty shouldBe false
}
}
}

"Multiple Periode and BekreftelseHendelse events update state correctly and send events when necessary" {
with(ApplicationTestContext(initialWallClockTime = startTime)) {
with(kafkaKeyContext()) {
val (id, key, periode1) = periode(identitetsnummer = identitetsnummer, startetMetadata = metadata(tidspunkt = startTime))
val (id2, key2, periode2) = periode(identitetsnummer = "98765432109", startetMetadata = metadata(tidspunkt = startTime))

periodeTopic.pipeInput(key, periode1)
hendelseLoggTopicOut.isEmpty shouldBe true

periodeTopic.pipeInput(key2, periode2)
hendelseLoggTopicOut.isEmpty shouldBe true

val graceperiodeUtloeptHendelse1 = graceperiodeUtloeptHendelse(periodeId = periode1.id, arbeidssoekerId = id)
bekreftelseHendelseLoggTopic.pipeInput(key, graceperiodeUtloeptHendelse1)
hendelseLoggTopicOut.isEmpty shouldBe false

val graceperiodeUtloeptHendelse2 = graceperiodeUtloeptHendelse(periodeId = periode2.id, arbeidssoekerId = id2)
bekreftelseHendelseLoggTopic.pipeInput(key2, graceperiodeUtloeptHendelse2)
hendelseLoggTopicOut.isEmpty shouldBe false
}
}
}

})

fun baOmAaAvslutteHendelse(periodeId: UUID, arbeidssoekerId: Long) = BaOmAaAvsluttePeriode(
hendelseId = UUID.randomUUID(),
periodeId = periodeId,
arbeidssoekerId = arbeidssoekerId,
hendelseTidspunkt = Instant.now(),
)

fun graceperiodeUtloeptHendelse(periodeId: UUID, arbeidssoekerId: Long) = RegisterGracePeriodeUtloept(
hendelseId = UUID.randomUUID(),
periodeId = periodeId,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package no.nav.paw.bekreftelse.internehendelser

import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.module.kotlin.readValue
Expand Down Expand Up @@ -31,7 +32,11 @@ object BekreftelseHendelseSerializer: Serializer<BekreftelseHendelse> {
object BekreftelseHendelseDeserializer: Deserializer<BekreftelseHendelse> {
override fun deserialize(topic: String?, data: ByteArray?): BekreftelseHendelse {
val node = objectMapper.readTree(data)
return when (val hendelseType = node.get("hendelseType")?.asText()) {
return deserializeNode(node)
}

fun deserializeNode(node: JsonNode) =
when (val hendelseType = node.get("hendelseType")?.asText()) {
leveringsfristUtloeptHendelseType -> objectMapper.readValue<LeveringsfristUtloept>(node.traverse())
eksternGracePeriodeUtloeptHendelseType -> objectMapper.readValue<EksternGracePeriodeUtloept>(node.traverse())
registerGracePeriodeUtloeptHendelseType -> objectMapper.readValue<RegisterGracePeriodeUtloept>(node.traverse())
Expand All @@ -42,5 +47,5 @@ object BekreftelseHendelseDeserializer: Deserializer<BekreftelseHendelse> {
baOmAaAvsluttePeriodeHendelsesType -> objectMapper.readValue<BaOmAaAvsluttePeriode>(node.traverse())
else -> throw IllegalArgumentException("Ukjent hendelseType: $hendelseType")
}
}
}
}

0 comments on commit be2a0f7

Please sign in to comment.