Skip to content

Commit

Permalink
feat(api): postgresql, prisma, helm, etc...
Browse files Browse the repository at this point in the history
  • Loading branch information
marcolongol committed Aug 20, 2024
1 parent 5abf707 commit b1ba3d7
Show file tree
Hide file tree
Showing 29 changed files with 1,609 additions and 180 deletions.
29 changes: 25 additions & 4 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,16 @@ print(
""".strip()
)

config.define_string("env", False, "The environment to deploy to")

VALUES_DICT = {
"LOCAL": "./chart/values-local.yaml",
"DEV": "./chart/values-dev.yaml",
"STAGING": "./chart/values-staging.yaml",
"PROD": "/chart/./values-prod.yaml",
}

cfg = config.parse()

# SECTION: APP
# ---
Expand All @@ -30,7 +40,10 @@ local_resource(
labels=["app"],
trigger_mode=TRIGGER_MODE_AUTO,
auto_init=False,
links=[link("http://localhost:4200", "web")],
links=[
link("http://localhost:4200", "app"),
link("http://localhost:4200/api", "api"),
],
)

local_resource(
Expand Down Expand Up @@ -69,17 +82,25 @@ local_resource(
labels=["api"],
trigger_mode=TRIGGER_MODE_AUTO,
auto_init=False,
links=[link("http://localhost:3000", "api")],
links=[link("http://localhost:3000/api", "api")],
)

# SECTION: K8s
# ---
k8s_yaml(helm("./chart", "marcolongo-cloud", "marcolongo-cloud", "./chart/values.yaml"))
k8s_yaml(
helm(
"./chart",
"marcolongo-cloud",
"marcolongo-cloud",
values=VALUES_DICT[cfg.get("env", "LOCAL")],
)
)

k8s_resource(
"marcolongo-cloud-app",
port_forwards=[
port_forward(80, name="web"),
port_forward(80, name="app"),
port_forward(80, name="api", link_path="/api"),
],
labels=["app"],
auto_init=False,
Expand Down
22 changes: 22 additions & 0 deletions apps/api-e2e/src/support/global-setup.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,37 @@
import { spawn } from 'node:child_process';

import { PostgreSqlContainer } from '@testcontainers/postgresql';

export default async function setup() {
// Start services that that the app needs to run (e.g. database, docker-compose, etc.).
console.log('\nSetting up...\n');

// Start a PostgreSQL container.
const psqlContainer = await new PostgreSqlContainer()
.withExposedPorts({
container: 5432,
host: 5432,
})
.start();

// Set the API_DATABASE_URL environment variable.
process.env.API_DATABASE_URL = psqlContainer.getConnectionUri();

// Run the database migrations.
const migrate = spawn('nx', ['run', 'api:prisma-migrate'], {
shell: true,
stdio: 'pipe',
});

// Start the API server.
const server = spawn('nx', ['run', 'api:serve'], {
shell: true,
stdio: 'pipe',
});

// Store the PostgreSQL container in `globalThis` to access it in global teardown.
globalThis.__PSQL_CONTAINER__ = psqlContainer;

// Store the server process in `globalThis` to access it in global teardown.
globalThis.__SERVER_PROCESS__ = server;

Expand Down
4 changes: 4 additions & 0 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/package.json ./package.json
COPY dist/apps/api/ .
RUN npx prisma generate
RUN chown -R node:node /app
USER node
EXPOSE 3000
CMD ["nodemon", "main.js"]
Expand All @@ -30,6 +32,8 @@ WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY --from=deps /app/package.json ./package.json
COPY dist/apps/api .
RUN chown -R node:node /app
RUN npx prisma generate
USER node
EXPOSE 3000
CMD ["dumb-init", "node", "main.js"]
7 changes: 5 additions & 2 deletions apps/api/chart/Chart.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,8 @@ dependencies:
- name: postgresql
repository: https://charts.bitnami.com/bitnami
version: 15.5.23
digest: sha256:768502dbaeb78304556d6fae616ea831217d8c589090d0b9e1198e934c38a563
generated: "2024-08-19T09:07:01.973555449Z"
- name: common
repository: https://charts.bitnami.com/bitnami
version: 2.22.0
digest: sha256:921a69c10c7e46d74f0588dfeedace1af6b0c4b60657d932a71cd7084817fda1
generated: "2024-08-19T22:05:20.6674906-07:00"
3 changes: 3 additions & 0 deletions apps/api/chart/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,6 @@ dependencies:
condition: postgresql.enabled
version: 15.5.23
repository: https://charts.bitnami.com/bitnami
- name: common
repository: https://charts.bitnami.com/bitnami
version: 2.x.x
92 changes: 91 additions & 1 deletion apps/api/chart/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ Selector labels
{{- define "chart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- end -}}

{{/*
Create the name of the service account to use
Expand All @@ -60,3 +60,93 @@ Create the name of the service account to use
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

{{/*
Create a default fully qualified postgresql name.
*/}}
{{- define "api.postgresql.fullname" -}}
{{- include "common.names.dependency.fullname" (dict "chartName" "postgresql" "chartValues" .Values.postgresql "context" $) -}}
{{- end -}}

{{/*
Add environment variables to configure database name
*/}}
{{- define "api.database.name" -}}
{{- ternary .Values.postgresql.auth.database .Values.externalDatabase.database .Values.postgresql.enabled | quote -}}
{{- end -}}

{{/*
Add environment variables to configure database host
*/}}
{{- define "api.database.host" -}}
{{- ternary (include "api.postgresql.fullname" .) .Values.externalDatabase.host .Values.postgresql.enabled | quote -}}
{{- end -}}

{{/*
Add environment variables to configure database port
*/}}
{{- define "api.database.port" -}}
{{- ternary "5432" .Values.externalDatabase.port .Values.postgresql.enabled | quote -}}
{{- end -}}

{{/*
Add environment variables to configure database user
*/}}
{{- define "api.database.user" -}}
{{- ternary .Values.postgresql.auth.username .Values.externalDatabase.user .Values.postgresql.enabled | quote -}}
{{- end -}}

{{/*
Get the postgresql credentials secret
*/}}
{{- define "api.database.secretName" -}}
{{- if .Values.postgresql.enabled -}}
{{- default (include "api.postgresql.fullname" .) (tpl .Values.postgresql.auth.existingSecret $) -}}
{{- else -}}
{{- default (printf "%s-externaldb" .Release.Name) (tpl .Values.externalDatabase.existingSecret $) -}}
{{- end -}}
{{- end -}}

{{/*
Get the postgresql credentials secret key
*/}}
{{- define "api.database.existingSecret.key" -}}
{{- if .Values.postgresql.enabled -}}
{{- printf "%s" "password" -}}
{{- else -}}
{{- if .Values.externalDatabase.existingSecret -}}
{{- if .Values.externalDatabase.existingSecretPasswordKey -}}
{{- printf "%s" .Values.externalDatabase.existingSecretPasswordKey -}}
{{- else -}}
{{- printf "%s" "password" -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}

{{/*
Add environment variables to configure database values
*/}}
{{- define "api.configure.database" -}}
- name: API_DATABASE_NAME
value: {{ include "api.database.name" . }}
- name: API_DATABASE_USERNAME
value: {{ include "api.database.user" . }}
{{- if or (not .Values.postgresql.enabled) .Values.postgresql.auth.enablePostgresUser }}
- name: API_DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "api.database.secretName" . }}
key: {{ include "api.database.existingSecret.key" . }}
{{- else }}
- name: ALLOW_EMPTY_PASSWORD
value: "yes"
{{- end }}
- name: API_DATABASE_HOST
value: {{ include "api.database.host" . }}
- name: API_DATABASE_PORT
value: {{ include "api.database.port" . }}
- name: API_DATABASE_URL
value: "postgresql://$(API_DATABASE_USERNAME):$(API_DATABASE_PASSWORD)@$(API_DATABASE_HOST):$(API_DATABASE_PORT)/$(API_DATABASE_NAME)"
{{- end -}}

20 changes: 20 additions & 0 deletions apps/api/chart/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,32 @@ spec:
serviceAccountName: {{ include "chart.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
- name: migrate
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
command:
- "/bin/sh"
args:
- -ec
- |
#!/bin/sh
echo "Current working directory: $(pwd)"
echo "Listing files in current directory: $(ls)"
echo "Running migrations..."
npx prisma migrate deploy
env:
{{- include "api.configure.database" . | nindent 12 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
{{- include "api.configure.database" . | nindent 12 }}
ports:
- name: api
containerPort: {{ .Values.service.port }}
Expand Down
60 changes: 57 additions & 3 deletions apps/api/chart/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ resources:

livenessProbe:
httpGet:
path: /api
path: /api/health
port: api
readinessProbe:
httpGet:
path: /api
path: /api/health
port: api

autoscaling:
Expand Down Expand Up @@ -110,5 +110,59 @@ tolerations: []

affinity: {}

## PostgreSQL chart configuration
## ref: https://github.com/bitnami/charts/blob/main/bitnami/postgresql/values.yaml
## @param postgresql.enabled Switch to enable or disable the PostgreSQL helm chart
## @param postgresql.auth.enablePostgresUser Assign a password to the "postgres" admin user. Otherwise, remote access will be blocked for this user
## @param postgresql.auth.username Name for a custom user to create
## @param postgresql.auth.password Password for the custom user to create
## @param postgresql.auth.database Name for a custom database to create
## @param postgresql.auth.existingSecret Name of existing secret to use for PostgreSQL credentials
## @param postgresql.architecture PostgreSQL architecture (`standalone` or `replication`)
##
postgresql:
enabled: false
enabled: true
auth:
enablePostgresUser: true
username: "administrator"
password: ""
database: "marcolongodb"
existingSecret: ""
architecture: "standalone"
primary:
## PostgreSQL Primary resource requests and limits
## ref: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
## @param postgresql.primary.resourcesPreset Set container resources according to one common preset (allowed values: none, nano, small, medium, large, xlarge, 2xlarge). This is ignored if primary.resources is set (primary.resources is recommended for production).
## More information: https://github.com/bitnami/charts/blob/main/bitnami/common/templates/_resources.tpl#L15
##
resourcePreset: "nano"
## @param postgresql.primary.resources Set container requests and limits for different resources like CPU or memory (essential for production workloads)
## Example:
## resources:
## requests:
## cpu: 2
## memory: 512Mi
## limits:
## cpu: 3
## memory: 1024Mi
##
resources: {}

## External PostgreSQL configuration
## All of these values are only used when postgresql.enabled is set to false
## @param externalDatabase.host Database host
## @param externalDatabase.port Database port number
## @param externalDatabase.user Non-root username for Airflow
## @param externalDatabase.password Password for the non-root username for Airflow
## @param externalDatabase.database Airflow database name
## @param externalDatabase.existingSecret Name of an existing secret resource containing the database credentials
## @param externalDatabase.existingSecretPasswordKey Name of an existing secret key containing the database credentials
##
externalDatabase:
host: localhost
port: 5432
user: administrator
database: marcolongodb
password: ""
existingSecret: ""
existingSecretPasswordKey: ""
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
"@nestjs/swagger": "^7.3.1",
"@nestjs/testing": "^10.0.2",
"@nx/webpack": "19.6.1",
"@prisma/client": "5.5.2",
"webpack": "5.92.1",
"webpack-node-externals": "^3.0.0"
}
Expand Down
11 changes: 11 additions & 0 deletions apps/api/prisma/migrations/20240820083537_0_init/migration.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL NOT NULL,
"email" TEXT NOT NULL,
"name" TEXT,

CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);

-- CreateIndex
CREATE UNIQUE INDEX "User_email_key" ON "User"("email");
3 changes: 3 additions & 0 deletions apps/api/prisma/migrations/migration_lock.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Please do not edit this file manually
# It should be added in your version-control system (i.e. Git)
provider = "postgresql"
17 changes: 17 additions & 0 deletions apps/api/prisma/schema.prisma
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
generator client {
provider = "prisma-client-js"
}

datasource db {
provider = "postgresql"
url = env("API_DATABASE_URL")
}

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
}



Loading

0 comments on commit b1ba3d7

Please sign in to comment.