Merge pull request #13 from Aignosi/feature/SIENTIAPDE-1309

SIENTIAPDE-1309: Enhance Project Configuration, Documentation, and Deployment
This commit is contained in:
Bruno Domingues
2025-11-07 16:32:36 -03:00
committed by GitHub
14 changed files with 198 additions and 91 deletions

View File

@@ -202,3 +202,24 @@ bin/local/
# Cache directories
.cache/
cache/
# Development and configuration files
.env.example
requirements-dev.txt
pyproject.toml
sonar-project.properties
todo-list.txt
validate.sh
run_local.sh
LICENSE
# Helm charts (development only)
sientia-module/
*.yaml
# Local directories
data/
logs/
models/
temp/
scripts/

5
.gitignore vendored
View File

@@ -235,7 +235,12 @@ scouter/pipelines/**/triggers.yaml
# Ignore temporary files
*.swp
# Ignore test run reports in model_manager/reports/temp (but keep temp folder and .gitkeep)
model_manager/reports/temp/*
!model_manager/reports/temp/.gitkeep
# Miscellaneous
git_key*
git_log
tmp/
sientia-module/

View File

@@ -28,7 +28,7 @@ ENV PATH="/opt/venv/bin:$PATH"
RUN pip install --upgrade pip setuptools wheel
# Copy requirements files for better Docker layer caching
COPY requirements.txt requirements-dev.txt ./
COPY requirements.txt ./
# Install only production dependencies with no cache
RUN --mount=type=ssh echo "=== Installing dependencies ===" && \

View File

@@ -59,6 +59,8 @@ An enterprise-grade ML model training orchestration platform built on Temporal.
- [Code Quality Standards](#code-quality-standards)
- [License](#license)
- [Support](#support)
- [Docker](#docker)
- [Helm Chart](#helm-chart)
## Features
@@ -1035,13 +1037,13 @@ For support and questions:
### Create image
```shell
```bash
$ docker build --ssh default --no-cache --progress=plain -t aignosi.azurecr.io/sientia-dataops-model-manager:0.0.0 .
```
### Create container
```shell
```bash
$ docker run --env-file .env --network="host" --name sientia-dataops-model-manager -d aignosi.azurecr.io/sientia-dataops-model-manager:0.0.0
$ docker logs -f sientia-dataops-model-manager
@@ -1049,16 +1051,64 @@ $ docker logs -f sientia-dataops-model-manager
### Login using access token
```shell
```bash
$ docker login -u bruno-aignosi -p LD/IyZ4vtDI7khRYnH4HzfdTx3toorg6hlCetJM54n+ACRDim3xO aignosi.azurecr.io
```
### Push image to repository
```shell
```bash
$ docker push aignosi.azurecr.io/sientia-dataops-model-manager:0.0.0
```
## Helm Chart
### Reference
https://aignosi-wiki.atlassian.net/wiki/spaces/IT1/pages/274563074/Como+utilizar+o+Helm+Repo+Privado
### Add Helm Chart repository
```bash
$ helm repo add sientia \
https://raw.githubusercontent.com/Aignosi/sientia-dataops-helm-repo/refs/heads/main/ \
--username $GITHUB_USER \
--password $GITHUB_PASS
# Update repository
$ helm repo update
# List repositories
$ helm repo list
# List versions of a specific chart
$ helm search repo sientia --versions
# List all charts available
$ helm search repo sientia
# List chart details
$ helm show all sientia/sientia-module
# Download chart to current directory
$ helm pull sientia/sientia-module --version 0.6.0 --untar
# Remove chart directory
$ rm -rf sientia-module
```
### Helm Install
```shell
$ helm upgrade --install sientia-dataops-model-manager sientia/sientia-module -n sientia --create-namespace -f ./values.yaml --version 0.6.0
```
### Uninstall Helm Chart
```shell
$ helm uninstall sientia-dataops-model-manager -n sientia
```
---
**Note**: The Model Manager system is designed for production use in industrial ML environments. Ensure proper security configuration and network isolation for production deployments.

View File

View File

@@ -15,20 +15,20 @@ class ExperimentStatus(str, Enum):
Attributes:
ORCHESTRATOR_VALIDATION_ERROR: Error in the parameters validation.
MAGE_WAITING_PROC: Initial status indicating experiment is registered and waiting for processing.
ORCHESTRATOR_WAITING_PROC: Initial status indicating experiment is registered and waiting for processing.
TRAINING_SUCCESS: Training completed successfully with model and metrics calculated.
TRAINING_ERROR: Training failed due to data issues, model errors, or other exceptions.
MLFLOW_SENT: Model successfully saved to MLFlow.
MLFLOW_SEND_ERROR: Model saving to MLFlow failed due to connection or serialization errors.
TRACKING_SENT: Model successfully saved to MLFlow.
TRACKING_SEND_ERROR: Model saving to MLFlow failed due to connection or serialization errors.
FILE_DELETED: Cleanup completed successfully with all artifacts removed.
FILE_DELETE_ERROR: Cleanup failed due to file system or MinIO errors.
"""
ORCHESTRATOR_VALIDATION_ERROR = 'ORCHESTRATOR_VALIDATION_ERROR'
MAGE_WAITING_PROC = 'MAGE_WAITING_PROC'
ORCHESTRATOR_WAITING_PROC = 'ORCHESTRATOR_WAITING_PROC'
TRAINING_SUCCESS = 'TRAINING_SUCCESS'
TRAINING_ERROR = 'TRAINING_ERROR'
MLFLOW_SENT = 'MLFLOW_SENT'
MLFLOW_SEND_ERROR = 'MLFLOW_SEND_ERROR'
TRACKING_SENT = 'TRACKING_SENT'
TRACKING_SEND_ERROR = 'TRACKING_SEND_ERROR'
FILE_DELETED = 'FILE_DELETED'
FILE_DELETE_ERROR = 'FILE_DELETE_ERROR'

View File

@@ -306,7 +306,7 @@ class ModelRepository:
"""
# Use microsecond precision to reduce collision probability
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S_%f')
run_dir = path.join(base_path, f'{run_name}_{timestamp}')
run_dir = path.join(base_path, 'temp', f'{run_name}_{timestamp}')
try:
makedirs(run_dir, exist_ok=True)

View File

@@ -163,7 +163,7 @@ class TrainModel:
Validate and convert training parameters from dict to TrainModelParams.
This method calls the validate_train_params activity to convert and validate
the input parameters. On success, updates DB status to MAGE_WAITING_PROC.
the input parameters. On success, updates DB status to ORCHESTRATOR_WAITING_PROC.
On error, updates DB status to ORCHESTRATOR_VALIDATION_ERROR.
Args:
@@ -192,7 +192,7 @@ class TrainModel:
metadata=metadata,
experiment_run_id=experiment_run_id,
update_type=UpdateType.STATUS,
status=ExperimentStatus.MAGE_WAITING_PROC,
status=ExperimentStatus.ORCHESTRATOR_WAITING_PROC,
)
return train_params
@@ -246,7 +246,7 @@ class TrainModel:
metadata=metadata,
experiment_run_id=experiment_run_id,
update_type=UpdateType.MODEL_SAVED,
status=ExperimentStatus.MLFLOW_SENT,
status=ExperimentStatus.TRACKING_SENT,
run_name=train_result.get('run_name'),
)
@@ -260,7 +260,7 @@ class TrainModel:
status = ExperimentStatus.TRAINING_ERROR
if isinstance(e, ModelTrainingError) and (e.model_trained and not e.model_saved):
status = ExperimentStatus.MLFLOW_SEND_ERROR
status = ExperimentStatus.TRACKING_SEND_ERROR
await self._update_experiment_run(
metadata=metadata,

View File

@@ -120,7 +120,7 @@ def insert_experiment_run(file_name: str, request_data: dict) -> int:
(
request_data['experimentName'],
request_data['username'],
'MAGE_REQUEST_SENT',
'ORCHESTRATOR_REQUEST_SENT',
now,
now,
MINIO_BUCKET,

View File

@@ -5,11 +5,11 @@ from model_manager.utils.models.experiment_status import ExperimentStatus
def test_experiment_status_values():
"""Test that all expected status values exist."""
assert ExperimentStatus.MAGE_WAITING_PROC == 'MAGE_WAITING_PROC'
assert ExperimentStatus.ORCHESTRATOR_WAITING_PROC == 'ORCHESTRATOR_WAITING_PROC'
assert ExperimentStatus.TRAINING_SUCCESS == 'TRAINING_SUCCESS'
assert ExperimentStatus.TRAINING_ERROR == 'TRAINING_ERROR'
assert ExperimentStatus.MLFLOW_SENT == 'MLFLOW_SENT'
assert ExperimentStatus.MLFLOW_SEND_ERROR == 'MLFLOW_SEND_ERROR'
assert ExperimentStatus.TRACKING_SENT == 'TRACKING_SENT'
assert ExperimentStatus.TRACKING_SEND_ERROR == 'TRACKING_SEND_ERROR'
assert ExperimentStatus.FILE_DELETED == 'FILE_DELETED'
assert ExperimentStatus.FILE_DELETE_ERROR == 'FILE_DELETE_ERROR'
@@ -28,11 +28,11 @@ def test_experiment_status_is_string():
def test_experiment_status_membership():
"""Test membership checks for status values."""
assert 'MAGE_WAITING_PROC' in [s.value for s in ExperimentStatus]
assert 'ORCHESTRATOR_WAITING_PROC' in [s.value for s in ExperimentStatus]
assert 'TRAINING_SUCCESS' in [s.value for s in ExperimentStatus]
assert 'TRAINING_ERROR' in [s.value for s in ExperimentStatus]
assert 'MLFLOW_SENT' in [s.value for s in ExperimentStatus]
assert 'MLFLOW_SEND_ERROR' in [s.value for s in ExperimentStatus]
assert 'TRACKING_SENT' in [s.value for s in ExperimentStatus]
assert 'TRACKING_SEND_ERROR' in [s.value for s in ExperimentStatus]
assert 'FILE_DELETED' in [s.value for s in ExperimentStatus]
assert 'FILE_DELETE_ERROR' in [s.value for s in ExperimentStatus]
@@ -41,39 +41,43 @@ def test_experiment_status_iteration():
"""Test that enum can be iterated."""
statuses = list(ExperimentStatus)
assert len(statuses) == 8
assert ExperimentStatus.MAGE_WAITING_PROC in statuses
assert ExperimentStatus.ORCHESTRATOR_WAITING_PROC in statuses
assert ExperimentStatus.TRAINING_SUCCESS in statuses
assert ExperimentStatus.TRAINING_ERROR in statuses
assert ExperimentStatus.MLFLOW_SENT in statuses
assert ExperimentStatus.MLFLOW_SEND_ERROR in statuses
assert ExperimentStatus.TRACKING_SENT in statuses
assert ExperimentStatus.TRACKING_SEND_ERROR in statuses
assert ExperimentStatus.FILE_DELETED in statuses
assert ExperimentStatus.FILE_DELETE_ERROR in statuses
def test_experiment_status_comparison():
"""Test that enum values can be compared with strings."""
assert ExperimentStatus.MAGE_WAITING_PROC == 'MAGE_WAITING_PROC'
assert ExperimentStatus.ORCHESTRATOR_WAITING_PROC == 'ORCHESTRATOR_WAITING_PROC'
assert ExperimentStatus.TRAINING_SUCCESS == 'TRAINING_SUCCESS'
assert ExperimentStatus.TRAINING_ERROR != 'TRAINING_SUCCESS'
def test_experiment_status_access_by_name():
"""Test accessing enum members by name."""
assert ExperimentStatus['MAGE_WAITING_PROC'] == ExperimentStatus.MAGE_WAITING_PROC
assert (
ExperimentStatus['ORCHESTRATOR_WAITING_PROC'] == ExperimentStatus.ORCHESTRATOR_WAITING_PROC
)
assert ExperimentStatus['TRAINING_SUCCESS'] == ExperimentStatus.TRAINING_SUCCESS
assert ExperimentStatus['TRAINING_ERROR'] == ExperimentStatus.TRAINING_ERROR
assert ExperimentStatus['MLFLOW_SENT'] == ExperimentStatus.MLFLOW_SENT
assert ExperimentStatus['MLFLOW_SEND_ERROR'] == ExperimentStatus.MLFLOW_SEND_ERROR
assert ExperimentStatus['TRACKING_SENT'] == ExperimentStatus.TRACKING_SENT
assert ExperimentStatus['TRACKING_SEND_ERROR'] == ExperimentStatus.TRACKING_SEND_ERROR
assert ExperimentStatus['FILE_DELETED'] == ExperimentStatus.FILE_DELETED
assert ExperimentStatus['FILE_DELETE_ERROR'] == ExperimentStatus.FILE_DELETE_ERROR
def test_experiment_status_access_by_value():
"""Test accessing enum members by value."""
assert ExperimentStatus('MAGE_WAITING_PROC') == ExperimentStatus.MAGE_WAITING_PROC
assert (
ExperimentStatus('ORCHESTRATOR_WAITING_PROC') == ExperimentStatus.ORCHESTRATOR_WAITING_PROC
)
assert ExperimentStatus('TRAINING_SUCCESS') == ExperimentStatus.TRAINING_SUCCESS
assert ExperimentStatus('TRAINING_ERROR') == ExperimentStatus.TRAINING_ERROR
assert ExperimentStatus('MLFLOW_SENT') == ExperimentStatus.MLFLOW_SENT
assert ExperimentStatus('MLFLOW_SEND_ERROR') == ExperimentStatus.MLFLOW_SEND_ERROR
assert ExperimentStatus('TRACKING_SENT') == ExperimentStatus.TRACKING_SENT
assert ExperimentStatus('TRACKING_SEND_ERROR') == ExperimentStatus.TRACKING_SEND_ERROR
assert ExperimentStatus('FILE_DELETED') == ExperimentStatus.FILE_DELETED
assert ExperimentStatus('FILE_DELETE_ERROR') == ExperimentStatus.FILE_DELETE_ERROR

View File

@@ -10,7 +10,7 @@ from model_manager.utils.models import (
def test_experiment_status_import():
"""Test that ExperimentStatus can be imported from models package."""
assert ExperimentStatus is not None
assert hasattr(ExperimentStatus, 'MAGE_WAITING_PROC')
assert hasattr(ExperimentStatus, 'ORCHESTRATOR_WAITING_PROC')
assert hasattr(ExperimentStatus, 'TRAINING_SUCCESS')

View File

@@ -289,7 +289,7 @@ def test_create_run_directory_success(
result = repo._create_run_directory('/tmp/reports', 'test_run') # noqa: S108
expected_path = os.path.join('/tmp/reports', 'test_run_20240101_120000_123456') # noqa: S108
expected_path = os.path.join('/tmp/reports/temp', 'test_run_20240101_120000_123456') # noqa: S108
assert result == expected_path
mock_makedirs.assert_called_once_with(expected_path, exist_ok=True)

View File

@@ -286,9 +286,9 @@ async def test_train_model_mlflow_error(mock_workflow_module, mock_train_params)
with pytest.raises(ModelTrainingError):
await workflow_instance._train_model(mock_train_params, 123, metadata)
# Verify MLFLOW_SEND_ERROR status was set
# Verify TRACKING_SEND_ERROR status was set
call_args = mock_workflow_module.execute_activity_method.call_args_list[1]
assert call_args[0][1]['status'] == ExperimentStatus.MLFLOW_SEND_ERROR
assert call_args[0][1]['status'] == ExperimentStatus.TRACKING_SEND_ERROR
@pytest.mark.asyncio
@@ -359,14 +359,14 @@ async def test_update_experiment_run_status_only(mock_workflow_module):
metadata=metadata,
experiment_run_id=123,
update_type=UpdateType.STATUS,
status=ExperimentStatus.MAGE_WAITING_PROC,
status=ExperimentStatus.ORCHESTRATOR_WAITING_PROC,
)
# Verify activity was called with correct parameters
call_args = mock_workflow_module.execute_activity_method.call_args[0]
assert call_args[1]['experiment_run_id'] == 123
assert call_args[1]['update_type'] == UpdateType.STATUS
assert call_args[1]['status'] == ExperimentStatus.MAGE_WAITING_PROC
assert call_args[1]['status'] == ExperimentStatus.ORCHESTRATOR_WAITING_PROC
assert 'error_message' not in call_args[1] or call_args[1].get('error_message') is None
@@ -411,7 +411,7 @@ async def test_update_experiment_run_with_run_name(mock_workflow_module):
metadata=metadata,
experiment_run_id=123,
update_type=UpdateType.MODEL_SAVED,
status=ExperimentStatus.MLFLOW_SENT,
status=ExperimentStatus.TRACKING_SENT,
run_name='test-run-123',
)
@@ -438,9 +438,9 @@ async def test_run_complete_workflow_success(
mock_workflow_module.execute_activity_method = AsyncMock(
side_effect=[
mock_train_params, # validate_train_params
None, # update status (MAGE_WAITING_PROC)
None, # update status (ORCHESTRATOR_WAITING_PROC)
train_result, # train_model
None, # update status (MLFLOW_SENT)
None, # update status (TRACKING_SENT)
None, # cleanup_resources
None, # update status (FILE_DELETED)
]
@@ -490,7 +490,7 @@ async def test_run_workflow_training_error(
mock_workflow_module.execute_activity_method = AsyncMock(
side_effect=[
mock_train_params, # validate_train_params
None, # update status (MAGE_WAITING_PROC)
None, # update status (ORCHESTRATOR_WAITING_PROC)
RuntimeError('Training failed'), # train_model fails
None, # update status (TRAINING_ERROR)
]
@@ -521,9 +521,9 @@ async def test_run_workflow_cleanup_error(
mock_workflow_module.execute_activity_method = AsyncMock(
side_effect=[
mock_train_params, # validate_train_params
None, # update status (MAGE_WAITING_PROC)
None, # update status (ORCHESTRATOR_WAITING_PROC)
train_result, # train_model
None, # update status (MLFLOW_SENT)
None, # update status (TRACKING_SENT)
RuntimeError('Cleanup failed'), # cleanup_resources fails
None, # update status (FILE_DELETE_ERROR)
]

View File

@@ -7,18 +7,19 @@ replicaCount: 1
# This sets the container image more information can be found here: https://kubernetes.io/docs/concepts/containers/images/
image:
repository: aignosi.azurecr.io/sientia-module-courier
repository: aignosi.azurecr.io/sientia-dataops-model-manager
# This sets the pull policy for images.
pullPolicy: Always
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: "0.0.2"
tag: "0.0.0"
0# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
# This is for the secrets for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
imagePullSecrets:
- name: docker-hub-secret
# This is to override the chart name.
nameOverride: "sientia-model-manager-worker"
fullnameOverride: "sientia-model-manager-worker"
nameOverride: "sientia-dataops-model-manager"
fullnameOverride: "sientia-dataops-model-manager"
namespace: sientia
# This section builds out the service account more information can be found here: https://kubernetes.io/docs/concepts/security/service-accounts/
@@ -31,7 +32,7 @@ serviceAccount:
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: "sientia-model-manager-worker"
name: "sientia-dataops-model-manager"
# This is for setting Kubernetes Annotations to a Pod.
# For more information checkout: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
@@ -51,7 +52,6 @@ securityContext: {}
# runAsNonRoot: true
# runAsUser: 1000
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
@@ -68,22 +68,21 @@ resources: {}
livenessProbe:
exec:
command:
- sh
- python3
- -c
- pgrep -f "model_manager.worker.worker"
- "import requests; requests.get('http://localhost:9090/metrics')"
initialDelaySeconds: 20
periodSeconds: 30
readinessProbe:
exec:
command:
- sh
- python3
- -c
- pgrep -f "model_manager.worker.worker"
- "import requests; requests.get('http://localhost:9090/metrics')"
initialDelaySeconds: 10
periodSeconds: 15
# This section is for setting up autoscaling more information can be found here: https://kubernetes.io/docs/concepts/workloads/autoscaling/
autoscaling:
enabled: false
@@ -93,17 +92,26 @@ autoscaling:
# targetMemoryUtilizationPercentage: 80
# Additional volumes on the output Deployment definition.
volumes: []
# - name: foo
# secret:
# secretName: mysecret
# optional: false
volumes:
- name: reports-volume
emptyDir:
sizeLimit: 1Gi
# Additional volumeMounts on the output Deployment definition.
volumeMounts: []
# - name: foo
# mountPath: "/etc/foo"
# readOnly: true
volumeMounts:
- name: reports-volume
mountPath: "/app/model_manager/reports/temp"
# Deployment strategy configuration
# More information: https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#strategy
deploymentStrategy:
type: Recreate
# rollingUpdate:
# maxSurge: 0
# maxUnavailable: 1
# Number of old ReplicaSets to retain
revisionHistoryLimit: 2
nodeSelector: {}
@@ -118,7 +126,6 @@ services:
port: 9091
targetPort: 9091
name: sdk-metrics
metrics:
enabled: true
type: ClusterIP
@@ -141,48 +148,32 @@ serviceMonitor:
path: /metrics
interval: 30s
relabelings: []
additionalLabels:
release: kube-prometheus-stack
env:
# Entrypoint variables
- name: GITHUB_REPO_URL
value: "git@github.com:Aignosi/sientia-dataops-model-manager.git"
- name: GITHUB_BRANCH
value: SIENTIAPDE-1222-ajustar-a-library-para-fazer-o-download-do-courier
- name: PYTHON_APP
value: "model_manager.worker.worker"
# Application variables
- name: POSTGRES_HOST
value: "paradedb-rw.paradedb.svc.cluster.local"
- name: POSTGRES_PORT
value: "5432"
- name: POSTGRES_USER
value: "sientia"
value: "postgres"
- name: POSTGRES_PASSWORD
value: "sientia"
value: "nFqc81y6kwmr2zuAIx43DhiOosFCVPpeEfTtTWZflkNjB2j1KtEeIANkhFR9mAX3"
- name: POSTGRES_DBNAME
value: "sientia"
value: "sientia-core-mlops-bff"
- name: POSTGRES_MIN_CONNECTIONS
value: "10"
- name: POSTGRES_MAX_CONNECTIONS
value: "30"
- name: MLFLOW_HOST
value: "http://sientia-tracker-mlflow-tracking.sientia-tracker.svc.cluster.local"
- name: MLFLOW_PORT
value: "80"
- name: MLFLOW_URL
value: "http://sientia-tracker-mlflow-tracking.sientia-tracker.svc.cluster.local:80"
- name: MLFLOW_USERNAME
value: "aignosi"
- name: MLFLOW_PASSWORD
value: "1L0FP50j3ncp123"
- name: KAFKA_BOOTSTRAP_SERVERS
value: "kafka.kafka.svc.cluster.local:9092"
- name: LOG_LEVEL
value: "DEBUG"
- name: HTTP_METRICS_PORT
@@ -208,15 +199,51 @@ env:
- name: MONGODB_TTL_INDEX_HOURS
value: "1"
- name: MINIO_ENDPOINT_URL
value: "http://minio.minio.svc.cluster.local:9000"
- name: MINIO_ACCESS_KEY
value: "model-training-user"
- name: MINIO_SECRET_KEY
value: "modelTrainingUser123"
- name: MINIO_REGION
value: "us-east-1"
- name: MINIO_USE_SSL
value: "false"
- name: MINIO_MAX_RETRY_ATTEMPTS
value: "3"
- name: MINIO_RETRY_MODE
value: "adaptive"
- name: MINIO_CONNECT_TIMEOUT
value: "10"
- name: MINIO_READ_TIMEOUT
value: "60"
- name: TIMEOUT_VALIDATE_PARAMS
value: "30"
- name: TIMEOUT_TRAIN_MODEL
value: "2700"
- name: TIMEOUT_DELETE_FILE
value: "120"
- name: TIMEOUT_UPDATE_DATABASE
value: "30"
- name: EXTRA_PIP_REQUIREMENTS
value: "git+https://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@github.com/Aignosi/sientia-mlops-library.git"
- name: POD_ID
valueFrom:
fieldRef:
fieldPath: metadata.name
ssh:
enabled: true
enabled: false
secretName: git-ssh-key-sientia-model-manager-worker
sshPath: /mnt/.ssh
knownHostsPath: /mnt/known_hosts
# kubectl create secret docker-registry docker-hub-secret --namespace sientia --docker-server=http://aignosi.azurecr.io --docker-username=aignosi --docker-password=5I5zpQ6sRaHqX1hD3dr+2mo647yO3FRc359/wu6gsP+ACRDRz5mp
# helm upgrade --install sientia-model-manager-worker sientia/sientia-module -n sientia --create-namespace -f ./values.yaml --version 0.5.0
# helm upgrade --install sientia-dataops-model-manager sientia/sientia-module -n sientia --create-namespace -f ./values.yaml --version 0.6.0
# kubectl create secret generic git-ssh-key-sientia-model-manager-worker \
# --namespace sientia \