diff --git a/helm/litellm-helm/templates/_helpers.tpl b/helm/litellm-helm/templates/_helpers.tpl index 338ee5294f3..230d2acaeef 100644 --- a/helm/litellm-helm/templates/_helpers.tpl +++ b/helm/litellm-helm/templates/_helpers.tpl @@ -285,10 +285,6 @@ and the same spend transaction buffer. - name: LITELLM_LOG value: {{ .Values.logLevel | quote }} {{- end }} -{{- if and (not (kindIs "invalid" .Values.rustGateway.enabled)) (not (hasKey (default dict .Values.envVars) "LITELLM_RUST")) }} -- name: LITELLM_RUST - value: {{ .Values.rustGateway.enabled | toString | quote }} -{{- end }} {{- if .Values.envVars }} {{- range $key, $val := .Values.envVars }} - name: {{ $key }} diff --git a/helm/litellm-helm/templates/deployment.yaml b/helm/litellm-helm/templates/deployment.yaml index a37193f0efa..b2be2339875 100644 --- a/helm/litellm-helm/templates/deployment.yaml +++ b/helm/litellm-helm/templates/deployment.yaml @@ -58,6 +58,14 @@ spec: env: {{- include "litellm.lensConnectionEnv" . | nindent 12 }} {{- include "litellm.proxyEnv" . | nindent 12 }} + {{- $userSetsRust := hasKey (default dict .Values.envVars) "LITELLM_RUST" }} + {{- range .Values.extraEnvVars }} + {{- if eq .name "LITELLM_RUST" }}{{ $userSetsRust = true }}{{ end }} + {{- end }} + {{- if and (kindIs "bool" .Values.rust.enabled) (not $userSetsRust) }} + - name: LITELLM_RUST + value: {{ .Values.rust.enabled | quote }} + {{- end }} {{- if .Values.liteadmin.enabled }} - name: LITELLM_ADMIN_AGENT_URL value: {{ printf "http://%s-liteadmin:10000" (include "litellm.fullname" . | trunc 53 | trimSuffix "-") | quote }} diff --git a/helm/litellm-helm/tests/rust_gateway_tests.yaml b/helm/litellm-helm/tests/rust_gateway_tests.yaml deleted file mode 100644 index b183d66cb70..00000000000 --- a/helm/litellm-helm/tests/rust_gateway_tests.yaml +++ /dev/null @@ -1,52 +0,0 @@ -suite: Rust forwarding gateway -templates: - - deployment.yaml - - configmap-litellm.yaml -tests: - - it: leaves the image default in place when unset - template: deployment.yaml - asserts: - - notContains: - path: spec.template.spec.containers[0].env - content: - name: LITELLM_RUST - any: true - - it: turns forwarding off explicitly - template: deployment.yaml - set: - rustGateway.enabled: false - asserts: - - contains: - path: spec.template.spec.containers[0].env - content: - name: LITELLM_RUST - value: "false" - - it: enables forwarding without changing command or probes - template: deployment.yaml - set: - rustGateway.enabled: true - asserts: - - contains: - path: spec.template.spec.containers[0].env - content: - name: LITELLM_RUST - value: "true" - - equal: - path: spec.template.spec.containers[0].livenessProbe.httpGet.port - value: http - - it: respects an explicit environment override - template: deployment.yaml - set: - rustGateway.enabled: true - envVars.LITELLM_RUST: "false" - asserts: - - contains: - path: spec.template.spec.containers[0].env - content: - name: LITELLM_RUST - value: "false" - - notContains: - path: spec.template.spec.containers[0].env - content: - name: LITELLM_RUST - value: "true" diff --git a/helm/litellm-helm/tests/rust_tests.yaml b/helm/litellm-helm/tests/rust_tests.yaml new file mode 100644 index 00000000000..762ad1438d4 --- /dev/null +++ b/helm/litellm-helm/tests/rust_tests.yaml @@ -0,0 +1,87 @@ +suite: Rust switch +templates: + - deployment.yaml + - configmap-litellm.yaml +tests: + - it: leaves LITELLM_RUST unset by default + template: deployment.yaml + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: + name: LITELLM_RUST + any: true + - it: sets LITELLM_RUST to false + template: deployment.yaml + set: + rust.enabled: false + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: LITELLM_RUST + value: "false" + - it: sets LITELLM_RUST to true + template: deployment.yaml + set: + rust.enabled: true + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: LITELLM_RUST + value: "true" + - it: keeps LITELLM_RUST off the collector sidecar + template: deployment.yaml + set: + rust.enabled: true + collector.enabled: true + asserts: + - equal: + path: spec.template.spec.containers[1].name + value: litellm-collector + - notContains: + path: spec.template.spec.containers[1].env + content: + name: LITELLM_RUST + any: true + - it: lets envVars override the value + template: deployment.yaml + set: + rust.enabled: true + envVars.LITELLM_RUST: "false" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: LITELLM_RUST + value: "false" + - notContains: + path: spec.template.spec.containers[0].env + content: + name: LITELLM_RUST + value: "true" + - it: lets extraEnvVars override the value without a duplicate entry + template: deployment.yaml + set: + rust.enabled: true + extraEnvVars: + - name: LITELLM_RUST + value: "false" + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: + name: LITELLM_RUST + value: "false" + - notContains: + path: spec.template.spec.containers[0].env + content: + name: LITELLM_RUST + value: "true" + - it: rejects a value that is not a boolean + template: deployment.yaml + set: + rust.enabled: "yes" + asserts: + - failedTemplate: {} diff --git a/helm/litellm-helm/values.schema.json b/helm/litellm-helm/values.schema.json new file mode 100644 index 00000000000..a4191ca992a --- /dev/null +++ b/helm/litellm-helm/values.schema.json @@ -0,0 +1,16 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "rust": { + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + } + } + } + } +} diff --git a/helm/litellm-helm/values.yaml b/helm/litellm-helm/values.yaml index 129f8ae9c99..019f1b5fd55 100644 --- a/helm/litellm-helm/values.yaml +++ b/helm/litellm-helm/values.yaml @@ -4,9 +4,14 @@ replicaCount: 1 -rustGateway: - # null inherits the image default; true or false sets LITELLM_RUST +rust: + # Sets LITELLM_RUST on the proxy container. null leaves it unset. true runs the + # Rust forwarding server on the public port in front of the Python workers and + # turns on the opt-in Rust routes, false keeps every switchable route on Python. + # A LITELLM_RUST in envVars or extraEnvVars wins, and this wins over one from + # environmentSecrets or environmentConfigMaps enabled: + liteadmin: enabled: false existingSecret: "" diff --git a/helm/litellm/templates/gateway/deployment.yaml b/helm/litellm/templates/gateway/deployment.yaml index 419bafc84d9..4b2bdb81552 100644 --- a/helm/litellm/templates/gateway/deployment.yaml +++ b/helm/litellm/templates/gateway/deployment.yaml @@ -60,16 +60,13 @@ spec: - name: LITELLM_CORS_ORIGINS value: {{ include "litellm.ui.publicOrigin" . | quote }} {{- end }} - {{- $rustGateway := .Values.gateway.rustGateway | default dict }} - {{- $rustGatewayOverridden := false }} + {{- $userSetsRust := false }} {{- range .Values.gateway.extraEnv }} - {{- if eq .name "LITELLM_RUST" }} - {{- $rustGatewayOverridden = true }} + {{- if eq .name "LITELLM_RUST" }}{{ $userSetsRust = true }}{{ end }} {{- end }} - {{- end }} - {{- if and (not (kindIs "invalid" $rustGateway.enabled)) (not $rustGatewayOverridden) }} + {{- if and (kindIs "bool" .Values.gateway.rust.enabled) (not $userSetsRust) }} - name: LITELLM_RUST - value: {{ $rustGateway.enabled | toString | quote }} + value: {{ .Values.gateway.rust.enabled | quote }} {{- end }} {{- include "litellm.serverEnv" (dict "root" $ "component" .Values.gateway) | nindent 12 }} {{- if .Values.gateway.config.create }} diff --git a/helm/litellm/tests/rust_gateway_tests.yaml b/helm/litellm/tests/rust_tests.yaml similarity index 57% rename from helm/litellm/tests/rust_gateway_tests.yaml rename to helm/litellm/tests/rust_tests.yaml index 0a887d23e95..e3944f5ad63 100644 --- a/helm/litellm/tests/rust_gateway_tests.yaml +++ b/helm/litellm/tests/rust_tests.yaml @@ -1,11 +1,11 @@ -suite: Rust forwarding gateway +suite: Rust switch templates: - gateway/deployment.yaml - gateway/configmap.yaml values: - ./values/required.yaml tests: - - it: leaves the image default in place when unset + - it: leaves LITELLM_RUST unset by default template: gateway/deployment.yaml asserts: - notContains: @@ -13,33 +13,44 @@ tests: content: name: LITELLM_RUST any: true - - it: turns forwarding off explicitly + - it: sets LITELLM_RUST to false template: gateway/deployment.yaml set: - gateway.rustGateway.enabled: false + gateway.rust.enabled: false asserts: - contains: path: spec.template.spec.containers[0].env content: name: LITELLM_RUST value: "false" - - it: enables forwarding without changing command or probes + - it: sets LITELLM_RUST to true template: gateway/deployment.yaml set: - gateway.rustGateway.enabled: true + gateway.rust.enabled: true asserts: - contains: path: spec.template.spec.containers[0].env content: name: LITELLM_RUST value: "true" - - equal: - path: spec.template.spec.containers[0].livenessProbe.httpGet.port - value: http - - it: respects an explicit extraEnv override + - it: keeps LITELLM_RUST off the collector sidecar template: gateway/deployment.yaml set: - gateway.rustGateway.enabled: true + gateway.rust.enabled: true + gateway.collector.enabled: true + asserts: + - equal: + path: spec.template.spec.containers[1].name + value: collector + - notContains: + path: spec.template.spec.containers[1].env + content: + name: LITELLM_RUST + any: true + - it: lets extraEnv override the value + template: gateway/deployment.yaml + set: + gateway.rust.enabled: true gateway.extraEnv: - name: LITELLM_RUST value: "false" @@ -54,3 +65,9 @@ tests: content: name: LITELLM_RUST value: "true" + - it: rejects a value that is not a boolean + template: gateway/deployment.yaml + set: + gateway.rust.enabled: "yes" + asserts: + - failedTemplate: {} diff --git a/helm/litellm/values.schema.json b/helm/litellm/values.schema.json new file mode 100644 index 00000000000..8f8dd21525f --- /dev/null +++ b/helm/litellm/values.schema.json @@ -0,0 +1,20 @@ +{ + "$schema": "https://json-schema.org/draft-07/schema#", + "type": "object", + "properties": { + "gateway": { + "properties": { + "rust": { + "properties": { + "enabled": { + "type": [ + "boolean", + "null" + ] + } + } + } + } + } + } +} diff --git a/helm/litellm/values.yaml b/helm/litellm/values.yaml index 0a992d0acdf..4353afa91d5 100644 --- a/helm/litellm/values.yaml +++ b/helm/litellm/values.yaml @@ -294,8 +294,12 @@ gateway: # Number of uvicorn worker processes per gateway pod. Sets NUM_WORKERS, # consumed by the gateway image entrypoint. Default is 1. numWorkers: 1 - rustGateway: - # null inherits the image default; true or false sets LITELLM_RUST + rust: + # Sets LITELLM_RUST on the gateway container. null leaves it unset. true runs + # the Rust forwarding server on the public port in front of the Python workers + # and turns on the opt-in Rust routes, false keeps every switchable route on + # Python. A LITELLM_RUST in extraEnv wins, and this wins over one from + # envConfigMaps or envSecrets enabled: extraEnv: [] # Add extra environment variables to the gateway envConfigMaps: [] # Add extra environment variables to the gateway from config maps