local kube = import "k8s/configs/base.libsonnet"; local images = import "k8s/configs/images.libsonnet"; local templates = import "k8s/configs/templates/templates.libsonnet"; // N.B. Memcached password is not currently configurable // because I don't know if it can be configured via environment variable. local SecretParams = kube.simpleFieldStruct([ "name", "namespace", "admin_password", "psql_password", ]) { // "gitea" psql_name: "Z2l0ZWE=", psql_user: "Z2l0ZWE=", }; local InitSecret(params) = kube.Secret(params.namespace, params.name) { type: "Opaque", stringData+: { "init_gitea.sh": ||| #!/bin/bash mkdir -p /data/git/.ssh chmod -R 700 /data/git/.ssh mkdir -p /data/gitea/conf cp /etc/gitea/conf/app.ini /data/gitea/conf/app.ini chmod a+rwx /data/gitea/conf/app.ini echo '[database]' >> /data/gitea/conf/app.ini echo "DB_TYPE = $DB_TYPE" >> /data/gitea/conf/app.ini echo "HOST = $DB_HOST" >> /data/gitea/conf/app.ini echo "NAME = $DB_NAME" >> /data/gitea/conf/app.ini echo "PASSWD = $DB_PASSWD" >> /data/gitea/conf/app.ini echo "USER = $DB_USER" >> /data/gitea/conf/app.ini nc -v -w2 -z gitea-pg 5432 && \ su git -c ' \ set -x; \ gitea migrate; \ gitea admin user create --username gitea_admin --password "$(echo %(admin_password)s | base64 -d)" --email gitea@local.domain --admin --must-change-password=false \ || \ gitea admin user change-password --username gitea_admin --password "$(echo %(admin_password)s | base64 -d)"; \ ' ||| % {admin_password: params.admin_password}, } }; local Secret(params) = kube.Secret(params.namespace, params.name) { type: "Opaque", data+: { "psql-name": params.psql_name, "psql-user": params.psql_user, "psql-password": params.psql_password, } }; local Params = kube.simpleFieldStruct([ "namespace", "name", "ingressHost", "memcacheService", "postgresDbService", "postgresDbNamespace", "secretName", "initSecretName", "dataClaimName", ]) { image: images.Prod["gitea/gitea"], memcachePort: 11211, postgresDbPort: 5432, resources: { requests: { cpu: "300m", memory: "1500Mi", }, limits: { cpu: "600m", memory: "3000Mi", }, }, }; local ConfigMap(params) = kube.ConfigMap(params.namespace, params.name) { data: { "app.ini": ||| [cache] ADAPTER = memcache ENABLED = false HOST = %(memcacheService)s.%(namespace)s.default.svc.cluster.local:%(memcachePort)d [database] DB_TYPE = postgres [security] INSTALL_LOCK = true [service] DISABLE_REGISTRATION = true [server] APP_DATA_PATH = /data DOMAIN = %(ingressHost)s HTTP_PORT = 3000 PROTOCOL = http ROOT_URL = https://%(ingressHost)s ||| % { memcacheService: params.memcacheService, namespace: params.namespace, memcachePort: params.memcachePort, ingressHost: params.ingressHost, }, // SSH disabled because cluster port configuration is difficult. //SSH_DOMAIN = gitea.cheapassbox.com //SSH_LISTEN_PORT = 22 //SSH_PORT = 22 } }; local Labels(params) = { name: params.name, phase: "prod", }; local Selector(params) = { name: params.name, phase: "prod", }; local Annotations(params) = templates.annotations(params.filePath, std.thisFile); local Service(params) = kube.Service(params.namespace, params.name) { metadata+: { labels+: Labels(params), annotations+: Annotations(params), }, spec+: { selector: Selector(params), type: "ClusterIP", ports: [ { name: "http", port: 80, targetPort: 3000, }, ], } }; // Not used for now. local SshService(params) = kube.Service(params.namespace, params.name) { metadata+: { labels+: Labels(params), annotations+: Annotations(params), }, spec+: { type: "ClusterIP", ports: [ { name: "ssh", port: 22, targetPort: 22, protocol: "TCP", }, ], } }; local StatefulSet(params) = kube.StatefulSet(params.namespace, params.name) { metadata+: { labels+: Labels(params), annotations+: Annotations(params), }, spec+: { replicas: 1, selector: { matchLabels: Selector(params) }, serviceName: params.name, template: { metadata: { labels+: Labels(params), annotations+: Annotations(params), }, spec+: { securityContext: { fsGroup: 1000 }, initContainers: [ { name: "init", image: params.image, command: ["/usr/sbin/init_gitea.sh"], env: [ { name: "DB_TYPE", value: "postgres", }, { name: "DB_HOST", value: params.postgresDbService + "." + params.postgresDbNamespace + ".svc.cluster.local:" + params.postgresDbPort, }, { name: "DB_NAME", valueFrom: { secretKeyRef: { name: params.secretName, key: "psql-name" }, }, }, { name: "DB_USER", valueFrom: { secretKeyRef: { name: params.secretName, key: "psql-user" }, }, }, { name: "DB_PASSWD", valueFrom: { secretKeyRef: { name: params.secretName, key: "psql-password" }, }, }, ], volumeMounts: [ { name: "init", mountPath: "/usr/sbin", }, { name: "config", mountPath: "/etc/gitea/conf", }, { name: "data", mountPath: "/data", } ] }, ], terminationGracePeriodSeconds: 120, containers: [ { name: "gitea", image: params.image, imagePullPolicy: "IfNotPresent", env: [ /* { name: "SSH_LISTEN_PORT" value: "22" }, { name: "SSH_PORT" value: "22" }, */ { name: "DB_TYPE", value: "postgres", }, { name: "DB_HOST", value: params.postgresDbService + "." + params.postgresDbNamespace + ".svc.cluster.local:" + params.postgresDbPort, }, { name: "DB_NAME", valueFrom: { secretKeyRef: { name: params.secretName, key: "psql-name" }, }, }, { name: "DB_USER", valueFrom: { secretKeyRef: { name: params.secretName, key: "psql-user" }, }, }, { name: "DB_PASSWD", valueFrom: { secretKeyRef: { name: params.secretName, key: "psql-password" }, }, }, ], ports: [ /* { name: "ssh", containerPort: 22 }, */ { name: "http", containerPort: 3000 } ], livenessProbe: { tcpSocket: { port: "http" }, initialDelaySeconds: 200, timeoutSeconds: 1, periodSeconds: 10, successThreshold: 1, failureThreshold: 10, }, readinessProbe: { tcpSocket: { port: "http", }, initialDelaySeconds: 5, periodSeconds: 10, successThreshold: 1, failureThreshold: 3, }, resources: params.resources, volumeMounts: [ { name: "data", mountPath: "/data", }, ], }, ], volumes: [ { name: "init", secret: { secretName: params.initSecretName, defaultMode: 511, }, }, { name: "config", configMap: { name: params.name, } }, { name: "data", persistentVolumeClaim: { claimName: params.dataClaimName, }, } ], }, }, }, }; { SecretParams: SecretParams, InitSecret: InitSecret, Secret: Secret, Params: Params, ConfigMap: ConfigMap, Service: Service, StatefulSet: StatefulSet, App(params): { resources+: kube.List() { items_: { configMap: ConfigMap(params), service: Service(params), statefulSet: StatefulSet(params), }, }, }, }