From 6a54011d79b2a11f37ba9912cd5d814a3d1c50d3 Mon Sep 17 00:00:00 2001 From: Fabio Kaiser Rauber Date: Thu, 29 Jan 2026 17:12:11 -0300 Subject: [PATCH] First version of Saberes Caduser chart --- charts/caduser/v0.1.0/Chart.lock | 6 + charts/caduser/v0.1.0/Chart.yaml | 24 ++ charts/caduser/v0.1.0/README.md | 102 +++++++++ charts/caduser/v0.1.0/app-readme.md | 5 + .../caduser/v0.1.0/charts/memcached-0.9.3.tgz | Bin 0 -> 27882 bytes charts/caduser/v0.1.0/questions.yaml | 212 ++++++++++++++++++ charts/caduser/v0.1.0/templates/NOTES.txt | 18 ++ charts/caduser/v0.1.0/templates/_helpers.tpl | 76 +++++++ .../caduser/v0.1.0/templates/deployment.yaml | 134 +++++++++++ charts/caduser/v0.1.0/templates/hpa.yaml | 28 +++ charts/caduser/v0.1.0/templates/ingress.yaml | 36 +++ .../v0.1.0/templates/postgresql-cluster.yaml | 34 +++ .../caduser/v0.1.0/templates/pvc-media.yaml | 21 ++ charts/caduser/v0.1.0/templates/service.yaml | 15 ++ .../v0.1.0/templates/serviceaccount.yaml | 12 + charts/caduser/v0.1.0/values.yaml | 134 +++++++++++ 16 files changed, 857 insertions(+) create mode 100644 charts/caduser/v0.1.0/Chart.lock create mode 100644 charts/caduser/v0.1.0/Chart.yaml create mode 100644 charts/caduser/v0.1.0/README.md create mode 100644 charts/caduser/v0.1.0/app-readme.md create mode 100644 charts/caduser/v0.1.0/charts/memcached-0.9.3.tgz create mode 100644 charts/caduser/v0.1.0/questions.yaml create mode 100644 charts/caduser/v0.1.0/templates/NOTES.txt create mode 100644 charts/caduser/v0.1.0/templates/_helpers.tpl create mode 100644 charts/caduser/v0.1.0/templates/deployment.yaml create mode 100644 charts/caduser/v0.1.0/templates/hpa.yaml create mode 100644 charts/caduser/v0.1.0/templates/ingress.yaml create mode 100644 charts/caduser/v0.1.0/templates/postgresql-cluster.yaml create mode 100644 charts/caduser/v0.1.0/templates/pvc-media.yaml create mode 100644 charts/caduser/v0.1.0/templates/service.yaml create mode 100644 charts/caduser/v0.1.0/templates/serviceaccount.yaml create mode 100644 charts/caduser/v0.1.0/values.yaml diff --git a/charts/caduser/v0.1.0/Chart.lock b/charts/caduser/v0.1.0/Chart.lock new file mode 100644 index 0000000..1698e84 --- /dev/null +++ b/charts/caduser/v0.1.0/Chart.lock @@ -0,0 +1,6 @@ +dependencies: +- name: memcached + repository: oci://registry-1.docker.io/cloudpirates + version: 0.9.3 +digest: sha256:49e682658df3168f5001acab4149fec6a44a954d4355d5c55f19b17eebe62f60 +generated: "2026-01-29T17:01:33.905882774-03:00" diff --git a/charts/caduser/v0.1.0/Chart.yaml b/charts/caduser/v0.1.0/Chart.yaml new file mode 100644 index 0000000..cccd178 --- /dev/null +++ b/charts/caduser/v0.1.0/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: caduser +description: Sistema de Cadastro de Usuários - Saberes + +# A chart can be either an 'application' or a 'library' chart. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +appVersion: 1.0.0 + +icon: https://git.interlegis.leg.br/SEIT/rancher-charts/raw/master/images/interlegis.png + +dependencies: +- name: memcached + version: 0.9.3 + repository: oci://registry-1.docker.io/cloudpirates + condition: memcached.enabled diff --git a/charts/caduser/v0.1.0/README.md b/charts/caduser/v0.1.0/README.md new file mode 100644 index 0000000..738d2bc --- /dev/null +++ b/charts/caduser/v0.1.0/README.md @@ -0,0 +1,102 @@ +# CadUser - Sistema de Cadastro de Usuários + +Sistema de cadastro e gerenciamento de usuários desenvolvido pelo Interlegis. + +## Instalação + +```bash +helm install caduser ./caduser -f values.yaml +``` + +## Pré-requisitos + +- Kubernetes 1.19+ +- Helm 3.0+ +- CloudNativePG Operator (https://cloudnative-pg.io/) +- Ingress Controller (nginx) +- Cert-manager (opcional, para TLS com Let's Encrypt) + +## Parâmetros + +### Configurações da Aplicação + +| Parâmetro | Descrição | Padrão | +|-----------|-----------|--------| +| `caduser.hostname` | Hostname para acesso ao CadUser | `caduser.domain.net` | +| `caduser.adminUsers` | E-mails dos administradores (separados por vírgula) | `admin@example.com` | +| `caduser.debug` | Habilitar modo debug | `False` | + +### Configurações de E-mail + +| Parâmetro | Descrição | Padrão | +|-----------|-----------|--------| +| `caduser.emailHost` | Servidor SMTP | `smtp.domain.net` | +| `caduser.emailPort` | Porta SMTP | `25` | +| `caduser.emailUseTls` | Usar TLS | `False` | +| `caduser.emailUseSsl` | Usar SSL | `False` | +| `caduser.defaultFromEmail` | E-mail remetente | `no-reply@domain.net` | + +### Configurações de Banco de Dados (CloudNativePG) + +| Parâmetro | Descrição | Padrão | +|-----------|-----------|--------| +| `postgresql.enabled` | Criar cluster PostgreSQL | `true` | +| `postgresql.clusterName` | Nome do cluster | `caduser-pg` | +| `postgresql.instances` | Número de instâncias | `1` | +| `postgresql.databaseName` | Nome do banco | `caduser` | +| `postgresql.owner` | Usuário dono do banco | `caduser` | +| `postgresql.storageSize` | Tamanho do volume | `1Gi` | +| `postgresql.image` | Imagem PostgreSQL | `ghcr.io/cloudnative-pg/postgresql:17.2` | + +### Configurações de Cache + +| Parâmetro | Descrição | Padrão | +|-----------|-----------|--------| +| `memcached.internal` | Usar Memcached interno | `true` | + +### Configurações de Ingress + +| Parâmetro | Descrição | Padrão | +|-----------|-----------|--------| +| `ingress.enabled` | Habilitar Ingress | `true` | +| `ingress.class` | Classe do Ingress | `nginx` | +| `ingress.tls.enabled` | Habilitar TLS | `true` | + +### Persistência + +| Parâmetro | Descrição | Padrão | +|-----------|-----------|--------| +| `persistence.enabled` | Habilitar persistência | `true` | +| `persistence.size` | Tamanho do volume de mídia | `2Gi` | +| `persistence.accessMode` | Modo de acesso | `ReadWriteOnce` | + +### Recursos + +| Parâmetro | Descrição | Padrão | +|-----------|-----------|--------| +| `resources.requests.cpu` | CPU solicitada | `35m` | +| `resources.requests.memory` | Memória solicitada | `512Mi` | +| `resources.limits.cpu` | Limite de CPU | `1000m` | +| `resources.limits.memory` | Limite de memória | `1000Mi` | + +## Integrações + +### Moodle + +Para integrar com o Moodle, configure: + +```yaml +caduser: + moodleBaseUrl: "https://moodle.example.com" + moodleApiToken: "seu-token-aqui" +``` + +### MaxMind GeoIP + +Para habilitar geolocalização com MaxMind: + +```yaml +caduser: + maxmindAccountId: "seu-account-id" + maxmindLicenceKey: "sua-chave" +``` \ No newline at end of file diff --git a/charts/caduser/v0.1.0/app-readme.md b/charts/caduser/v0.1.0/app-readme.md new file mode 100644 index 0000000..a3467dc --- /dev/null +++ b/charts/caduser/v0.1.0/app-readme.md @@ -0,0 +1,5 @@ +# Sistema de Cadastro de Usuários - CadUser + +Utilize o formulário abaixo para configurar o CadUser. + +O CadUser é um sistema de cadastro e gerenciamento de usuários para o Saberes. diff --git a/charts/caduser/v0.1.0/charts/memcached-0.9.3.tgz b/charts/caduser/v0.1.0/charts/memcached-0.9.3.tgz new file mode 100644 index 0000000000000000000000000000000000000000..9b1d97f0259e83f8cf9cbf33d9ef7da1b4166a85 GIT binary patch literal 27882 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 Z{`vm-{`oUM{}%uN|Np-vVzdB20su~rX}SOa literal 0 HcmV?d00001 diff --git a/charts/caduser/v0.1.0/questions.yaml b/charts/caduser/v0.1.0/questions.yaml new file mode 100644 index 0000000..d38d2ac --- /dev/null +++ b/charts/caduser/v0.1.0/questions.yaml @@ -0,0 +1,212 @@ +labels: + io.cattle.role: project +categories: +- Gerenciamento +questions: +# Informações Básicas +- variable: caduser.hostname + default: "caduser.teste.leg.br" + description: "Endereço para acesso ao CadUser" + label: "URL do CadUser" + type: string + group: Básico + required: true +- variable: caduser.adminUsers + default: "admin@example.com" + description: "E-mails dos usuários administradores (separados por vírgula)" + label: "Administradores" + type: string + group: Básico + required: true +- variable: caduser.debug + default: "False" + description: "Habilitar modo de depuração?" + label: "Debug" + type: enum + group: Básico + options: + - "True" + - "False" + required: false + +# Ingress +- variable: ingress.tls.enabled + default: true + type: boolean + description: "Habilitar criptografia do protocolo HTTP (HTTPS)?" + label: "Habilitar TLS?" + required: false + group: Ingress + show_subquestion_if: false + +# Correio +- variable: caduser.defaultFromEmail + default: "no-reply@interlegis.leg.br" + description: "Remetente dos e-mails enviados pelo CadUser" + label: "Remetente" + type: string + group: Correio + required: false +- variable: caduser.emailSubjectPrefix + default: "[CadUser]" + description: "Prefixo no assunto dos e-mails" + label: "Prefixo do assunto" + type: string + group: Correio + required: false +- variable: caduser.emailUseTls + default: "False" + description: "Usar TLS ao conectar no servidor SMTP?" + label: "Usar TLS" + type: enum + group: Correio + options: + - "True" + - "False" + required: false +- variable: caduser.emailUseSsl + default: "False" + description: "Usar SSL ao conectar no servidor SMTP?" + label: "Usar SSL" + type: enum + group: Correio + options: + - "True" + - "False" + required: false +- variable: caduser.emailPort + default: 25 + description: "Porta de envio de E-mail (SMTP)" + type: int + label: "Porta SMTP" + required: false + group: Correio +- variable: caduser.emailHost + default: "smtp.interlegis.leg.br" + description: "Servidor de envio de e-mail (SMTP)" + label: "Servidor SMTP" + type: string + group: Correio + required: false +- variable: caduser.emailHostUser + default: "" + description: "Usuário para autenticação SMTP (se necessário)" + label: "Usuário SMTP" + type: string + group: Correio + required: false +- variable: caduser.emailHostPassword + default: "" + description: "Senha para autenticação SMTP (se necessário)" + label: "Senha SMTP" + type: password + group: Correio + required: false + +# Integrações +- variable: caduser.moodleBaseUrl + default: "" + description: "URL base do Moodle (se integração habilitada)" + label: "URL Moodle" + type: string + group: Integrações + required: false +- variable: caduser.moodleApiToken + default: "" + description: "Token de API do Moodle (se integração habilitada)" + label: "Token API Moodle" + type: password + group: Integrações + required: false +- variable: caduser.maxmindAccountId + default: "" + description: "ID da conta MaxMind (para geolocalização)" + label: "MaxMind Account ID" + type: string + group: Integrações + required: false +- variable: caduser.maxmindLicenceKey + default: "" + description: "Chave de licença MaxMind" + label: "MaxMind License Key" + type: password + group: Integrações + required: false + +# PostgreSQL (CloudNativePG) +- variable: postgresql.enabled + default: true + description: "Criar cluster PostgreSQL (CloudNativePG)?" + label: "PostgreSQL Habilitado" + type: boolean + group: Banco de Dados + required: true + show_subquestion_if: true + subquestions: + - variable: postgresql.instances + default: 1 + description: "Número de instâncias PostgreSQL" + label: "Instâncias" + type: int + required: true + - variable: postgresql.storageSize + default: "1Gi" + description: "Tamanho do volume persistente para PostgreSQL" + label: "Tamanho do Volume PostgreSQL" + type: string + required: false + +# Memcached +- variable: memcached.enabled + default: true + description: "Usar servidor Memcached interno?" + label: "Memcached Interno" + type: boolean + group: Cache + required: true + +# Persistência +- variable: persistence.enabled + default: true + description: "Habilitar persistência para arquivos de mídia?" + label: "Persistência" + type: boolean + group: Armazenamento + required: false +- variable: persistence.size + default: "2Gi" + description: "Tamanho do volume persistente para arquivos de mídia" + label: "Tamanho do Volume" + type: string + group: Armazenamento + required: false + +# Recursos +- variable: resources.requests.cpu + default: "35m" + description: "CPU solicitada" + label: "CPU Request" + type: string + group: Recursos + required: false +- variable: resources.requests.memory + default: "512Mi" + description: "Memória solicitada" + label: "Memory Request" + type: string + group: Recursos + required: false +- variable: resources.limits.cpu + default: "1000m" + description: "Limite de CPU" + label: "CPU Limit" + type: string + group: Recursos + required: false +- variable: resources.limits.memory + default: "1000Mi" + description: "Limite de memória" + label: "Memory Limit" + type: string + group: Recursos + required: false diff --git a/charts/caduser/v0.1.0/templates/NOTES.txt b/charts/caduser/v0.1.0/templates/NOTES.txt new file mode 100644 index 0000000..bb82316 --- /dev/null +++ b/charts/caduser/v0.1.0/templates/NOTES.txt @@ -0,0 +1,18 @@ +1. Get the application URL by running these commands: +{{- if .Values.ingress.enabled }} + http{{ if .Values.ingress.tls.enabled }}s{{ end }}://{{ .Values.caduser.hostname }} +{{- else if contains "NodePort" .Values.service.type }} + export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "caduser.fullname" . }}) + export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}") + echo http://$NODE_IP:$NODE_PORT +{{- else if contains "LoadBalancer" .Values.service.type }} + NOTE: It may take a few minutes for the LoadBalancer IP to be available. + You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "caduser.fullname" . }}' + export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "caduser.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}") + echo http://$SERVICE_IP:{{ .Values.service.port }} +{{- else if contains "ClusterIP" .Values.service.type }} + export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "caduser.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") + export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") + echo "Visit http://127.0.0.1:8080 to use your application" + kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT +{{- end }} diff --git a/charts/caduser/v0.1.0/templates/_helpers.tpl b/charts/caduser/v0.1.0/templates/_helpers.tpl new file mode 100644 index 0000000..ffa59c5 --- /dev/null +++ b/charts/caduser/v0.1.0/templates/_helpers.tpl @@ -0,0 +1,76 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "caduser.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. +*/}} +{{- define "caduser.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 "caduser.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "caduser.labels" -}} +helm.sh/chart: {{ include "caduser.chart" . }} +{{ include "caduser.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "caduser.selectorLabels" -}} +app.kubernetes.io/name: {{ include "caduser.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "caduser.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "caduser.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} + +{{/* +Create the postgresql fullname +*/}} +{{- define "postgresql.fullname" -}} +{{- printf "%s-%s" .Release.Name "postgresql" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create the memcached fullname +*/}} +{{- define "memcached.fullname" -}} +{{- printf "%s-%s" .Release.Name "memcached" | trunc 63 | trimSuffix "-" }} +{{- end }} diff --git a/charts/caduser/v0.1.0/templates/deployment.yaml b/charts/caduser/v0.1.0/templates/deployment.yaml new file mode 100644 index 0000000..e3cfac2 --- /dev/null +++ b/charts/caduser/v0.1.0/templates/deployment.yaml @@ -0,0 +1,134 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "caduser.fullname" . }} + labels: + {{- include "caduser.labels" . | nindent 4 }} +spec: +{{- if not .Values.autoscaling.enabled }} + replicas: {{ .Values.replicaCount }} +{{- end }} + selector: + matchLabels: + {{- include "caduser.selectorLabels" . | nindent 6 }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "caduser.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "caduser.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: 80 + protocol: TCP + env: + - name: DATABASE_URL + valueFrom: + secretKeyRef: + name: {{ .Values.postgresql.clusterName }}-app + key: uri + - name: MEMCACHED_LOCATION + value: {{ printf "%s:11211" (include "memcached.fullname" .) | quote }} + - name: ADMINS + value: "{{ .Values.caduser.adminUsers }}" + - name: DEBUG + value: "{{ .Values.caduser.debug }}" + - name: EMAIL_PORT + value: "{{ .Values.caduser.emailPort }}" + - name: EMAIL_HOST + value: "{{ .Values.caduser.emailHost }}" + - name: EMAIL_HOST_USER + value: "{{ .Values.caduser.emailHostUser }}" + - name: EMAIL_HOST_PASSWORD + value: "{{ .Values.caduser.emailHostPassword }}" + - name: EMAIL_SUBJECT_PREFIX + value: "{{ .Values.caduser.emailSubjectPrefix }}" + - name: EMAIL_USE_LOCALTIME + value: "{{ .Values.caduser.emailUseLocaltime }}" + - name: EMAIL_USE_TLS + value: "{{ .Values.caduser.emailUseTls }}" + - name: EMAIL_USE_SSL + value: "{{ .Values.caduser.emailUseSsl }}" + - name: EMAIL_TIMEOUT + value: "{{ .Values.caduser.emailTimeout }}" + - name: DEFAULT_FROM_EMAIL + value: "{{ .Values.caduser.defaultFromEmail }}" + - name: MAXMIND_ACCOUNT_ID + value: "{{ .Values.caduser.maxmindAccountId }}" + - name: MAXMIND_LICENCE_KEY + value: "{{ .Values.caduser.maxmindLicenceKey }}" + - name: MOODLE_BASE_URL + value: "{{ .Values.caduser.moodleBaseUrl }}" + - name: MOODLE_API_TOKEN + value: "{{ .Values.caduser.moodleApiToken }}" + - name: LANG + value: "pt_BR.UTF-8" + volumeMounts: + - mountPath: /srv/interlegis/caduser/media + name: media + livenessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 60 + failureThreshold: 3 + periodSeconds: 60 + successThreshold: 1 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: / + port: http + initialDelaySeconds: 30 + failureThreshold: 3 + periodSeconds: 30 + successThreshold: 1 + timeoutSeconds: 5 + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumes: + - name: media + {{- if .Values.persistence.enabled }} + persistentVolumeClaim: + claimName: {{ include "caduser.fullname" . }}-media + {{- else }} + emptyDir: {} + {{- end }} + {{- with .Values.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + affinity: + podAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + {{- if eq .Values.persistence.accessMode "ReadWriteOnce" }} + - weight: 100 + podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/name + operator: In + values: + - {{ include "caduser.name" . }} + topologyKey: kubernetes.io/hostname + {{- end }} + {{- with .Values.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} diff --git a/charts/caduser/v0.1.0/templates/hpa.yaml b/charts/caduser/v0.1.0/templates/hpa.yaml new file mode 100644 index 0000000..8c80190 --- /dev/null +++ b/charts/caduser/v0.1.0/templates/hpa.yaml @@ -0,0 +1,28 @@ +{{- if .Values.autoscaling.enabled }} +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: {{ include "caduser.fullname" . }} + labels: + {{- include "caduser.labels" . | nindent 4 }} +spec: + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "caduser.fullname" . }} + minReplicas: {{ .Values.autoscaling.minReplicas }} + maxReplicas: {{ .Values.autoscaling.maxReplicas }} + metrics: + {{- if .Values.autoscaling.targetCPUUtilizationPercentage }} + - type: Resource + resource: + name: cpu + targetAverageUtilization: {{ .Values.autoscaling.targetCPUUtilizationPercentage }} + {{- end }} + {{- if .Values.autoscaling.targetMemoryUtilizationPercentage }} + - type: Resource + resource: + name: memory + targetAverageUtilization: {{ .Values.autoscaling.targetMemoryUtilizationPercentage }} + {{- end }} +{{- end }} diff --git a/charts/caduser/v0.1.0/templates/ingress.yaml b/charts/caduser/v0.1.0/templates/ingress.yaml new file mode 100644 index 0000000..8f18a16 --- /dev/null +++ b/charts/caduser/v0.1.0/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "caduser.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "caduser.labels" . | nindent 4 }} + annotations: + kubernetes.io/ingress.class: {{ .Values.ingress.class }} +{{- if .Values.ingress.tls.enabled }} + cert-manager.io/cluster-issuer: letsencrypt-production +{{- end }} + {{- with .Values.ingress.annotations }} + {{- toYaml . | nindent 4 }} + {{- end }} +spec: +{{- if .Values.ingress.tls.enabled }} + tls: + - hosts: + - {{ .Values.caduser.hostname }} + secretName: {{ $fullName }}-tls +{{- end }} + rules: + - host: {{ .Values.caduser.hostname }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} +{{- end }} diff --git a/charts/caduser/v0.1.0/templates/postgresql-cluster.yaml b/charts/caduser/v0.1.0/templates/postgresql-cluster.yaml new file mode 100644 index 0000000..f7075e3 --- /dev/null +++ b/charts/caduser/v0.1.0/templates/postgresql-cluster.yaml @@ -0,0 +1,34 @@ +{{- if .Values.postgresql.enabled }} +apiVersion: postgresql.cnpg.io/v1 +kind: Cluster +metadata: + name: {{ .Values.postgresql.clusterName }} + labels: + {{- include "caduser.labels" . | nindent 4 }} +spec: + instances: {{ .Values.postgresql.instances }} + + imageName: {{ .Values.postgresql.image }} + + bootstrap: + initdb: + database: {{ .Values.postgresql.databaseName }} + owner: {{ .Values.postgresql.owner }} + localeCollate: {{ .Values.postgresql.initdb.localeCollate }} + localeCType: {{ .Values.postgresql.initdb.localeCType }} + encoding: {{ .Values.postgresql.initdb.encoding }} + + storage: + size: {{ .Values.postgresql.storageSize }} +{{- if .Values.postgresql.storageClass }} + storageClass: {{ .Values.postgresql.storageClass }} +{{- end }} + + resources: + {{- toYaml .Values.postgresql.resources | nindent 4 }} + +{{- if .Values.postgresql.superuserSecret }} + superuserSecret: + name: {{ .Values.postgresql.superuserSecret }} +{{- end }} +{{- end }} diff --git a/charts/caduser/v0.1.0/templates/pvc-media.yaml b/charts/caduser/v0.1.0/templates/pvc-media.yaml new file mode 100644 index 0000000..f35da7a --- /dev/null +++ b/charts/caduser/v0.1.0/templates/pvc-media.yaml @@ -0,0 +1,21 @@ +{{- if .Values.persistence.enabled }} +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include "caduser.fullname" . }}-media + labels: + {{- include "caduser.labels" . | nindent 4 }} +spec: + accessModes: + - {{ .Values.persistence.accessMode }} + resources: + requests: + storage: {{ .Values.persistence.size }} +{{- if .Values.persistence.storageClass }} +{{- if (eq "-" .Values.persistence.storageClass) }} + storageClassName: "" +{{- else }} + storageClassName: {{ .Values.persistence.storageClass }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/caduser/v0.1.0/templates/service.yaml b/charts/caduser/v0.1.0/templates/service.yaml new file mode 100644 index 0000000..f69e75a --- /dev/null +++ b/charts/caduser/v0.1.0/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "caduser.fullname" . }} + labels: + {{- include "caduser.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "caduser.selectorLabels" . | nindent 4 }} diff --git a/charts/caduser/v0.1.0/templates/serviceaccount.yaml b/charts/caduser/v0.1.0/templates/serviceaccount.yaml new file mode 100644 index 0000000..41323e5 --- /dev/null +++ b/charts/caduser/v0.1.0/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "caduser.serviceAccountName" . }} + labels: + {{- include "caduser.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/caduser/v0.1.0/values.yaml b/charts/caduser/v0.1.0/values.yaml new file mode 100644 index 0000000..ac949c8 --- /dev/null +++ b/charts/caduser/v0.1.0/values.yaml @@ -0,0 +1,134 @@ +# Default values for caduser. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: porto.interlegis.leg.br/ilb/caduser + pullPolicy: IfNotPresent + # Overrides the image tag whose default is the chart appVersion. + tag: "" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + # Specifies whether a service account should be created + create: true + # Annotations to add to the service account + annotations: {} + # The name of the service account to use. + # If not set and create is true, a name is generated using the fullname template + name: "" + +podAnnotations: {} + +podSecurityContext: + fsGroup: 101 # GID for the volume + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 80 + +persistence: + enabled: false + #storageClass: "" + accessMode: ReadWriteOnce + size: 2Gi + +caduser: + adminUsers: "admin@example.com" + debug: 'False' + emailPort: 25 + emailHost: smtp.domain.net + emailHostUser: "" + emailHostPassword: "" + emailSubjectPrefix: "[CadUser]" + emailUseLocaltime: 'False' + emailUseTls: 'False' + emailUseSsl: 'False' + emailTimeout: 10 + defaultFromEmail: no-reply@domain.net + maxmindAccountId: "" + maxmindLicenceKey: "" + moodleBaseUrl: "" + moodleApiToken: "" + hostname: 'caduser.domain.net' + +ingress: + enabled: true + class: nginx + tls: + enabled: true + # extra annotations only + annotations: {} + +postgresql: + # CloudNativePG cluster configuration + enabled: true + clusterName: caduser-pg + instances: 1 + image: ghcr.io/cloudnative-pg/postgresql:17.2 + databaseName: caduser + owner: caduser + storageSize: 1Gi + #storageClass: "" + superuserSecret: "" # If empty, will be auto-generated + # Locale settings for Brazilian Portuguese + initdb: + localeCollate: pt_BR.UTF-8 + localeCType: pt_BR.UTF-8 + encoding: UTF8 + resources: + requests: + cpu: 40m + memory: 128Mi + limits: + cpu: 1000m + memory: 512Mi + +memcached: + enabled: true + image: + repository: memcached + tag: "1.6.40" + service: + port: 11211 + resources: + requests: + cpu: 20m + memory: 64Mi + limits: + cpu: 100m + memory: 128Mi + +resources: + limits: + cpu: 1000m + memory: 1000Mi + requests: + cpu: 35m + memory: 512Mi + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 100 + targetCPUUtilizationPercentage: 80 + # targetMemoryUtilizationPercentage: 80 + +nodeSelector: {} + +tolerations: [] + +affinity: {}