Skip to content

Added initial docker/kubernetes/helm support #121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Use an official Python slim image
FROM python:3.10-slim

# Set a non-root user and group
RUN addgroup --system appgroup && adduser --system --group --home /app appuser

# Set working directory
WORKDIR /app/opentakserver

# Copy the contents of the current directory (i.e. the opentakserver folder) to /app
COPY . /app/

# Set ownership of the /app directory to the non-root user
RUN chown -R appuser:appgroup /app

# Install required system packages (if needed)
RUN apt-get update && apt-get install -y --no-install-recommends \
curl \
&& rm -rf /var/lib/apt/lists/*

# Create a Python virtual environment
RUN python -m venv /app/venv
ENV PATH="/app/venv/bin:$PATH"

# Upgrade pip and install OpenTAKServer along with any requirements
RUN pip install --upgrade pip && pip install poetry

RUN poetry config virtualenvs.create false \
&& poetry lock \
&& poetry install --no-interaction --no-ansi

# Set the non-root user for running the container
USER appuser

# Expose the port the application listens on
EXPOSE 8081
EXPOSE 8089

# Start OpenTAKServer when the container runs
CMD ["/bin/sh", "-c", "DOCKER_WORKAROUND=true flask db upgrade && opentakserver"]
6 changes: 6 additions & 0 deletions helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: opentakserver
description: A Helm chart for deploying OpenTAKServer
type: application
version: 0.1.0
appVersion: "latest"
23 changes: 23 additions & 0 deletions helm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenTAKServer Helm Chart

## Build

1. **Validate chart**
helm lint helm/

2. **Build chart**
helm package helm/

## Installation

1. **Update values.yaml**
Adjust values to fit your environment.

2. **Install the Chart**
helm install opentakserver ./opentakserver-helm

3. **Upgrade the Chart**
helm upgrade opentakserver ./opentakserver-helm

4. **Uninstall**
helm uninstall opentakserver
46 changes: 46 additions & 0 deletions helm/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: opentakserver-api
image: "{{ .Values.image.api.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8081
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
{{- range $key, $value := .Values.secretEnv }}
- name: {{ $key }}
valueFrom:
secretKeyRef:
name: opentakserver-secret
key: {{ $key }}
{{- end }}
volumeMounts:
- name: {{ .Values.volume.name }}
mountPath: {{ .Values.volume.mountPath }}
- name: opentakserver-ui
image: "{{ .Values.image.ui.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 8080
volumes:
- name: {{ .Values.volume.name }}
persistentVolumeClaim:
claimName: {{ .Release.Name }}-pvc
31 changes: 31 additions & 0 deletions helm/templates/ingressroute.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{{- if .Values.ingress.enabled -}}
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: {{ .Release.Name }}-ingress
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/name: {{ .Release.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
entryPoints:
- {{ .Values.ingress.entryPoint }}
routes:
- match: Host(`{{ .Values.ingress.host }}`) && (PathPrefix(`/api`) || PathPrefix(`/socket.io`))
kind: Rule
services:
- name: opentakserver-api
port: {{ .Values.service.api.port }}
- match: Host(`{{ .Values.ingress.host }}`) && PathPrefix(`/Marti`)
kind: Rule
services:
- name: opentakserver-api
port: {{ .Values.service.api.port }}
- match: Host(`{{ .Values.ingress.host }}`) && PathPrefix(`/`)
kind: Rule
services:
- name: opentakserver-ui
port: {{ .Values.service.ui.port }}
tls:
certResolver: {{ .Values.ingress.certResolver }}
{{- end }}
10 changes: 10 additions & 0 deletions helm/templates/pvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Release.Name }}-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ .Values.volume.size }}
9 changes: 9 additions & 0 deletions helm/templates/secrets.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Secret
metadata:
name: opentakserver-secret
type: Opaque
data:
{{- range .Values.secretEnv }}
{{ .name }}: {{ .value | b64enc }}
{{- end }}
27 changes: 27 additions & 0 deletions helm/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-api
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.api.port }}
targetPort: 8081
protocol: TCP
name: http
selector:
app: {{ .Release.Name }}
---
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-ui
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.ui.port }}
targetPort: 8080
protocol: TCP
name: http
selector:
app: {{ .Release.Name }}
44 changes: 44 additions & 0 deletions helm/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
replicaCount: 1

image:
api:
repository: server/opentakserver
ui:
repository: server/opentakserver-ui
tag: latest
pullPolicy: Always

service:
type: ClusterIP
api:
port: 5000
ui:
port: 5001

volume:
name: opentakserver-storage
size: 1Gi
mountPath: /app/data

env:
- name: OTS_DATA_FOLDER
value: /app/data
- name: OTS_RABBITMQ_SERVER_ADDRESS
value: rabbitmq
- name: OTS_RABBITMQ_USERNAME
value: user
- name: OTS_LISTENER_ADDRESS
value: 0.0.0.0

ingress:
enabled: true
host: "myopentakserver.instance.com"
entryPoint: "websecure"
certResolver: "myresolver"

secretEnv:
- name: OTS_RABBITMQ_PASSWORD
value: password

nodeSelector: {}
tolerations: []
28 changes: 16 additions & 12 deletions opentakserver/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@
from opentakserver.SocketServer import SocketServer
from pyfiglet import Figlet

try:
from opentakserver.mumble.mumble_ice_app import MumbleIceDaemon
except ModuleNotFoundError:
print("Mumble auth not supported on this platform")
if os.getenv('DOCKER_WORKAROUND', 'false').lower() != 'true':
try:
from opentakserver.mumble.mumble_ice_app import MumbleIceDaemon
except ModuleNotFoundError:
print("Mumble auth not supported on this platform")


def init_extensions(app):
Expand Down Expand Up @@ -114,14 +115,17 @@ def init_extensions(app):
socketio_logger = logger
socketio.init_app(app, logger=socketio_logger)

rabbit_connection = pika.BlockingConnection(pika.ConnectionParameters(app.config.get("OTS_RABBITMQ_SERVER_ADDRESS")))
channel = rabbit_connection.channel()
channel.exchange_declare('cot', durable=True, exchange_type='fanout')
channel.exchange_declare('dms', durable=True, exchange_type='direct')
channel.exchange_declare('chatrooms', durable=True, exchange_type='direct')
channel.queue_declare(queue='cot_controller')
channel.exchange_declare(exchange='cot_controller', exchange_type='fanout')
channel.exchange_declare("missions", durable=True, exchange_type='topic') # For Data Sync mission feeds
if os.getenv('DOCKER_WORKAROUND', 'false').lower() != 'true':
rabbit_credentials = pika.PlainCredentials(app.config.get("OTS_RABBITMQ_USERNAME"), app.config.get("OTS_RABBITMQ_PASSWORD"))
rabbit_host = app.config.get("OTS_RABBITMQ_SERVER_ADDRESS")
rabbit_connection = pika.BlockingConnection(pika.ConnectionParameters(host=rabbit_host, credentials=rabbit_credentials))
channel = rabbit_connection.channel()
channel.exchange_declare('cot', durable=True, exchange_type='fanout')
channel.exchange_declare('dms', durable=True, exchange_type='direct')
channel.exchange_declare('chatrooms', durable=True, exchange_type='direct')
channel.queue_declare(queue='cot_controller')
channel.exchange_declare(exchange='cot_controller', exchange_type='fanout')
channel.exchange_declare("missions", durable=True, exchange_type='topic') # For Data Sync mission feeds

cot_thread = CoTController(app.app_context(), logger, db, socketio)
app.cot_thread = cot_thread
Expand Down
Loading