From ed8cba13a74b345cce8267241f3c9cb1d09be8cc Mon Sep 17 00:00:00 2001 From: Isaac Johnson Date: Wed, 18 Jun 2025 07:05:24 -0500 Subject: [PATCH] Docker, Helm and Gitea Workflow --- .gitea/workflows/cicd.yaml | 19 +++++++++ Dockerfile | 27 ++++++++++++ helm/logingest/Chart.yaml | 5 +++ helm/logingest/templates/deployment.yaml | 44 +++++++++++++++++++ helm/logingest/templates/ingress.yaml | 39 +++++++++++++++++ helm/logingest/templates/service.yaml | 15 +++++++ helm/logingest/values.yaml | 54 ++++++++++++++++++++++++ server.js | 4 +- services/logService.js | 11 +++-- utils/validation.js | 8 ++-- 10 files changed, 217 insertions(+), 9 deletions(-) create mode 100644 .gitea/workflows/cicd.yaml create mode 100644 Dockerfile create mode 100644 helm/logingest/Chart.yaml create mode 100644 helm/logingest/templates/deployment.yaml create mode 100644 helm/logingest/templates/ingress.yaml create mode 100644 helm/logingest/templates/service.yaml create mode 100644 helm/logingest/values.yaml diff --git a/.gitea/workflows/cicd.yaml b/.gitea/workflows/cicd.yaml new file mode 100644 index 0000000..c537cc6 --- /dev/null +++ b/.gitea/workflows/cicd.yaml @@ -0,0 +1,19 @@ +name: Gitea Actions Demo +run-name: ${{ gitea.actor }} is testing out Gitea Actions 🚀 +on: [push] + +jobs: + Explore-Gitea-Actions: + runs-on: ubuntu-latest + steps: + - run: echo "🎉 The job was automatically triggered by a ${{ gitea.event_name }} event." + - run: echo "🐧 This job is now running on a ${{ runner.os }} server hosted by Gitea!" + - run: echo "🔎 The name of your branch is ${{ gitea.ref }} and your repository is ${{ gitea.repository }}." + - name: Check out repository code + uses: actions/checkout@v4 + - run: echo "💡 The ${{ gitea.repository }} repository has been cloned to the runner." + - run: echo "🖥️ The workflow is now ready to test your code on the runner." + - name: List files in the repository + run: | + ls ${{ gitea.workspace }} + - run: echo "🍏 This job's status is ${{ job.status }}." diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..d290d86 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM node:20-slim + +WORKDIR /app + +# Copy package files +COPY package*.json ./ + +# Install dependencies +RUN npm install --production + +# Copy application code +COPY . . + +# Environment variables with defaults +ENV PORT=3000 \ + DB_HOST=postgres-svc \ + DB_PORT=5432 \ + DB_NAME=logapp \ + DB_USER=postgres \ + DB_PASSWORD=postgrespass \ + DB_SSL=false \ + AUTH_USERNAME=admin \ + AUTH_PASSWORD=password123 + +EXPOSE 3000 + +CMD ["node", "server.js"] \ No newline at end of file diff --git a/helm/logingest/Chart.yaml b/helm/logingest/Chart.yaml new file mode 100644 index 0000000..cae5abf --- /dev/null +++ b/helm/logingest/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: logingest +description: Log ingestion microservice +version: 0.1.0 +appVersion: "1.0.0" \ No newline at end of file diff --git a/helm/logingest/templates/deployment.yaml b/helm/logingest/templates/deployment.yaml new file mode 100644 index 0000000..1bb530b --- /dev/null +++ b/helm/logingest/templates/deployment.yaml @@ -0,0 +1,44 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "logingest.fullname" . }} + labels: + {{- include "logingest.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "logingest.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "logingest.selectorLabels" . | nindent 8 }} + spec: + serviceAccountName: {{ include "logingest.serviceAccountName" . }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: logport + containerPort: {{ .values.app.port }} + protocol: TCP + env: + - name: DB_HOST + value: "{{ .Values.db.host }}" + - name: DB_PORT + value: "{{ .Values.db.port }}" + - name: DB_NAME + value: {{ .Values.db.database }} + - name: DB_USER + value: {{ .Values.db.user }} + - name: DB_SSL + value: {{ .Values.db.ssl | quote }} + - name: DB_PASSWORD + value: {{ .Values.db.password | quote }} + {{- range $key, $value := .Values.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} \ No newline at end of file diff --git a/helm/logingest/templates/ingress.yaml b/helm/logingest/templates/ingress.yaml new file mode 100644 index 0000000..f1e833c --- /dev/null +++ b/helm/logingest/templates/ingress.yaml @@ -0,0 +1,39 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "logingest.fullname" . }} + labels: + {{- include "logingest.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + ingressClassName: {{ .Values.ingress.className }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + pathType: {{ .pathType }} + backend: + service: + name: {{ include "logingest.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/helm/logingest/templates/service.yaml b/helm/logingest/templates/service.yaml new file mode 100644 index 0000000..5256030 --- /dev/null +++ b/helm/logingest/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "logingest.fullname" . }} + labels: + {{- include "logingest.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: {{ .values.app.port }} + protocol: TCP + name: logport + selector: + {{- include "logingest.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/helm/logingest/values.yaml b/helm/logingest/values.yaml new file mode 100644 index 0000000..a8a8145 --- /dev/null +++ b/helm/logingest/values.yaml @@ -0,0 +1,54 @@ +replicaCount: 1 + +image: + repository: logingest + pullPolicy: IfNotPresent + tag: "latest" + +nameOverride: "" +fullnameOverride: "" + +app: + port: 3000 + +serviceAccount: + create: true + name: "" + +service: + type: ClusterIP + port: 3000 + +ingress: + enabled: false + className: "nginx" + annotations: + kubernetes.io/ingress.class: nginx + # nginx.ingress.kubernetes.io/rewrite-target: / + hosts: + - host: chart-example.local + paths: + - path: / + pathType: Prefix + +resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 100m + memory: 128Mi + +db: + host: localhost + database: logapp + user: postgres + password: postgrespass + port: 5432 + ssl: false + persistence: + enabled: false + +env: + AUTH_USERNAME: admin + AUTH_PASSWORD: password123 \ No newline at end of file diff --git a/server.js b/server.js index 2adac98..eba6384 100644 --- a/server.js +++ b/server.js @@ -29,11 +29,11 @@ try { // Create logs table if it doesn't exist await client.query(` CREATE TABLE IF NOT EXISTS logs ( - id bigint PRIMARY KEY, + id varchar(20) PRIMARY KEY, body text NOT NULL, project text NOT NULL DEFAULT 'Project 1', type text NOT NULL DEFAULT 'Info', - date date NOT NULL, + date text NOT NULL, avatar_src text NOT NULL DEFAULT '/rectangle-15.png', owner text NOT NULL DEFAULT 'N/A', description text NOT NULL, diff --git a/services/logService.js b/services/logService.js index 18e0f13..c2c4816 100644 --- a/services/logService.js +++ b/services/logService.js @@ -4,8 +4,8 @@ export async function createLogEntry(client, data) { // Create log entry with defaults const logEntry = { - id: epochTime, - body: data.message.substring(0, 200), // First 200 characters + id: epochTime.toString(), + body: data.body, // Changed from body to message project: data.project || 'Project 1', type: data.type || 'Info', date: now.toISOString().split('T')[0], // YYYY-MM-DD format @@ -37,6 +37,10 @@ export async function createLogEntry(client, data) { ]; try { + // Log the query and values before execution + console.log('Executing SQL:', query); + console.log('With values:', values); + const result = await client.query(query, values); const insertedData = result.rows[0]; @@ -52,4 +56,5 @@ export async function createLogEntry(client, data) { console.error('Database error:', error); throw new Error(`Failed to insert log entry: ${error.message}`); } -} \ No newline at end of file +} + diff --git a/utils/validation.js b/utils/validation.js index 6c1bedb..65581a5 100644 --- a/utils/validation.js +++ b/utils/validation.js @@ -8,10 +8,10 @@ export function validateLogData(data) { } // Validate required message field - if (!data.message || typeof data.message !== 'string') { - errors.push('message field is required and must be a string'); - } else if (data.message.trim().length === 0) { - errors.push('message field cannot be empty'); + if (!data.body || typeof data.body !== 'string') { + errors.push('body field is required and must be a string'); + } else if (data.body.trim().length === 0) { + errors.push('body field cannot be empty'); } // Validate optional fields if provided