diff --git a/helm/.gitignore b/helm/.gitignore new file mode 100644 index 0000000000..27240bcf51 --- /dev/null +++ b/helm/.gitignore @@ -0,0 +1,2 @@ +charts +values-local.yaml \ No newline at end of file diff --git a/helm/.helmignore b/helm/.helmignore new file mode 100644 index 0000000000..0e8a0eb36f --- /dev/null +++ b/helm/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/helm/Chart.lock b/helm/Chart.lock new file mode 100644 index 0000000000..5192736fe0 --- /dev/null +++ b/helm/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: redis + repository: https://charts.bitnami.com/bitnami + version: 20.2.1 +- name: postgresql + repository: https://charts.bitnami.com/bitnami + version: 15.5.32 +digest: sha256:d9755a578cb81acf58b8d5fe937eb76d14f210666d8e2859328c9055a9dfba8a +generated: "2024-12-29T10:25:00.270180265+05:45" diff --git a/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000000..7f232d1b42 --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: the-deep-helm +description: "Helm Chart to deploy the deep server Infrastructure" + +type: application +version: 0.0.1-SET-BY-CICD +sources: + - https://github.com/the-deep/server + +dependencies: + - name: redis + version: "20.2.1" + repository: https://charts.bitnami.com/bitnami + condition: redis.enabled + - name: postgresql + version: 15.5.32 + condition: postgresql.enabled + repository: https://charts.bitnami.com/bitnami \ No newline at end of file diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl new file mode 100644 index 0000000000..83545dd7fc --- /dev/null +++ b/helm/templates/_helpers.tpl @@ -0,0 +1,54 @@ +{{/* + Expand the name of the chart. +*/}} +{{- define "the-deep.name" -}} + {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* + Create a default fully qualified app name. + We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). + If release name contains chart name it will be used as a full name. + https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#dns-label-names +*/}} + {{- define "the-deep.fullname" -}} + {{- if .Values.fullnameOverride }} + {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} + {{- else }} + {{- $name := default .Chart.Name .Values.nameOverride }} + {{- if contains $name .Release.Name }} + {{- .Release.Name | trunc 63 | trimSuffix "-" }} + {{- else }} + {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} + {{- end }} + {{- end }} +{{- end }} + +{{/* + Create chart name and version as used by the chart label. +*/}} +{{- define "the-deep.chart" -}} + {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* + Create the name of the service account to use +*/}} + {{- define "the-deep.serviceAccountName" -}} + {{- if .Values.serviceAccount.create }} + {{- default (include "the-deep.fullname" .) .Values.serviceAccount.name }} + {{- else }} + {{- default "default" .Values.serviceAccount.name }} + {{- end }} +{{- end }} + +{{/* + Create the name of the secret to be used by the the-deep +*/}} +{{- define "the-deep.secretname" -}} + {{- if .Values.secretsName }} + {{- .Values.secretsName -}} + {{- else }} + {{- printf "%s-secret" (include "the-deep.fullname" .) -}} + {{- end -}} +{{- end -}} \ No newline at end of file diff --git a/helm/templates/api/deployment.yaml b/helm/templates/api/deployment.yaml new file mode 100644 index 0000000000..8e3c986173 --- /dev/null +++ b/helm/templates/api/deployment.yaml @@ -0,0 +1,51 @@ +{{- if .Values.api.enabled -}} + +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ template "the-deep.fullname" . }}-api + labels: + app: {{ include "the-deep.fullname" . }} + component: api + environment: {{ .Values.environment }} + release: {{ .Release.Name }} + annotations: + reloader.stakater.com/auto: "true" +spec: + replicas: {{ .Values.api.replicaCount }} + selector: + matchLabels: + app: {{ include "the-deep.fullname" . }} + component: api + template: + metadata: + labels: + app: {{ include "the-deep.fullname" . }} + component: api + annotations: + checksum/secret: {{ include (print $.Template.BasePath "/config/secret.yaml") . | sha256sum }} + checksum/configmap: {{ include (print $.Template.BasePath "/config/configmap.yaml") . | sha256sum }} + spec: + containers: + - name: api + image: "{{ $.Values.image.name }}:{{ $.Values.image.tag }}" + imagePullPolicy: {{ $.Values.image.imagePullPolicy }} + command: ["scripts/run_web.sh"] + ports: + - name: http + containerPort: {{ .Values.api.containerPort }} + protocol: TCP + resources: + {{- toYaml .Values.api.resources | nindent 12 }} + envFrom: + - secretRef: + name: {{ template "the-deep.secretname" . }} + - configMapRef: + name: {{ template "the-deep.fullname" . }}-api-configmap + + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + +{{- end}} \ No newline at end of file diff --git a/helm/templates/api/ingress.yaml b/helm/templates/api/ingress.yaml new file mode 100644 index 0000000000..3e6f2659a0 --- /dev/null +++ b/helm/templates/api/ingress.yaml @@ -0,0 +1,33 @@ +{{ if .Values.ingress.enabled -}} + +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ template "the-deep.fullname" . }}-api + labels: + app: {{ include "the-deep.fullname" . }} + component: api + environment: {{ .Values.environment }} + release: {{ .Release.Name }} +spec: + ingressClassName: {{ required "ingress.className" .Values.ingress.className | quote }} + rules: + - host: {{ required "ingress.host" .Values.ingress.host | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ template "the-deep.fullname" . }}-api + port: + number: 80 + + {{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ required "ingress.host" .Values.ingress.host | quote }} + secretName: {{ template "the-deep.fullname" . }}-api-tls + {{- end }} + +{{- end }} \ No newline at end of file diff --git a/helm/templates/api/service.yaml b/helm/templates/api/service.yaml new file mode 100644 index 0000000000..04e3ddf910 --- /dev/null +++ b/helm/templates/api/service.yaml @@ -0,0 +1,21 @@ +{{- if .Values.api.enabled -}} + +apiVersion: v1 +kind: Service +metadata: + name: {{ template "the-deep.fullname" . }}-api + labels: + app: {{ include "the-deep.fullname" . }} + component: api + environment: {{ .Values.environment }} + release: {{ .Release.Name }} +spec: + type: ClusterIP + selector: + app: {{ include "the-deep.fullname" . }} + component: api + ports: + - protocol: TCP + port: 80 + targetPort: {{ .Values.api.containerPort }} +{{- end }} \ No newline at end of file diff --git a/helm/templates/argo-hooks/hook-job.yaml b/helm/templates/argo-hooks/hook-job.yaml new file mode 100644 index 0000000000..479ec16875 --- /dev/null +++ b/helm/templates/argo-hooks/hook-job.yaml @@ -0,0 +1,44 @@ +{{- range $hookName, $hook := .Values.argoHooks }} + +{{- if $hook.enabled }} + +--- +apiVersion: batch/v1 +kind: Job +metadata: + {{- if $hook.preserveHistory }} + generateName: {{ template "the-deep.fullname" $ }}-{{ $hookName }}- + {{- else }} + name: {{ template "the-deep.fullname" $ }}-{{ $hookName }} + {{- end }} + annotations: + argocd.argoproj.io/hook: {{ $hook.hook }} +spec: + template: + spec: + restartPolicy: "Never" + containers: + - name: {{ $hookName }} + image: "{{ $.Values.image.name }}:{{ $.Values.image.tag }}" + imagePullPolicy: {{ $.Values.image.imagePullPolicy }} + command: {{ toYaml $hook.command | trim | nindent 12 }} + resources: + requests: + cpu: {{ default $.Values.api.resources.requests.cpu $hook.requestsCpu }} + memory: {{ default $.Values.api.resources.requests.memory $hook.requestsMemory }} + limits: + cpu: {{ default $.Values.api.resources.limits.cpu $hook.limitsCpu }} + memory: {{ default $.Values.api.resources.limits.memory $hook.limitsMemory }} + envFrom: + - secretRef: + name: {{ template "the-deep.secretname" $ }} + - configMapRef: + name: {{ template "the-deep.fullname" $ }}-api-configmap + + {{- with $.Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} +{{- end }} + +{{- end }} \ No newline at end of file diff --git a/helm/templates/config/configmap.yaml b/helm/templates/config/configmap.yaml new file mode 100644 index 0000000000..f94445f806 --- /dev/null +++ b/helm/templates/config/configmap.yaml @@ -0,0 +1,33 @@ +kind: ConfigMap +apiVersion: v1 +metadata: + name: {{ template "the-deep.fullname" . }}-api-configmap + labels: + app: {{ include "the-deep.fullname" . }} + environment: {{ .Values.environment }} + release: {{ .Release.Name }} + +data: + APP_RELEASE: {{ .Values.image.tag | quote }} + DEEP_ENVIRONMENT: {{ .Values.environment | quote | upper }} + DJANGO_DEBUG: {{ required "env.DJANGO_DEBUG" .Values.env.DJANGO_DEBUG | quote }} + + # Domain + DEEP_FRONTEND_HOST: {{ required "env.DEEP_FRONTEND_HOST" .Values.env.DEEP_FRONTEND_HOST | quote }} + DEEP_BACKEND_HOST: {{ required "env.DEEP_BACKEND_HOST" .Values.env.DEEP_BACKEND_HOST | quote }} + DEEP_FRONTEND_ARY_HOST: {{ required "env.DEEP_FRONTEND_ARY_HOST" .Values.env.DEEP_FRONTEND_ARY_HOST | quote }} + DEEP_HTTPS: {{ required "env.DEEP_HTTPS" .Values.env.DEEP_HTTPS | quote }} + DJANGO_ALLOWED_HOST: {{ required "env.DJANGO_ALLOWED_HOST" .Values.env.DJANGO_ALLOWED_HOST | quote }} + SESSION_COOKIE_DOMAIN: {{ required "env.SESSION_COOKIE_DOMAIN" .Values.env.SESSION_COOKIE_DOMAIN | quote }} + CSRF_COOKIE_DOMAIN: {{ required "env.CSRF_COOKIE_DOMAIN" .Values.env.CSRF_COOKIE_DOMAIN | quote }} + + # cors + CORS_ALLOWED_ORIGINS: {{ required "env.CORS_ALLOWED_ORIGINS" .Values.env.CORS_ALLOWED_ORIGINS | quote }} + + # Sentry + SENTRY_SAMPLE_RATE: {{ required "env.SENTRY_SAMPLE_RATE" .Values.env.SENTRY_SAMPLE_RATE | quote }} + + # Additional configs + {{- range $name, $value := .Values.envAdditional }} + {{ $name }}: {{ $value | quote }} + {{- end }} \ No newline at end of file diff --git a/helm/templates/config/secret.yaml b/helm/templates/config/secret.yaml new file mode 100644 index 0000000000..dcd1a3a4b3 --- /dev/null +++ b/helm/templates/config/secret.yaml @@ -0,0 +1,55 @@ +kind: Secret +apiVersion: v1 +metadata: + name: {{ template "the-deep.secretname" . }} + labels: + app: {{ include "the-deep.fullname" . }} + environment: {{ .Values.environment }} + release: {{ .Release.Name }} +type: Opaque +stringData: + # Django secret key + DJANGO_SECRET_KEY: {{ required "secrets.DJANGO_SECRET_KEY" .Values.secrets.DJANGO_SECRET_KEY | quote }} + + # Database + {{- if .Values.postgresql.enabled }} + DATABASE_NAME: {{.Values.postgresql.auth.database | quote }} + DATABASE_USER: {{.Values.postgresql.auth.username | quote }} + DATABASE_PASSWORD: {{.Values.postgresql.auth.password | quote }} + DATABASE_PORT: {{ include "postgresql.v1.service.port" .Subcharts.postgresql | quote }} + DATABASE_HOST: {{ include "postgresql.v1.primary.fullname" .Subcharts.postgresql }} + {{- else }} + DATABASE_NAME: {{ required "secrets.DATABASE_NAME" .Values.secrets.DB_NAME | quote }} + DATABASE_USER: {{ required "secrets.DATABASE_USER" .Values.secrets.DATABASE_USER | quote }} + DATABASE_PASSWORD: {{ required "secrets.DATABASE_PASSWORD" .Values.secrets.DATABASE_PASSWORD | quote }} + DATABASE_PORT: {{ required "secrets.DATABASE_PORT" .Values.secrets.DATABASE_PORT | quote }} + DATABASE_HOST: {{ required "secrets.DATABASE_HOST" .Values.secrets.DATABASE_HOST | quote }} + {{- end }} + + # Sentry + SENTRY_DSN: {{ required "secrets.SENTRY_DSN" .Values.secrets.SENTRY_DSN | quote }} + + # Redis + {{- if .Values.redis.enabled }} + CELERY_REDIS_URL: "redis://{{ printf "%s-master" (include "common.names.fullname" .Subcharts.redis) }}:6379/0" + DJANGO_CACHE_REDIS_URL: "redis://{{ printf "%s-master" (include "common.names.fullname" .Subcharts.redis) }}:6379/2" + TEST_DJANGO_CACHE_REDIS_URL: "redis://{{ printf "%s-master" (include "common.names.fullname" .Subcharts.redis) }}:6379/12" + {{- else }} + CELERY_REDIS_URL: {{ required "secrets.CELERY_REDIS_URL" .Values.secrets.CELERY_REDIS_URL | quote }} + DJANGO_CACHE_REDIS_URL: {{ required "secrets.DJANGO_CACHE_REDIS_URL" .Values.secrets.DJANGO_CACHE_REDIS_URL | quote }} + TEST_DJANGO_CACHE_REDIS_URL: {{ required "secrets.TEST_DJANGO_CACHE_REDIS_URL" .Values.secrets.TEST_DJANGO_CACHE_REDIS_URL | quote }} + {{- end }} + + #Email + SMTP_EMAIL_HOST: {{ required "env.SMTP_EMAIL_HOST" .Values.secrets.SMTP_EMAIL_HOST | quote }} + SMTP_EMAIL_PORT: {{ required "env.SMTP_EMAIL_PORT" .Values.secrets.SMTP_EMAIL_PORT | quote }} + SMTP_EMAIL_USERNAME: {{ required "env.SMTP_EMAIL_USERNAME" .Values.secrets.SMTP_EMAIL_USERNAME | quote }} + SMTP_EMAIL_PASSWORD: {{ required "env.SMTP_EMAIL_PASSWORD" .Values.secrets.SMTP_EMAIL_PASSWORD | quote }} + + # Hcaptcha + HCAPTCHA_SECRET: {{ required "secrets.HCAPTCHA_SECRET" .Values.secrets.HCAPTCHA_SECRET | quote }} + + # Additional secrets + {{- range $name, $value := .Values.secretsAdditional }} + {{ $name }}: {{ $value | quote }} + {{- end }} \ No newline at end of file diff --git a/helm/values-test.yaml b/helm/values-test.yaml new file mode 100644 index 0000000000..129ea18acc --- /dev/null +++ b/helm/values-test.yaml @@ -0,0 +1,65 @@ +environment: test + +image: + name: test + tag: test + +ingress: + enabled: true + host: test.the-deep.com + className: "nginx" + +env: + APP_RELEASE: test + # DEEP_ENVIRONMENT: using .environment + DJANGO_DEBUG: false + + # Domain + DEEP_FRONTEND_HOST: dummy + DEEP_BACKEND_HOST: dummy + DEEP_HTTPS: https + DEEP_FRONTEND_ARY_HOST: dummy + DJANGO_ALLOWED_HOST: dummy + SESSION_COOKIE_DOMAIN: dummy + CSRF_COOKIE_DOMAIN: dummy + + # cors + CORS_ALLOWED_ORIGINS: dummy + + # Sentry + SENTRY_SAMPLE_RATE: 0.2 + + envAdditional: + # Additional configs + # EXAMPLE: MY_CONFIG: "my-value" + +secrets: + DJANGO_SECRET_KEY: asdasdasdasdasd + + # Database + DATABASE_NAME: dummy + DATABASE_USER: dummy + DATABASE_PASSWORD: dummy + DATABASE_PORT: dummy + DATABASE_HOST: dummy + + # Sentry + SENTRY_DSN: dummy + + # Redis + CELERY_REDIS_URL: dummy + DJANGO_CACHE_REDIS_URL: dummy + TEST_DJANGO_CACHE_REDIS_URL: dummy + + #Email + SMTP_EMAIL_HOST: dummy + SMTP_EMAIL_PORT: dummy + SMTP_EMAIL_USERNAME: dummy + SMTP_EMAIL_PASSWORD: dummy + + # Hcaptcha + HCAPTCHA_SECRET: dummy + + secretsAdditional: + # Additional secrets + # EXAMPLE: MY_SECRET: "my-secret-value" \ No newline at end of file diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000000..3fb5a87cfe --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,123 @@ +environment: prod + +image: + name: SET-BY-CICD-IMAGE + tag: SET-BY-CICD-TAG + +ingress: + enabled: false + host: + className: + tls: + enabled: false + secretName: + +redis: + enabled: true + architecture: standalone + fullnameOverride: the-deep-redis + auth: + enabled: false + master: + persistence: + enabled: true + size: .5Gi + storageClass: + +postgresql: + enabled: false + fullnameOverride: "" + architecture: standalone + auth: + postgresPassword: "" + username: "" + password: "" + database: "" + primary: + persistence: + enabled: true + storageClass: "" + size: 8G + +api: + enabled: true + replicaCount: 1 + containerPort: 80 + resources: + requests: + cpu: "2" + memory: 0.5Gi + limits: + cpu: "2" + memory: 1Gi + +argoHooks: + # NOTE: Make sure keys are lowercase + db-migrate: + enabled: true + hook: PostSync + preserveHistory: true + command: ["./manage.py", "migrate"] + requestsCpu: 0.1 + requestsMemory: 1G + limitsCpu: 4 + limitsMemory: 2G + collect-static: + enabled: true + hook: PostSync + command: ["./manage.py", "collectstatic", "--noinput"] + +env: + # APP_RELEASE: using .image.tag + # DEEP_ENVIRONMENT: using .environment + DJANGO_DEBUG: false + + # Domain + DEEP_FRONTEND_HOST: + DEEP_BACKEND_HOST: + DEEP_HTTPS: https + DEEP_FRONTEND_ARY_HOST: + DJANGO_ALLOWED_HOST: + SESSION_COOKIE_DOMAIN: + CSRF_COOKIE_DOMAIN: + + # cors + CORS_ALLOWED_ORIGINS: + + # Sentry + SENTRY_SAMPLE_RATE: 0.2 + + envAdditional: + # Additional configs + # EXAMPLE: MY_CONFIG: "my-value" + +secrets: + DJANGO_SECRET_KEY: + + # Database + DATABASE_NAME: + DATABASE_USER: + DATABASE_PASSWORD: + DATABASE_PORT: + DATABASE_HOST: + + # Sentry + SENTRY_DSN: + + # Redis + CELERY_REDIS_URL: + DJANGO_CACHE_REDIS_URL: + TEST_DJANGO_CACHE_REDIS_URL: + + #Email + SMTP_EMAIL_HOST: + SMTP_EMAIL_PORT: + SMTP_EMAIL_USERNAME: + SMTP_EMAIL_PASSWORD: + + # Hcaptcha + HCAPTCHA_SECRET: + + secretsAdditional: + # Additional secrets + # EXAMPLE: MY_SECRET: "my-secret-value" \ No newline at end of file