diff --git a/.github/workflows/ci-main.yml b/.github/workflows/ci-main.yml index fbea119..4e588a3 100644 --- a/.github/workflows/ci-main.yml +++ b/.github/workflows/ci-main.yml @@ -17,4 +17,9 @@ jobs: - e2e-tests - backend-tests uses: ./.github/workflows/docker.yml -# TODO: add deployment as step + deploy-to-kubernetes: + needs: + - build-publish-images + uses: ./.github/workflows/helm.yml + secrets: + KUBECONF: ${{ secrets.KUBECONF }} diff --git a/.github/workflows/ci-pull-request.yml b/.github/workflows/ci-pull-request.yml index e73edb2..1e75d20 100644 --- a/.github/workflows/ci-pull-request.yml +++ b/.github/workflows/ci-pull-request.yml @@ -7,12 +7,18 @@ on: permissions: write-all jobs: - e2e-tests: - uses: ./.github/workflows/e2e-tests.yml - backend-tests: - uses: ./.github/workflows/backend-tests.yml + # e2e-tests: + # uses: ./.github/workflows/e2e-tests.yml + # backend-tests: + # uses: ./.github/workflows/backend-tests.yml build-publish-images: - needs: - - e2e-tests - - backend-tests + # needs: + # - e2e-tests + # - backend-tests uses: ./.github/workflows/docker.yml + deploy-to-kubernetes: + needs: + - build-publish-images + uses: ./.github/workflows/helm.yml + secrets: + KUBECONF: ${{ secrets.KUBECONF }} diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 5ed5b33..274c46b 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -30,45 +30,55 @@ jobs: with: context: ./client push: true - tags: ghcr.io/aet-devops25/team-the-merge-doctors/client:latest + tags: ghcr.io/aet-devops25/team-the-merge-doctors/client:${{ github.sha }} + + - name: Build & push Client image (Kubernetes Production) + uses: docker/build-push-action@v4 + with: + context: ./client + push: true + tags: ghcr.io/aet-devops25/team-the-merge-doctors/client-kubernetes-production:${{ github.sha }} + build-args: | + NODE_ENV=production-kubernetes - name: Build & push GenAI image uses: docker/build-push-action@v4 with: context: ./genai push: true - tags: ghcr.io/aet-devops25/team-the-merge-doctors/genai:latest + tags: ghcr.io/aet-devops25/team-the-merge-doctors/genai:${{ github.sha }} - name: Build & push Ollama image uses: docker/build-push-action@v4 with: context: ./genai/ollama push: true - tags: ghcr.io/aet-devops25/team-the-merge-doctors/ollama:latest + tags: ghcr.io/aet-devops25/team-the-merge-doctors/ollama:${{ github.sha }} - name: Build & push User Service image uses: docker/build-push-action@v4 with: context: ./server/userservice push: true - tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/user-service:latest + tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/user-service:${{ github.sha }} - name: Build & push Mentorship Service image uses: docker/build-push-action@v4 with: context: ./server/mentorshipservice push: true - tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/mentorship-service:latest + tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/mentorship-service:${{ github.sha }} - name: Build & push Rating Service image uses: docker/build-push-action@v4 with: context: ./server/ratingservice push: true - tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/rating-service:latest + tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/rating-service:${{ github.sha }} + - name: Build & push Gateway Service image uses: docker/build-push-action@v4 with: context: ./server/gateway push: true - tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/gateway-service:latest + tags: ghcr.io/aet-devops25/team-the-merge-doctors/server/gateway-service:${{ github.sha }} diff --git a/.github/workflows/e2e-tests.yml b/.github/workflows/e2e-tests.yml index 6f45c3c..8ea5d2f 100644 --- a/.github/workflows/e2e-tests.yml +++ b/.github/workflows/e2e-tests.yml @@ -18,7 +18,7 @@ jobs: - uses: docker/setup-compose-action@v1 name: Setup Docker - + - name: Generate JWT Key run: | ./docker/backend_config_files/jwk-key-generator.sh diff --git a/.github/workflows/helm.yml b/.github/workflows/helm.yml index c10e1fc..049638b 100644 --- a/.github/workflows/helm.yml +++ b/.github/workflows/helm.yml @@ -1,10 +1,10 @@ -name: Manual k8s (Helm) deployment +name: k8s (Helm) deployment on: - workflow_dispatch: - inputs: - open_api_key: - description: "Your Open API key" + workflow_call: + secrets: + KUBECONF: + description: "Base64‑encoded kubeconfig file" required: true jobs: @@ -15,10 +15,10 @@ jobs: uses: actions/checkout@v4 - name: Set up kubectl - uses: azure/setup-kubectl@v3 + uses: azure/setup-kubectl@v4 - name: Set up Helm - uses: azure/setup-helm@v3 + uses: azure/setup-helm@v4 - name: Log in to GHCR uses: docker/login-action@v2 @@ -29,22 +29,25 @@ jobs: - name: Set up kubeconfig run: | - mkdir $HOME/.kube - printf '%s' "${{ secrets.STUDENTKUBECONFIG }}" > $HOME/.kube/config - chmod 600 $HOME/.kube/config + mkdir -p ~/.kube + echo "${{ secrets.KUBECONF }}" | base64 --decode > ~/.kube/config + chmod 600 ~/.kube/config + echo "KUBECONF=~/.kube/config" >> $GITHUB_ENV - - name: Debug kubeconfig - run: | - kubectl config get-contexts - cat $HOME/.kube/config - - # TODO: we are currently just using the latest containers without building them beforehand. Maybe add deployment as step of the pipeline on commits on the main branch - - name: Replace OPEN API key + - name: Set up kubeconfig run: | - cp ./helm/values.yaml.template ./helm/values.yaml - sed -i 's//test/g' ./helm/values.yaml + mkdir -p ~/.kube + echo "$KUBECONF_B64" | base64 --decode > ~/.kube/config + chmod 600 ~/.kube/config + echo "KUBECONF=~/.kube/config" >> $GITHUB_ENV + env: + KUBECONF_B64: ${{ secrets.KUBECONF }} - name: Deploy using Helm + env: + KUBECONF: ${{ runner.home }}/.kube/config run: | helm upgrade --install mentor-pulse ./helm/ \ --namespace team-the-merge-doctors \ + --set tag=${{ github.sha }} \ + --debug diff --git a/.gitignore b/.gitignore index 7211963..74dcd0d 100644 --- a/.gitignore +++ b/.gitignore @@ -376,7 +376,4 @@ sketch ### Vue ### # gitignore template for Vue.js projects # -# Recommended template: Node.gitignore - -# Helm -values.yaml \ No newline at end of file +# Recommended template: Node.gitignore \ No newline at end of file diff --git a/README.md b/README.md index d7a33a6..41547a7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,33 @@ # Mentor Pulse +TODO: short introduction what mentor pulse is + +## Local Development Setup + +TODO: documentation to add for project setup (e.g. how to start with docker) + +``` +docker compose up --build +``` + +``` +docker compose down -v +``` + +### Loading Mock Data + +TODO: add link to mock data scripts + +## Deployment + +TODO: add documentation about deployments + +### Kubernetes + +TODO: add link to kubernetes + +### EC2 + ## Endpoint Documentation The endpoints are documented using OpenAPI or Swagger schemas: @@ -12,6 +40,12 @@ The endpoints are documented using OpenAPI or Swagger schemas: Alternatively, you can also find the endpoints in the controllers of the services (e.g. [MentorProfileController](server/mentorshipservice/src/main/java/com/mentorpulse/mentorshipservice/controller/MentorProfileController.java), [GenAI](genai/controllers/api_controller.py)). Additionally, some are also documented in `.bru` files (see [mentor-pulse-bruno](/docs/mentor-pulse-bruno/)). -## Setup +## Generating Open API Schemas for Microservices -TODO: documentation to add for project setup (e.g. how to start with docker) +This is how you can generate schemas for the Java microservices. For [genai](/genai/README.md) the setup is different. + +1. Start database via `docker compose up --build postgres-db`. +2. Start service via `docker compose up --build ` for which you want to generate the schema. +3. Navigate to service that you want to generate the schema for. Execute `./gradlew generateOpenApiDocs` in root + directory of service. Alternatively, open `http:///v3/api-docs.yaml` in a browser and move the schema to + the correct folder in the service. diff --git a/client/.env b/client/.env new file mode 100644 index 0000000..1c0a237 --- /dev/null +++ b/client/.env @@ -0,0 +1 @@ +MENTORSHIP_SERVICE_PROD_URL=http://mentorship- \ No newline at end of file diff --git a/client/Dockerfile b/client/Dockerfile index e78d894..f2bd7af 100644 --- a/client/Dockerfile +++ b/client/Dockerfile @@ -13,6 +13,9 @@ RUN pnpm install --frozen-lockfile COPY . . +ARG NODE_ENV=development +ENV NODE_ENV=${NODE_ENV} + RUN pnpm run build # Stage 2 @@ -27,6 +30,9 @@ COPY --from=build /app/dist ./dist EXPOSE 3000 +ARG NODE_ENV=development +ENV NODE_ENV=${NODE_ENV} + CMD ["serve", "-s", "dist", "-l", "3000"] diff --git a/client/README.md b/client/README.md index 671d126..e58e2de 100644 --- a/client/README.md +++ b/client/README.md @@ -31,7 +31,7 @@ The client is tested using E2E/UI tests. We use playwright as the framework for 3. Run Tests: `pnpm exec playwright test` 4. Show Report: `pnpm exec playwright show-report` -## Execute tests with UI +### Execute tests with UI Alternatively, you can also execute the tests using a UI. diff --git a/client/src/main.tsx b/client/src/main.tsx index de03e06..b14c371 100644 --- a/client/src/main.tsx +++ b/client/src/main.tsx @@ -24,8 +24,16 @@ declare module '@tanstack/react-router' { } } +if (process.env.NODE_ENV === 'production-kubernetes') { + axios.defaults.baseURL = + 'https://mentor-pulse-devops25.student.k8s.aet.cit.tum.de'; +} else { + axios.defaults.baseURL = 'http://localhost:80'; +} + axios.interceptors.request.use( (config) => { + console.log('Base URL:', axios.defaults.baseURL); const token = localStorage.getItem('token'); if (token) { const parsedToken = JSON.parse(token); diff --git a/compose.yml b/compose.yml index 6afa8e5..f3a7b8a 100644 --- a/compose.yml +++ b/compose.yml @@ -38,9 +38,8 @@ services: platform: linux/amd64 image: ghcr.io/aet-devops25/team-the-merge-doctors/ollama:latest build: - context: ./genai/ollama + context: genai/ollama dockerfile: Dockerfile - container_name: ollama ports: - "11434:11434" volumes: diff --git a/docs/mentor-pulse-bruno/production-kubernetes/folder.bru b/docs/mentor-pulse-bruno/production-kubernetes/folder.bru new file mode 100644 index 0000000..83d564b --- /dev/null +++ b/docs/mentor-pulse-bruno/production-kubernetes/folder.bru @@ -0,0 +1,8 @@ +meta { + name: production-kubernetes + seq: 5 +} + +auth { + mode: inherit +} diff --git a/docs/mentor-pulse-bruno/production-kubernetes/genai.bru b/docs/mentor-pulse-bruno/production-kubernetes/genai.bru new file mode 100644 index 0000000..3c16d77 --- /dev/null +++ b/docs/mentor-pulse-bruno/production-kubernetes/genai.bru @@ -0,0 +1,17 @@ +meta { + name: genai + type: http + seq: 1 +} + +post { + url: https://mentor-pulse-devops25.student.k8s.aet.cit.tum.de/api/genai/summarize + body: json + auth: inherit +} + +body:json { + { + "textToSummarize": 'test', + } +} diff --git a/genai/ollama/Dockerfile b/genai/ollama/Dockerfile index be28155..82b42dd 100644 --- a/genai/ollama/Dockerfile +++ b/genai/ollama/Dockerfile @@ -5,4 +5,6 @@ RUN ollama serve & \ ollama pull llama3.2 && \ pkill ollama +EXPOSE 11434 + ENTRYPOINT ["ollama", "serve"] \ No newline at end of file diff --git a/genai/utils/langchain_utils.py b/genai/utils/langchain_utils.py index 5b5b36d..44321e8 100644 --- a/genai/utils/langchain_utils.py +++ b/genai/utils/langchain_utils.py @@ -10,7 +10,7 @@ def _get_llm(): """Get Ollama LLM instance""" try: - base_url = os.getenv('OLLAMA_BASE_URL', 'http://localhost:11434') + base_url = os.getenv('OLLAMA_BASE_URL', 'http://ollama-service:11434') return OllamaLLM(model="llama3.2", base_url=base_url) except Exception as e: logger.error(f"Failed to initialize Ollama LLM: {e}") diff --git a/helm/README.md b/helm/README.md index 10cf419..d3be368 100644 --- a/helm/README.md +++ b/helm/README.md @@ -5,14 +5,51 @@ 1. Download kube config file from cluster. 2. Place it at `~/.kube/config` -## Project Setup +## Deploy -1. Copy `values.yaml.template` and rename it to `values.yaml`. +Run the following commands in this directory to deploy the application to the cluster. +The first two commands only need to be executed once. -## Deploy +1. Generate JWT secret key + +``` +../docker/backend_config_files/jwk-key-generator.sh +``` + +2. Create Secret in Kubernetes + +``` +kubectl create secret generic jwt-secret \ + --from-file=jwt-secret.key=/jwt-secret.key \ + -n +``` + +3. Deploy to cluster + +``` +helm upgrade --install mentor-pulse . --namespace team-the-merge-doctors --set tag= +``` + +## Remove Deployment + +To remove the deployment and delete everything from cluster (expect secrets and configs), execute the following command. + +``` +kubectl delete all --all -n team-the-merge-doctors +``` + +## Debugging + +Some helpful commands for debugging. + +Inspect the logs of a pod. + +``` +kubectl logs -n team-the-merge-doctors +``` -Run the following command in this directory to deploy the application to the cluster. +ssh into a pod. ``` -helm upgrade --install mentor-pulse . --namespace team-the-merge-doctors +kubectl exec -it -n team-the-merge-doctors -- /bin/sh ``` diff --git a/helm/templates/configmap.yaml b/helm/templates/configmaps/backend-environment-config.yaml similarity index 87% rename from helm/templates/configmap.yaml rename to helm/templates/configmaps/backend-environment-config.yaml index bde28ed..4e1308a 100644 --- a/helm/templates/configmap.yaml +++ b/helm/templates/configmaps/backend-environment-config.yaml @@ -5,6 +5,6 @@ metadata: data: FLASK_ENV: development FLASK_APP: app.py - POSTGRES_HOST: db + POSTGRES_HOST: postgres-db POSTGRES_PORT: "5432" POSTGRES_GEN_AI_DB: genai_backend \ No newline at end of file diff --git a/helm/templates/configmaps/postgres-hba-config.yaml b/helm/templates/configmaps/postgres-hba-config.yaml new file mode 100644 index 0000000..e0221a2 --- /dev/null +++ b/helm/templates/configmaps/postgres-hba-config.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-hba-config +data: + pg_hba.conf: | + # "local" is for Unix domain socket connections only + local all postgres trust + local all all md5 + # IPv4 local connections: + host all postgres 127.0.0.1/32 trust + host all all 127.0.0.1/32 md5 + # IPv6 local connections: + host all postgres ::1/128 trust + host all all ::1/128 md5 + # Allow replication connections from localhost, by a user with the + # replication privilege. + local replication all trust + host replication all 127.0.0.1/32 trust + host replication all ::1/128 trust + + host all all all md5 \ No newline at end of file diff --git a/helm/templates/configmaps/postgres-init-config.yaml b/helm/templates/configmaps/postgres-init-config.yaml new file mode 100644 index 0000000..81ab1ae --- /dev/null +++ b/helm/templates/configmaps/postgres-init-config.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: postgres-init-script +data: + init.sh: | + #!/bin/bash + set -e + echo "Using PGDATA=$PGDATA" + + # backup existing HBA config + cp "$PGDATA/pg_hba.conf" "$PGDATA/pg_hba.conf.bak" + + pg_ctl -D "$PGDATA" reload + + psql -v ON_ERROR_STOP=1 <<-EOSQL + CREATE USER merge_doctor_backend WITH PASSWORD 'qweasdzxc'; + CREATE DATABASE genai_backend WITH OWNER merge_doctor_backend; + CREATE DATABASE user_backend WITH OWNER merge_doctor_backend; + CREATE DATABASE rating_backend WITH OWNER merge_doctor_backend; + CREATE DATABASE mentorship_backend WITH OWNER merge_doctor_backend; + GRANT ALL PRIVILEGES ON DATABASE genai_backend TO merge_doctor_backend; + \c genai_backend + + GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO merge_doctor_backend; + GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO merge_doctor_backend; + GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO merge_doctor_backend; + GRANT ALL PRIVILEGES ON DATABASE user_backend TO merge_doctor_backend; + GRANT ALL PRIVILEGES ON DATABASE rating_backend TO merge_doctor_backend; + GRANT ALL PRIVILEGES ON DATABASE mentorship_backend TO merge_doctor_backend; + EOSQL \ No newline at end of file diff --git a/helm/templates/deployments/client-deployment.yaml b/helm/templates/deployments/client-deployment.yaml index c39ecfc..014332f 100644 --- a/helm/templates/deployments/client-deployment.yaml +++ b/helm/templates/deployments/client-deployment.yaml @@ -15,14 +15,10 @@ spec: spec: containers: - name: client - image: "{{ .Values.client.image.repository }}:{{ .Values.client.image.tag }}" + image: "{{ .Values.client.image.repository }}:{{ .Values.tag }}" imagePullPolicy: {{ .Values.client.image.pullPolicy }} - resources: - limits: - cpu: "500m" - memory: "256Mi" - requests: - cpu: "50m" - memory: "50Mi" ports: - containerPort: {{ .Values.client.service.targetPort }} + env: + - name: NODE_ENV + value: production-kubernetes diff --git a/helm/templates/deployments/database-deployment.yaml b/helm/templates/deployments/database-deployment.yaml index 1931558..e2d23c2 100644 --- a/helm/templates/deployments/database-deployment.yaml +++ b/helm/templates/deployments/database-deployment.yaml @@ -1 +1,44 @@ -# TODO: add database deployment \ No newline at end of file +apiVersion: apps/v1 +kind: Deployment +metadata: + name: postgres-db-deployment + namespace: {{ .Values.namespace }} +spec: + replicas: 1 + selector: + matchLabels: + app: {{ .Values.postgresDb.selector }} + template: + metadata: + labels: + app: {{ .Values.postgresDb.selector }} + spec: + containers: + - name: postgres-db-container + image: postgres:15 + ports: + - containerPort: 5432 + envFrom: + - configMapRef: + name: {{ .Values.backendEnvironmentConfigMapName }} + - secretRef: + name: {{ .Values.secretsName }} + volumeMounts: + # - name: {{ .Values.postgresDb.dataVolumeName }} + # mountPath: /var/lib/postgresql/data + - name: postgres-init-script + mountPath: /docker-entrypoint-initdb.d/init.sh + subPath: init.sh + - name: postgres-hba-config + mountPath: /etc/postgresql/pg_hba.conf + subPath: pg_hba.conf + volumes: + # - name: {{ .Values.postgresDb.dataVolumeName }} + # persistentVolumeClaim: + # claimName: {{ .Values.postgresDb.persistentVolume }} + - name: postgres-init-script + configMap: + name: postgres-init-script + - name: postgres-hba-config + configMap: + name: postgres-hba-config \ No newline at end of file diff --git a/helm/templates/deployments/genai-microservice-deployment.yaml b/helm/templates/deployments/genai-microservice-deployment.yaml index e0c47b0..4b3709b 100644 --- a/helm/templates/deployments/genai-microservice-deployment.yaml +++ b/helm/templates/deployments/genai-microservice-deployment.yaml @@ -15,18 +15,14 @@ spec: spec: containers: - name: genai-microservice-container - image: "{{ .Values.genaiMicroservice.image.repository }}:{{ .Values.genaiMicroservice.image.tag }}" + image: "{{ .Values.genaiMicroservice.image.repository }}:{{ .Values.tag }}" imagePullPolicy: {{ .Values.genaiMicroservice.image.pullPolicy }} - resources: - limits: - cpu: "500m" - memory: "256Mi" - requests: - cpu: "50m" - memory: "50Mi" ports: - containerPort: {{ .Values.genaiMicroservice.service.targetPort }} + env: + - name: OLLAMA_BASE_URL + value: "http://{{ .Values.ollama.service.name }}:11434" envFrom: - configMapRef: name: {{ .Values.backendEnvironmentConfigMapName }} diff --git a/helm/templates/deployments/mentorship-microservice-deployment.yaml b/helm/templates/deployments/mentorship-microservice-deployment.yaml new file mode 100644 index 0000000..b847de1 --- /dev/null +++ b/helm/templates/deployments/mentorship-microservice-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mentorship-microservice-deployment + namespace: {{ .Values.namespace }} +spec: + replicas: {{ .Values.mentorshipMicroservice.replicaCount }} + selector: + matchLabels: + app: {{ .Values.mentorshipMicroservice.selector }} + template: + metadata: + labels: + app: {{ .Values.mentorshipMicroservice.selector }} + spec: + containers: + - name: user-microservice-container + image: "{{ .Values.mentorshipMicroservice.image.repository }}:{{ .Values.tag }}" + imagePullPolicy: {{ .Values.mentorshipMicroservice.image.pullPolicy }} + ports: + - containerPort: {{ .Values.mentorshipMicroservice.service.targetPort }} + env: + - name: SPRING_PROFILES_ACTIVE + value: kubernetes + envFrom: + - configMapRef: + name: {{ .Values.backendEnvironmentConfigMapName }} + - secretRef: + name: {{ .Values.secretsName }} \ No newline at end of file diff --git a/helm/templates/deployments/ollama-deployment.yaml b/helm/templates/deployments/ollama-deployment.yaml new file mode 100644 index 0000000..7198634 --- /dev/null +++ b/helm/templates/deployments/ollama-deployment.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ollama-deployment + namespace: {{ .Values.namespace }} +spec: + replicas: {{ .Values.ollama.replicaCount }} + selector: + matchLabels: + app: {{ .Values.ollama.selector }} + template: + metadata: + labels: + app: {{ .Values.ollama.selector }} + spec: + containers: + - name: ollama-container + image: "{{ .Values.ollama.image.repository }}:{{ .Values.tag }}" + imagePullPolicy: {{ .Values.ollama.image.pullPolicy }} + ports: + - containerPort: {{ .Values.ollama.service.targetPort }} \ No newline at end of file diff --git a/helm/templates/deployments/rating-microservice-deployment.yaml b/helm/templates/deployments/rating-microservice-deployment.yaml new file mode 100644 index 0000000..e211d41 --- /dev/null +++ b/helm/templates/deployments/rating-microservice-deployment.yaml @@ -0,0 +1,26 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: rating-microservice-deployment + namespace: {{ .Values.namespace }} +spec: + replicas: {{ .Values.ratingMicroservice.replicaCount }} + selector: + matchLabels: + app: {{ .Values.ratingMicroservice.selector }} + template: + metadata: + labels: + app: {{ .Values.ratingMicroservice.selector }} + spec: + containers: + - name: user-microservice-container + image: "{{ .Values.ratingMicroservice.image.repository }}:{{ .Values.tag }}" + imagePullPolicy: {{ .Values.ratingMicroservice.image.pullPolicy }} + ports: + - containerPort: {{ .Values.ratingMicroservice.service.targetPort }} + envFrom: + - configMapRef: + name: {{ .Values.backendEnvironmentConfigMapName }} + - secretRef: + name: {{ .Values.secretsName }} \ No newline at end of file diff --git a/helm/templates/deployments/user-microservice-service.yaml b/helm/templates/deployments/user-microservice-deployment.yaml similarity index 71% rename from helm/templates/deployments/user-microservice-service.yaml rename to helm/templates/deployments/user-microservice-deployment.yaml index 80530fe..531bc12 100644 --- a/helm/templates/deployments/user-microservice-service.yaml +++ b/helm/templates/deployments/user-microservice-deployment.yaml @@ -15,19 +15,20 @@ spec: spec: containers: - name: user-microservice-container - image: "{{ .Values.userMicroservice.image.repository }}:{{ .Values.userMicroservice.image.tag }}" + image: "{{ .Values.userMicroservice.image.repository }}:{{ .Values.tag }}" imagePullPolicy: {{ .Values.userMicroservice.image.pullPolicy }} - resources: - limits: - cpu: "500m" - memory: "256Mi" - requests: - cpu: "50m" - memory: "50Mi" ports: - containerPort: {{ .Values.userMicroservice.service.targetPort }} envFrom: - configMapRef: name: {{ .Values.backendEnvironmentConfigMapName }} - secretRef: - name: {{ .Values.secretsName }} \ No newline at end of file + name: {{ .Values.secretsName }} + volumeMounts: + - name: jwt-secret-volume + mountPath: /home/cnf/mentorpulse-certificates + readOnly: true + volumes: + - name: jwt-secret-volume + secret: + secretName: jwt-secret \ No newline at end of file diff --git a/helm/templates/ingress.yaml b/helm/templates/ingress.yaml index 9adf006..a4f7826 100644 --- a/helm/templates/ingress.yaml +++ b/helm/templates/ingress.yaml @@ -1 +1,63 @@ -# TODO: add ingress \ No newline at end of file +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: mentor-pulse-ingress + namespace: {{ .Values.namespace }} + {{- $annotations := .Values.ingress.annotations | default dict }} + {{- if $annotations }} + annotations: + {{- toYaml $annotations | nindent 4 }} + {{- end }} +spec: + {{- if .Values.ingress.tls }} + tls: + - hosts: + - {{ .Values.ingress.host }} + secretName: "mentor-pulse-tls" + {{- end }} + rules: + - host: {{ .Values.ingress.host }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ .Values.client.service.name }} + port: + number: {{ .Values.client.service.port }} + - path: /api/mentorship + pathType: Prefix + backend: + service: + name: {{ .Values.mentorshipMicroservice.service.name }} + port: + number: {{ .Values.mentorshipMicroservice.service.port }} + - path: /api/user + pathType: Prefix + backend: + service: + name: {{ .Values.userMicroservice.service.name }} + port: + number: {{ .Values.userMicroservice.service.port }} + - path: /api/rating + pathType: Prefix + backend: + service: + name: {{ .Values.ratingMicroservice.service.name }} + port: + number: {{ .Values.ratingMicroservice.service.port }} + - path: /api/genai + pathType: Prefix + backend: + service: + name: {{ .Values.genaiMicroservice.service.name }} + port: + number: {{ .Values.genaiMicroservice.service.port }} + - path: /api/generate + pathType: Prefix + backend: + service: + name: {{ .Values.ollama.service.name }} + port: + number: {{ .Values.ollama.service.port }} \ No newline at end of file diff --git a/helm/templates/services/client-service.yaml b/helm/templates/services/client-service.yaml index 31fc68a..b0fb757 100644 --- a/helm/templates/services/client-service.yaml +++ b/helm/templates/services/client-service.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: client-service + name: {{ .Values.client.service.name }} namespace: {{ .Values.namespace }} spec: selector: diff --git a/helm/templates/services/database-service.yaml b/helm/templates/services/database-service.yaml index 4eec7bf..78f2671 100644 --- a/helm/templates/services/database-service.yaml +++ b/helm/templates/services/database-service.yaml @@ -1 +1,13 @@ -# TODO: add database service \ No newline at end of file +apiVersion: v1 +kind: Service +metadata: + name: postgres-db + namespace: {{ .Values.namespace }} +spec: + selector: + app: {{ .Values.postgresDb.selector }} + ports: + - port: {{ .Values.postgresDb.port }} + targetPort: {{ .Values.postgresDb.port }} + protocol: TCP + type: ClusterIP \ No newline at end of file diff --git a/helm/templates/services/genai-microservice-service.yaml b/helm/templates/services/genai-microservice-service.yaml index 7c1ec93..085d1bf 100644 --- a/helm/templates/services/genai-microservice-service.yaml +++ b/helm/templates/services/genai-microservice-service.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: genai-service + name: {{ .Values.genaiMicroservice.service.name }} namespace: {{ .Values.namespace }} spec: selector: diff --git a/helm/templates/services/mentorship-microservice-service.yaml b/helm/templates/services/mentorship-microservice-service.yaml new file mode 100644 index 0000000..4d9e3c2 --- /dev/null +++ b/helm/templates/services/mentorship-microservice-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.mentorshipMicroservice.service.name }} + namespace: {{ .Values.namespace }} +spec: + selector: + app: {{ .Values.mentorshipMicroservice.selector }} + ports: + - port: {{ .Values.mentorshipMicroservice.service.port }} + targetPort: {{ .Values.mentorshipMicroservice.service.targetPort }} + protocol: TCP + type: {{ .Values.mentorshipMicroservice.service.type }} diff --git a/helm/templates/services/ollama-service.yaml b/helm/templates/services/ollama-service.yaml new file mode 100644 index 0000000..33c8a35 --- /dev/null +++ b/helm/templates/services/ollama-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.ollama.service.name }} + namespace: {{ .Values.namespace }} +spec: + selector: + app: {{ .Values.ollama.selector }} + ports: + - port: {{ .Values.ollama.service.port }} + targetPort: {{ .Values.ollama.service.targetPort }} + protocol: TCP + type: {{ .Values.ollama.service.type }} \ No newline at end of file diff --git a/helm/templates/services/rating-microservice-service.yaml b/helm/templates/services/rating-microservice-service.yaml new file mode 100644 index 0000000..92f0589 --- /dev/null +++ b/helm/templates/services/rating-microservice-service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.ratingMicroservice.service.name }} + namespace: {{ .Values.namespace }} +spec: + selector: + app: {{ .Values.ratingMicroservice.selector }} + ports: + - port: {{ .Values.ratingMicroservice.service.port }} + targetPort: {{ .Values.ratingMicroservice.service.targetPort }} + protocol: TCP + type: {{ .Values.ratingMicroservice.service.type }} diff --git a/helm/templates/services/user-microservice-service.yaml b/helm/templates/services/user-microservice-service.yaml index cc721d8..cfdd807 100644 --- a/helm/templates/services/user-microservice-service.yaml +++ b/helm/templates/services/user-microservice-service.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Service metadata: - name: user-microservice-service + name: {{ .Values.userMicroservice.service.name }} namespace: {{ .Values.namespace }} spec: selector: diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..0bcfc4b --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,97 @@ +namespace: team-the-merge-doctors + +userMicroservice: + image: + repository: ghcr.io/aet-devops25/team-the-merge-doctors/server/user-service + pullPolicy: Always + service: + type: ClusterIP + port: 8210 + targetPort: 8210 + name: user-microservice-service + selector: user-microservice-selector + replicaCount: 1 + +mentorshipMicroservice: + image: + repository: ghcr.io/aet-devops25/team-the-merge-doctors/server/mentorship-service + pullPolicy: Always + service: + type: ClusterIP + port: 8310 + targetPort: 8310 + name: mentorship-microservice-service + selector: mentorship-microservice-selector + replicaCount: 1 + +ratingMicroservice: + image: + repository: ghcr.io/aet-devops25/team-the-merge-doctors/server/rating-service + pullPolicy: Always + service: + type: ClusterIP + port: 8410 + targetPort: 8410 + name: rating-microservice-service + selector: rating-microservice-selector + replicaCount: 1 + +genaiMicroservice: + image: + repository: ghcr.io/aet-devops25/team-the-merge-doctors/genai + pullPolicy: Always + service: + type: ClusterIP + port: 5001 + targetPort: 5001 + name: genai + selector: genai-microservice-selector + replicaCount: 1 + +client: + image: + repository: ghcr.io/aet-devops25/team-the-merge-doctors/client-kubernetes-production + pullPolicy: Always + service: + type: ClusterIP + port: 3000 + targetPort: 3000 + name: client-microservice-service + replicaCount: 1 + selector: client-selector + +postgresDb: + selector: postgres-db + persistentVolume: postgres-persistent-volume + replicaCount: 1 + port: 5432 + dataVolumeName: postgresdata + +ingress: + enabled: true + className: "nginx" + host: mentor-pulse-devops25.student.k8s.aet.cit.tum.de + tls: true + annotations: + cert-manager.io/cluster-issuer: "letsencrypt-prod" + +ollama: + image: + repository: ghcr.io/aet-devops25/team-the-merge-doctors/ollama + pullPolicy: Always + service: + type: ClusterIP + port: 11434 + targetPort: 11434 + name: ollama-service + selector: ollama-selector + replicaCount: 1 + +tag: latest + +secrets: + postgresUser: postgres + postgresPassword: postgres_password + +backendEnvironmentConfigMapName: backend-environment-config-map +secretsName: secrets diff --git a/helm/values.yaml.template b/helm/values.yaml.template deleted file mode 100644 index 5f3334f..0000000 --- a/helm/values.yaml.template +++ /dev/null @@ -1,44 +0,0 @@ -namespace: team-the-merge-doctors - -userMicroservice: - image: - repository: ghcr.io/aet-devops25/team-the-merge-doctors/server/user-service - tag: latest - pullPolicy: Always - service: - type: ClusterIP - port: 8210 - targetPort: 8210 - selector: user-microservice-selector - replicaCount: 1 - -genaiMicroservice: - image: - repository: ghcr.io/aet-devops25/team-the-merge-doctors/genai - tag: latest - pullPolicy: Always - service: - type: ClusterIP - port: 5001 - targetPort: 5001 - selector: genai-microservice-selector - replicaCount: 1 - -client: - image: - repository: ghcr.io/aet-devops25/team-the-merge-doctors/client - tag: latest - pullPolicy: Always - service: - type: ClusterIP - port: 3000 - targetPort: 80 - replicaCount: 1 - selector: client-selector - -secrets: - postgresUser: postgres - postgresPassword: postgres_password - -backendEnvironmentConfigMapName: backend-environment-config-map -secretsName: secrets diff --git a/server/README.md b/server/README.md deleted file mode 100644 index b3e09b4..0000000 --- a/server/README.md +++ /dev/null @@ -1,7 +0,0 @@ -## Generating Open API Schemas - -1. Start database via `docker compose up --build postgres-db`. -2. Start service via `docker compose up --build ` for which you want to generate the schema. -3. Navigate to service that you want to generate the schema for. Execute `./gradlew generateOpenApiDocs` in root - directory of service. Alternatively, open `http:///v3/api-docs.yaml` in a browser and move the schema to - the correct folder in the service. diff --git a/server/mentorshipservice/src/main/java/com/mentorpulse/mentorshipservice/config/LlmClientConfig.java b/server/mentorshipservice/src/main/java/com/mentorpulse/mentorshipservice/config/LlmClientConfig.java index cc91a67..2299274 100644 --- a/server/mentorshipservice/src/main/java/com/mentorpulse/mentorshipservice/config/LlmClientConfig.java +++ b/server/mentorshipservice/src/main/java/com/mentorpulse/mentorshipservice/config/LlmClientConfig.java @@ -9,6 +9,9 @@ @Configuration public class LlmClientConfig { + @Value("${genai.http-secured:false}") + private boolean genaiHttpSecured; + @Value("${genai.host}") private String host; @@ -17,7 +20,12 @@ public class LlmClientConfig { @Bean public RestTemplate restTemplate(RestTemplateBuilder builder) { - String url = String.format("http://%s:%s/api", host, port); + String url; + if (genaiHttpSecured) { + url = String.format("https://%s/api/genai", host); + } else { + url = String.format("http://%s:%s/api/genai", host, port); + } System.out.println(url); return builder .rootUri(url) diff --git a/server/mentorshipservice/src/main/resources/application-dev.yaml b/server/mentorshipservice/src/main/resources/application-dev.yaml index c5c40fe..93d2960 100644 --- a/server/mentorshipservice/src/main/resources/application-dev.yaml +++ b/server/mentorshipservice/src/main/resources/application-dev.yaml @@ -2,6 +2,7 @@ postgres: ip: localhost genai: + http-secured: false host: localhost spring: diff --git a/server/mentorshipservice/src/main/resources/application-kubernetes.yaml b/server/mentorshipservice/src/main/resources/application-kubernetes.yaml new file mode 100644 index 0000000..c04229d --- /dev/null +++ b/server/mentorshipservice/src/main/resources/application-kubernetes.yaml @@ -0,0 +1,4 @@ +genai: + http-secured: true + host: mentor-pulse-devops25.student.k8s.aet.cit.tum.de + diff --git a/server/mentorshipservice/src/main/resources/application.yaml b/server/mentorshipservice/src/main/resources/application.yaml index 75d19b0..cf85e40 100644 --- a/server/mentorshipservice/src/main/resources/application.yaml +++ b/server/mentorshipservice/src/main/resources/application.yaml @@ -6,6 +6,7 @@ postgres: db-name: mentorship_backend genai: + http-secured: false host: genai port: 5001 diff --git a/server/scripts/README.md b/server/scripts/README.md index aa17a52..f015f03 100644 --- a/server/scripts/README.md +++ b/server/scripts/README.md @@ -1,5 +1,9 @@ # Generate Users and Load Users Script +TODO: give overview of scripts + +TODO: use same mock data as in [client tests](../../client/tests/resources/) + ## Installation 1. Create a virtual environment diff --git a/server/scripts/mock_mentor_profiles/load_mock_profiles.py b/server/scripts/mock_mentor_profiles/load_mock_profiles.py index 44fd32f..2c1bdfc 100644 --- a/server/scripts/mock_mentor_profiles/load_mock_profiles.py +++ b/server/scripts/mock_mentor_profiles/load_mock_profiles.py @@ -4,7 +4,7 @@ from pathlib import Path # Change the endpoint if it will be used for production -BASE_URL = "http://localhost:8310/api/mentorship" +BASE_URL = "http://localhost/api/mentorship" BASE_URL ENDPOINTS = { "skill": f"{BASE_URL}/createSkill",