Spaces:
Paused
Paused
Commit
Β·
ae122c6
1
Parent(s):
f870b34
feat(deploy): add helm chart
Browse files- .pre-commit-config.yaml +1 -0
- Makefile +18 -1
- deploy/helm/.helmignore +23 -0
- deploy/helm/Chart.yaml +13 -0
- deploy/helm/templates/NOTES.txt +36 -0
- deploy/helm/templates/_helpers.tpl +51 -0
- deploy/helm/templates/configmap.yaml +10 -0
- deploy/helm/templates/deployment.yaml +81 -0
- deploy/helm/templates/secret.yaml +16 -0
- deploy/helm/templates/service.yaml +20 -0
- deploy/helm/values.yaml +90 -0
- scripts/cleanup-helm.sh +86 -0
- scripts/cleanup-k8s.sh +83 -0
- scripts/deploy-helm.sh +94 -0
- scripts/deploy-k8s.sh +7 -96
- scripts/load-credentials.sh +113 -0
.pre-commit-config.yaml
CHANGED
@@ -4,6 +4,7 @@ repos:
|
|
4 |
hooks:
|
5 |
- id: check-yaml
|
6 |
args: ['--allow-multiple-documents']
|
|
|
7 |
- id: end-of-file-fixer
|
8 |
- id: trailing-whitespace
|
9 |
|
|
|
4 |
hooks:
|
5 |
- id: check-yaml
|
6 |
args: ['--allow-multiple-documents']
|
7 |
+
exclude: '^deploy/helm/templates/.*\.yaml$'
|
8 |
- id: end-of-file-fixer
|
9 |
- id: trailing-whitespace
|
10 |
|
Makefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
.PHONY: help venv install run test lint format clean setup-secrets deploy-k8s
|
2 |
|
3 |
PYTHON=python
|
4 |
PIP=pip
|
@@ -15,7 +15,11 @@ help:
|
|
15 |
@echo " lint Run pre-commit hooks (includes black, yaml, gitleaks)"
|
16 |
@echo " format Format code with black"
|
17 |
@echo " setup-secrets Copy and edit secrets template for local dev"
|
|
|
18 |
@echo " deploy-k8s Deploy application to Kubernetes"
|
|
|
|
|
|
|
19 |
@echo " clean Remove Python cache and virtual environment"
|
20 |
|
21 |
venv:
|
@@ -42,9 +46,22 @@ setup-secrets:
|
|
42 |
cp -n tests/secrets/nebius_secrets.py.template tests/secrets/cred.py; \
|
43 |
echo "Edit tests/secrets/cred.py to add your own API credentials."
|
44 |
|
|
|
|
|
|
|
|
|
45 |
deploy-k8s:
|
46 |
./scripts/deploy-k8s.sh
|
47 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
48 |
clean:
|
49 |
rm -rf $(VENV) __pycache__ */__pycache__ .pytest_cache .mypy_cache .coverage .hypothesis
|
50 |
find . -type f -name '*.pyc' -delete
|
|
|
1 |
+
.PHONY: help venv install run test lint format clean setup-secrets check-creds deploy-k8s deploy-helm cleanup-k8s cleanup-helm
|
2 |
|
3 |
PYTHON=python
|
4 |
PIP=pip
|
|
|
15 |
@echo " lint Run pre-commit hooks (includes black, yaml, gitleaks)"
|
16 |
@echo " format Format code with black"
|
17 |
@echo " setup-secrets Copy and edit secrets template for local dev"
|
18 |
+
@echo " check-creds Check and validate all required credentials"
|
19 |
@echo " deploy-k8s Deploy application to Kubernetes"
|
20 |
+
@echo " deploy-helm Deploy application using Helm"
|
21 |
+
@echo " cleanup-k8s Clean up Kubernetes deployment"
|
22 |
+
@echo " cleanup-helm Clean up Helm deployment"
|
23 |
@echo " clean Remove Python cache and virtual environment"
|
24 |
|
25 |
venv:
|
|
|
46 |
cp -n tests/secrets/nebius_secrets.py.template tests/secrets/cred.py; \
|
47 |
echo "Edit tests/secrets/cred.py to add your own API credentials."
|
48 |
|
49 |
+
check-creds:
|
50 |
+
@echo "π Checking credentials..."
|
51 |
+
@./scripts/load-credentials.sh
|
52 |
+
|
53 |
deploy-k8s:
|
54 |
./scripts/deploy-k8s.sh
|
55 |
|
56 |
+
deploy-helm:
|
57 |
+
./scripts/deploy-helm.sh
|
58 |
+
|
59 |
+
cleanup-k8s:
|
60 |
+
./scripts/cleanup-k8s.sh
|
61 |
+
|
62 |
+
cleanup-helm:
|
63 |
+
./scripts/cleanup-helm.sh
|
64 |
+
|
65 |
clean:
|
66 |
rm -rf $(VENV) __pycache__ */__pycache__ .pytest_cache .mypy_cache .coverage .hypothesis
|
67 |
find . -type f -name '*.pyc' -delete
|
deploy/helm/.helmignore
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Patterns to ignore when building packages.
|
2 |
+
# This supports shell glob matching, relative path matching, and
|
3 |
+
# negation (prefixed with !). Only one pattern per line.
|
4 |
+
.DS_Store
|
5 |
+
# Common VCS dirs
|
6 |
+
.git/
|
7 |
+
.gitignore
|
8 |
+
.bzr/
|
9 |
+
.bzrignore
|
10 |
+
.hg/
|
11 |
+
.hgignore
|
12 |
+
.svn/
|
13 |
+
# Common backup files
|
14 |
+
*.swp
|
15 |
+
*.bak
|
16 |
+
*.tmp
|
17 |
+
*.orig
|
18 |
+
*~
|
19 |
+
# Various IDEs
|
20 |
+
.project
|
21 |
+
.idea/
|
22 |
+
*.tmproj
|
23 |
+
.vscode/
|
deploy/helm/Chart.yaml
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
apiVersion: v2
|
2 |
+
name: yuga-planner
|
3 |
+
description: A Helm chart for Yuga Planner application
|
4 |
+
type: application
|
5 |
+
version: 0.1.0
|
6 |
+
appVersion: "latest"
|
7 |
+
maintainers:
|
8 |
+
- name: Yuga Planner Team
|
9 |
+
keywords:
|
10 |
+
- planner
|
11 |
+
- ai
|
12 |
+
- application
|
13 |
+
home: https://github.com/blackopsrepl/yuga-planner
|
deploy/helm/templates/NOTES.txt
ADDED
@@ -0,0 +1,36 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
1. Get the application URL by running these commands:
|
2 |
+
{{- if eq .Values.service.type "NodePort" }}
|
3 |
+
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ .Values.app.name }}-service)
|
4 |
+
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
5 |
+
echo http://$NODE_IP:$NODE_PORT
|
6 |
+
{{- else if eq .Values.service.type "LoadBalancer" }}
|
7 |
+
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
8 |
+
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ .Values.app.name }}-service'
|
9 |
+
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ .Values.app.name }}-service --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
10 |
+
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
11 |
+
{{- else if eq .Values.service.type "ClusterIP" }}
|
12 |
+
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "yuga-planner.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
13 |
+
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
14 |
+
echo "Visit http://127.0.0.1:8080 to use your application"
|
15 |
+
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
16 |
+
{{- end }}
|
17 |
+
|
18 |
+
2. Check the deployment status:
|
19 |
+
kubectl get deployments {{ .Values.app.name }} -n {{ .Release.Namespace }}
|
20 |
+
|
21 |
+
3. View the pods:
|
22 |
+
kubectl get pods -l app={{ .Values.app.name }} -n {{ .Release.Namespace }}
|
23 |
+
|
24 |
+
4. Check the logs:
|
25 |
+
kubectl logs -l app={{ .Values.app.name }} -n {{ .Release.Namespace }} -f
|
26 |
+
|
27 |
+
Note: Make sure to set the required environment variables before deployment:
|
28 |
+
- NEBIUS_API_KEY
|
29 |
+
- NEBIUS_MODEL
|
30 |
+
- MODAL_TOKEN_ID
|
31 |
+
- MODAL_TOKEN_SECRET
|
32 |
+
- HF_MODEL
|
33 |
+
- HF_TOKEN
|
34 |
+
|
35 |
+
You can substitute these values using envsubst before installation:
|
36 |
+
envsubst < values.yaml | helm install yuga-planner ./helm --values -
|
deploy/helm/templates/_helpers.tpl
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{{/*
|
2 |
+
Expand the name of the chart.
|
3 |
+
*/}}
|
4 |
+
{{- define "yuga-planner.name" -}}
|
5 |
+
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
6 |
+
{{- end }}
|
7 |
+
|
8 |
+
{{/*
|
9 |
+
Create a default fully qualified app name.
|
10 |
+
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
11 |
+
If release name contains chart name it will be used as a full name.
|
12 |
+
*/}}
|
13 |
+
{{- define "yuga-planner.fullname" -}}
|
14 |
+
{{- if .Values.fullnameOverride }}
|
15 |
+
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
16 |
+
{{- else }}
|
17 |
+
{{- $name := default .Chart.Name .Values.nameOverride }}
|
18 |
+
{{- if contains $name .Release.Name }}
|
19 |
+
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
20 |
+
{{- else }}
|
21 |
+
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
22 |
+
{{- end }}
|
23 |
+
{{- end }}
|
24 |
+
{{- end }}
|
25 |
+
|
26 |
+
{{/*
|
27 |
+
Create chart name and version as used by the chart label.
|
28 |
+
*/}}
|
29 |
+
{{- define "yuga-planner.chart" -}}
|
30 |
+
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
31 |
+
{{- end }}
|
32 |
+
|
33 |
+
{{/*
|
34 |
+
Common labels
|
35 |
+
*/}}
|
36 |
+
{{- define "yuga-planner.labels" -}}
|
37 |
+
helm.sh/chart: {{ include "yuga-planner.chart" . }}
|
38 |
+
{{ include "yuga-planner.selectorLabels" . }}
|
39 |
+
{{- if .Chart.AppVersion }}
|
40 |
+
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
41 |
+
{{- end }}
|
42 |
+
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
43 |
+
{{- end }}
|
44 |
+
|
45 |
+
{{/*
|
46 |
+
Selector labels
|
47 |
+
*/}}
|
48 |
+
{{- define "yuga-planner.selectorLabels" -}}
|
49 |
+
app.kubernetes.io/name: {{ include "yuga-planner.name" . }}
|
50 |
+
app.kubernetes.io/instance: {{ .Release.Name }}
|
51 |
+
{{- end }}
|
deploy/helm/templates/configmap.yaml
ADDED
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
apiVersion: v1
|
2 |
+
kind: ConfigMap
|
3 |
+
metadata:
|
4 |
+
name: {{ .Values.app.name }}-config
|
5 |
+
labels:
|
6 |
+
app: {{ .Values.app.name }}
|
7 |
+
{{- include "yuga-planner.labels" . | nindent 4 }}
|
8 |
+
data:
|
9 |
+
JAVA_HOME: {{ .Values.env.java.home | quote }}
|
10 |
+
PATH: {{ .Values.env.java.path | quote }}
|
deploy/helm/templates/deployment.yaml
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
apiVersion: apps/v1
|
2 |
+
kind: Deployment
|
3 |
+
metadata:
|
4 |
+
name: {{ .Values.app.name }}
|
5 |
+
labels:
|
6 |
+
app: {{ .Values.app.name }}
|
7 |
+
{{- include "yuga-planner.labels" . | nindent 4 }}
|
8 |
+
spec:
|
9 |
+
replicas: {{ .Values.deployment.replicas }}
|
10 |
+
selector:
|
11 |
+
matchLabels:
|
12 |
+
app: {{ .Values.app.name }}
|
13 |
+
{{- include "yuga-planner.selectorLabels" . | nindent 6 }}
|
14 |
+
template:
|
15 |
+
metadata:
|
16 |
+
labels:
|
17 |
+
app: {{ .Values.app.name }}
|
18 |
+
{{- include "yuga-planner.selectorLabels" . | nindent 8 }}
|
19 |
+
spec:
|
20 |
+
containers:
|
21 |
+
- name: {{ .Values.app.name }}
|
22 |
+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
23 |
+
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
24 |
+
ports:
|
25 |
+
- containerPort: {{ .Values.container.port }}
|
26 |
+
name: {{ .Values.container.name }}
|
27 |
+
protocol: {{ .Values.service.protocol }}
|
28 |
+
env:
|
29 |
+
- name: JAVA_HOME
|
30 |
+
valueFrom:
|
31 |
+
configMapKeyRef:
|
32 |
+
name: {{ .Values.app.name }}-config
|
33 |
+
key: JAVA_HOME
|
34 |
+
- name: PATH
|
35 |
+
valueFrom:
|
36 |
+
configMapKeyRef:
|
37 |
+
name: {{ .Values.app.name }}-config
|
38 |
+
key: PATH
|
39 |
+
- name: NEBIUS_API_KEY
|
40 |
+
valueFrom:
|
41 |
+
secretKeyRef:
|
42 |
+
name: {{ .Values.app.name }}-secrets
|
43 |
+
key: NEBIUS_API_KEY
|
44 |
+
- name: NEBIUS_MODEL
|
45 |
+
valueFrom:
|
46 |
+
secretKeyRef:
|
47 |
+
name: {{ .Values.app.name }}-secrets
|
48 |
+
key: NEBIUS_MODEL
|
49 |
+
- name: MODAL_TOKEN_ID
|
50 |
+
valueFrom:
|
51 |
+
secretKeyRef:
|
52 |
+
name: {{ .Values.app.name }}-secrets
|
53 |
+
key: MODAL_TOKEN_ID
|
54 |
+
- name: MODAL_TOKEN_SECRET
|
55 |
+
valueFrom:
|
56 |
+
secretKeyRef:
|
57 |
+
name: {{ .Values.app.name }}-secrets
|
58 |
+
key: MODAL_TOKEN_SECRET
|
59 |
+
- name: HF_MODEL
|
60 |
+
valueFrom:
|
61 |
+
secretKeyRef:
|
62 |
+
name: {{ .Values.app.name }}-secrets
|
63 |
+
key: HF_MODEL
|
64 |
+
- name: HF_TOKEN
|
65 |
+
valueFrom:
|
66 |
+
secretKeyRef:
|
67 |
+
name: {{ .Values.app.name }}-secrets
|
68 |
+
key: HF_TOKEN
|
69 |
+
command: {{ .Values.deployment.command | toJson }}
|
70 |
+
args:
|
71 |
+
{{- range .Values.deployment.args }}
|
72 |
+
- {{ . | quote }}
|
73 |
+
{{- end }}
|
74 |
+
resources:
|
75 |
+
{{- toYaml .Values.resources | nindent 10 }}
|
76 |
+
livenessProbe:
|
77 |
+
{{- toYaml .Values.probes.liveness | nindent 10 }}
|
78 |
+
readinessProbe:
|
79 |
+
{{- toYaml .Values.probes.readiness | nindent 10 }}
|
80 |
+
securityContext:
|
81 |
+
{{- toYaml .Values.securityContext | nindent 10 }}
|
deploy/helm/templates/secret.yaml
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
apiVersion: v1
|
2 |
+
kind: Secret
|
3 |
+
metadata:
|
4 |
+
name: {{ .Values.app.name }}-secrets
|
5 |
+
labels:
|
6 |
+
app: {{ .Values.app.name }}
|
7 |
+
{{- include "yuga-planner.labels" . | nindent 4 }}
|
8 |
+
type: Opaque
|
9 |
+
stringData:
|
10 |
+
# These values will be populated from environment variables during deployment
|
11 |
+
NEBIUS_API_KEY: {{ .Values.secrets.nebiusApiKey | quote }}
|
12 |
+
NEBIUS_MODEL: {{ .Values.secrets.nebiusModel | quote }}
|
13 |
+
MODAL_TOKEN_ID: {{ .Values.secrets.modalTokenId | quote }}
|
14 |
+
MODAL_TOKEN_SECRET: {{ .Values.secrets.modalTokenSecret | quote }}
|
15 |
+
HF_MODEL: {{ .Values.secrets.hfModel | quote }}
|
16 |
+
HF_TOKEN: {{ .Values.secrets.hfToken | quote }}
|
deploy/helm/templates/service.yaml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
apiVersion: v1
|
2 |
+
kind: Service
|
3 |
+
metadata:
|
4 |
+
name: {{ .Values.app.name }}-service
|
5 |
+
labels:
|
6 |
+
app: {{ .Values.app.name }}
|
7 |
+
{{- include "yuga-planner.labels" . | nindent 4 }}
|
8 |
+
spec:
|
9 |
+
type: {{ .Values.service.type }}
|
10 |
+
ports:
|
11 |
+
- port: {{ .Values.service.port }}
|
12 |
+
targetPort: {{ .Values.service.targetPort }}
|
13 |
+
{{- if eq .Values.service.type "NodePort" }}
|
14 |
+
nodePort: {{ .Values.service.nodePort }}
|
15 |
+
{{- end }}
|
16 |
+
protocol: {{ .Values.service.protocol }}
|
17 |
+
name: {{ .Values.container.name }}
|
18 |
+
selector:
|
19 |
+
app: {{ .Values.app.name }}
|
20 |
+
{{- include "yuga-planner.selectorLabels" . | nindent 4 }}
|
deploy/helm/values.yaml
ADDED
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Default values for yuga-planner.
|
2 |
+
# This is a YAML-formatted file.
|
3 |
+
# Declare variables to be passed into your templates.
|
4 |
+
|
5 |
+
# Application configuration
|
6 |
+
app:
|
7 |
+
name: yuga-planner
|
8 |
+
|
9 |
+
# Image configuration
|
10 |
+
image:
|
11 |
+
repository: ghcr.io/blackopsrepl/yuga-planner-test
|
12 |
+
tag: latest
|
13 |
+
pullPolicy: Always
|
14 |
+
|
15 |
+
# Service configuration
|
16 |
+
service:
|
17 |
+
type: NodePort
|
18 |
+
port: 80
|
19 |
+
targetPort: 7860
|
20 |
+
nodePort: 30860
|
21 |
+
protocol: TCP
|
22 |
+
|
23 |
+
# Container configuration
|
24 |
+
container:
|
25 |
+
port: 7860
|
26 |
+
name: http
|
27 |
+
|
28 |
+
# Resource configuration
|
29 |
+
resources:
|
30 |
+
requests:
|
31 |
+
memory: "512Mi"
|
32 |
+
cpu: "250m"
|
33 |
+
limits:
|
34 |
+
memory: "2Gi"
|
35 |
+
cpu: "1000m"
|
36 |
+
|
37 |
+
# Deployment configuration
|
38 |
+
deployment:
|
39 |
+
replicas: 1
|
40 |
+
command: ["python", "src/app.py"]
|
41 |
+
args:
|
42 |
+
- "--server-name"
|
43 |
+
- "0.0.0.0"
|
44 |
+
- "--server-port"
|
45 |
+
- "7860"
|
46 |
+
|
47 |
+
# Health check configuration
|
48 |
+
probes:
|
49 |
+
liveness:
|
50 |
+
httpGet:
|
51 |
+
path: /
|
52 |
+
port: 7860
|
53 |
+
initialDelaySeconds: 30
|
54 |
+
periodSeconds: 10
|
55 |
+
timeoutSeconds: 5
|
56 |
+
failureThreshold: 3
|
57 |
+
readiness:
|
58 |
+
httpGet:
|
59 |
+
path: /
|
60 |
+
port: 7860
|
61 |
+
initialDelaySeconds: 10
|
62 |
+
periodSeconds: 5
|
63 |
+
timeoutSeconds: 3
|
64 |
+
failureThreshold: 3
|
65 |
+
|
66 |
+
# Security context
|
67 |
+
securityContext:
|
68 |
+
runAsNonRoot: true
|
69 |
+
runAsUser: 1000
|
70 |
+
runAsGroup: 1000
|
71 |
+
allowPrivilegeEscalation: false
|
72 |
+
readOnlyRootFilesystem: false
|
73 |
+
capabilities:
|
74 |
+
drop:
|
75 |
+
- ALL
|
76 |
+
|
77 |
+
# Environment configuration
|
78 |
+
env:
|
79 |
+
java:
|
80 |
+
home: "/usr/lib/jvm/temurin-21-jdk-amd64"
|
81 |
+
path: "/usr/lib/jvm/temurin-21-jdk-amd64/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
|
82 |
+
|
83 |
+
# Secret configuration (values will be populated from environment variables during deployment)
|
84 |
+
secrets:
|
85 |
+
nebiusApiKey: "${NEBIUS_API_KEY}"
|
86 |
+
nebiusModel: "${NEBIUS_MODEL}"
|
87 |
+
modalTokenId: "${MODAL_TOKEN_ID}"
|
88 |
+
modalTokenSecret: "${MODAL_TOKEN_SECRET}"
|
89 |
+
hfModel: "${HF_MODEL}"
|
90 |
+
hfToken: "${HF_TOKEN}"
|
scripts/cleanup-helm.sh
ADDED
@@ -0,0 +1,86 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
set -e
|
3 |
+
|
4 |
+
# Yuga Planner Helm Cleanup Script
|
5 |
+
# This script removes the Helm release and all associated resources
|
6 |
+
|
7 |
+
echo "π§Ή Cleaning up Yuga Planner Helm deployment..."
|
8 |
+
|
9 |
+
# Check if helm is available
|
10 |
+
if ! command -v helm &> /dev/null; then
|
11 |
+
echo "β Error: helm is required but not installed."
|
12 |
+
echo "π‘ Install Helm from: https://helm.sh/docs/intro/install/"
|
13 |
+
exit 1
|
14 |
+
fi
|
15 |
+
|
16 |
+
# Configuration (same defaults as deploy script)
|
17 |
+
RELEASE_NAME="${HELM_RELEASE_NAME:-yuga-planner}"
|
18 |
+
# Get current namespace, fallback to default if not set
|
19 |
+
CURRENT_NAMESPACE=$(kubectl config view --minify --output 'jsonpath={..namespace}' 2>/dev/null || echo "default")
|
20 |
+
NAMESPACE="${HELM_NAMESPACE:-$CURRENT_NAMESPACE}"
|
21 |
+
|
22 |
+
echo "π¦ Helm Release: $RELEASE_NAME"
|
23 |
+
echo "π·οΈ Namespace: $NAMESPACE"
|
24 |
+
|
25 |
+
# Check if the release exists
|
26 |
+
if ! helm list -n "$NAMESPACE" | grep -q "^$RELEASE_NAME"; then
|
27 |
+
echo "βΉοΈ Helm release '$RELEASE_NAME' not found in namespace '$NAMESPACE'."
|
28 |
+
echo "β
Nothing to clean up."
|
29 |
+
exit 0
|
30 |
+
fi
|
31 |
+
|
32 |
+
# Show release information
|
33 |
+
echo "π Found Helm release:"
|
34 |
+
helm list -n "$NAMESPACE" | grep "^$RELEASE_NAME" || true
|
35 |
+
|
36 |
+
echo ""
|
37 |
+
echo "π Release details:"
|
38 |
+
helm status "$RELEASE_NAME" -n "$NAMESPACE" || true
|
39 |
+
|
40 |
+
# Confirm deletion
|
41 |
+
echo ""
|
42 |
+
read -p "β Are you sure you want to uninstall the Helm release '$RELEASE_NAME'? (y/N): " -n 1 -r
|
43 |
+
echo
|
44 |
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
45 |
+
echo "β Cleanup cancelled."
|
46 |
+
exit 0
|
47 |
+
fi
|
48 |
+
|
49 |
+
echo "ποΈ Uninstalling Helm release..."
|
50 |
+
helm uninstall "$RELEASE_NAME" -n "$NAMESPACE"
|
51 |
+
|
52 |
+
echo "β
Helm release uninstalled successfully!"
|
53 |
+
|
54 |
+
# Check if namespace should be cleaned up (optional)
|
55 |
+
if [ "$NAMESPACE" != "default" ]; then
|
56 |
+
echo ""
|
57 |
+
echo "π€ The namespace '$NAMESPACE' still exists."
|
58 |
+
read -p "β Do you want to delete the namespace '$NAMESPACE' as well? (y/N): " -n 1 -r
|
59 |
+
echo
|
60 |
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
61 |
+
# Check if namespace has other resources
|
62 |
+
OTHER_RESOURCES=$(kubectl get all -n "$NAMESPACE" --ignore-not-found=true 2>/dev/null | grep -v "^NAME" | wc -l)
|
63 |
+
if [ "$OTHER_RESOURCES" -gt 0 ]; then
|
64 |
+
echo "β οΈ Warning: Namespace '$NAMESPACE' contains other resources."
|
65 |
+
kubectl get all -n "$NAMESPACE" 2>/dev/null || true
|
66 |
+
read -p "β Are you sure you want to delete the entire namespace? (y/N): " -n 1 -r
|
67 |
+
echo
|
68 |
+
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
69 |
+
kubectl delete namespace "$NAMESPACE"
|
70 |
+
echo "β
Namespace '$NAMESPACE' deleted."
|
71 |
+
else
|
72 |
+
echo "βΉοΈ Namespace '$NAMESPACE' preserved."
|
73 |
+
fi
|
74 |
+
else
|
75 |
+
kubectl delete namespace "$NAMESPACE"
|
76 |
+
echo "β
Empty namespace '$NAMESPACE' deleted."
|
77 |
+
fi
|
78 |
+
else
|
79 |
+
echo "βΉοΈ Namespace '$NAMESPACE' preserved."
|
80 |
+
fi
|
81 |
+
fi
|
82 |
+
|
83 |
+
echo ""
|
84 |
+
echo "π Useful commands to verify cleanup:"
|
85 |
+
echo " β’ List remaining releases: helm list -A"
|
86 |
+
echo " β’ Check for remaining resources: kubectl get all -l app.kubernetes.io/instance=$RELEASE_NAME -A"
|
scripts/cleanup-k8s.sh
ADDED
@@ -0,0 +1,83 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
set -e
|
3 |
+
|
4 |
+
# Yuga Planner Kubernetes Cleanup Script
|
5 |
+
# This script removes all Kubernetes resources created by the deployment
|
6 |
+
|
7 |
+
echo "π§Ή Cleaning up Yuga Planner Kubernetes deployment..."
|
8 |
+
|
9 |
+
# Check if kubectl is available
|
10 |
+
if ! command -v kubectl &> /dev/null; then
|
11 |
+
echo "β Error: kubectl is required but not installed."
|
12 |
+
exit 1
|
13 |
+
fi
|
14 |
+
|
15 |
+
# Check if we're in the correct directory (project root)
|
16 |
+
if [ ! -f "deploy/kubernetes.yaml" ]; then
|
17 |
+
echo "β Error: kubernetes.yaml not found. Please run this script from the project root."
|
18 |
+
exit 1
|
19 |
+
fi
|
20 |
+
|
21 |
+
# Function to check if resources exist
|
22 |
+
check_resources() {
|
23 |
+
local resource_exists=false
|
24 |
+
|
25 |
+
if kubectl get deployment yuga-planner &> /dev/null; then
|
26 |
+
resource_exists=true
|
27 |
+
fi
|
28 |
+
|
29 |
+
if kubectl get service yuga-planner-service &> /dev/null; then
|
30 |
+
resource_exists=true
|
31 |
+
fi
|
32 |
+
|
33 |
+
if kubectl get secret yuga-planner-secrets &> /dev/null; then
|
34 |
+
resource_exists=true
|
35 |
+
fi
|
36 |
+
|
37 |
+
if kubectl get configmap yuga-planner-config &> /dev/null; then
|
38 |
+
resource_exists=true
|
39 |
+
fi
|
40 |
+
|
41 |
+
if [ "$resource_exists" = false ]; then
|
42 |
+
echo "βΉοΈ No Yuga Planner resources found in the current namespace."
|
43 |
+
return 1
|
44 |
+
fi
|
45 |
+
|
46 |
+
return 0
|
47 |
+
}
|
48 |
+
|
49 |
+
# Check if any resources exist
|
50 |
+
if ! check_resources; then
|
51 |
+
echo "β
Nothing to clean up."
|
52 |
+
exit 0
|
53 |
+
fi
|
54 |
+
|
55 |
+
# Show what will be deleted
|
56 |
+
echo "π Found the following Yuga Planner resources:"
|
57 |
+
kubectl get deployment,service,secret,configmap -l app=yuga-planner 2>/dev/null || true
|
58 |
+
|
59 |
+
# Confirm deletion
|
60 |
+
read -p "β Are you sure you want to delete these resources? (y/N): " -n 1 -r
|
61 |
+
echo
|
62 |
+
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
63 |
+
echo "β Cleanup cancelled."
|
64 |
+
exit 0
|
65 |
+
fi
|
66 |
+
|
67 |
+
echo "ποΈ Deleting Kubernetes resources..."
|
68 |
+
|
69 |
+
# Delete resources by label selector (safer approach)
|
70 |
+
echo " β’ Deleting deployment..."
|
71 |
+
kubectl delete deployment -l app=yuga-planner --ignore-not-found=true
|
72 |
+
|
73 |
+
echo " β’ Deleting service..."
|
74 |
+
kubectl delete service -l app=yuga-planner --ignore-not-found=true
|
75 |
+
|
76 |
+
echo " β’ Deleting secrets..."
|
77 |
+
kubectl delete secret -l app=yuga-planner --ignore-not-found=true
|
78 |
+
|
79 |
+
echo " β’ Deleting configmaps..."
|
80 |
+
kubectl delete configmap -l app=yuga-planner --ignore-not-found=true
|
81 |
+
|
82 |
+
echo "β
Cleanup complete!"
|
83 |
+
echo "π Verify cleanup: kubectl get all -l app=yuga-planner"
|
scripts/deploy-helm.sh
ADDED
@@ -0,0 +1,94 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
set -e
|
3 |
+
|
4 |
+
# Yuga Planner Helm Deployment Script
|
5 |
+
# This script loads credentials from environment variables or creds.py and deploys using Helm
|
6 |
+
|
7 |
+
echo "π Deploying Yuga Planner using Helm..."
|
8 |
+
|
9 |
+
# Check if we're in the correct directory (project root)
|
10 |
+
if [ ! -d "deploy/helm" ] && [ ! -f "deploy/helm/Chart.yaml" ]; then
|
11 |
+
echo "β Error: Helm chart not found. Please ensure deploy/helm/Chart.yaml exists."
|
12 |
+
exit 1
|
13 |
+
fi
|
14 |
+
|
15 |
+
# Get the script directory
|
16 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
17 |
+
|
18 |
+
# Source the credential loading script
|
19 |
+
source "${SCRIPT_DIR}/load-credentials.sh"
|
20 |
+
|
21 |
+
# Check and load credentials
|
22 |
+
if ! check_credentials; then
|
23 |
+
exit 1
|
24 |
+
fi
|
25 |
+
|
26 |
+
# Check if helm is available
|
27 |
+
if ! command -v helm &> /dev/null; then
|
28 |
+
echo "β Error: helm is required but not installed."
|
29 |
+
echo "π‘ Install Helm from: https://helm.sh/docs/intro/install/"
|
30 |
+
exit 1
|
31 |
+
fi
|
32 |
+
|
33 |
+
# Configuration
|
34 |
+
RELEASE_NAME="${HELM_RELEASE_NAME:-yuga-planner}"
|
35 |
+
# Get current namespace, fallback to default if not set
|
36 |
+
CURRENT_NAMESPACE=$(kubectl config view --minify --output 'jsonpath={..namespace}' 2>/dev/null || echo "default")
|
37 |
+
NAMESPACE="${HELM_NAMESPACE:-$CURRENT_NAMESPACE}"
|
38 |
+
CHART_PATH="${HELM_CHART_PATH:-deploy/helm}"
|
39 |
+
|
40 |
+
echo "π¦ Helm Release: $RELEASE_NAME"
|
41 |
+
echo "π·οΈ Namespace: $NAMESPACE"
|
42 |
+
echo "π Chart Path: $CHART_PATH"
|
43 |
+
|
44 |
+
# Create namespace if it doesn't exist
|
45 |
+
if ! kubectl get namespace "$NAMESPACE" &> /dev/null; then
|
46 |
+
echo "ποΈ Creating namespace: $NAMESPACE"
|
47 |
+
kubectl create namespace "$NAMESPACE"
|
48 |
+
fi
|
49 |
+
|
50 |
+
# Prepare Helm values with environment variables
|
51 |
+
HELM_VALUES=""
|
52 |
+
HELM_VALUES="$HELM_VALUES --set env.NEBIUS_API_KEY=$NEBIUS_API_KEY"
|
53 |
+
HELM_VALUES="$HELM_VALUES --set env.NEBIUS_MODEL=$NEBIUS_MODEL"
|
54 |
+
HELM_VALUES="$HELM_VALUES --set env.MODAL_TOKEN_ID=$MODAL_TOKEN_ID"
|
55 |
+
HELM_VALUES="$HELM_VALUES --set env.MODAL_TOKEN_SECRET=$MODAL_TOKEN_SECRET"
|
56 |
+
HELM_VALUES="$HELM_VALUES --set env.HF_MODEL=$HF_MODEL"
|
57 |
+
HELM_VALUES="$HELM_VALUES --set env.HF_TOKEN=$HF_TOKEN"
|
58 |
+
|
59 |
+
# Add optional environment variables if set
|
60 |
+
if [ ! -z "$IMAGE_TAG" ]; then
|
61 |
+
HELM_VALUES="$HELM_VALUES --set image.tag=$IMAGE_TAG"
|
62 |
+
fi
|
63 |
+
|
64 |
+
if [ ! -z "$REPLICAS" ]; then
|
65 |
+
HELM_VALUES="$HELM_VALUES --set replicaCount=$REPLICAS"
|
66 |
+
fi
|
67 |
+
|
68 |
+
# Check if release already exists
|
69 |
+
if helm list -n "$NAMESPACE" | grep -q "^$RELEASE_NAME"; then
|
70 |
+
echo "π Upgrading existing Helm release..."
|
71 |
+
helm upgrade "$RELEASE_NAME" "$CHART_PATH" \
|
72 |
+
--namespace "$NAMESPACE" \
|
73 |
+
$HELM_VALUES \
|
74 |
+
--timeout 300s \
|
75 |
+
--wait
|
76 |
+
else
|
77 |
+
echo "π Installing new Helm release..."
|
78 |
+
helm install "$RELEASE_NAME" "$CHART_PATH" \
|
79 |
+
--namespace "$NAMESPACE" \
|
80 |
+
$HELM_VALUES \
|
81 |
+
--timeout 300s \
|
82 |
+
--wait
|
83 |
+
fi
|
84 |
+
|
85 |
+
echo "β
Deployment complete!"
|
86 |
+
echo ""
|
87 |
+
echo "π Release Information:"
|
88 |
+
helm status "$RELEASE_NAME" -n "$NAMESPACE"
|
89 |
+
echo ""
|
90 |
+
echo "π Useful commands:"
|
91 |
+
echo " β’ Check pods: kubectl get pods -l app.kubernetes.io/instance=$RELEASE_NAME -n $NAMESPACE"
|
92 |
+
echo " β’ View logs: kubectl logs -l app.kubernetes.io/instance=$RELEASE_NAME -n $NAMESPACE -f"
|
93 |
+
echo " β’ Port forward: kubectl port-forward svc/$RELEASE_NAME 8080:80 -n $NAMESPACE"
|
94 |
+
echo " β’ Uninstall: helm uninstall $RELEASE_NAME -n $NAMESPACE"
|
scripts/deploy-k8s.sh
CHANGED
@@ -12,106 +12,17 @@ if [ ! -f "deploy/kubernetes.yaml" ]; then
|
|
12 |
exit 1
|
13 |
fi
|
14 |
|
15 |
-
#
|
16 |
-
|
17 |
-
local creds_file="tests/secrets/creds.py"
|
18 |
|
19 |
-
|
20 |
-
|
21 |
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
import sys
|
26 |
-
sys.path.append('tests/secrets')
|
27 |
-
import creds
|
28 |
-
print(creds.NEBIUS_API_KEY)
|
29 |
-
" 2>/dev/null || echo "")
|
30 |
-
fi
|
31 |
-
|
32 |
-
if [ -z "$NEBIUS_MODEL" ]; then
|
33 |
-
export NEBIUS_MODEL=$(python3 -c "
|
34 |
-
import sys
|
35 |
-
sys.path.append('tests/secrets')
|
36 |
-
import creds
|
37 |
-
print(creds.NEBIUS_MODEL)
|
38 |
-
" 2>/dev/null || echo "")
|
39 |
-
fi
|
40 |
-
|
41 |
-
if [ -z "$MODAL_TOKEN_ID" ]; then
|
42 |
-
export MODAL_TOKEN_ID=$(python3 -c "
|
43 |
-
import sys
|
44 |
-
sys.path.append('tests/secrets')
|
45 |
-
import creds
|
46 |
-
print(creds.MODAL_TOKEN_ID)
|
47 |
-
" 2>/dev/null || echo "")
|
48 |
-
fi
|
49 |
-
|
50 |
-
if [ -z "$MODAL_TOKEN_SECRET" ]; then
|
51 |
-
export MODAL_TOKEN_SECRET=$(python3 -c "
|
52 |
-
import sys
|
53 |
-
sys.path.append('tests/secrets')
|
54 |
-
import creds
|
55 |
-
print(creds.MODAL_TOKEN_SECRET)
|
56 |
-
" 2>/dev/null || echo "")
|
57 |
-
fi
|
58 |
-
|
59 |
-
if [ -z "$HF_MODEL" ]; then
|
60 |
-
export HF_MODEL=$(python3 -c "
|
61 |
-
import sys
|
62 |
-
sys.path.append('tests/secrets')
|
63 |
-
import creds
|
64 |
-
print(creds.HF_MODEL)
|
65 |
-
" 2>/dev/null || echo "")
|
66 |
-
fi
|
67 |
-
|
68 |
-
if [ -z "$HF_TOKEN" ]; then
|
69 |
-
export HF_TOKEN=$(python3 -c "
|
70 |
-
import sys
|
71 |
-
sys.path.append('tests/secrets')
|
72 |
-
import creds
|
73 |
-
print(creds.HF_TOKEN)
|
74 |
-
" 2>/dev/null || echo "")
|
75 |
-
fi
|
76 |
-
else
|
77 |
-
echo "β οΈ Warning: $creds_file not found"
|
78 |
-
fi
|
79 |
-
}
|
80 |
-
|
81 |
-
# Check if credentials are available in environment variables
|
82 |
-
echo "π Checking for credentials..."
|
83 |
-
|
84 |
-
missing_vars=()
|
85 |
-
required_vars=("NEBIUS_API_KEY" "NEBIUS_MODEL" "MODAL_TOKEN_ID" "MODAL_TOKEN_SECRET" "HF_MODEL" "HF_TOKEN")
|
86 |
-
|
87 |
-
for var in "${required_vars[@]}"; do
|
88 |
-
if [ -z "${!var}" ]; then
|
89 |
-
missing_vars+=("$var")
|
90 |
-
fi
|
91 |
-
done
|
92 |
-
|
93 |
-
if [ ${#missing_vars[@]} -gt 0 ]; then
|
94 |
-
echo "π Missing environment variables: ${missing_vars[*]}"
|
95 |
-
echo "π Attempting to load from creds.py..."
|
96 |
-
load_credentials
|
97 |
-
|
98 |
-
# Check again after loading from creds.py
|
99 |
-
missing_vars=()
|
100 |
-
for var in "${required_vars[@]}"; do
|
101 |
-
if [ -z "${!var}" ]; then
|
102 |
-
missing_vars+=("$var")
|
103 |
-
fi
|
104 |
-
done
|
105 |
-
|
106 |
-
if [ ${#missing_vars[@]} -gt 0 ]; then
|
107 |
-
echo "β Error: The following required environment variables are not set: ${missing_vars[*]}"
|
108 |
-
echo "π‘ Please set them in your environment or ensure tests/secrets/creds.py exists with the required values."
|
109 |
-
exit 1
|
110 |
-
fi
|
111 |
fi
|
112 |
|
113 |
-
echo "β
All credentials found"
|
114 |
-
|
115 |
# Check if envsubst is available
|
116 |
if ! command -v envsubst &> /dev/null; then
|
117 |
echo "β Error: envsubst is required but not installed. Please install gettext-base package."
|
|
|
12 |
exit 1
|
13 |
fi
|
14 |
|
15 |
+
# Get the script directory
|
16 |
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
17 |
|
18 |
+
# Source the credential loading script
|
19 |
+
source "${SCRIPT_DIR}/load-credentials.sh"
|
20 |
|
21 |
+
# Check and load credentials
|
22 |
+
if ! check_credentials; then
|
23 |
+
exit 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
24 |
fi
|
25 |
|
|
|
|
|
26 |
# Check if envsubst is available
|
27 |
if ! command -v envsubst &> /dev/null; then
|
28 |
echo "β Error: envsubst is required but not installed. Please install gettext-base package."
|
scripts/load-credentials.sh
ADDED
@@ -0,0 +1,113 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
# Yuga Planner Credential Loading Script
|
4 |
+
# This script loads credentials from environment variables or creds.py
|
5 |
+
|
6 |
+
# Function to load credentials from creds.py if environment variables are not set
|
7 |
+
load_credentials() {
|
8 |
+
local creds_file="tests/secrets/creds.py"
|
9 |
+
|
10 |
+
if [ -f "$creds_file" ]; then
|
11 |
+
echo "π Loading credentials from $creds_file..."
|
12 |
+
|
13 |
+
# Extract credentials from creds.py if environment variables are not set
|
14 |
+
if [ -z "$NEBIUS_API_KEY" ]; then
|
15 |
+
export NEBIUS_API_KEY=$(python3 -c "
|
16 |
+
import sys
|
17 |
+
sys.path.append('tests/secrets')
|
18 |
+
import creds
|
19 |
+
print(creds.NEBIUS_API_KEY)
|
20 |
+
" 2>/dev/null || echo "")
|
21 |
+
fi
|
22 |
+
|
23 |
+
if [ -z "$NEBIUS_MODEL" ]; then
|
24 |
+
export NEBIUS_MODEL=$(python3 -c "
|
25 |
+
import sys
|
26 |
+
sys.path.append('tests/secrets')
|
27 |
+
import creds
|
28 |
+
print(creds.NEBIUS_MODEL)
|
29 |
+
" 2>/dev/null || echo "")
|
30 |
+
fi
|
31 |
+
|
32 |
+
if [ -z "$MODAL_TOKEN_ID" ]; then
|
33 |
+
export MODAL_TOKEN_ID=$(python3 -c "
|
34 |
+
import sys
|
35 |
+
sys.path.append('tests/secrets')
|
36 |
+
import creds
|
37 |
+
print(creds.MODAL_TOKEN_ID)
|
38 |
+
" 2>/dev/null || echo "")
|
39 |
+
fi
|
40 |
+
|
41 |
+
if [ -z "$MODAL_TOKEN_SECRET" ]; then
|
42 |
+
export MODAL_TOKEN_SECRET=$(python3 -c "
|
43 |
+
import sys
|
44 |
+
sys.path.append('tests/secrets')
|
45 |
+
import creds
|
46 |
+
print(creds.MODAL_TOKEN_SECRET)
|
47 |
+
" 2>/dev/null || echo "")
|
48 |
+
fi
|
49 |
+
|
50 |
+
if [ -z "$HF_MODEL" ]; then
|
51 |
+
export HF_MODEL=$(python3 -c "
|
52 |
+
import sys
|
53 |
+
sys.path.append('tests/secrets')
|
54 |
+
import creds
|
55 |
+
print(creds.HF_MODEL)
|
56 |
+
" 2>/dev/null || echo "")
|
57 |
+
fi
|
58 |
+
|
59 |
+
if [ -z "$HF_TOKEN" ]; then
|
60 |
+
export HF_TOKEN=$(python3 -c "
|
61 |
+
import sys
|
62 |
+
sys.path.append('tests/secrets')
|
63 |
+
import creds
|
64 |
+
print(creds.HF_TOKEN)
|
65 |
+
" 2>/dev/null || echo "")
|
66 |
+
fi
|
67 |
+
else
|
68 |
+
echo "β οΈ Warning: $creds_file not found"
|
69 |
+
fi
|
70 |
+
}
|
71 |
+
|
72 |
+
# Function to check and validate required credentials
|
73 |
+
check_credentials() {
|
74 |
+
echo "π Checking for credentials..."
|
75 |
+
|
76 |
+
local missing_vars=()
|
77 |
+
local required_vars=("NEBIUS_API_KEY" "NEBIUS_MODEL" "MODAL_TOKEN_ID" "MODAL_TOKEN_SECRET" "HF_MODEL" "HF_TOKEN")
|
78 |
+
|
79 |
+
for var in "${required_vars[@]}"; do
|
80 |
+
if [ -z "${!var}" ]; then
|
81 |
+
missing_vars+=("$var")
|
82 |
+
fi
|
83 |
+
done
|
84 |
+
|
85 |
+
if [ ${#missing_vars[@]} -gt 0 ]; then
|
86 |
+
echo "π Missing environment variables: ${missing_vars[*]}"
|
87 |
+
echo "π Attempting to load from creds.py..."
|
88 |
+
load_credentials
|
89 |
+
|
90 |
+
# Check again after loading from creds.py
|
91 |
+
missing_vars=()
|
92 |
+
for var in "${required_vars[@]}"; do
|
93 |
+
if [ -z "${!var}" ]; then
|
94 |
+
missing_vars+=("$var")
|
95 |
+
fi
|
96 |
+
done
|
97 |
+
|
98 |
+
if [ ${#missing_vars[@]} -gt 0 ]; then
|
99 |
+
echo "β Error: The following required environment variables are not set: ${missing_vars[*]}"
|
100 |
+
echo "π‘ Please set them in your environment or ensure tests/secrets/creds.py exists with the required values."
|
101 |
+
return 1
|
102 |
+
fi
|
103 |
+
fi
|
104 |
+
|
105 |
+
echo "β
All credentials found"
|
106 |
+
return 0
|
107 |
+
}
|
108 |
+
|
109 |
+
# Main execution when script is run directly
|
110 |
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
111 |
+
check_credentials
|
112 |
+
exit $?
|
113 |
+
fi
|