Extend helm to support Serverless functions and Analytics (#110)

main
Andrey Zhavoronkov 4 years ago committed by GitHub
parent 7e20b279af
commit 5e2eda7601
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -185,7 +185,7 @@ jobs:
LOGS_DIR: "${{ github.workspace }}/rest_api" LOGS_DIR: "${{ github.workspace }}/rest_api"
run: | run: |
mkdir $LOGS_DIR mkdir $LOGS_DIR
docker logs test_cvat_1 > $LOGS_DIR/cvat.log docker logs test_cvat_server_1 > $LOGS_DIR/cvat.log
docker logs test_cvat_opa_1 2> $LOGS_DIR/cvat_opa.log docker logs test_cvat_opa_1 2> $LOGS_DIR/cvat_opa.log
- name: Uploading "cvat" container logs as an artifact - name: Uploading "cvat" container logs as an artifact

@ -151,7 +151,7 @@ jobs:
LOGS_DIR: "${{ github.workspace }}/rest_api" LOGS_DIR: "${{ github.workspace }}/rest_api"
run: | run: |
mkdir $LOGS_DIR mkdir $LOGS_DIR
docker logs test_cvat_1 > $LOGS_DIR/cvat.log docker logs test_cvat_server_1 > $LOGS_DIR/cvat.log
docker logs test_cvat_opa_1 2> $LOGS_DIR/cvat_opa.log docker logs test_cvat_opa_1 2> $LOGS_DIR/cvat_opa.log
- name: Uploading "cvat" container logs as an artifact - name: Uploading "cvat" container logs as an artifact
@ -288,7 +288,7 @@ jobs:
DJANGO_SU_EMAIL: 'admin@localhost.company' DJANGO_SU_EMAIL: 'admin@localhost.company'
DJANGO_SU_PASSWORD: '12qwaszx' DJANGO_SU_PASSWORD: '12qwaszx'
run: | run: |
docker exec -i cvat /bin/bash -c "echo \"from django.contrib.auth.models import User; User.objects.create_superuser('${DJANGO_SU_NAME}', '${DJANGO_SU_EMAIL}', '${DJANGO_SU_PASSWORD}')\" | python3 ~/manage.py shell" docker exec -i cvat_server /bin/bash -c "echo \"from django.contrib.auth.models import User; User.objects.create_superuser('${DJANGO_SU_NAME}', '${DJANGO_SU_EMAIL}', '${DJANGO_SU_PASSWORD}')\" | python3 ~/manage.py shell"
cd ./tests cd ./tests
yarn --frozen-lockfile yarn --frozen-lockfile

@ -23,6 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- OpenCV.js caching and autoload (<https://github.com/cvat-ai/cvat/pull/30>) - OpenCV.js caching and autoload (<https://github.com/cvat-ai/cvat/pull/30>)
- Publishing dev version of CVAT docker images (<https://github.com/cvat-ai/cvat/pull/53>) - Publishing dev version of CVAT docker images (<https://github.com/cvat-ai/cvat/pull/53>)
- Support of Human Pose Estimation, Facial Landmarks (and similar) use-cases, new shape type: Skeleton (<https://github.com/cvat-ai/cvat/pull/1>) - Support of Human Pose Estimation, Facial Landmarks (and similar) use-cases, new shape type: Skeleton (<https://github.com/cvat-ai/cvat/pull/1>)
- Added helm chart support for serverless functions and analytics (<https://github.com/cvat-ai/cvat/pull/110>)
### Changed ### Changed
- Bumped nuclio version to 1.8.14 - Bumped nuclio version to 1.8.14

@ -139,14 +139,16 @@ COPY --from=build-image /tmp/openh264/openh264*.tar.gz /tmp/ffmpeg/ffmpeg*.tar.g
# Copy python virtual environment and FFmpeg binaries from build-image # Copy python virtual environment and FFmpeg binaries from build-image
COPY --from=build-image /opt/venv /opt/venv COPY --from=build-image /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:${PATH}" ENV PATH="/opt/venv/bin:${PATH}"
ENV NUMPROCS=1
COPY --from=build-image /opt/ffmpeg /usr COPY --from=build-image /opt/ffmpeg /usr
# Install and initialize CVAT, copy all necessary files # Install and initialize CVAT, copy all necessary files
COPY --chown=${USER} components /tmp/components COPY --chown=${USER} components /tmp/components
COPY --chown=${USER} supervisord/ ${HOME}/supervisord
COPY --chown=${USER} ssh ${HOME}/.ssh COPY --chown=${USER} ssh ${HOME}/.ssh
COPY --chown=${USER} supervisord.conf mod_wsgi.conf wait-for-it.sh manage.py ${HOME}/ COPY --chown=${USER} mod_wsgi.conf wait-for-it.sh manage.py ${HOME}/
COPY --chown=${USER} cvat/ ${HOME}/cvat
COPY --chown=${USER} utils/ ${HOME}/utils COPY --chown=${USER} utils/ ${HOME}/utils
COPY --chown=${USER} cvat/ ${HOME}/cvat
# RUN all commands below as 'django' user # RUN all commands below as 'django' user
USER ${USER} USER ${USER}
@ -156,3 +158,4 @@ RUN mkdir data share media keys logs /tmp/supervisord
EXPOSE 8080 EXPOSE 8080
ENTRYPOINT ["/usr/bin/supervisord"] ENTRYPOINT ["/usr/bin/supervisord"]
CMD ["-c", "supervisord/all.conf"]

@ -23,13 +23,15 @@ services:
args: args:
ELK_VERSION: 6.8.23 ELK_VERSION: 6.8.23
depends_on: ['elasticsearch'] depends_on: ['elasticsearch']
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
restart: always restart: always
cvat_kibana_setup: cvat_kibana_setup:
container_name: cvat_kibana_setup container_name: cvat_kibana_setup
image: cvat/server:${CVAT_VERSION:-latest} image: cvat/server:${CVAT_VERSION:-latest}
volumes: ['./components/analytics/kibana:/home/django/kibana:ro'] volumes: ['./components/analytics/kibana:/home/django/kibana:ro']
depends_on: ['cvat'] depends_on: ['cvat_server']
working_dir: '/home/django' working_dir: '/home/django'
networks: networks:
- cvat - cvat
@ -72,7 +74,7 @@ services:
depends_on: ['elasticsearch'] depends_on: ['elasticsearch']
restart: always restart: always
cvat: cvat_server:
environment: environment:
DJANGO_LOG_SERVER_HOST: logstash DJANGO_LOG_SERVER_HOST: logstash
DJANGO_LOG_SERVER_PORT: 8080 DJANGO_LOG_SERVER_PORT: 8080

@ -1,5 +1,4 @@
server.host: 0.0.0.0 server.host: 0.0.0.0
elasticsearch.url: http://elasticsearch:9200
elasticsearch.requestHeadersWhitelist: ['cookie', 'authorization', 'x-forwarded-user'] elasticsearch.requestHeadersWhitelist: ['cookie', 'authorization', 'x-forwarded-user']
kibana.defaultAppId: 'discover' kibana.defaultAppId: 'discover'
server.basePath: /analytics server.basePath: /analytics

@ -21,7 +21,7 @@ http:
middlewares: middlewares:
analytics-auth: analytics-auth:
forwardauth: forwardauth:
address: http://cvat:8080/analytics address: http://cvat_server:8080/analytics
authRequestHeaders: authRequestHeaders:
- "Cookie" - "Cookie"
- "Authorization" - "Authorization"

@ -1,3 +1,4 @@
queue.type: persisted queue.type: persisted
queue.max_bytes: 1gb queue.max_bytes: 1gb
queue.checkpoint.writes: 20 queue.checkpoint.writes: 20
http.host: 0.0.0.0

@ -18,7 +18,7 @@ services:
ports: ports:
- '8070:8070' - '8070:8070'
cvat: cvat_server:
environment: environment:
CVAT_SERVERLESS: 1 CVAT_SERVERLESS: 1

@ -839,7 +839,7 @@ def _import(importer, request, rq_id, Serializer, file_field_name, location_conf
serializer = Serializer(data=request.data) serializer = Serializer(data=request.data)
serializer.is_valid(raise_exception=True) serializer.is_valid(raise_exception=True)
payload_file = serializer.validated_data[file_field_name] payload_file = serializer.validated_data[file_field_name]
fd, filename = mkstemp(prefix='cvat_') fd, filename = mkstemp(prefix='cvat_', dir=settings.TMP_FILES_ROOT)
with open(filename, 'wb+') as f: with open(filename, 'wb+') as f:
for chunk in payload_file.chunks(): for chunk in payload_file.chunks():
f.write(chunk) f.write(chunk)
@ -863,9 +863,10 @@ def _import(importer, request, rq_id, Serializer, file_field_name, location_conf
data = _import_from_cloud_storage(storage, file_name) data = _import_from_cloud_storage(storage, file_name)
fd, filename = mkstemp(prefix='cvat_') fd, filename = mkstemp(prefix='cvat_', dir=settings.TMP_FILES_ROOT)
with open(filename, 'wb+') as f: with open(filename, 'wb+') as f:
f.write(data.getbuffer()) f.write(data.getbuffer())
rq_job = queue.enqueue_call( rq_job = queue.enqueue_call(
func=importer, func=importer,
args=(filename, request.user.id, org_id), args=(filename, request.user.id, org_id),

@ -2096,7 +2096,7 @@ def _import_annotations(request, rq_id, rq_func, pk, format_name,
serializer = AnnotationFileSerializer(data=request.data) serializer = AnnotationFileSerializer(data=request.data)
if serializer.is_valid(raise_exception=True): if serializer.is_valid(raise_exception=True):
anno_file = serializer.validated_data['annotation_file'] anno_file = serializer.validated_data['annotation_file']
fd, filename = mkstemp(prefix='cvat_{}'.format(pk)) fd, filename = mkstemp(prefix='cvat_{}'.format(pk), dir=settings.TMP_FILES_ROOT)
with open(filename, 'wb+') as f: with open(filename, 'wb+') as f:
for chunk in anno_file.chunks(): for chunk in anno_file.chunks():
f.write(chunk) f.write(chunk)
@ -2114,7 +2114,7 @@ def _import_annotations(request, rq_id, rq_func, pk, format_name,
data = _import_from_cloud_storage(storage, filename) data = _import_from_cloud_storage(storage, filename)
fd, filename = mkstemp(prefix='cvat_') fd, filename = mkstemp(prefix='cvat_{}'.format(pk), dir=settings.TMP_FILES_ROOT)
with open(filename, 'wb+') as f: with open(filename, 'wb+') as f:
f.write(data.getbuffer()) f.write(data.getbuffer())
@ -2262,7 +2262,7 @@ def _import_project_dataset(request, rq_id, rq_func, pk, format_name, filename=N
serializer = DatasetFileSerializer(data=request.data) serializer = DatasetFileSerializer(data=request.data)
if serializer.is_valid(raise_exception=True): if serializer.is_valid(raise_exception=True):
dataset_file = serializer.validated_data['dataset_file'] dataset_file = serializer.validated_data['dataset_file']
fd, filename = mkstemp(prefix='cvat_{}'.format(pk)) fd, filename = mkstemp(prefix='cvat_{}'.format(pk), dir=settings.TMP_FILES_ROOT)
with open(filename, 'wb+') as f: with open(filename, 'wb+') as f:
for chunk in dataset_file.chunks(): for chunk in dataset_file.chunks():
f.write(chunk) f.write(chunk)
@ -2281,7 +2281,7 @@ def _import_project_dataset(request, rq_id, rq_func, pk, format_name, filename=N
data = _import_from_cloud_storage(storage, filename) data = _import_from_cloud_storage(storage, filename)
fd, filename = mkstemp(prefix='cvat_') fd, filename = mkstemp(prefix='cvat_', dir=settings.TMP_FILES_ROOT)
with open(filename, 'wb+') as f: with open(filename, 'wb+') as f:
f.write(data.getbuffer()) f.write(data.getbuffer())

@ -41,14 +41,16 @@ class LambdaGateway:
NUCLIO_ROOT_URL = '/api/functions' NUCLIO_ROOT_URL = '/api/functions'
def _http(self, method="get", scheme=None, host=None, port=None, def _http(self, method="get", scheme=None, host=None, port=None,
url=None, headers=None, data=None): function_namespace=None, url=None, headers=None, data=None):
NUCLIO_GATEWAY = '{}://{}:{}'.format( NUCLIO_GATEWAY = '{}://{}:{}'.format(
scheme or settings.NUCLIO['SCHEME'], scheme or settings.NUCLIO['SCHEME'],
host or settings.NUCLIO['HOST'], host or settings.NUCLIO['HOST'],
port or settings.NUCLIO['PORT']) port or settings.NUCLIO['PORT'])
NUCLIO_FUNCTION_NAMESPACE = function_namespace or settings.NUCLIO['FUNCTION_NAMESPACE']
extra_headers = { extra_headers = {
'x-nuclio-project-name': 'cvat', 'x-nuclio-project-name': 'cvat',
'x-nuclio-function-namespace': 'nuclio', 'x-nuclio-function-namespace': NUCLIO_FUNCTION_NAMESPACE,
'x-nuclio-invoke-via': 'domain-name',
} }
if headers: if headers:
extra_headers.update(headers) extra_headers.update(headers)
@ -77,6 +79,13 @@ class LambdaGateway:
return response return response
def invoke(self, func, payload): def invoke(self, func, payload):
if os.getenv('KUBERNETES_SERVICE_HOST'):
return self._http(method="post", url='/api/function_invocations',
data=payload, headers={
'x-nuclio-function-name': func.id,
'x-nuclio-path': '/'
})
# Note: call the function directly without the nuclio dashboard # Note: call the function directly without the nuclio dashboard
# host.docker.internal for Linux will work only with Docker 20.10+ # host.docker.internal for Linux will work only with Docker 20.10+
NUCLIO_TIMEOUT = settings.NUCLIO['DEFAULT_TIMEOUT'] NUCLIO_TIMEOUT = settings.NUCLIO['DEFAULT_TIMEOUT']

@ -284,7 +284,8 @@ NUCLIO = {
'SCHEME': os.getenv('CVAT_NUCLIO_SCHEME', 'http'), 'SCHEME': os.getenv('CVAT_NUCLIO_SCHEME', 'http'),
'HOST': os.getenv('CVAT_NUCLIO_HOST', 'localhost'), 'HOST': os.getenv('CVAT_NUCLIO_HOST', 'localhost'),
'PORT': os.getenv('CVAT_NUCLIO_PORT', 8070), 'PORT': os.getenv('CVAT_NUCLIO_PORT', 8070),
'DEFAULT_TIMEOUT': os.getenv('CVAT_NUCLIO_DEFAULT_TIMEOUT', 120) 'DEFAULT_TIMEOUT': os.getenv('CVAT_NUCLIO_DEFAULT_TIMEOUT', 120),
'FUNCTION_NAMESPACE': os.getenv('CVAT_NUCLIO_FUNCTION_NAMESPACE', 'nuclio'),
} }
RQ_SHOW_ADMIN_LINK = True RQ_SHOW_ADMIN_LINK = True

@ -13,7 +13,7 @@ services:
context: . context: .
dockerfile: Dockerfile.ci dockerfile: Dockerfile.ci
depends_on: depends_on:
- cvat - cvat_server
environment: environment:
COVERALLS_SERVICE_NAME: COVERALLS_SERVICE_NAME:
CONTAINER_COVERAGE_DATA_DIR: CONTAINER_COVERAGE_DATA_DIR:

@ -6,7 +6,7 @@
version: '3.3' version: '3.3'
services: services:
cvat: cvat_server:
build: build:
context: . context: .
args: args:

@ -25,8 +25,8 @@ services:
networks: networks:
- cvat - cvat
cvat: cvat_server:
container_name: cvat container_name: cvat_server
image: cvat/server:${CVAT_VERSION:-latest} image: cvat/server:${CVAT_VERSION:-latest}
restart: always restart: always
depends_on: depends_on:
@ -40,6 +40,8 @@ services:
CVAT_POSTGRES_HOST: 'cvat_db' CVAT_POSTGRES_HOST: 'cvat_db'
ADAPTIVE_AUTO_ANNOTATION: 'false' ADAPTIVE_AUTO_ANNOTATION: 'false'
no_proxy: elasticsearch,kibana,logstash,nuclio,opa,${no_proxy} no_proxy: elasticsearch,kibana,logstash,nuclio,opa,${no_proxy}
NUMPROCS: 1
command: -c supervisord/server.conf
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.http.services.cvat.loadbalancer.server.port=8080 - traefik.http.services.cvat.loadbalancer.server.port=8080
@ -55,12 +57,74 @@ services:
extra_hosts: extra_hosts:
- "host.docker.internal:host-gateway" - "host.docker.internal:host-gateway"
cvat_utils:
container_name: cvat_utils
image: cvat/server:${CVAT_VERSION:-latest}
restart: always
depends_on:
- cvat_redis
- cvat_db
- cvat_opa
environment:
CVAT_REDIS_HOST: 'cvat_redis'
CVAT_POSTGRES_HOST: 'cvat_db'
no_proxy: elasticsearch,kibana,logstash,nuclio,opa,${no_proxy}
command: -c supervisord/utils.conf
volumes:
- cvat_data:/home/django/data
- cvat_keys:/home/django/keys
- cvat_logs:/home/django/logs
networks:
- cvat
cvat_worker_default:
container_name: cvat_worker_default
image: cvat/server:${CVAT_VERSION:-latest}
restart: always
depends_on:
- cvat_redis
- cvat_db
- cvat_opa
environment:
CVAT_REDIS_HOST: 'cvat_redis'
CVAT_POSTGRES_HOST: 'cvat_db'
no_proxy: elasticsearch,kibana,logstash,nuclio,opa,${no_proxy}
NUMPROCS: 2
command: -c supervisord/worker.default.conf
volumes:
- cvat_data:/home/django/data
- cvat_keys:/home/django/keys
- cvat_logs:/home/django/logs
networks:
- cvat
cvat_worker_low:
container_name: cvat_worker_low
image: cvat/server:${CVAT_VERSION:-latest}
restart: always
depends_on:
- cvat_redis
- cvat_db
- cvat_opa
environment:
CVAT_REDIS_HOST: 'cvat_redis'
CVAT_POSTGRES_HOST: 'cvat_db'
no_proxy: elasticsearch,kibana,logstash,nuclio,opa,${no_proxy}
NUMPROCS: 1
command: -c supervisord/worker.low.conf
volumes:
- cvat_data:/home/django/data
- cvat_keys:/home/django/keys
- cvat_logs:/home/django/logs
networks:
- cvat
cvat_ui: cvat_ui:
container_name: cvat_ui container_name: cvat_ui
image: cvat/ui:${CVAT_VERSION:-latest} image: cvat/ui:${CVAT_VERSION:-latest}
restart: always restart: always
depends_on: depends_on:
- cvat - cvat_server
labels: labels:
- traefik.enable=true - traefik.enable=true
- traefik.http.services.cvat-ui.loadbalancer.server.port=80 - traefik.http.services.cvat-ui.loadbalancer.server.port=80

@ -26,10 +26,36 @@ appVersion: latest
dependencies: dependencies:
- name: redis - name: redis
version: "12.9.*" version: "16.13.*"
repository: https://charts.bitnami.com/bitnami repository: https://charts.bitnami.com/bitnami
condition: redis.enabled condition: redis.enabled
- name: postgresql - name: postgresql
version: "10.3.*" version: "10.16.*"
repository: https://charts.bitnami.com/bitnami repository: https://charts.bitnami.com/bitnami
condition: postgresql.enabled condition: postgresql.enabled
- name: nuclio
version: 0.12.1
repository: https://nuclio.github.io/nuclio/charts
condition: nuclio.enabled
- name: logstash
version: "6.8.*"
repository: https://helm.elastic.co
condition: analytics.enabled
- name: elasticsearch
version: "6.8.*"
repository: https://helm.elastic.co
condition: analytics.enabled
- name: kibana
version: "6.8.*"
repository: https://helm.elastic.co
condition: analytics.enabled
- name: traefik
version: 10.24.0
repository: https://helm.traefik.io/traefik
condition: ingress.enabled

@ -6,7 +6,8 @@
- [Optional steps](#optional-steps) - [Optional steps](#optional-steps)
- [Configuration](#configuration) - [Configuration](#configuration)
- [Postgresql password?](#postgresql-password) - [Postgresql password?](#postgresql-password)
- [Ingress parameters](#ingress-parameters) - [(Optional) Enable Auto annotation feature](#optional-enable-auto-annotation-feature)
- [(Optional) Enable Analytics](#optional-enable-analytics)
- [Deployment](#deployment) - [Deployment](#deployment)
- [With overrides:](#with-overrides) - [With overrides:](#with-overrides)
- [Without overrides:](#without-overrides) - [Without overrides:](#without-overrides)
@ -15,39 +16,54 @@
- [FAQ](#faq) - [FAQ](#faq)
- [What is kubernetes and how it is working?](#what-is-kubernetes-and-how-it-is-working) - [What is kubernetes and how it is working?](#what-is-kubernetes-and-how-it-is-working)
- [What is helm and how it is working?](#what-is-helm-and-how-it-is-working) - [What is helm and how it is working?](#what-is-helm-and-how-it-is-working)
- [How to enable ingress:](#how-to-enable-ingress) - [How to setup Minikube?](#how-to-setup-minikube)
- [How to understand what diff will be inflicted by 'helm upgrade'?](#how-to-understand-what-diff-will-be-inflicted-by-helm-upgrade) - [How to understand what diff will be inflicted by 'helm upgrade'?](#how-to-understand-what-diff-will-be-inflicted-by-helm-upgrade)
- [I want to use my own postgresql/redis with your chart.](#i-want-to-use-my-own-postgresqlredis-with-your-chart) - [I want to use my own postgresql/redis with your chart.](#i-want-to-use-my-own-postgresqlredis-with-your-chart)
- [I want to override some settings in values.yaml.](#i-want-to-override-some-settings-in-valuesyaml) - [I want to override some settings in values.yaml.](#i-want-to-override-some-settings-in-valuesyaml)
- [Why you used external charts to provide redis and postgres?](#why-you-used-external-charts-to-provide-redis-and-postgres) - [Why you used external charts to provide redis and postgres?](#why-you-used-external-charts-to-provide-redis-and-postgres)
## Prerequisites ## Prerequisites
1. Installed and configured [kubernetes](https://kubernetes.io/) cluster. 1. Installed and configured [kubernetes](https://kubernetes.io/) cluster. If you do not already have a cluster,
2. Installed [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl) you can create one by using [Minikube](https://github.com/kubernetes/minikube/). [How to setup Minikube](#how-to-setup-minikube).
3. Installed [Helm](https://helm.sh/). 1. Installed [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl)
4. Installed [dependencies](#installing-dependencies) 1. Installed [Helm](https://helm.sh/).
1. Installed [dependencies](#installing-dependencies)
### Installing dependencies ### Installing dependencies
To install and/or update run: To install and/or update run:
```sh ```shell
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm dependency update helm dependency update
``` ```
### Optional steps ### Optional steps
1. Install ingress of your choice (for example: <https://github.com/kubernetes/ingress-nginx>) 1. Ingress configuration for the Traefik ingress controller is enabled by default.
2. Create certificates for https (for example: <https://github.com/jetstack/cert-manager/>)
Note for Minikube use:
- because the Traefik creates its main service with `Loadbalanser` type,
which involve the assignment of externalIP by Cloud, what never happens on Minikube,
you need to explicitly set the externalIP address for the traefic service.
Add the following to `values.override.yaml` file:
```yaml
traefik:
service:
externalIPs:
- "your minikube IP (can be obtained with `minicube ip` command)"
```
- Also ensure that your CVAT ingress appears on your hosts file (/etc/hosts).
You can do this by running this command:
`cvat.local` is default domainname, you can override it via `values.override.yaml`.
```shell
echo "$(minikube ip) cvat.local" | sudo tee -a /etc/hosts
```
## Configuration ## Configuration
1. Create `values.override.yaml` file inside `helm-chart` directory. 1. Create `values.override.yaml` file inside `helm-chart` directory.
2. Fill `values.override.yaml` with new parameters for chart. 1. Fill `values.override.yaml` with new parameters for chart.
3. Override [postgresql password](#postgresql-password) 1. Override [postgresql password](#postgresql-password)
4. Create a rules.tar.gz archive containing all OPA rules inside this `helm-chart` directory. 1. Create a rules.tar.gz archive containing all OPA rules inside this `helm-chart` directory.
```sh ```shell
find ../cvat/apps/iam/rules -name "*.rego" -and ! -name '*test*' -exec basename {} \; | tar -czf rules.tar.gz -C ../cvat/apps/iam/rules/ -T - find ../cvat/apps/iam/rules -name "*.rego" -and ! -name '*test*' -exec basename {} \; | tar -czf rules.tar.gz -C ../cvat/apps/iam/rules/ -T -
``` ```
5. (Optional) Add [ingress parameters](#ingress-parameters)
### Postgresql password? ### Postgresql password?
Put below into your `values.override.yaml` Put below into your `values.override.yaml`
@ -66,48 +82,113 @@ postgresql:
existingSecret: <secret> existingSecret: <secret>
``` ```
### Ingress parameters ### (Optional) Enable Auto annotation feature
Paste below parameters to `values.override.yaml`
```yaml Before starting, ensure that the following prerequisites are met:
ingress: - The Nuclio [CLI (nuctl)](https://nuclio.io/docs/latest/reference/nuctl/nuctl/) is installed.
enabled: true To install the CLI, simply [download](https://github.com/nuclio/nuclio/releases)
annotations: the appropriate CLI version to your installation machine.
kubernetes.io/ingress.class: nginx
kubernetes.io/tls-acme: "true" 1. Set `nuclio.enabled: true` in your `values.override.yaml`
ingress.kubernetes.io/ssl-redirect: "true" 1. Run `helm dependency update` in `helm-chart` directory
nginx.ingress.kubernetes.io/use-regex: "true" 1. Because Nuclio functions are images that need to be pushed and pulled to/from the registry,
nginx.ingress.kubernetes.io/secure-backends: "true" you need to configure credentials to pull from your preferable registry with the following settings:
nginx.ingress.kubernetes.io/proxy-body-size: "0" Options:
nginx.ingress.kubernetes.io/proxy-send-timeout: "120" - `values.override.yaml` file:
nginx.ingress.kubernetes.io/proxy-read-timeout: "120" ```yaml
cert-manager.io/cluster-issuer: <issuer_name> registry:
hosts: loginUrl: someurl
- host: <your_domain> credentials:
paths: username: someuser
- path: "/api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.*" password: somepass
service: ```
name: <release_name>-backend-service - Or you can create a secret with credentials as described in the [guide](https://nuclio.io/docs/latest/setup/k8s/running-in-production-k8s/#the-preferred-deployment-method)
port: 8080 and set `registry.secretName=your-registry-credentials-secret-name` in the `values.override.yaml` file.
- path: "/"
pathType: "Prefix" - In the case of using Minikube, you can run a local unsecured registry with minikube add-ons:
service: ```shell
name: <release_name>-frontend-service minikube addons enable registry
port: 80 minikube addons enable registry-aliases
```
tls: Before Docker container images can be pushed to your newly created unsecure registry,
- hosts: you need to add its address (`$(minikube ip):5000`) to the list of unsecure registries to
- <your_domain> instruct Docker to accept working against it:
secretName: ingress-tls-cvat follow the instructions in the [Docker documentation](https://docs.docker.com/registry/insecure/#deploy-a-plain-http-registry)
```
You might also need to log into your registry account (docker login)
on the installation machine before running the deployment command.
1. Create cvat project:
```shell
nuctl --namespace <your cvat namespace> create project cvat
```
1. Finaly deploy the fuction, i.e.:
- using minikube registry:
```shell
nuctl deploy --project-name cvat --path serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio --registry $(minikube ip):5000 --run-registry registry.minikube
```
- using Docker hub:
```shell
nuctl deploy --project-name cvat --path serverless/tensorflow/faster_rcnn_inception_v2_coco/nuclio --registry docker.io/your_username
```
### (Optional) Enable Analytics
1. Set `analytics.enabled: true` in your `values.override.yaml`
1. Run `helm dependency update` in `helm-chart` directory
1. Since custom images are required here, you will need to create them yourself
and push them to your preferred docker registry.
You might also need to log into your registry account (docker login)
on the installation machine before running the push command.
How to set up local registry when using Minikube see [previous section](#how_to_enable_auto_annotation_feature)
- Let's build custom elasticsearch, logstash and kibana images with the following command
```shell
docker-compose -f docker-compose.yml -f components/analytics/docker-compose.analytics.yml build
```
- Tag images:
```shell
docker tag cvat_kibana:latest <your registry>/cvat_kibana:latest
docker tag cvat_elasticsearch:latest <your registry>/cvat_elasticsearch:latest
docker tag cvat_logstash:latest <your registry>/cvat_logstash:latest
```
- Push to registry
```shell
docker push <your registry>/cvat_kibana:latest
docker push <your registry>/cvat_elasticsearch:latest
docker push <your registry>/cvat_logstash:latest
```
- Add corresponding settings into `values.override.yaml`, i.e. for minikube registry:
```yaml
logstash:
image: "registry.minikube/cvat_logstash"
imageTag: "latest"
elasticsearch:
image: "registry.minikube/cvat_elasticsearch"
imageTag: "latest"
kibana:
image: "registry.minikube/cvat_kibana"
imageTag: "latest"
```
- Deploy
```shell
helm upgrade <release_name> --namespace <desired namespace> --install ./helm-chart -f ./helm-chart/values.yaml -f values.override.yaml
```
## Deployment ## Deployment
Make sure you are using correct kubernetes context. You can check it with `kubectl config current-context`. Make sure you are using correct kubernetes context. You can check it with `kubectl config current-context`.
> **Warning:** The k8s service name of Open Policy Agent is fixed to opa by default. > **Warning:** The k8s service name of Open Policy Agent is fixed to opa by default.
This is done to be compatible with CVAT 2.0 but limits this helm chart to a single release per namespace. > This is done to be compatible with CVAT 2.0 but limits this helm chart to a single release per namespace.
The OPA url currently can´t be set as an environment variable. > The OPA url currently can´t be set as an environment variable.
As soon as this is possible you can set cvat.opa.composeCompatibleServiceName > As soon as this is possible you can set cvat.opa.composeCompatibleServiceName
to false in your value.override.yaml and configure the opa url as additional env. > to false in your value.override.yaml and configure the opa url as additional env.
Execute following command from repo root directory Execute following command from repo root directory
### With overrides: ### With overrides:
@ -127,15 +208,17 @@ HELM_RELEASE_NAME="<release_name>" &&\
BACKEND_POD_NAME=$(kubectl get pod --namespace $HELM_RELEASE_NAMESPACE -l tier=backend,app.kubernetes.io/instance=$HELM_RELEASE_NAME -o jsonpath='{.items[0].metadata.name}') &&\ BACKEND_POD_NAME=$(kubectl get pod --namespace $HELM_RELEASE_NAMESPACE -l tier=backend,app.kubernetes.io/instance=$HELM_RELEASE_NAME -o jsonpath='{.items[0].metadata.name}') &&\
kubectl exec -it --namespace $HELM_RELEASE_NAMESPACE $BACKEND_POD_NAME -c cvat-backend-app-container -- python manage.py createsuperuser kubectl exec -it --namespace $HELM_RELEASE_NAMESPACE $BACKEND_POD_NAME -c cvat-backend-app-container -- python manage.py createsuperuser
``` ```
## FAQ ## FAQ
### What is kubernetes and how it is working? ### What is kubernetes and how it is working?
See <https://kubernetes.io/> See <https://kubernetes.io/>
### What is helm and how it is working? ### What is helm and how it is working?
See <https://helm.sh/> See <https://helm.sh/>
### How to enable ingress: ### How to setup Minikube
Just set `ingress.enabled:` to `true`, then copy example, uncomment it and change values there 1. Please follow the official Minikube installation [guide](https://minikube.sigs.k8s.io/docs/start/)
1. ```shell
minikube start --addons registry,registry-aliases
```
### How to understand what diff will be inflicted by 'helm upgrade'? ### How to understand what diff will be inflicted by 'helm upgrade'?
You can use <https://github.com/databus23/helm-diff#install> for that You can use <https://github.com/databus23/helm-diff#install> for that
### I want to use my own postgresql/redis with your chart. ### I want to use my own postgresql/redis with your chart.

@ -0,0 +1 @@
../serverless/common/openvino

@ -0,0 +1,56 @@
{{- $version := .Capabilities.KubeVersion.GitVersion -}}
{{- if and .Values.ingress.enabled .Values.analytics.enabled -}}
{{- $fullName := include "cvat.fullname" . -}}
{{- if semverCompare ">=1.19-0" $version -}}
apiVersion: networking.k8s.io/v1
{{- else if semverCompare ">=1.14-0" $version -}}
apiVersion: networking.k8s.io/v1beta1
{{- else -}}
apiVersion: extensions/v1beta1
{{- end }}
kind: Ingress
metadata:
name: {{ $fullName }}-analytics
namespace: {{ .Release.Namespace }}
labels:
{{- include "cvat.labels" . | nindent 4 }}
annotations:
traefik.ingress.kubernetes.io/router.middlewares: {{ $.Release.Namespace }}-stripprefix@kubernetescrd,
{{ $.Release.Namespace }}-forwardauth@kubernetescrd
{{- with .Values.analytics.ingress.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- if semverCompare ">=1.19-0" $version }}
ingressClassName: {{ .Values.ingress.className }}
{{- end }}
rules:
{{- range .Values.ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
- path: {{ $.Values.analytics.ingress.path }}
{{- if $.Values.analytics.ingress.pathType }}
pathType: {{ $.Values.analytics.ingress.pathType }}
{{- end }}
{{- if semverCompare ">=1.19-0" $version }}
backend:
service:
{{- if $.Values.analytics.external.useExternal }}
name: {{ $.Values.analytics.ingress.service.name }}
{{- else }}
name: {{ $.Release.Name }}-{{ $.Values.analytics.ingress.service.name }}
{{- end }}
port:
number: {{ $.Values.analytics.ingress.service.port }}
{{- else }}
backend:
{{- if $.Values.analytics.external.useExternal }}
serviceName: {{ $.Values.analytics.ingress.service.name }}
{{- else }}
serviceName: {{ $.Release.Name }}-{{ $.Values.analytics.ingress.service.name }}
{{- end }}
servicePort: {{ $.Values.analytics.ingress.service.port }}
{{- end }}
{{- end }}
{{- end }}

@ -0,0 +1,18 @@
{{- if and .Values.ingress.enabled .Values.analytics.enabled }}
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: forwardauth
namespace: {{ .Release.Namespace }}
annotations:
labels:
{{- include "cvat.labels" . | nindent 4 }}
spec:
forwardAuth:
address: http://{{ .Release.Name }}-backend-service:8080/analytics
authRequestHeaders:
- "Cookie"
- "Authorization"
{{- end }}

@ -0,0 +1,15 @@
{{- if and .Values.ingress.enabled .Values.analytics.enabled }}
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: stripprefix
namespace: {{ .Release.Namespace }}
annotations:
labels:
{{- include "cvat.labels" . | nindent 4 }}
spec:
stripPrefix:
prefixes:
- /analytics
{{- end }}

@ -0,0 +1,192 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-backend-server
namespace: {{ .Release.Namespace }}
labels:
app: cvat-app
tier: backend
component: server
{{- include "cvat.labels" . | nindent 4 }}
{{- with .Values.cvat.backend.server.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.cvat.backend.server.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.cvat.backend.server.replicas }}
strategy:
type: Recreate
selector:
matchLabels:
{{- include "cvat.labels" . | nindent 6 }}
{{- with .Values.cvat.backend.server.labels }}
{{- toYaml . | nindent 6 }}
{{- end }}
app: cvat-app
tier: backend
component: server
template:
metadata:
labels:
app: cvat-app
tier: backend
component: server
{{- include "cvat.labels" . | nindent 8 }}
{{- with .Values.cvat.backend.server.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.cvat.backend.server.annotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: cvat-app-backend-server-container
image: {{ .Values.cvat.backend.image }}:{{ .Values.cvat.backend.tag }}
{{- with .Values.cvat.backend.server.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
args: ["-c", "supervisord/server.conf"]
env:
- name: ALLOWED_HOSTS
value: {{ .Values.cvat.backend.server.envs.ALLOWED_HOSTS | squote}}
- name: DJANGO_MODWSGI_EXTRA_ARGS
value: {{ .Values.cvat.backend.server.envs.DJANGO_MODWSGI_EXTRA_ARGS}}
{{- if .Values.redis.enabled }}
- name: CVAT_REDIS_HOST
value: "{{ .Release.Name }}-redis-master"
{{- else }}
- name: CVAT_REDIS_HOST
value: "{{ .Values.redis.external.host }}"
{{- end }}
{{- if .Values.postgresql.enabled }}
- name: CVAT_POSTGRES_HOST
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-hostname
- name: CVAT_POSTGRES_USER
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-username
- name: CVAT_POSTGRES_DBNAME
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-database
- name: CVAT_POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-password
{{- else }}
- name: CVAT_POSTGRES_HOST
value: "{{ .Values.postgresql.external.host }}"
- name: CVAT_POSTGRES_USER
value: "{{ .Values.postgresql.external.user }}"
- name: CVAT_POSTGRES_DBNAME
value: "{{ .Values.postgresql.external.dbname }}"
- name: CVAT_POSTGRES_PASSWORD
value: "{{ .Values.postgresql.external.password }}"
- name: CVAT_POSTGRES_PORT
value: "{{ .Values.postgresql.external.port }}"
{{- end }}
{{- if .Values.nuclio.enabled }}
- name: CVAT_SERVERLESS
value: "1"
- name: CVAT_NUCLIO_HOST
value: "{{ .Release.Name }}-nuclio-dashboard"
- name: CVAT_NUCLIO_FUNCTION_NAMESPACE
value: "{{ .Release.Namespace }}"
{{- end }}
{{- if .Values.analytics.enabled}}
- name: CVAT_ANALYTICS
value: "1"
- name: DJANGO_LOG_SERVER_HOST
{{- if .Values.analytics.external.useExternal }}
value: "{{ .Values.analytics.logServerHost }}"
{{- else}}
value: "{{ .Release.Name }}-logstash"
{{- end}}
- name: DJANGO_LOG_SERVER_PORT
{{- if .Values.analytics.external.useExternal }}
value: "{{ .Values.analytics.logServerPort }}"
{{- else}}
value: "8080"
{{- end}}
{{- end}}
{{- with .Values.cvat.backend.server.additionalEnv }}
{{- toYaml . | nindent 10 }}
{{- end }}
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /home/django/data
name: cvat-backend-data
subPath: data
- mountPath: /home/django/keys
name: cvat-backend-data
subPath: keys
- mountPath: /home/django/logs
name: cvat-backend-data
subPath: logs
- mountPath: /home/django/models
name: cvat-backend-data
subPath: models
{{- with .Values.cvat.backend.server.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }}
{{- end }}
initContainers:
{{- if .Values.cvat.backend.permissionFix.enabled }}
- name: user-data-permission-fix
image: busybox
command: ["/bin/chmod", "-R", "777", "/home/django"]
{{- with .Values.cvat.backend.server.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
{{- if .Values.cvat.backend.defaultStorage.enabled }}
- mountPath: /home/django/data
name: cvat-backend-data
subPath: data
- mountPath: /home/django/keys
name: cvat-backend-data
subPath: keys
- mountPath: /home/django/logs
name: cvat-backend-data
subPath: logs
- mountPath: /home/django/models
name: cvat-backend-data
subPath: models
{{- end }}
{{- with .Values.cvat.backend.server.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- end }}
{{- with .Values.cvat.backend.server.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.cvat.backend.server.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
{{- if .Values.cvat.backend.defaultStorage.enabled }}
- name: cvat-backend-data
persistentVolumeClaim:
claimName: "{{ .Release.Name }}-backend-data"
{{- end }}
{{- with .Values.cvat.backend.server.additionalVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}

@ -7,11 +7,16 @@ metadata:
{{- include "cvat.labels" . | nindent 4 }} {{- include "cvat.labels" . | nindent 4 }}
app: cvat-app app: cvat-app
tier: backend tier: backend
annotations:
{{- with .Values.cvat.backend.service.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
spec: spec:
selector: selector:
app: cvat-app app: cvat-app
tier: backend tier: backend
component: server
{{- include "cvat.labels" . | nindent 4 }} {{- include "cvat.labels" . | nindent 4 }}
{{- with .Values.cvat.backend.service }} {{- with .Values.cvat.backend.service.spec }}
{{- toYaml . | nindent 2 }} {{- toYaml . | nindent 2 }}
{{- end }} {{- end }}

@ -1,61 +1,57 @@
apiVersion: apps/v1 apiVersion: apps/v1
kind: Deployment kind: Deployment
metadata: metadata:
name: {{ .Release.Name }}-backend name: {{ .Release.Name }}-backend-utils
namespace: {{ .Release.Namespace }} namespace: {{ .Release.Namespace }}
labels: labels:
app: cvat-app app: cvat-app
tier: backend tier: backend
component: utils
{{- include "cvat.labels" . | nindent 4 }} {{- include "cvat.labels" . | nindent 4 }}
{{- with .Values.cvat.backend.labels }} {{- with .Values.cvat.backend.utils.labels }}
{{- toYaml . | nindent 4 }} {{- toYaml . | nindent 4 }}
{{- end }} {{- end }}
{{- with .Values.cvat.backend.annotations }} {{- with .Values.cvat.backend.utils.annotations }}
annotations: annotations:
{{- toYaml . | nindent 4 }} {{- toYaml . | nindent 4 }}
{{- end }} {{- end }}
spec: spec:
replicas: {{ .Values.cvat.backend.replicas }} replicas: {{ .Values.cvat.backend.utils.replicas }}
strategy: strategy:
type: Recreate type: Recreate
selector: selector:
matchLabels: matchLabels:
{{- include "cvat.labels" . | nindent 6 }} {{- include "cvat.labels" . | nindent 6 }}
{{- with .Values.cvat.backend.labels }} {{- with .Values.cvat.backend.utils.labels }}
{{- toYaml . | nindent 6 }} {{- toYaml . | nindent 6 }}
{{- end }} {{- end }}
app: cvat-app app: cvat-app-utils
tier: backend tier: backend
component: utils
template: template:
metadata: metadata:
labels: labels:
app: cvat-app app: cvat-app-utils
tier: backend tier: backend
component: utils
{{- include "cvat.labels" . | nindent 8 }} {{- include "cvat.labels" . | nindent 8 }}
{{- with .Values.cvat.backend.labels }} {{- with .Values.cvat.backend.utils.labels }}
{{- toYaml . | nindent 8 }} {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
{{- with .Values.cvat.backend.annotations }} {{- with .Values.cvat.backend.utils.annotations }}
annotations: annotations:
{{- toYaml . | nindent 8 }} {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
spec: spec:
containers: containers:
- name: cvat-backend-app-container - name: cvat-app-backend-utils-container
image: {{ .Values.cvat.backend.image }}:{{ .Values.cvat.backend.tag }} image: {{ .Values.cvat.backend.image }}:{{ .Values.cvat.backend.tag }}
{{- with .Values.cvat.backend.resources }} {{- with .Values.cvat.backend.utils.resources }}
resources: resources:
{{- toYaml . | nindent 12 }} {{- toYaml . | nindent 12 }}
{{- end }} {{- end }}
args: ["-c", "supervisord/utils.conf"]
env: env:
- name: DJANGO_MODWSGI_EXTRA_ARGS
value: {{ .Values.cvat.backend.envs.DJANGO_MODWSGI_EXTRA_ARGS}}
- name: ALLOWED_HOSTS
value: {{ .Values.cvat.backend.envs.ALLOWED_HOSTS | squote}}
- name: UI_HOST
value: "{{ .Release.Name }}-frontend-service"
- name: UI_PORT
value: "{{ .Values.cvat.frontend.service.ports }}"
{{- if .Values.redis.enabled }} {{- if .Values.redis.enabled }}
- name: CVAT_REDIS_HOST - name: CVAT_REDIS_HOST
value: "{{ .Release.Name }}-redis-master" value: "{{ .Release.Name }}-redis-master"
@ -94,9 +90,15 @@ spec:
- name: CVAT_POSTGRES_PASSWORD - name: CVAT_POSTGRES_PASSWORD
value: "{{ .Values.postgresql.external.password }}" value: "{{ .Values.postgresql.external.password }}"
- name: CVAT_POSTGRES_PORT - name: CVAT_POSTGRES_PORT
value: "{{ .Values.postgresql.external.port }}" value: "{{ .Values.postgresql.external.port }}"
{{- end }} {{- end }}
{{- with .Values.cvat.backend.additionalEnv }} {{- if .Values.nuclio }}
- name: CVAT_SERVERLESS
value: "1"
- name: CVAT_NUCLIO_HOST
value: "{{ .Release.Name }}-nuclio-dashboard"
{{- end }}
{{- with .Values.cvat.backend.utils.additionalEnv }}
{{- toYaml . | nindent 10 }} {{- toYaml . | nindent 10 }}
{{- end }} {{- end }}
ports: ports:
@ -114,7 +116,7 @@ spec:
- mountPath: /home/django/models - mountPath: /home/django/models
name: cvat-backend-data name: cvat-backend-data
subPath: models subPath: models
{{- with .Values.cvat.backend.additionalVolumeMounts }} {{- with .Values.cvat.backend.utils.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }} {{- toYaml . | nindent 10 }}
{{- end }} {{- end }}
initContainers: initContainers:
@ -122,7 +124,7 @@ spec:
- name: user-data-permission-fix - name: user-data-permission-fix
image: busybox image: busybox
command: ["/bin/chmod", "-R", "777", "/home/django"] command: ["/bin/chmod", "-R", "777", "/home/django"]
{{- with .Values.cvat.backend.resources }} {{- with .Values.cvat.backend.utils.resources }}
resources: resources:
{{- toYaml . | nindent 12 }} {{- toYaml . | nindent 12 }}
{{- end }} {{- end }}
@ -141,15 +143,15 @@ spec:
name: cvat-backend-data name: cvat-backend-data
subPath: models subPath: models
{{- end }} {{- end }}
{{- with .Values.cvat.backend.additionalVolumeMounts }} {{- with .Values.cvat.backend.utils.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }} {{- toYaml . | nindent 10 }}
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- with .Values.cvat.backend.affinity }} {{- with .Values.cvat.backend.utils.affinity }}
affinity: affinity:
{{- toYaml . | nindent 8 }} {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
{{- with .Values.cvat.backend.tolerations }} {{- with .Values.cvat.backend.utils.tolerations }}
tolerations: tolerations:
{{- toYaml . | nindent 8 }} {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
@ -159,7 +161,7 @@ spec:
persistentVolumeClaim: persistentVolumeClaim:
claimName: "{{ .Release.Name }}-backend-data" claimName: "{{ .Release.Name }}-backend-data"
{{- end }} {{- end }}
{{- with .Values.cvat.backend.additionalVolumes }} {{- with .Values.cvat.backend.utils.additionalVolumes }}
{{- toYaml . | nindent 8 }} {{- toYaml . | nindent 8 }}
{{- end }} {{- end }}
{{- with .Values.imagePullSecrets }} {{- with .Values.imagePullSecrets }}

@ -0,0 +1,173 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-backend-worker-default
namespace: {{ .Release.Namespace }}
labels:
app: cvat-app
tier: backend
component: worker-default
{{- include "cvat.labels" . | nindent 4 }}
{{- with .Values.cvat.backend.worker.default.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.cvat.backend.worker.default.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.cvat.backend.worker.default.replicas }}
strategy:
type: Recreate
selector:
matchLabels:
{{- include "cvat.labels" . | nindent 6 }}
{{- with .Values.cvat.backend.worker.default.labels }}
{{- toYaml . | nindent 6 }}
{{- end }}
app: cvat-app-worker-default
tier: backend
component: worker-default
template:
metadata:
labels:
app: cvat-app-worker-default
tier: backend
component: worker-default
{{- include "cvat.labels" . | nindent 8 }}
{{- with .Values.cvat.backend.worker.default.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.cvat.backend.worker.default.annotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: cvat-app-backend-worker-default-container
image: {{ .Values.cvat.backend.image }}:{{ .Values.cvat.backend.tag }}
{{- with .Values.cvat.backend.worker.default.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
args: ["-c", "supervisord/worker.default.conf"]
env:
{{- if .Values.redis.enabled }}
- name: CVAT_REDIS_HOST
value: "{{ .Release.Name }}-redis-master"
{{- else }}
- name: CVAT_REDIS_HOST
value: "{{ .Values.redis.external.host }}"
{{- end }}
{{- if .Values.postgresql.enabled }}
- name: CVAT_POSTGRES_HOST
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-hostname
- name: CVAT_POSTGRES_USER
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-username
- name: CVAT_POSTGRES_DBNAME
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-database
- name: CVAT_POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-password
{{- else }}
- name: CVAT_POSTGRES_HOST
value: "{{ .Values.postgresql.external.host }}"
- name: CVAT_POSTGRES_USER
value: "{{ .Values.postgresql.external.user }}"
- name: CVAT_POSTGRES_DBNAME
value: "{{ .Values.postgresql.external.dbname }}"
- name: CVAT_POSTGRES_PASSWORD
value: "{{ .Values.postgresql.external.password }}"
- name: CVAT_POSTGRES_PORT
value: "{{ .Values.postgresql.external.port }}"
{{- end }}
{{- if .Values.nuclio }}
- name: CVAT_SERVERLESS
value: "1"
- name: CVAT_NUCLIO_HOST
value: "{{ .Release.Name }}-nuclio-dashboard"
{{- end }}
{{- with .Values.cvat.backend.worker.default.additionalEnv }}
{{- toYaml . | nindent 10 }}
{{- end }}
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /home/django/data
name: cvat-backend-data
subPath: data
- mountPath: /home/django/keys
name: cvat-backend-data
subPath: keys
- mountPath: /home/django/logs
name: cvat-backend-data
subPath: logs
- mountPath: /home/django/models
name: cvat-backend-data
subPath: models
- mountPath: /home/django/tmp_storage
name: cvat-backend-data
subPath: tmp_storage
{{- with .Values.cvat.backend.worker.default.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }}
{{- end }}
initContainers:
{{- if .Values.cvat.backend.permissionFix.enabled }}
- name: user-data-permission-fix
image: busybox
command: ["/bin/chmod", "-R", "777", "/home/django"]
{{- with .Values.cvat.backend.worker.default.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
{{- if .Values.cvat.backend.defaultStorage.enabled }}
- mountPath: /home/django/data
name: cvat-backend-data
subPath: data
- mountPath: /home/django/keys
name: cvat-backend-data
subPath: keys
- mountPath: /home/django/logs
name: cvat-backend-data
subPath: logs
- mountPath: /home/django/models
name: cvat-backend-data
subPath: models
{{- end }}
{{- with .Values.cvat.backend.worker.default.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- end }}
{{- with .Values.cvat.backend.worker.default.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.cvat.backend.worker.default.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
{{- if .Values.cvat.backend.defaultStorage.enabled }}
- name: cvat-backend-data
persistentVolumeClaim:
claimName: "{{ .Release.Name }}-backend-data"
{{- end }}
{{- with .Values.cvat.backend.worker.default.additionalVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}

@ -0,0 +1,173 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-backend-worker-low
namespace: {{ .Release.Namespace }}
labels:
app: cvat-app
tier: backend
component: worker-low
{{- include "cvat.labels" . | nindent 4 }}
{{- with .Values.cvat.backend.worker.low.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.cvat.backend.worker.low.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
replicas: {{ .Values.cvat.backend.worker.low.replicas }}
strategy:
type: Recreate
selector:
matchLabels:
{{- include "cvat.labels" . | nindent 6 }}
{{- with .Values.cvat.backend.worker.low.labels }}
{{- toYaml . | nindent 6 }}
{{- end }}
app: cvat-app
tier: backend
component: worker-low
template:
metadata:
labels:
app: cvat-app
tier: backend
component: worker-low
{{- include "cvat.labels" . | nindent 8 }}
{{- with .Values.cvat.backend.worker.low.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.cvat.backend.worker.low.annotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- name: cvat-app-backend-worker-low-container
image: {{ .Values.cvat.backend.image }}:{{ .Values.cvat.backend.tag }}
{{- with .Values.cvat.backend.worker.low.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
args: ["-c", "supervisord/worker.low.conf"]
env:
{{- if .Values.redis.enabled }}
- name: CVAT_REDIS_HOST
value: "{{ .Release.Name }}-redis-master"
{{- else }}
- name: CVAT_REDIS_HOST
value: "{{ .Values.redis.external.host }}"
{{- end }}
{{- if .Values.postgresql.enabled }}
- name: CVAT_POSTGRES_HOST
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-hostname
- name: CVAT_POSTGRES_USER
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-username
- name: CVAT_POSTGRES_DBNAME
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-database
- name: CVAT_POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: "{{ .Release.Name }}-{{ .Values.postgresql.secret.name }}"
key: postgresql-password
{{- else }}
- name: CVAT_POSTGRES_HOST
value: "{{ .Values.postgresql.external.host }}"
- name: CVAT_POSTGRES_USER
value: "{{ .Values.postgresql.external.user }}"
- name: CVAT_POSTGRES_DBNAME
value: "{{ .Values.postgresql.external.dbname }}"
- name: CVAT_POSTGRES_PASSWORD
value: "{{ .Values.postgresql.external.password }}"
- name: CVAT_POSTGRES_PORT
value: "{{ .Values.postgresql.external.port }}"
{{- end }}
{{- if .Values.nuclio }}
- name: CVAT_SERVERLESS
value: "1"
- name: CVAT_NUCLIO_HOST
value: "{{ .Release.Name }}-nuclio-dashboard"
{{- end }}
{{- with .Values.cvat.backend.worker.low.additionalEnv }}
{{- toYaml . | nindent 10 }}
{{- end }}
ports:
- containerPort: 8080
volumeMounts:
- mountPath: /home/django/data
name: cvat-backend-data
subPath: data
- mountPath: /home/django/keys
name: cvat-backend-data
subPath: keys
- mountPath: /home/django/logs
name: cvat-backend-data
subPath: logs
- mountPath: /home/django/models
name: cvat-backend-data
subPath: models
- mountPath: /home/django/tmp_storage
name: cvat-backend-data
subPath: tmp_storage
{{- with .Values.cvat.backend.worker.low.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }}
{{- end }}
initContainers:
{{- if .Values.cvat.backend.permissionFix.enabled }}
- name: user-data-permission-fix
image: busybox
command: ["/bin/chmod", "-R", "777", "/home/django"]
{{- with .Values.cvat.backend.worker.low.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
volumeMounts:
{{- if .Values.cvat.backend.defaultStorage.enabled }}
- mountPath: /home/django/data
name: cvat-backend-data
subPath: data
- mountPath: /home/django/keys
name: cvat-backend-data
subPath: keys
- mountPath: /home/django/logs
name: cvat-backend-data
subPath: logs
- mountPath: /home/django/models
name: cvat-backend-data
subPath: models
{{- end }}
{{- with .Values.cvat.backend.worker.low.additionalVolumeMounts }}
{{- toYaml . | nindent 10 }}
{{- end }}
{{- end }}
{{- with .Values.cvat.backend.worker.low.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.cvat.backend.worker.low.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
{{- if .Values.cvat.backend.defaultStorage.enabled }}
- name: cvat-backend-data
persistentVolumeClaim:
claimName: "{{ .Release.Name }}-backend-data"
{{- end }}
{{- with .Values.cvat.backend.worker.low.additionalVolumes }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}

@ -0,0 +1,19 @@
{{- if .Values.nuclio.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: cvat-nuclio-openvino-common
namespace: {{ .Release.Namespace }}
labels:
{{- include "cvat.labels" . | nindent 4 }}
app: cvat-app
tier: nuclio
{{- if semverCompare ">=1.21-0" .Capabilities.KubeVersion.GitVersion }}
immutable: true
{{- end }}
binaryData:
python3: |-
{{ .Files.Get "nuclio_func_common_files/python3" | b64enc }}
model_loader.py:
{{ .Files.Get "nuclio_func_common_files/model_loader.py" | b64enc }}
{{- end}}

@ -14,4 +14,4 @@ immutable: true
binaryData: binaryData:
rules.tar.gz: |- rules.tar.gz: |-
{{ .Files.Get "rules.tar.gz" | b64enc }} {{ .Files.Get "rules.tar.gz" | b64enc }}
{{- end}} {{- end}}

@ -20,7 +20,7 @@ metadata:
{{- end }} {{- end }}
spec: spec:
{{- if semverCompare ">=1.19-0" $version }} {{- if semverCompare ">=1.19-0" $version }}
ingressClassName: nginx ingressClassName: {{ .Values.ingress.className }}
{{- end }} {{- end }}
{{- if .Values.ingress.tls }} {{- if .Values.ingress.tls }}
tls: tls:
@ -45,7 +45,7 @@ spec:
{{- if semverCompare ">=1.19-0" $version }} {{- if semverCompare ">=1.19-0" $version }}
backend: backend:
service: service:
name: {{ .service.name }} name: {{ $.Release.Name }}-{{ .service.name }}
port: port:
number: {{ .service.port }} number: {{ .service.port }}
{{- else }} {{- else }}

@ -2,61 +2,75 @@
# This is a YAML-formatted file. # This is a YAML-formatted file.
# Declare variables to be passed into your templates. # Declare variables to be passed into your templates.
imagePullSecrets: [] imagePullSecrets: []
nameOverride: "" nameOverride: ""
fullnameOverride: "" fullnameOverride: ""
cvat: cvat:
backend: backend:
server:
replicas: 1
labels: {}
annotations: {}
resources: {}
affinity: {}
tolerations: []
envs:
ALLOWED_HOSTS: "*"
DJANGO_MODWSGI_EXTRA_ARGS: ""
additionalEnv: []
additionalVolumes: []
additionalVolumeMounts: []
worker:
default:
replicas: 2
labels: {}
annotations: {}
resources: {}
affinity: {}
tolerations: []
additionalEnv: []
additionalVolumes: []
additionalVolumeMounts: []
low:
replicas: 1
labels: {}
annotations: {}
resources: {}
affinity: {}
tolerations: []
additionalEnv: []
additionalVolumes: []
additionalVolumeMounts: []
utils:
replicas: 1
labels: {}
annotations: {}
resources: {}
affinity: {}
tolerations: []
additionalEnv: []
additionalVolumes: []
additionalVolumeMounts: []
replicas: 1 replicas: 1
image: cvat/server image: cvat/server
tag: latest tag: latest
permissionFix: permissionFix:
enabled: true enabled: true
labels: {}
# test: test
annotations: {}
# test.io/test: test
resources: {}
affinity: {}
tolerations: []
# nodeAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# nodeSelectorTerms:
# - matchExpressions:
# - key: kubernetes.io/e2e-az-name
# operator: In
# values:
# - e2e-az1
# - e2e-az2
envs:
ALLOWED_HOSTS: "*"
DJANGO_MODWSGI_EXTRA_ARGS: ""
additionalEnv: []
# Example:
# - name: volume-from-secret
# - name: TEST
# value: "test"
additionalVolumes: []
# Example(assumes that pvc was already created):
# - name: tmp
# persistentVolumeClaim:
# claimName: tmp
additionalVolumeMounts: []
# Example:
# - mountPath: /tmp
# name: tmp
# subPath: test
service: service:
type: ClusterIP annotations:
ports: traefik.ingress.kubernetes.io/service.sticky.cookie: "true"
- port: 8080 spec:
targetPort: 8080 type: ClusterIP
protocol: TCP ports:
name: http - port: 8080
targetPort: 8080
protocol: TCP
name: http
defaultStorage: defaultStorage:
enabled: true enabled: true
size: 20Gi size: 20Gi
frontend: frontend:
replicas: 1 replicas: 1
image: cvat/ui image: cvat/ui
@ -154,7 +168,7 @@ postgresql:
user: postgres user: postgres
password: postgres password: postgres
dbname: cvat dbname: cvat
# If not external following config will be applied by default # If not external following config will be applied by default
global: global:
postgresql: postgresql:
existingSecret: cvat-postgres-secret existingSecret: cvat-postgres-secret
@ -173,38 +187,125 @@ redis:
#See https://github.com/bitnami/charts/blob/master/bitnami/redis/ for more info #See https://github.com/bitnami/charts/blob/master/bitnami/redis/ for more info
enabled: true enabled: true
external: external:
host: 127.0.0.1 host: 127.0.0.1
usePassword: false auth:
enabled: false
cluster: cluster:
enabled: false enabled: false
ingress: nuclio:
enabled: false enabled: false
# Example for nginx ingress and cert manager # See https://github.com/nuclio/nuclio/blob/master/hack/k8s/helm/nuclio/values.yaml for more info
# annotations: # registry:
# kubernetes.io/ingress.class: nginx # loginUrl: someurl
# kubernetes.io/tls-acme: "true" # credentials:
# ingress.kubernetes.io/ssl-redirect: "true" # username: someuser
# nginx.ingress.kubernetes.io/use-regex: "true" # password: somepass
# nginx.ingress.kubernetes.io/secure-backends: "true"
# nginx.ingress.kubernetes.io/proxy-body-size: "0" analytics:
# nginx.ingress.kubernetes.io/proxy-send-timeout: "120" enabled: false
# nginx.ingress.kubernetes.io/proxy-read-timeout: "120" external:
# cert-manager.io/cluster-issuer: <issuer_name> useExternal: false
# hosts: logServerHost: logstash
# - host: <your domain> logServerPort: 8080
# paths: ingress:
# - path: "/api/.*|git/.*|tensorflow/.*|auto_annotation/.*|analytics/.*|static/.*|admin|admin/.*|documentation/.*|dextr/.*|reid/.*" path: /analytics
# service: pathType: "Prefix"
# name: <release_name>-backend-service annotations:
# port: 8080 kubernetes.io/ingress.class: traefik
# - path : "/" service:
# pathType: "Prefix" name: kibana
# service: port: 5601
# name: <release_name>-frontend-service
# port: 80 # Because custom images are required here, you'll need to build them yourself and add them to your preferred docker registry.
# # Ignored if analytics.enabled is false
# tls: # See https://github.com/elastic/helm-charts/blob/main/logstash/values.yaml for details
# - hosts: logstash:
# - <your domain> image: "your_logstash_image"
# secretName: ingress-tls-cvat imageTag: "latest"
# For compatibility with compose config
extraEnvs:
- name: "LOGSTASH_OUTPUT_HOST"
value: "elasticsearch-master:9200"
- name: LOGSTASH_OUTPUT_USER
value: ""
- name: LOGSTASH_OUTPUT_PASS
value: ""
imagePullPolicy: Always
service:
type: ClusterIP
ports:
- name: http
port: 8080
protocol: TCP
targetPort: 8080
# Ignored if analytics.enabled is false
# See https://github.com/elastic/helm-charts/blob/main/elasticsearch/values.yaml for details
elasticsearch:
image: "your_elasticsearch_image"
imageTag: "latest"
replicas: 1
minimumMasterNodes: 1
# Ignored if analytics.enabled is false
# See https://github.com/elastic/helm-charts/blob/main/kibana/values.yaml for details
kibana:
image: "your_kibana_image"
imageTag: "latest"
ingress:
enabled: true
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: web
kubernetes.io/ingress.class: traefik
hosts:
- host: cvat.local
paths:
- path: /api
pathType: "Prefix"
service:
name: backend-service
port: 8080
- path: /admin
pathType: "Prefix"
service:
name: backend-service
port: 8080
- path: /django-rq
pathType: "Prefix"
service:
name: backend-service
port: 8080
- path: /git
pathType: "Prefix"
service:
name: backend-service
port: 8080
- path: /opencv
pathType: "Prefix"
service:
name: backend-service
port: 8080
- path: /profiler
pathType: "Prefix"
service:
name: backend-service
port: 8080
- path : /
pathType: "Prefix"
service:
name: frontend-service
port: 80
# tls:
# - hosts:
# - <your_domain>
# secretName: ingress-tls-cvat
traefik:
logs:
general:
level: INFO
service:
externalIPs:
# - "192.168.49.2"

@ -19,6 +19,16 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.dextr image: cvat/openvino.dextr
baseImage: openvino/ubuntu18_runtime:2020.2 baseImage: openvino/ubuntu18_runtime:2020.2

@ -35,8 +35,18 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.omz.intel.face-detection-0205 image: cvat.openvino.omz.intel.face-detection-0205
baseImage: openvino/ubuntu18_dev:2021.1 baseImage: openvino/ubuntu18_dev:2021.1
directives: directives:

@ -16,8 +16,18 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.omz.intel.person-reidentification-retail-0300 image: cvat.openvino.omz.intel.person-reidentification-retail-0300
baseImage: openvino/ubuntu18_dev:2020.2 baseImage: openvino/ubuntu18_dev:2020.2
directives: directives:

@ -39,8 +39,18 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.omz.intel.semantic-segmentation-adas-0001 image: cvat.openvino.omz.intel.semantic-segmentation-adas-0001
baseImage: openvino/ubuntu18_dev:2020.2 baseImage: openvino/ubuntu18_dev:2020.2
directives: directives:

@ -19,8 +19,18 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.omz.intel.text-detection-0004 image: cvat.openvino.omz.intel.text-detection-0004
baseImage: openvino/ubuntu18_dev:2020.2 baseImage: openvino/ubuntu18_dev:2020.2
directives: directives:

@ -1,5 +1,5 @@
metadata: metadata:
name: openvino-omz-public-faster_rcnn_inception_v2_coco name: openvino-omz-public-faster_rcnn_inception-v2-coco
namespace: cvat namespace: cvat
annotations: annotations:
name: Faster RCNN name: Faster RCNN
@ -98,8 +98,18 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.omz.public.faster_rcnn_inception_v2_coco image: cvat.openvino.omz.public.faster_rcnn_inception_v2_coco
baseImage: openvino/ubuntu18_dev:2020.2 baseImage: openvino/ubuntu18_dev:2020.2
directives: directives:

@ -101,8 +101,18 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.omz.public.mask_rcnn_inception_resnet_v2_atrous_coco image: cvat.openvino.omz.public.mask_rcnn_inception_resnet_v2_atrous_coco
baseImage: openvino/ubuntu18_dev:2020.2 baseImage: openvino/ubuntu18_dev:2020.2
directives: directives:

@ -98,6 +98,16 @@ spec:
- name: NUCLIO_PYTHON_EXE_PATH - name: NUCLIO_PYTHON_EXE_PATH
value: /opt/nuclio/common/openvino/python3 value: /opt/nuclio/common/openvino/python3
volumes:
- volume:
name: openvino-common
configMap:
name: "cvat-nuclio-openvino-common"
defaultMode: 0750
volumeMount:
name: openvino-common
mountPath: /opt/nuclio/common/openvino
build: build:
image: cvat/openvino.omz.public.yolo-v3-tf image: cvat/openvino.omz.public.yolo-v3-tf
baseImage: openvino/ubuntu18_dev:2020.2 baseImage: openvino/ubuntu18_dev:2020.2

@ -1,5 +1,5 @@
metadata: metadata:
name: pth.facebookresearch.detectron2.retinanet_r101 name: pth.facebookresearch.detectron2.retinanet-r101
namespace: cvat namespace: cvat
annotations: annotations:
name: RetinaNet R101 name: RetinaNet R101
@ -96,7 +96,7 @@ spec:
eventTimeout: 30s eventTimeout: 30s
build: build:
image: cvat/pth.facebookresearch.detectron2.retinanet_r101 image: cvat.pth.facebookresearch.detectron2.retinanet_r101
baseImage: ubuntu:20.04 baseImage: ubuntu:20.04
directives: directives:

@ -1,5 +1,5 @@
metadata: metadata:
name: pth.facebookresearch.detectron2.retinanet_r101 name: pth.facebookresearch.detectron2.retinanet-r101
namespace: cvat namespace: cvat
annotations: annotations:
name: RetinaNet R101 name: RetinaNet R101
@ -96,7 +96,7 @@ spec:
eventTimeout: 30s eventTimeout: 30s
build: build:
image: cvat/pth.facebookresearch.detectron2.retinanet_r101 image: cvat.pth.facebookresearch.detectron2.retinanet_r101
baseImage: ubuntu:20.04 baseImage: ubuntu:20.04
directives: directives:

@ -17,7 +17,7 @@ spec:
value: /opt/nuclio/SiamMask:/opt/nuclio/SiamMask/experiments/siammask_sharp value: /opt/nuclio/SiamMask:/opt/nuclio/SiamMask/experiments/siammask_sharp
build: build:
image: cvat/pth.foolwood.siammask image: cvat.pth.foolwood.siammask
baseImage: nvidia/cuda:11.1-devel-ubuntu20.04 baseImage: nvidia/cuda:11.1-devel-ubuntu20.04
directives: directives:

@ -17,7 +17,7 @@ spec:
value: /opt/nuclio/SiamMask:/opt/nuclio/SiamMask/experiments/siammask_sharp value: /opt/nuclio/SiamMask:/opt/nuclio/SiamMask/experiments/siammask_sharp
build: build:
image: cvat/pth.foolwood.siammask image: cvat.pth.foolwood.siammask
baseImage: ubuntu:20.04 baseImage: ubuntu:20.04
directives: directives:

@ -21,7 +21,7 @@ spec:
value: /opt/nuclio/fbrs value: /opt/nuclio/fbrs
build: build:
image: cvat/pth.saic-vul.fbrs image: cvat.pth.saic-vul.fbrs
baseImage: python:3.6.11 baseImage: python:3.6.11
directives: directives:

@ -21,7 +21,7 @@ spec:
value: /opt/nuclio/hrnet value: /opt/nuclio/hrnet
build: build:
image: cvat/pth.saic-vul.hrnet image: cvat-pth.saic-vul.hrnet
baseImage: ubuntu:20.04 baseImage: ubuntu:20.04
directives: directives:

@ -22,7 +22,7 @@ spec:
value: /opt/nuclio/iog value: /opt/nuclio/iog
build: build:
image: cvat/pth.shiyinzhang.iog image: cvat.pth.shiyinzhang.iog
baseImage: continuumio/miniconda3 baseImage: continuumio/miniconda3
directives: directives:

@ -95,7 +95,7 @@ spec:
handler: main:handler handler: main:handler
eventTimeout: 30s eventTimeout: 30s
build: build:
image: cvat/ultralytics-yolov5 image: cvat.ultralytics-yolov5
baseImage: ultralytics/yolov5:latest-cpu baseImage: ultralytics/yolov5:latest-cpu
directives: directives:

@ -96,7 +96,7 @@ spec:
eventTimeout: 30s eventTimeout: 30s
build: build:
image: cvat/tf.faster_rcnn_inception_v2_coco image: cvat.tf.faster_rcnn_inception_v2_coco
baseImage: tensorflow/tensorflow:2.1.1-gpu baseImage: tensorflow/tensorflow:2.1.1-gpu
directives: directives:

@ -96,7 +96,7 @@ spec:
eventTimeout: 30s eventTimeout: 30s
build: build:
image: cvat/tf.faster_rcnn_inception_v2_coco image: cvat.tf.faster_rcnn_inception_v2_coco
baseImage: tensorflow/tensorflow:2.1.1 baseImage: tensorflow/tensorflow:2.1.1
directives: directives:

@ -100,7 +100,7 @@ spec:
- name: MASK_RCNN_DIR - name: MASK_RCNN_DIR
value: /opt/nuclio/Mask_RCNN value: /opt/nuclio/Mask_RCNN
build: build:
image: cvat/tf.matterport.mask_rcnn image: cvat.tf.matterport.mask_rcnn
baseImage: tensorflow/tensorflow:1.15.5-gpu-py3 baseImage: tensorflow/tensorflow:1.15.5-gpu-py3
directives: directives:
postCopy: postCopy:

@ -101,7 +101,7 @@ spec:
- name: MASK_RCNN_DIR - name: MASK_RCNN_DIR
value: /opt/nuclio/Mask_RCNN value: /opt/nuclio/Mask_RCNN
build: build:
image: cvat/tf.matterport.mask_rcnn image: cvat.tf.matterport.mask_rcnn
baseImage: tensorflow/tensorflow:1.13.1-py3 baseImage: tensorflow/tensorflow:1.13.1-py3
directives: directives:
postCopy: postCopy:
@ -114,7 +114,7 @@ spec:
- kind: RUN - kind: RUN
value: curl -L https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5 -o Mask_RCNN/mask_rcnn_coco.h5 value: curl -L https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5 -o Mask_RCNN/mask_rcnn_coco.h5
- kind: RUN - kind: RUN
value: pip3 install numpy cython pyyaml keras==2.1.0 scikit-image Pillow value: pip3 install numpy cython pyyaml keras==2.1.0 scikit-image 'imageio<=2.9.0' Pillow
triggers: triggers:
myHttpTrigger: myHttpTrigger:

@ -43,7 +43,7 @@ Backup data:
```bash ```bash
mkdir backup mkdir backup
docker run --rm --name temp_backup --volumes-from cvat_db -v $(pwd)/backup:/backup ubuntu tar -cjvf /backup/cvat_db.tar.bz2 /var/lib/postgresql/data docker run --rm --name temp_backup --volumes-from cvat_db -v $(pwd)/backup:/backup ubuntu tar -cjvf /backup/cvat_db.tar.bz2 /var/lib/postgresql/data
docker run --rm --name temp_backup --volumes-from cvat -v $(pwd)/backup:/backup ubuntu tar -cjvf /backup/cvat_data.tar.bz2 /home/django/data docker run --rm --name temp_backup --volumes-from cvat_server -v $(pwd)/backup:/backup ubuntu tar -cjvf /backup/cvat_data.tar.bz2 /home/django/data
# [optional] # [optional]
docker run --rm --name temp_backup --volumes-from cvat_elasticsearch -v $(pwd)/backup:/backup ubuntu tar -cjvf /backup/cvat_events.tar.bz2 /usr/share/elasticsearch/data docker run --rm --name temp_backup --volumes-from cvat_elasticsearch -v $(pwd)/backup:/backup ubuntu tar -cjvf /backup/cvat_events.tar.bz2 /usr/share/elasticsearch/data
``` ```
@ -74,7 +74,7 @@ Restore data:
```bash ```bash
cd <path_to_backup_folder> cd <path_to_backup_folder>
docker run --rm --name temp_backup --volumes-from cvat_db -v $(pwd):/backup ubuntu bash -c "cd /var/lib/postgresql/data && tar -xvf /backup/cvat_db.tar.bz2 --strip 4" docker run --rm --name temp_backup --volumes-from cvat_db -v $(pwd):/backup ubuntu bash -c "cd /var/lib/postgresql/data && tar -xvf /backup/cvat_db.tar.bz2 --strip 4"
docker run --rm --name temp_backup --volumes-from cvat -v $(pwd):/backup ubuntu bash -c "cd /home/django/data && tar -xvf /backup/cvat_data.tar.bz2 --strip 3" docker run --rm --name temp_backup --volumes-from cvat_server -v $(pwd):/backup ubuntu bash -c "cd /home/django/data && tar -xvf /backup/cvat_data.tar.bz2 --strip 3"
# [optional] # [optional]
docker run --rm --name temp_backup --volumes-from cvat_elasticsearch -v $(pwd):/backup ubuntu bash -c "cd /usr/share/elasticsearch/data && tar -xvf /backup/cvat_events.tar.bz2 --strip 4" docker run --rm --name temp_backup --volumes-from cvat_elasticsearch -v $(pwd):/backup ubuntu bash -c "cd /usr/share/elasticsearch/data && tar -xvf /backup/cvat_events.tar.bz2 --strip 4"
``` ```

@ -108,7 +108,7 @@ For access from China, read [sources for users from China](#sources-for-users-fr
below: below:
```bash ```bash
docker exec -it cvat bash -ic 'python3 ~/manage.py createsuperuser' docker exec -it cvat_server bash -ic 'python3 ~/manage.py createsuperuser'
``` ```
Choose a username and a password for your admin account. For more information Choose a username and a password for your admin account. For more information
@ -181,14 +181,14 @@ For access from China, read [sources for users from China](#sources-for-users-fr
below: below:
```bash ```bash
winpty docker exec -it cvat bash -ic 'python3 ~/manage.py createsuperuser' winpty docker exec -it cvat_server bash -ic 'python3 ~/manage.py createsuperuser'
``` ```
If you don't have winpty installed or the above command does not work, you may also try the following: If you don't have winpty installed or the above command does not work, you may also try the following:
```bash ```bash
# enter docker image first # enter docker image first
docker exec -it cvat /bin/bash docker exec -it cvat_server /bin/bash
# then run # then run
python3 ~/manage.py createsuperuser python3 ~/manage.py createsuperuser
``` ```
@ -257,7 +257,7 @@ For access from China, read [sources for users from China](#sources-for-users-fr
below: below:
```bash ```bash
docker exec -it cvat bash -ic 'python3 ~/manage.py createsuperuser' docker exec -it cvat_server bash -ic 'python3 ~/manage.py createsuperuser'
``` ```
Choose a username and a password for your admin account. For more information Choose a username and a password for your admin account. For more information
@ -369,9 +369,10 @@ docker-compose.override.yml for this purpose:
version: '3.3' version: '3.3'
services: services:
cvat: cvat_server:
environment: volumes:
CVAT_SHARE_URL: 'Mounted from /mnt/share host directory' - cvat_share:/home/django/share:ro
cvat_worker_default:
volumes: volumes:
- cvat_share:/home/django/share:ro - cvat_share:/home/django/share:ro
@ -383,9 +384,7 @@ volumes:
o: bind o: bind
``` ```
You can change the share device path to your actual share. For user convenience You can change the share device path to your actual share.
we have defined the environment variable \$CVAT_SHARE_URL. This variable
contains a text (url for example) which is shown in the client-share browser.
You can [mount](/docs/administration/advanced/mounting_cloud_storages/) You can [mount](/docs/administration/advanced/mounting_cloud_storages/)
your cloud storage as a FUSE and use it later as a share. your cloud storage as a FUSE and use it later as a share.

@ -18,7 +18,7 @@ weight: 1
groups to the user. Please use the command below to create an admin account: groups to the user. Please use the command below to create an admin account:
```bash ```bash
docker exec -it cvat bash -ic 'python3 ~/manage.py createsuperuser' docker exec -it cvat_server bash -ic 'python3 ~/manage.py createsuperuser'
``` ```
- If you want to create a non-admin account, you can do that using the link below - If you want to create a non-admin account, you can do that using the link below

@ -6,7 +6,7 @@ If you have any problems with a git repository cloning inside the CVAT:
- Make sure that SSH keys have been added to the CVAT container: - Make sure that SSH keys have been added to the CVAT container:
```bash ```bash
docker exec -it cvat bash -ic 'ls .ssh' docker exec -it cvat_server bash -ic 'ls .ssh'
``` ```
- If you need a proxy for connecting to the Internet, specify the socks_proxy variable before build the container. - If you need a proxy for connecting to the Internet, specify the socks_proxy variable before build the container.
@ -19,7 +19,7 @@ socks_proxy=proxy-example.com:1080 docker-compose build
- Try to clone a repository via SSH directly in the container by the command: - Try to clone a repository via SSH directly in the container by the command:
```bash ```bash
docker exec -it cvat bash -ic 'cd /tmp -r && git clone <ssh_repository_url>' docker exec -it cvat_server bash -ic 'cd /tmp -r && git clone <ssh_repository_url>'
``` ```
- Finally try to clone it on your local machine and if it's successful, contact with us via [Gitter chat](https://gitter.im/opencv-cvat) or [Github issues](https://github.com/opencv/cvat/issues). - Finally try to clone it on your local machine and if it's successful, contact with us via [Gitter chat](https://gitter.im/opencv-cvat) or [Github issues](https://github.com/opencv/cvat/issues).

@ -0,0 +1,37 @@
[unix_http_server]
file = /tmp/supervisord/supervisor.sock
[supervisorctl]
serverurl = unix:///tmp/supervisord/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisord]
nodaemon=true
logfile=%(ENV_HOME)s/logs/supervisord.log ; supervisord log file
logfile_maxbytes=50MB ; maximum size of logfile before rotation
logfile_backups=10 ; number of backed up logfiles
loglevel=debug ; info, debug, warn, trace
pidfile=/tmp/supervisord/supervisord.pid ; pidfile location
childlogdir=%(ENV_HOME)s/logs/ ; where child log files will live
[program:clamav_update]
command=bash -c "if [ \"${CLAM_AV}\" = 'yes' ]; then /usr/bin/freshclam -d \
-l %(ENV_HOME)s/logs/freshclam.log --foreground=true; fi"
[program:runserver]
; Here need to run a couple of commands to initialize DB and copy static files.
; We cannot initialize DB on build because the DB should be online. Also some
; apps are dynamically loaded by an environment variable. It can lead to issues
; with docker cache. Thus it is necessary to run collectstatic here for such
; apps.
command=%(ENV_HOME)s/wait-for-it.sh %(ENV_CVAT_POSTGRES_HOST)s:5432 -t 0 -- bash -ic \
"rm -f /tmp/cvat-server/httpd.pid && python3 ~/manage.py migrate && \
python3 ~/manage.py collectstatic --no-input && \
exec python3 $HOME/manage.py runmodwsgi --log-to-terminal --port 8080 \
--limit-request-body 1073741824 --log-level INFO --include-file ~/mod_wsgi.conf \
%(ENV_DJANGO_MODWSGI_EXTRA_ARGS)s --locale %(ENV_LC_ALL)s \
--server-root /tmp/cvat-server"
numprocs=%(ENV_NUMPROCS)s

@ -0,0 +1,37 @@
[unix_http_server]
file = /tmp/supervisord/supervisor.sock
[supervisorctl]
serverurl = unix:///tmp/supervisord/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisord]
nodaemon=true
logfile=%(ENV_HOME)s/logs/supervisord.log ; supervisord log file
logfile_maxbytes=50MB ; maximum size of logfile before rotation
logfile_backups=10 ; number of backed up logfiles
loglevel=debug ; info, debug, warn, trace
pidfile=/tmp/supervisord/supervisord.pid ; pidfile location
childlogdir=%(ENV_HOME)s/logs/ ; where child log files will live
[program:ssh-agent]
command=bash -c "rm /tmp/ssh-agent.sock -f && /usr/bin/ssh-agent -d -a /tmp/ssh-agent.sock"
priority=1
autorestart=true
[program:git_status_updater]
command=%(ENV_HOME)s/wait-for-it.sh %(ENV_CVAT_REDIS_HOST)s:6379 -t 0 -- bash -ic \
"python3 ~/manage.py update_git_states"
environment=SSH_AUTH_SOCK="/tmp/ssh-agent.sock"
numprocs=1
[program:rqscheduler]
command=%(ENV_HOME)s/wait-for-it.sh %(ENV_CVAT_REDIS_HOST)s:6379 -t 0 -- bash -ic \
"python3 /opt/venv/bin/rqscheduler --host %(ENV_CVAT_REDIS_HOST)s -i 30"
environment=SSH_AUTH_SOCK="/tmp/ssh-agent.sock"
numprocs=1
environment=SSH_AUTH_SOCK="/tmp/ssh-agent.sock"

@ -0,0 +1,37 @@
[unix_http_server]
file = /tmp/supervisord/supervisor.sock
[supervisorctl]
serverurl = unix:///tmp/supervisord/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisord]
nodaemon=true
logfile=%(ENV_HOME)s/logs/supervisord.log ; supervisord log file
logfile_maxbytes=50MB ; maximum size of logfile before rotation
logfile_backups=10 ; number of backed up logfiles
loglevel=debug ; info, debug, warn, trace
pidfile=/tmp/supervisord/supervisord.pid ; pidfile location
childlogdir=%(ENV_HOME)s/logs/ ; where child log files will live
[program:ssh-agent]
command=bash -c "rm /tmp/ssh-agent.sock -f && /usr/bin/ssh-agent -d -a /tmp/ssh-agent.sock"
priority=1
autorestart=true
[program:rqworker_default]
command=%(ENV_HOME)s/wait-for-it.sh %(ENV_CVAT_REDIS_HOST)s:6379 -t 0 -- bash -ic \
"exec python3 %(ENV_HOME)s/manage.py rqworker -v 3 default"
environment=SSH_AUTH_SOCK="/tmp/ssh-agent.sock"
numprocs=%(ENV_NUMPROCS)s
process_name=rqworker_default_%(process_num)s
environment=SSH_AUTH_SOCK="/tmp/ssh-agent.sock"
[program:clamav_update]
command=bash -c "if [ \"${CLAM_AV}\" = 'yes' ]; then /usr/bin/freshclam -d \
-l %(ENV_HOME)s/logs/freshclam.log --foreground=true; fi"
numprocs=1

@ -0,0 +1,36 @@
[unix_http_server]
file = /tmp/supervisord/supervisor.sock
[supervisorctl]
serverurl = unix:///tmp/supervisord/supervisor.sock
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisord]
nodaemon=true
logfile=%(ENV_HOME)s/logs/supervisord.log ; supervisord log file
logfile_maxbytes=50MB ; maximum size of logfile before rotation
logfile_backups=10 ; number of backed up logfiles
loglevel=debug ; info, debug, warn, trace
pidfile=/tmp/supervisord/supervisord.pid ; pidfile location
childlogdir=%(ENV_HOME)s/logs/ ; where child log files will live
[program:ssh-agent]
command=bash -c "rm /tmp/ssh-agent.sock -f && /usr/bin/ssh-agent -d -a /tmp/ssh-agent.sock"
priority=1
autorestart=true
[program:rqworker_low]
command=%(ENV_HOME)s/wait-for-it.sh %(ENV_CVAT_REDIS_HOST)s:6379 -t 0 -- bash -ic \
"exec python3 %(ENV_HOME)s/manage.py rqworker -v 3 low"
environment=SSH_AUTH_SOCK="/tmp/ssh-agent.sock"
numprocs=%(ENV_NUMPROCS)s
[program:clamav_update]
command=bash -c "if [ \"${CLAM_AV}\" = 'yes' ]; then /usr/bin/freshclam -d \
-l %(ENV_HOME)s/logs/freshclam.log --foreground=true; fi"
numprocs=1
environment=SSH_AUTH_SOCK="/tmp/ssh-agent.sock"

@ -21,7 +21,7 @@ context('Connected file share.', () => {
.should('be.visible') .should('be.visible')
.within(() => { .within(() => {
cy.get('[aria-label="plus-square"]').click(); cy.get('[aria-label="plus-square"]').click();
cy.exec('docker exec -i cvat /bin/bash -c "ls ~/share"').then((command) => { cy.exec('docker exec -i cvat_server /bin/bash -c "ls ~/share"').then((command) => {
stdoutToList = command.stdout.split('\n'); stdoutToList = command.stdout.split('\n');
// [image_case_107_1.png, image_case_107_2.png, image_case_107_3.png] // [image_case_107_1.png, image_case_107_2.png, image_case_107_3.png]
expect(stdoutToList.length).to.be.eq(3); expect(stdoutToList.length).to.be.eq(3);
@ -75,7 +75,7 @@ context('Connected file share.', () => {
expect(fileRenameCommand.code).to.be.eq(0); expect(fileRenameCommand.code).to.be.eq(0);
}, },
); );
cy.exec('docker exec -i cvat /bin/bash -c "find ~/share -name *.png -type f"').then( cy.exec('docker exec -i cvat_server /bin/bash -c "find ~/share -name *.png -type f"').then(
(findFilesCommand) => { (findFilesCommand) => {
// [image_case_107_2.png, image_case_107_3.png] // [image_case_107_2.png, image_case_107_3.png]
expect(findFilesCommand.stdout.split('\n').length).to.be.eq(2); expect(findFilesCommand.stdout.split('\n').length).to.be.eq(2);

@ -1,6 +1,6 @@
version: '3.3' version: '3.3'
services: services:
cvat: cvat_server:
environment: environment:
DJANGO_SETTINGS_MODULE: cvat.settings.email_settings DJANGO_SETTINGS_MODULE: cvat.settings.email_settings

@ -1,8 +1,6 @@
version: '3.3' version: '3.3'
services: services:
cvat: cvat_worker_default:
environment:
CVAT_SHARE_URL: 'Mounted from asset for case 107 host directory'
volumes: volumes:
- ./tests/cypress/integration/actions_tasks3/assets/case_107:/home/django/share:rw - ./tests/cypress/integration/actions_tasks3/assets/case_107:/home/django/share:rw

@ -68,8 +68,8 @@ for i, color in enumerate(colormap):
To backup DB and data volume, please use commands below. To backup DB and data volume, please use commands below.
```console ```console
docker exec test_cvat_1 python manage.py dumpdata --indent 2 --natural-foreign --exclude=auth.permission --exclude=contenttypes > assets/cvat_db/data.json docker exec test_cvat_server_1 python manage.py dumpdata --indent 2 --natural-foreign --exclude=auth.permission --exclude=contenttypes > assets/cvat_db/data.json
docker exec test_cvat_1 tar -cjv /home/django/data > assets/cvat_db/cvat_data.tar.bz2 docker exec test_cvat_server_1 tar -cjv /home/django/data > assets/cvat_db/cvat_data.tar.bz2
``` ```
> Note: if you won't be use --indent options or will be use with other value > Note: if you won't be use --indent options or will be use with other value
@ -89,8 +89,8 @@ python shared/utils/dump_objects.py
To restore DB and data volume, please use commands below. To restore DB and data volume, please use commands below.
```console ```console
cat shared/assets/cvat_db/data.json | docker exec -i test_cvat_1 python manage.py loaddata --format=json - cat shared/assets/cvat_db/data.json | docker exec -i test_cvat_server_1 python manage.py loaddata --format=json -
cat shared/assets/cvat_db/cvat_data.tar.bz2 | docker exec -i test_cvat_1 tar --strip 3 -C /home/django/data/ -xj cat shared/assets/cvat_db/cvat_data.tar.bz2 | docker exec -i test_cvat_server_1 tar --strip 3 -C /home/django/data/ -xj
``` ```
## Assets directory structure ## Assets directory structure
@ -174,7 +174,7 @@ Assets directory has two parts:
``` ```
docker exec test_cvat_db_1 dropdb --if-exists cvat docker exec test_cvat_db_1 dropdb --if-exists cvat
docker exec test_cvat_db_1 createdb cvat docker exec test_cvat_db_1 createdb cvat
docker exec test_cvat_1 python manage.py migrate docker exec test_cvat_server_1 python manage.py migrate
``` ```
1. Perform migrate when some relation does not exists. Example of error message: 1. Perform migrate when some relation does not exists. Example of error message:
@ -183,7 +183,7 @@ Assets directory has two parts:
``` ```
Solution: Solution:
``` ```
docker exec test_cvat_1 python manage.py migrate docker exec test_cvat_server_1 python manage.py migrate
``` ```
1. If for some reason you need to recreate cvat database, but using `dropdb` 1. If for some reason you need to recreate cvat database, but using `dropdb`
@ -195,5 +195,5 @@ Assets directory has two parts:
In this case you should terminate all existent connections for cvat database, In this case you should terminate all existent connections for cvat database,
you can perform it with command: you can perform it with command:
``` ```
docker exec test_cvat_db_1 psql -U root -d postgres -v from=cvat -v to=test_db -f restore.sql docker exec test_cvat_db_1 psql -U root -d postgres -v from=cvat_server -v to=test_db -f restore.sql
``` ```

@ -87,7 +87,7 @@ def docker_cp(source, target):
def exec_cvat(command): def exec_cvat(command):
_run(f"docker exec {PREFIX}_cvat_1 {command}") _run(f"docker exec {PREFIX}_cvat_server_1 {command}")
def exec_cvat_db(command): def exec_cvat_db(command):
@ -104,12 +104,12 @@ def running_containers():
def dump_db(): def dump_db():
if 'test_cvat_1' not in running_containers(): if 'test_cvat_server_1' not in running_containers():
pytest.exit("CVAT is not running") pytest.exit("CVAT is not running")
with open(osp.join(CVAT_DB_DIR, "data.json"), "w") as f: with open(osp.join(CVAT_DB_DIR, "data.json"), "w") as f:
try: try:
run( # nosec run( # nosec
"docker exec test_cvat_1 \ "docker exec test_cvat_server_1 \
python manage.py dumpdata \ python manage.py dumpdata \
--indent 2 --natural-foreign \ --indent 2 --natural-foreign \
--exclude=auth.permission --exclude=contenttypes".split(), --exclude=auth.permission --exclude=contenttypes".split(),
@ -150,13 +150,13 @@ def wait_for_server():
def restore_data_volumes(): def restore_data_volumes():
docker_cp( docker_cp(
osp.join(CVAT_DB_DIR, "cvat_data.tar.bz2"), osp.join(CVAT_DB_DIR, "cvat_data.tar.bz2"),
f"{PREFIX}_cvat_1:/tmp/cvat_data.tar.bz2", f"{PREFIX}_cvat_server_1:/tmp/cvat_data.tar.bz2",
) )
exec_cvat("tar --strip 3 -xjf /tmp/cvat_data.tar.bz2 -C /home/django/data/") exec_cvat("tar --strip 3 -xjf /tmp/cvat_data.tar.bz2 -C /home/django/data/")
def start_services(rebuild=False): def start_services(rebuild=False):
if any([cn in ["cvat", "cvat_db"] for cn in running_containers()]): if any([cn in ["cvat_server", "cvat_db"] for cn in running_containers()]):
pytest.exit( pytest.exit(
"It's looks like you already have running cvat containers. Stop them and try again. " "It's looks like you already have running cvat containers. Stop them and try again. "
f"List of running containers: {', '.join(running_containers())}" f"List of running containers: {', '.join(running_containers())}"
@ -172,7 +172,7 @@ def start_services(rebuild=False):
docker_cp( docker_cp(
osp.join(CVAT_DB_DIR, "restore.sql"), f"{PREFIX}_cvat_db_1:/tmp/restore.sql" osp.join(CVAT_DB_DIR, "restore.sql"), f"{PREFIX}_cvat_db_1:/tmp/restore.sql"
) )
docker_cp(osp.join(CVAT_DB_DIR, "data.json"), f"{PREFIX}_cvat_1:/tmp/data.json") docker_cp(osp.join(CVAT_DB_DIR, "data.json"), f"{PREFIX}_cvat_server_1:/tmp/data.json")
@pytest.fixture(autouse=True, scope="session") @pytest.fixture(autouse=True, scope="session")

Loading…
Cancel
Save