diff --git a/.github/workflows/lint-test.yaml b/.github/workflows/lint-test.yaml index 7b68951f..1e8c71ea 100644 --- a/.github/workflows/lint-test.yaml +++ b/.github/workflows/lint-test.yaml @@ -11,14 +11,6 @@ jobs: with: fetch-depth: 0 - - name: Envsubst - uses: danielr1996/envsubst-action@1.0.0 - env: - SLACK_TOKEN: ${{ secrets.SLACK_TOKEN }} - with: - input: charts/flagsmith/ci/e2e-test-values.yaml - output: charts/flagsmith/ci/e2e-test-values.yaml - - name: Set up Helm uses: azure/setup-helm@v4 with: diff --git a/charts/flagsmith/ci/e2e-test-values.yaml b/charts/flagsmith/ci/e2e-test-values.yaml deleted file mode 100644 index b131a30f..00000000 --- a/charts/flagsmith/ci/e2e-test-values.yaml +++ /dev/null @@ -1,13 +0,0 @@ -_destructiveTests: - enabled: true - -frontend: - extraEnv: - SLACK_TOKEN: "${SLACK_TOKEN}" - -api: - analytics: - enabled: true - extraEnv: - EMAIL_BACKEND: "django.core.mail.backends.console.EmailBackend" - FE_E2E_TEST_USER_EMAIL: nightwatch@solidstategroup.com diff --git a/charts/flagsmith/ci/test-values.yaml b/charts/flagsmith/ci/test-values.yaml index 699d2174..0c8b7a86 100644 --- a/charts/flagsmith/ci/test-values.yaml +++ b/charts/flagsmith/ci/test-values.yaml @@ -1,2 +1,24 @@ tests: enabled: true + +influxdb2: + enabled: false + +devPostgresql: + enabled: true + +databaseExternal: + replicas: + databases: + - url: postgres://user:password@127.0.0.1:5432/flagsmith + + - type: postgres + host: 127.0.0.1 + port: 5433 + database: flagsmith + username: user + password: password + + - fromExistingSecret: + name: test-replica-secret + key: database-url diff --git a/charts/flagsmith/templates/_api_environment.yaml b/charts/flagsmith/templates/_api_environment.yaml index 67a4486b..c0053033 100644 --- a/charts/flagsmith/templates/_api_environment.yaml +++ b/charts/flagsmith/templates/_api_environment.yaml @@ -10,6 +10,34 @@ name: {{ template "flagsmith.fullname" . }} key: DATABASE_URL {{- end }} +{{/* +Replica database URLs can be passed in different ways: +- Plaintext URL +- Plaintext dictionary config +- Secret reference +*/}} +{{- range $index, $db := .Values.databaseExternal.replicas.databases }} +- name: REPLICA_DATABASE_URL_{{ $index }} + {{- if $db.fromExistingSecret }} + valueFrom: + secretKeyRef: + name: {{ $db.fromExistingSecret.name }} + key: {{ $db.fromExistingSecret.key }} + {{- else }} + value: {{ include "flagsmith.api.formatDatabaseUrl" $db | quote }} + {{- end }} +{{- end }} +{{- range $index, $db := .Values.databaseExternal.crossRegionReplicas.databases }} +- name: CROSS_REGION_REPLICA_DATABASE_URL_{{ $index }} + {{- if $db.fromExistingSecret }} + valueFrom: + secretKeyRef: + name: {{ $db.fromExistingSecret.name }} + key: {{ $db.fromExistingSecret.key }} + {{- else }} + value: {{ include "flagsmith.api.formatDatabaseUrl" $db | quote }} + {{- end }} +{{- end }} - name: DJANGO_SECRET_KEY valueFrom: secretKeyRef: @@ -101,10 +129,6 @@ - name: USE_X_FORWARDED_HOST value: 'true' {{- end }} -{{- if and .Values._destructiveTests.enabled .Values._destructiveTests.testToken }} -- name: E2E_TEST_AUTH_TOKEN - value: {{ .Values._destructiveTests.testToken | quote }} -{{- end }} {{- if .Values.api.logging.format }} - name: LOG_FORMAT value: {{ .Values.api.logging.format }} diff --git a/charts/flagsmith/templates/_helpers.tpl b/charts/flagsmith/templates/_helpers.tpl index 975c3464..64d5d399 100644 --- a/charts/flagsmith/templates/_helpers.tpl +++ b/charts/flagsmith/templates/_helpers.tpl @@ -253,16 +253,6 @@ Frontend environment - name: FLAGSMITH_PROXY_API_URL value: http://{{ include "flagsmith.fullname" . }}-api.{{ .Release.Namespace }}:{{ .Values.service.api.port }} {{- end }} -{{- if and .Values._destructiveTests.enabled .Values._destructiveTests.testToken }} -- name: E2E_TEST_TOKEN_E2E - value: {{ .Values._destructiveTests.testToken | quote }} -- name: E2E_TEST_TOKEN - value: {{ .Values._destructiveTests.testToken | quote }} -- name: FLAGSMITH_API - value: {{ include "flagsmith.fullname" . }}-api.{{ .Release.Namespace }}:{{ .Values.service.api.port }}/api/v1/ -- name: ENABLE_INFLUXDB_FEATURES - value: {{ .Values.influxdb2.enabled | ternary "true" "false" | squote }} -{{- end }} {{- range $envName, $envValue := .Values.frontend.extraEnv }} - name: {{ $envName }} value: {{ $envValue | quote }} @@ -316,27 +306,6 @@ Database URL for application {{- end }} {{- end }} -{{/* -Curl Test container -*/}} -{{- define "flagsmith.tests.curlContainer" -}} -name: {{ .name }} -image: curlimages/curl -command: ['curl'] -args: - - --fail - - --max-time - - {{ .maxTime | squote }} - - --silent -{{- if not .printResponseBody }} - - --output - - /dev/null -{{- end }} - - --write-out - - 'URL: %{url_effective}\nHTTP status code: %{http_code}\nBytes downloaded: %{size_download}\nTime taken: %{time_total}s\n' - - {{ .url | squote }} -{{- end }} - {{/* Replicas */}} @@ -346,6 +315,27 @@ replicas: {{ . }} {{- end }} {{- end }} +{{/* +Determine database URL for direct URL format or component parts +*/}} +{{- define "flagsmith.api.formatDatabaseUrl" -}} +{{- if .url -}} + {{- .url -}} +{{- else -}} + {{- $type := .type | default "postgres" -}} + {{- $port := .port | default "5432" -}} + {{- $password := .password | default "" -}} + {{- $username := required "Must specify a database username" .username -}} + {{- $host := required "Must specify a database host" .host -}} + {{- $database := required "Must specify a database name" .database -}} + + {{- if $password -}} + {{- printf "%s://%s:%s@%s:%v/%s" $type $username $password $host $port $database -}} + {{- else -}} + {{- printf "%s://%s@%s:%v/%s" $type $username $host $port $database -}} + {{- end -}} +{{- end -}} +{{- end -}} {{- define "flagsmith.api.secretKeySecretName" -}} {{- if .Values.api.secretKeyFromExistingSecret.enabled -}} diff --git a/charts/flagsmith/templates/tests.yaml b/charts/flagsmith/templates/tests.yaml new file mode 100644 index 00000000..5934d753 --- /dev/null +++ b/charts/flagsmith/templates/tests.yaml @@ -0,0 +1,54 @@ +{{- if .Values.tests.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ .Release.Name }}-test-serviceaccount + labels: + {{- include "flagsmith.labels" . | nindent 4 }} + app.kubernetes.io/component: test-replica-database-urls + annotations: + {{- $annotations := include "flagsmith.annotations" .Values.common }} + {{- if $annotations }} + {{- $annotations | nindent 4 }} + {{- end }} +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: {{ .Release.Name }}-test-role + labels: + {{- include "flagsmith.labels" . | nindent 4 }} +rules: + - apiGroups: ["apps"] + resources: ["deployments"] + verbs: ["get"] + - apiGroups: [""] + resources: ["pods"] + verbs: ["get", "list"] + - apiGroups: [""] + resources: ["pods/exec"] + verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ .Release.Name }}-test-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: {{ .Release.Name }}-test-role +subjects: + - kind: ServiceAccount + name: {{ .Release.Name }}-test-serviceaccount +--- +apiVersion: v1 +kind: Secret +metadata: + name: test-replica-secret + labels: + app.kubernetes.io/component: test-replica-secret +type: Opaque +stringData: + database-url: "postgres://user:password@127.0.0.1:5434/flagsmith" + +{{- end }} diff --git a/charts/flagsmith/templates/tests/test-api-http-health.yaml b/charts/flagsmith/templates/tests/test-api-http-health.yaml deleted file mode 100644 index e1df698b..00000000 --- a/charts/flagsmith/templates/tests/test-api-http-health.yaml +++ /dev/null @@ -1,24 +0,0 @@ -{{- if and .Values.tests.enabled .Values.tests.api.enabled }} -apiVersion: v1 -kind: Pod -metadata: - name: {{ template "flagsmith.fullname" . }}-test-api-http-health - labels: - {{- include "flagsmith.labels" . | nindent 4 }} - app.kubernetes.io/component: test-api-http-health - annotations: - {{- $annotations := include "flagsmith.annotations" .Values.common }} - {{- if $annotations }} - {{- $annotations | nindent 4 }} - {{- end }} - "helm.sh/hook": test -spec: - containers: - {{- $args := dict }} - {{- $_ := set $args "name" "api-health" }} - {{- $_ := set $args "maxTime" .Values.tests.api.maxTime }} - {{- $_ := set $args "printResponseBody" .Values.tests.api.printResponseBody }} - {{- $_ := set $args "url" (printf "%s-api:%d/health" (include "flagsmith.fullname" . ) (.Values.service.api.port | int64)) }} - - {{ include "flagsmith.tests.curlContainer" $args | nindent 6 }} - restartPolicy: Never -{{- end }} diff --git a/charts/flagsmith/templates/tests/test-e2e.yaml b/charts/flagsmith/templates/tests/test-e2e.yaml deleted file mode 100644 index 5f332e7b..00000000 --- a/charts/flagsmith/templates/tests/test-e2e.yaml +++ /dev/null @@ -1,33 +0,0 @@ -{{- if .Values.frontend.enabled }} -{{- if and .Values._destructiveTests.enabled .Values._destructiveTests.e2e.enabled }} -apiVersion: v1 -kind: Pod -metadata: - name: {{ template "flagsmith.fullname" . }}-test-e2e - labels: - {{- include "flagsmith.labels" . | nindent 4 }} - app.kubernetes.io/component: test-e2e - annotations: - {{- $annotations := include "flagsmith.annotations" .Values.common }} - {{- if $annotations }} - {{- $annotations | nindent 4 }} - {{- end }} - "helm.sh/hook": test -spec: -{{- if .Values.api.image.imagePullSecrets }} - imagePullSecrets: -{{ toYaml .Values.api.image.imagePullSecrets | indent 4 }} -{{- end }} - containers: - - name: e2e - image: {{ .Values._destructiveTests.e2e.image.repository }}:{{ .Values._destructiveTests.e2e.image.tag | default .Values.api.image.tag | default (printf "%s" .Chart.AppVersion) }} - imagePullPolicy: {{ .Values.frontend.image.imagePullPolicy }} - env: {{ include "flagsmith.frontend.environment" . | nindent 8 }} - resources: {{ .Values._destructiveTests.e2e.resources | toYaml | nindent 8 }} - command: - - bash - - -c - - "sed -i 's|http://flagsmith-api:8000.*/|http://'$FLAGSMITH_API'|' ./env/project_e2e.js ./common/project.js && cat ./env/project_e2e.js ./common/project.js && npm run test" - restartPolicy: Never -{{- end }} -{{- end }} diff --git a/charts/flagsmith/templates/tests/test-frontend-http.yaml b/charts/flagsmith/templates/tests/test-frontend-http.yaml deleted file mode 100644 index 70fea976..00000000 --- a/charts/flagsmith/templates/tests/test-frontend-http.yaml +++ /dev/null @@ -1,26 +0,0 @@ -{{- if .Values.frontend.enabled }} -{{- if and .Values.tests.enabled .Values.tests.frontend.enabled }} -apiVersion: v1 -kind: Pod -metadata: - name: {{ template "flagsmith.fullname" . }}-test-frontend-http - labels: - {{- include "flagsmith.labels" . | nindent 4 }} - app.kubernetes.io/component: test-frontend-http - annotations: - {{- $annotations := include "flagsmith.annotations" .Values.common }} - {{- if $annotations }} - {{- $annotations | nindent 4 }} - {{- end }} - "helm.sh/hook": test -spec: - containers: - {{- $args := dict }} - {{- $_ := set $args "name" "frontend" }} - {{- $_ := set $args "maxTime" .Values.tests.frontend.maxTime }} - {{- $_ := set $args "printResponseBody" .Values.tests.frontend.printResponseBody }} - {{- $_ := set $args "url" (printf "%s-frontend:%d" (include "flagsmith.fullname" . ) (.Values.service.frontend.port | int64)) }} - - {{ include "flagsmith.tests.curlContainer" $args | nindent 6 }} - restartPolicy: Never -{{- end }} -{{- end }} diff --git a/charts/flagsmith/templates/tests/test-replica-database-urls.yaml b/charts/flagsmith/templates/tests/test-replica-database-urls.yaml new file mode 100644 index 00000000..6a28bba6 --- /dev/null +++ b/charts/flagsmith/templates/tests/test-replica-database-urls.yaml @@ -0,0 +1,48 @@ +{{- if and .Values.tests.enabled }} +apiVersion: v1 +kind: Pod +metadata: + name: {{ template "flagsmith.fullname" . }}-test-replica-database-urls + labels: + {{- include "flagsmith.labels" . | nindent 4 }} + app.kubernetes.io/component: test-replica-database-urls + annotations: + {{- $annotations := include "flagsmith.annotations" .Values.common }} + {{- if $annotations }} + {{- $annotations | nindent 4 }} + {{- end }} + "helm.sh/hook": test +spec: + containers: + - name: test-replica-database-urls + image: bitnami/kubectl + command: + - /bin/bash + - -c + - | + set -e + set -o pipefail + + expected_replicas=( + "postgres://user:password@127.0.0.1:5432/flagsmith" + "postgres://user:password@127.0.0.1:5433/flagsmith" + "postgres://user:password@127.0.0.1:5434/flagsmith" + ) + + # Get all environment variables in one command + replicas=( $( + kubectl exec deploy/{{ template "flagsmith.fullname" . }}-api --\ + sh -c "echo \$REPLICA_DATABASE_URL_0; echo \$REPLICA_DATABASE_URL_1; echo \$REPLICA_DATABASE_URL_2" + ) ) + + for i in "${!expected_replicas[@]}"; do + echo "REPLICA_DATABASE_URL_$i = ${replicas[$i]}" + if [ "${replicas[$i]}" != "${expected_replicas[$i]}" ]; then + echo "Replica $i did not match expected value. Expected: ${expected_replicas[$i]}, Got: ${replicas[$i]}" + exit 1 + fi + done + + serviceAccountName: {{ .Release.Name }}-test-serviceaccount + restartPolicy: Never +{{- end }} diff --git a/charts/flagsmith/values.yaml b/charts/flagsmith/values.yaml index 408dbd75..5c59903b 100644 --- a/charts/flagsmith/values.yaml +++ b/charts/flagsmith/values.yaml @@ -259,6 +259,24 @@ databaseExternal: enabled: false name: null key: null + # Configuration for replica databases used for read operations + replicas: + # List of replica database configurations + databases: [] + # Example: + # databases: + # - url: postgres://user:password@replica1.db.host/flagsmith + # - type: postgres + # host: replica2.db.host + # port: 5432 + # database: flagsmith + # username: user + # password: password + # - fromExistingSecret: + # name: my-replica-secret + # key: database-url + crossRegionReplicas: + databases: [] pgbouncer: enabled: false @@ -503,33 +521,7 @@ jobs: # These tests just make non-destructive requests to the services in # the cluster. Enabling this and running helm test is safe. tests: - # A test is enabled if both this and the specific test is enabled enabled: false - api: - enabled: true - maxTime: 10 - printResponseBody: false - frontend: - enabled: true - maxTime: 10 - printResponseBody: false - -# These are used for integration testing the chart and the -# application. Enabling this will mean that data in a release is -# destroyed or corrupted if the tests are run. -_destructiveTests: - # A test is enabled if both this and the specific test is enabled - enabled: false - testToken: test-e2e-token - e2e: - enabled: true - image: - repository: flagsmith/flagsmith-e2e-tests - tag: null - imagePullPolicy: IfNotPresent - resources: - requests: - memory: 1Gi # -- Array of extra K8s manifests to deploy ## Note: Supports use of custom Helm templates