Skip to content

Commit

Permalink
release v0.7.2
Browse files Browse the repository at this point in the history
  • Loading branch information
kikkomep committed Apr 6, 2022
2 parents 305bcd7 + a847e90 commit 64769e7
Show file tree
Hide file tree
Showing 30 changed files with 886 additions and 71 deletions.
2 changes: 2 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
**/__pycache__
**/.npm
*.pyc
backups
data
docker/Dockerfile
docker*.yml
package-lock.json
**/node_modules
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ instance
*.pyc
./certs
**/node_modules
backups
data
lifemonitor/static/dist
lifemonitor/static/src/node_modules
docker-compose.yml
utils/certs/data
tests/config/data/crates/*.zip
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ services:
entrypoint: /bin/bash
restart: "no"
command: |
-c "wait-for-postgres.sh && flask init db"
-c "wait-for-postgres.sh && ./lm-admin.py db init"
depends_on:
- "db"
env_file: *env_file
Expand Down
2 changes: 1 addition & 1 deletion docker-compose.test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ services:
restart: "no"
entrypoint: /bin/bash
command: |
-c "wait-for-postgres.sh && flask init db && /usr/local/bin/lm_entrypoint.sh"
-c "wait-for-postgres.sh && ./lm-admin.py db init && /usr/local/bin/lm_entrypoint.sh"
environment:
- "FLASK_ENV=testingSupport"
- "HOME=/lm"
Expand Down
6 changes: 3 additions & 3 deletions docker/lifemonitor.Dockerfile
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
FROM python:3.7-buster as base
FROM python:3.9-buster as base

# Install base requirements
RUN apt-get update -q \
&& apt-get install -y --no-install-recommends \
bash \
bash lftp rsync \
redis-tools \
postgresql-client-11 \
&& apt-get clean -y && rm -rf /var/lib/apt/lists
Expand Down Expand Up @@ -60,7 +60,7 @@ RUN mkdir -p /var/data/lm \
USER lm

# Copy lifemonitor app
COPY --chown=lm:lm app.py gunicorn.conf.py /lm/
COPY --chown=lm:lm app.py lm-admin.py gunicorn.conf.py /lm/
COPY --chown=lm:lm specs /lm/specs
COPY --chown=lm:lm lifemonitor /lm/lifemonitor
COPY --chown=lm:lm migrations /lm/migrations
Expand Down
4 changes: 2 additions & 2 deletions k8s/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ 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.7.0
version: 0.8.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: 0.7.1
appVersion: 0.7.2

# Chart dependencies
dependencies:
Expand Down
10 changes: 10 additions & 0 deletions k8s/pvc-backend-backup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-api-backup
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 1Gi
22 changes: 22 additions & 0 deletions k8s/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,25 @@ Define mount points shared by some pods.
- name: lifemonitor-data
mountPath: "/var/data/lm"
{{- end -}}


{{/*
Define command to mirror (cluster) local backup to a remote site via SFTP
*/}}
{{- define "backup.remote.command" -}}
{{- if and .Values.backup.remote .Values.backup.remote.enabled }}
{{- if eq (.Values.backup.remote.protocol | lower) "sftp" }}
{{- printf "lftp -c \"open -u %s,%s sftp://%s; mirror -e -R /var/data/backup %s \""
.Values.backup.remote.user .Values.backup.remote.password
.Values.backup.remote.host .Values.backup.remote.path
}}
{{- else if eq (.Values.backup.remote.protocol | lower) "ftps" }}
{{- printf "lftp -c \"%s %s open -u %s,%s ftp://%s; mirror -e -R /var/data/backup %s \""
"set ftp:ssl-auth TLS; set ftp:ssl-force true;"
"set ftp:ssl-protect-list yes; set ftp:ssl-protect-data yes;"
.Values.backup.remote.user .Values.backup.remote.password
.Values.backup.remote.host .Values.backup.remote.path
}}
{{- end }}
{{- end }}
{{- end }}
2 changes: 1 addition & 1 deletion k8s/templates/backend-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ spec:
image: {{ include "chart.lifemonitor.image" . }}
imagePullPolicy: {{ .Values.lifemonitor.imagePullPolicy }}
command: ["/bin/sh","-c"]
args: ["wait-for-redis.sh && wait-for-postgres.sh && flask init wait-for-db"]
args: ["wait-for-redis.sh && wait-for-postgres.sh && ./lm-admin.py db wait-for-db"]
env:
{{- include "lifemonitor.common-env" . | nindent 12 }}
volumeMounts:
Expand Down
51 changes: 51 additions & 0 deletions k8s/templates/job-backup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{{- if .Values.backup.enabled -}}
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: {{ include "chart.fullname" . }}-backup
labels:
app.kubernetes.io/name: {{ include "chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
spec:
schedule: "{{ .Values.backup.schedule }}"
successfulJobsHistoryLimit: {{ .Values.backup.successfulJobsHistoryLimit }}
failedJobsHistoryLimit: {{ .Values.backup.failedJobsHistoryLimit }}
jobTemplate:
spec:
template:
spec:
containers:
- name: lifemonitor-backup
image: {{ include "chart.lifemonitor.image" . }}
imagePullPolicy: {{ .Values.lifemonitor.imagePullPolicy }}
command: ["/bin/bash","-c"]
args:
- wait-for-redis.sh && wait-for-postgres.sh ;
./lm-admin.py backup ;
env:
{{- include "lifemonitor.common-env" . | nindent 12 }}
volumeMounts:
{{- include "lifemonitor.common-volume-mounts" . | nindent 12 }}
- name: lifemonitor-backup
mountPath: "/var/data/backup"
restartPolicy: OnFailure
volumes:
{{- include "lifemonitor.common-volume" . | nindent 10 }}
- name: lifemonitor-backup
persistentVolumeClaim:
claimName: {{ .Values.backup.existingClaim }}
{{- with .Values.lifemonitor.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.lifemonitor.affinity }}
affinity:
{{- toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.lifemonitor.tolerations }}
tolerations:
{{- toYaml . | nindent 10 }}
{{- end }}
backoffLimit: 4
{{- end }}
2 changes: 1 addition & 1 deletion k8s/templates/job-init.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ spec:
image: {{ include "chart.lifemonitor.image" . }}
imagePullPolicy: {{ .Values.lifemonitor.imagePullPolicy }}
command: ["/bin/sh","-c"]
args: ["wait-for-redis.sh && wait-for-postgres.sh && flask init db && flask task-queue reset"]
args: ["wait-for-redis.sh && wait-for-postgres.sh && ./lm-admin.py db init && ./lm-admin.py task-queue reset"]
env:
{{- include "lifemonitor.common-env" . | nindent 10 }}
volumeMounts:
Expand Down
16 changes: 16 additions & 0 deletions k8s/templates/secret.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,22 @@ stringData:
MAIL_USE_SSL={{- if .Values.mail.ssl -}}True{{- else -}}False{{- end }}
MAIL_DEFAULT_SENDER={{ .Values.mail.default_sender }}
{{- if .Values.backup.enabled }}
# Backups
BACKUP_LOCAL_PATH="/var/data/backup"
{{- if .Values.backup.retain_days }}
BACKUP_RETAIN_DAYS={{ .Values.backup.retain_days }}
{{- end }}
{{- if .Values.backup.remote.enabled }}
BACKUP_REMOTE_PATH={{ .Values.backup.remote.path }}
BACKUP_REMOTE_HOST={{ .Values.backup.remote.host }}
BACKUP_REMOTE_USER={{ .Values.backup.remote.user }}
BACKUP_REMOTE_PASSWORD={{ .Values.backup.remote.password }}
BACKUP_REMOTE_ENABLE_TLS={{- if .Values.backup.remote.tls }}True{{- else -}}False{{- end }}
{{- end }}
{{- end }}
# Set admin credentials
LIFEMONITOR_ADMIN_PASSWORD={{ .Values.lifemonitor.administrator.password }}
Expand Down
2 changes: 1 addition & 1 deletion k8s/templates/worker-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ spec:
image: {{ include "chart.lifemonitor.image" . }}
imagePullPolicy: {{ .Values.lifemonitor.imagePullPolicy }}
command: ["/bin/sh","-c"]
args: ["wait-for-redis.sh && wait-for-postgres.sh && flask init wait-for-db"]
args: ["wait-for-redis.sh && wait-for-postgres.sh && ./lm-admin.py db wait-for-db"]
env:
{{- include "lifemonitor.common-env" . | nindent 12 }}
volumeMounts:
Expand Down
18 changes: 18 additions & 0 deletions k8s/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,24 @@ mail:
ssl: true
default_sender: ""

# Backup settings
backup:
enabled: false
schedule: "* 3 * * *"
retain_days: 30
successfulJobsHistoryLimit: 30
failedJobsHistoryLimit: 30
existingClaim: data-api-backup
# Settings to mirror the (cluster) local backup
# to a remote site via FTPS or SFTP
remote:
enabled: false
user: username
password: password
host: 10.0.1.135
path: /user/home/lm-backups
tls: true

lifemonitor:
replicaCount: 1

Expand Down
53 changes: 28 additions & 25 deletions lifemonitor/commands/api_key.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,44 +33,47 @@
# define the blueprint for DB commands
blueprint = Blueprint('api-key', __name__)

# set CLI help
blueprint.cli.help = "Manage admin API keys"


@blueprint.cli.command('create')
@click.argument("username")
@click.option("--scope", "scope", # type=click.Choice(ApiKey.SCOPES),
@click.option("--scope", "scope",
default="read", show_default=True)
@click.option("--length", "length", default=40, type=int, show_default=True)
@with_appcontext
def api_key_create(username, scope="read", length=40):
def api_key_create(scope="read", length=40):
"""
Create an API Key for a given user (identified by username)
Create an API Key for the 'admin' user
"""
logger.debug("Finding User '%s'...", username)
username = "admin"
logger.debug("Finding user '%s'...", username)
user = User.find_by_username(username)
if not user:
print("User not found", file=sys.stderr)
sys.exit(99)
logger.debug("User found: %r", user)
api_key = generate_new_api_key(user, scope, length)
print("%r" % api_key)
logger.debug("ApiKey created")
logger.debug("Api key created")


@blueprint.cli.command('list')
@click.argument("username")
@with_appcontext
def api_key_list(username):
def api_key_list():
"""
Create an API Key for a given user (identified by username)
Create an API Key for the 'admin' user
"""
logger.debug("Finding User '%s'...", username)
username = "admin"
logger.debug("Finding user '%s'...", username)
user = User.find_by_username(username)
if not user:
print("User not found", file=sys.stderr)
sys.exit(99)
logger.debug("User found: %r", user)
logger.info('-' * 82)
logger.info("User '%s' ApiKeys", user.username)
logger.info('-' * 82)
print('-' * 82)
print("Api keys of user '%s'" % user.username)
print('-' * 82)
for key in user.api_keys:
print(key)

Expand All @@ -80,27 +83,27 @@ def api_key_list(username):
@with_appcontext
def api_key_delete(api_key):
"""
Create an API Key for a given user (identified by username)
Create an API Key for the 'admin' user
"""
logger.debug("Finding ApiKey '%s'...", api_key)
logger.debug("Finding Api key '%s'...", api_key)
key = ApiKey.find(api_key)
if not key:
print("ApiKey not found", file=sys.stderr)
print("Api key not found", file=sys.stderr)
sys.exit(99)
logger.debug("ApiKey found: %r", key)
logger.debug("Api key found: %r", key)
key.delete()
print("ApiKey '%s' deleted!" % api_key)
logger.debug("ApiKey created")
print("Api key '%s' deleted!" % api_key)
logger.debug("Api key created")


@blueprint.cli.command('clean')
@click.argument("username")
@with_appcontext
def api_key_clean(username):
def api_key_clean():
"""
Create an API Key for a given user (identified by username)
Create an API Key for the 'admin' user
"""
logger.debug("Finding User '%s'...", username)
username = "admin"
logger.debug("Finding user '%s'...", username)
user = User.find_by_username(username)
if not user:
print("User not found", file=sys.stderr)
Expand All @@ -109,7 +112,7 @@ def api_key_clean(username):
count = 0
for key in user.api_keys:
key.delete()
print("ApiKey '%s' deleted!" % key.key)
print("Api key '%s' deleted!" % key.key)
count += 1
print("%d ApiKeys deleted!" % count, file=sys.stderr)
logger.debug("ApiKeys of User '%s' deleted!", user.username)
logger.debug("ApiKeys of user '%s' deleted!", user.username)
Loading

0 comments on commit 64769e7

Please sign in to comment.