diff --git a/Makefile b/Makefile index 847fa963..444509b2 100644 --- a/Makefile +++ b/Makefile @@ -347,3 +347,7 @@ start-tilt: ## start the kubernetes cluster using kind start-tilt-keycloak: ## start the kubernetes cluster using kind, without Pro Connect for authentication, use keycloak DEV_ENV=dev-keycloak tilt up -f ./bin/Tiltfile .PHONY: build-k8s-cluster + +start-tilt-dinum: ## start the kubernetes cluster using kind, without Pro Connect for authentication, but with DINUM styles + DEV_ENV=dev-dinum tilt up -f ./bin/Tiltfile +.PHONY: build-k8s-cluster diff --git a/bin/Tiltfile b/bin/Tiltfile index 36596f75..4cbaa10c 100644 --- a/bin/Tiltfile +++ b/bin/Tiltfile @@ -2,6 +2,15 @@ load('ext://uibutton', 'cmd_button', 'bool_input', 'location') load('ext://namespace', 'namespace_create', 'namespace_inject') namespace_create('meet') +DEV_ENV = os.getenv('DEV_ENV', 'dev') + +if DEV_ENV == 'dev-dinum': + update_settings(suppress_unused_image_warnings=["localhost:5001/meet-frontend-generic:latest"]) + +if DEV_ENV == 'dev-keycloak': + update_settings(suppress_unused_image_warnings=["localhost:5001/meet-frontend-dinum:latest"]) + + def clean_old_images(image_name): local('docker images -q %s | tail -n +2 | xargs -r docker rmi' % image_name) @@ -22,7 +31,19 @@ docker_build( clean_old_images('localhost:5001/meet-backend') docker_build( - 'localhost:5001/meet-frontend:latest', + 'localhost:5001/meet-frontend-dinum:latest', + context='..', + dockerfile='../docker/dinum-frontend/Dockerfile', + only=['./src/frontend', './docker', './.dockerignore'], + target = 'frontend-production', + live_update=[ + sync('../src/frontend', '/home/frontend'), + ] +) +clean_old_images('localhost:5001/meet-frontend-dinum') + +docker_build( + 'localhost:5001/meet-frontend-generic:latest', context='..', dockerfile='../src/frontend/Dockerfile', only=['./src/frontend', './docker', './.dockerignore'], @@ -31,7 +52,7 @@ docker_build( sync('../src/frontend', '/home/frontend'), ] ) -clean_old_images('localhost:5001/meet-frontend') +clean_old_images('localhost:5001/meet-frontend-generic') docker_build( 'localhost:5001/meet-summary:latest', diff --git a/src/helm/env.d/dev-dinum/values.egress.yaml.gotmpl b/src/helm/env.d/dev-dinum/values.egress.yaml.gotmpl new file mode 100644 index 00000000..5d09dfca --- /dev/null +++ b/src/helm/env.d/dev-dinum/values.egress.yaml.gotmpl @@ -0,0 +1,43 @@ +replicaCount: 1 +terminationGracePeriodSeconds: 18000 + +egress: + log_level: debug + ws_url: ws://livekit-livekit-server:80 + insecure: true + enable_chrome_sandbox: true + {{- with .Values.livekit.keys }} + {{- range $key, $value := . }} + api_key: {{ $key }} + api_secret: {{ $value }} + {{- end }} + {{- end }} + redis: + address: redis-master:6379 + password: pass + s3: + access_key: meet + secret: password + region: local + bucket: meet-media-storage + endpoint: http://minio:9000 + force_path_style: true + +loadBalancer: + type: nginx + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" + tls: + - hosts: + - livekit-egress.127.0.0.1.nip.io + secretName: livekit-egress-dinum-cert + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + +nodeSelector: {} +resources: {} diff --git a/src/helm/env.d/dev-dinum/values.livekit.yaml.gotmpl b/src/helm/env.d/dev-dinum/values.livekit.yaml.gotmpl new file mode 100644 index 00000000..aac470fa --- /dev/null +++ b/src/helm/env.d/dev-dinum/values.livekit.yaml.gotmpl @@ -0,0 +1,50 @@ +replicaCount: 1 +terminationGracePeriodSeconds: 18000 + +image: + repository: localhost:5001/meet-livekit + pullPolicy: Always + tag: "latest" + +livekit: + log_level: debug + rtc: + use_external_ip: false + port_range_start: 50000 + port_range_end: 60000 + tcp_port: 7881 + redis: + address: redis-master:6379 + password: pass + keys: + turn: + enabled: true + udp_port: 443 + domain: livekit.127.0.0.1.nip.io + loadBalancerAnnotations: {} + + webhook: + api_key: + urls: + - https://meet.127.0.0.1.nip.io/api/v1.0/rooms/webhooks-livekit/ + + +loadBalancer: + type: nginx + annotations: + nginx.ingress.kubernetes.io/rewrite-target: / + nginx.ingress.kubernetes.io/ssl-redirect: "true" + cert-manager.io/cluster-issuer: "letsencrypt-prod" + tls: + - hosts: + - livekit.127.0.0.1.nip.io + secretName: livekit-dinum-cert + +autoscaling: + enabled: false + minReplicas: 1 + maxReplicas: 5 + targetCPUUtilizationPercentage: 60 + +nodeSelector: {} +resources: {} diff --git a/src/helm/env.d/dev-dinum/values.meet.yaml.gotmpl b/src/helm/env.d/dev-dinum/values.meet.yaml.gotmpl new file mode 100644 index 00000000..058dd707 --- /dev/null +++ b/src/helm/env.d/dev-dinum/values.meet.yaml.gotmpl @@ -0,0 +1,219 @@ +image: + repository: localhost:5001/meet-backend + pullPolicy: Always + tag: "latest" + +backend: + replicas: 1 + envVars: + DJANGO_CSRF_TRUSTED_ORIGINS: https://meet.127.0.0.1.nip.io,http://meet.127.0.0.1.nip.io + DJANGO_CONFIGURATION: Production + DJANGO_ALLOWED_HOSTS: meet.127.0.0.1.nip.io + DJANGO_SECRET_KEY: {{ .Values.djangoSecretKey }} + DJANGO_SETTINGS_MODULE: meet.settings + DJANGO_SILENCED_SYSTEM_CHECKS: security.W004, security.W008 + DJANGO_SUPERUSER_PASSWORD: admin + DJANGO_EMAIL_HOST: "mailcatcher" + DJANGO_EMAIL_PORT: 1025 + DJANGO_EMAIL_USE_SSL: False + DJANGO_EMAIL_BRAND_NAME: "La Suite Numérique" + DJANGO_EMAIL_SUPPORT_EMAIL: "test@yopmail.com" + DJANGO_EMAIL_LOGO_IMG: https://meet.127.0.0.1.nip.io/assets/logo-suite-numerique.png + DJANGO_EMAIL_DOMAIN: meet.127.0.0.1.nip.io + DJANGO_EMAIL_APP_BASE_URL: https://meet.127.0.0.1.nip.io + OIDC_OP_JWKS_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/certs + OIDC_OP_AUTHORIZATION_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/auth + OIDC_OP_TOKEN_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/token + OIDC_OP_USER_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/userinfo + OIDC_OP_LOGOUT_ENDPOINT: https://keycloak.127.0.0.1.nip.io/realms/meet/protocol/openid-connect/logout + OIDC_RP_CLIENT_ID: meet + OIDC_RP_CLIENT_SECRET: ThisIsAnExampleKeyForDevPurposeOnly + OIDC_RP_SIGN_ALGO: RS256 + OIDC_RP_SCOPES: "openid email" + OIDC_REDIRECT_ALLOWED_HOSTS: https://meet.127.0.0.1.nip.io + OIDC_AUTH_REQUEST_EXTRA_PARAMS: "{'acr_values': 'eidas1'}" + LOGIN_REDIRECT_URL: https://meet.127.0.0.1.nip.io + LOGIN_REDIRECT_URL_FAILURE: https://meet.127.0.0.1.nip.io + LOGOUT_REDIRECT_URL: https://meet.127.0.0.1.nip.io + DB_HOST: postgres-postgresql + DB_NAME: meet + DB_USER: dinum + DB_PASSWORD: pass + DB_PORT: 5432 + POSTGRES_DB: meet + POSTGRES_USER: dinum + POSTGRES_PASSWORD: pass + REDIS_URL: redis://default:pass@redis-master:6379/1 + STORAGES_STATICFILES_BACKEND: django.contrib.staticfiles.storage.StaticFilesStorage + {{- with .Values.livekit.keys }} + {{- range $key, $value := . }} + LIVEKIT_API_SECRET: {{ $value }} + LIVEKIT_API_KEY: {{ $key }} + {{- end }} + {{- end }} + LIVEKIT_API_URL: https://livekit.127.0.0.1.nip.io/ + ALLOW_UNREGISTERED_ROOMS: False + FRONTEND_SILENCE_LIVEKIT_DEBUG: False + FRONTEND_SUPPORT: "{'id': '58ea6697-8eba-4492-bc59-ad6562585041', 'help_article_transcript': 'https://lasuite.crisp.help/fr/article/visio-transcript-1sjq43x', 'help_article_recording': 'https://lasuite.crisp.help/fr/article/visio-enregistrement-wgc8o0', 'help_article_more_tools': 'https://lasuite.crisp.help/fr/article/visio-tools-bvxj23'}" + FRONTEND_TRANSCRIPT: "{'form_beta_users': 'https://grist.numerique.gouv.fr/o/docs/forms/3fFfvJoTBEQ6ZiMi8zsQwX/17'}" + FRONTEND_FEEDBACK: "{'url': 'https://grist.numerique.gouv.fr/o/docs/cbMv4G7pLY3Z/USER-RESEARCH-or-LA-SUITE/f/26'}" + FRONTEND_CUSTOM_CSS_URL: './assets/dinum-styles.css' + FRONTEND_USE_FRENCH_GOV_FOOTER: True + FRONTEND_USE_PROCONNECT_BUTTON: True + FRONTEND_MANIFEST_LINK: "https://docs.numerique.gouv.fr/docs/1ef86abf-f7e0-46ce-b6c7-8be8b8af4c3d/" + AWS_S3_ENDPOINT_URL: http://minio.meet.svc.cluster.local:9000 + AWS_S3_ACCESS_KEY_ID: meet + AWS_S3_SECRET_ACCESS_KEY: password + AWS_STORAGE_BUCKET_NAME: meet-media-storage + AWS_S3_REGION_NAME: local + RECORDING_ENABLE: True + RECORDING_STORAGE_EVENT_ENABLE: True + RECORDING_STORAGE_EVENT_TOKEN: password + SUMMARY_SERVICE_ENDPOINT: http://meet-summary:80/api/v1/tasks/ + SUMMARY_SERVICE_API_TOKEN: password + SCREEN_RECORDING_BASE_URL: https://meet.127.0.0.1.nip.io/recordings + ROOM_TELEPHONY_ENABLED: True + SSL_CERT_FILE: /usr/local/lib/python3.12/site-packages/certifi/cacert.pem + + + migrate: + command: + - "/bin/sh" + - "-c" + - | + python manage.py migrate --no-input && + python manage.py create_demo --force + restartPolicy: Never + + command: + - "gunicorn" + - "-c" + - "/usr/local/etc/gunicorn/meet.py" + - "meet.wsgi:application" + - "--reload" + + createsuperuser: + command: + - "/bin/sh" + - "-c" + - | + python manage.py createsuperuser --email admin@example.com --password admin + restartPolicy: Never + + # Extra volume mounts to manage our local custom CA and avoid to set ssl_verify: false + extraVolumeMounts: + - name: certs + mountPath: /usr/local/lib/python3.12/site-packages/certifi/cacert.pem + subPath: cacert.pem + + # Extra volumes to manage our local custom CA and avoid to set ssl_verify: false + extraVolumes: + - name: certs + configMap: + name: certifi + items: + - key: cacert.pem + path: cacert.pem + +frontend: + + replicas: 1 + + image: + repository: localhost:5001/meet-frontend-dinum + pullPolicy: Always + tag: "latest" + +ingress: + enabled: true + host: meet.127.0.0.1.nip.io + +ingressAdmin: + enabled: true + host: meet.127.0.0.1.nip.io + +posthog: + ingress: + enabled: false + + ingressAssets: + enabled: false + +summary: + replicas: 1 + envVars: + APP_NAME: summary-microservice + APP_API_TOKEN: password + AWS_STORAGE_BUCKET_NAME: meet-media-storage + AWS_S3_ENDPOINT_URL: minio.meet.svc.cluster.local:9000 + AWS_S3_ACCESS_KEY_ID: meet + AWS_S3_SECRET_ACCESS_KEY: password + OPENAI_API_KEY: password + OPENAI_BASE_URL: https://albertine.beta.numerique.gouv.fr/v1 + OPENAI_ASR_MODEL: large-v2 + OPENAI_LLM_MODEL: meta-llama/Llama-3.1-8B-Instruct + AWS_S3_SECURE_ACCESS: False + WEBHOOK_API_TOKEN: password + WEBHOOK_URL: https://www.mock-impress.com/webhook/ + CELERY_BROKER_URL: redis://default:pass@redis-master:6379/1 + CELERY_RESULT_BACKEND: redis://default:pass@redis-master:6379/1 + + image: + repository: localhost:5001/meet-summary + pullPolicy: Always + tag: "latest" + + command: + - "uvicorn" + - "summary.main:app" + - "--host" + - "0.0.0.0" + - "--port" + - "8000" + - "--reload" + +celery: + replicas: 1 + envVars: + APP_NAME: summary-microservice + APP_API_TOKEN: password + AWS_STORAGE_BUCKET_NAME: meet-media-storage + AWS_S3_ENDPOINT_URL: minio.meet.svc.cluster.local:9000 + AWS_S3_ACCESS_KEY_ID: meet + AWS_S3_SECRET_ACCESS_KEY: password + OPENAI_API_KEY: password + OPENAI_BASE_URL: https://albertine.beta.numerique.gouv.fr/v1 + OPENAI_ASR_MODEL: large-v2 + OPENAI_LLM_MODEL: meta-llama/Llama-3.1-8B-Instruct + AWS_S3_SECURE_ACCESS: False + WEBHOOK_API_TOKEN: password + WEBHOOK_URL: https://www.mock-impress.com/webhook/ + CELERY_BROKER_URL: redis://default:pass@redis-master:6379/1 + CELERY_RESULT_BACKEND: redis://default:pass@redis-master:6379/1 + + image: + repository: localhost:5001/meet-summary + pullPolicy: Always + tag: "latest" + + command: + - "celery" + - "-A" + - "summary.core.celery_worker" + - "worker" + - "--pool=solo" + - "--loglevel=info" + +ingressMedia: + enabled: true + host: meet.127.0.0.1.nip.io + + annotations: + nginx.ingress.kubernetes.io/auth-url: https://meet.127.0.0.1.nip.io/api/v1.0/recordings/media-auth/ + nginx.ingress.kubernetes.io/auth-response-headers: "Authorization, X-Amz-Date, X-Amz-Content-SHA256" + nginx.ingress.kubernetes.io/upstream-vhost: minio.meet.svc.cluster.local:9000 + nginx.ingress.kubernetes.io/rewrite-target: /meet-media-storage/$1 + +serviceMedia: + host: minio.meet.svc.cluster.local + port: 9000 diff --git a/src/helm/env.d/dev-dinum/values.secrets.yaml b/src/helm/env.d/dev-dinum/values.secrets.yaml new file mode 100644 index 00000000..e1352e49 --- /dev/null +++ b/src/helm/env.d/dev-dinum/values.secrets.yaml @@ -0,0 +1,12 @@ +djangoSecretKey: u!vbjDW71aru&OZA%NZQi0x +livekit: + keys: + devkey: secret + webhook: + api_key: devkey +livekitApi: + key: devkey + secret: secret +oidc: + clientId: meet + clientSecret: ThisIsAnExampleKeyForDevPurposeOnly diff --git a/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl b/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl index d0bd871e..42dc0ff0 100644 --- a/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl +++ b/src/helm/env.d/dev-keycloak/values.meet.yaml.gotmpl @@ -136,7 +136,7 @@ frontend: replicas: 1 image: - repository: localhost:5001/meet-frontend + repository: localhost:5001/meet-frontend-generic pullPolicy: Always tag: "latest" diff --git a/src/helm/helmfile.yaml b/src/helm/helmfile.yaml index 5457ee3c..d3cd23f7 100644 --- a/src/helm/helmfile.yaml +++ b/src/helm/helmfile.yaml @@ -3,6 +3,10 @@ environments: values: - version: 0.0.1 - env.d/{{ .Environment.Name }}/values.secrets.yaml + dev-dinum: + values: + - version: 0.0.1 + - env.d/{{ .Environment.Name }}/values.secrets.yaml dev: values: - version: 0.0.1