Skip to content

Commit

Permalink
Automated InfluxDB setup steps (#97)
Browse files Browse the repository at this point in the history
  • Loading branch information
plumdog authored Jan 5, 2023
1 parent 4cec00c commit 41af34c
Show file tree
Hide file tree
Showing 6 changed files with 179 additions and 1 deletion.
2 changes: 1 addition & 1 deletion charts/flagsmith/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ apiVersion: v2
name: flagsmith
description: Flagsmith
type: application
version: 0.13.0
version: 0.14.0
appVersion: 2.34.0
dependencies:
- name: postgresql
Expand Down
11 changes: 11 additions & 0 deletions charts/flagsmith/ci/influxdb-test-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
tests:
enabled: true

api:
extraEnv:
ENABLE_INFLUXDB_FEATURES: 'true'
influxdbSetup:
enabled: true

influxdb2:
enabled: true
132 changes: 132 additions & 0 deletions charts/flagsmith/templates/_influxdb_setup.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
# File extension is .txt not .py just because helm's linting complains
# about non txt/tpl/yaml/yml extensions.

import os
import sys

from influxdb_client import InfluxDBClient

influxdb_url = os.environ["INFLUXDB_URL"]
influxdb_token = os.environ["INFLUXDB_TOKEN"]
influxdb_organization_name = os.environ["INFLUXDB_ORG"]
influxdb_setup_ping_retries = int(os.environ.get("INFLUXDB_SETUP_PING_RETRIES", 30))
influxdb_setup_ping_delay_seconds = int(os.environ.get("INFLUXDB_SETUP_PING_DELAY_SECONDS", 2))

print("Configuring InfluxDB at {}".format(influxdb_url))

client = InfluxDBClient(url=influxdb_url, token=influxdb_token)
print("Checking for ping...")
for attempt in range(1, influxdb_setup_ping_retries+1):
if client.ping():
break
else:
print(f"Failed to ping after {influxdb_setup_ping_retries} retries (with {influxdb_setup_ping_delay_seconds}s delay between each retry)")
sys.exit(1)

print("Successfully pinged influxdb")

matching_organizations = client.organizations_api().find_organizations(org=influxdb_organization_name)

if not matching_organizations:
print("No organizations found, not creating")
sys.exit(1)

if len(matching_organizations) > 1:
print(f"Found multiple organizations with name {influxdb_organization_name}. This should not happen.")
sys.exit(1)

organization = matching_organizations[0]

buckets_to_ensure_exist = ["default", "default_downsampled_15m", "default_downsampled_1h"]
buckets_api = client.buckets_api()
print("Creating buckets if needed...")
for bucket_name in buckets_to_ensure_exist:
existing_bucket = buckets_api.find_bucket_by_name(bucket_name)
if not existing_bucket:
print(f"Bucket {bucket_name} does not exist. Creating...")
buckets_api.create_bucket(bucket_name=bucket_name, org_id=organization.id)
print(f"Created bucket {bucket_name}.")
else:
print(f"Bucket {bucket_name} already exists. Nothing to do.")
print("Finished creating buckets if needed.")


tasks_to_ensure_exist = [{
"name": "Downsample (API Requests)",
"flux": """
data = from(bucket: "default")
|> range(start: -duration(v: int(v: task.every) * 2))
|> filter(fn: (r) =>
(r._measurement == "api_call"))

data
|> aggregateWindow(fn: sum, every: 15m)
|> filter(fn: (r) =>
(exists r._value))
|> to(bucket: "default_downsampled_15m")
""",
"every": "15m",
}, {
"name": "Downsample (Flag Evaluations)",
"flux": """
data = from(bucket: "default")
|> range(start: -duration(v: int(v: task.every) * 2))
|> filter(fn: (r) =>
(r._measurement == "feature_evaluation"))

data
|> aggregateWindow(fn: sum, every: 15m)
|> filter(fn: (r) =>
(exists r._value))
|> to(bucket: "default_downsampled_15m")
""",
"every": "15m",
}, {
"name": "Downsample API 1h",
"flux": """
data = from(bucket: "default")
|> range(start: -duration(v: int(v: task.every) * 2))
|> filter(fn: (r) =>
(r._measurement == "api_call"))

data
|> aggregateWindow(fn: sum, every: 1h)
|> filter(fn: (r) =>
(exists r._value))
|> to(bucket: "default_downsampled_1h")
""",
"every": "1h",
}, {
"name": "Downsample API 1h - Flag Analytics",
"flux": """
data = from(bucket: "default")
|> range(start: -duration(v: int(v: task.every) * 2))
|> filter(fn: (r) =>
(r._measurement == "feature_evaluation"))
|> filter(fn: (r) =>
(r._field == "request_count"))
|> group(columns: ["feature_id", "environment_id"])

data
|> aggregateWindow(fn: sum, every: 1h)
|> filter(fn: (r) =>
(exists r._value))
|> set(key: "_measurement", value: "feature_evaluation")
|> set(key: "_field", value: "request_count")
|> to(bucket: "default_downsampled_1h")
""",
"every": "1h",
}]

print("Creating tasks if needed...")
tasks = client.tasks_api()
for task_definition in tasks_to_ensure_exist:
if not tasks.find_tasks(name=task_definition["name"], org_id=organization.id):
print("Task {} does not exist. Creating...".format(task_definition["name"]))
tasks.create_task_every(task_definition["name"], task_definition["flux"], task_definition["every"], organization)
print("Created task {}.".format(task_definition["name"]))
else:
print("Task {} already exists. Nothing to do.".format(task_definition["name"]))
print("Finished creating tasks if needed.")

print("Finished configuring InfluxDB at {}".format(influxdb_url))
12 changes: 12 additions & 0 deletions charts/flagsmith/templates/configmap-influxdb-setup.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{{- if .Values.api.influxdbSetup.enabled }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "flagsmith.fullname" . }}-influxdb-setup
labels:
{{- include "flagsmith.labels" . | nindent 4 }}
app.kubernetes.io/component: influxdb-setup
data:
influxdb_setup.py: |
{{ include (print $.Template.BasePath "/_influxdb_setup.txt") . | indent 4 }}
{{- end }}
21 changes: 21 additions & 0 deletions charts/flagsmith/templates/deployment-api.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ spec:
{{- if and .Values.influxdbExternal.enabled (not .Values.influxdbExternal.tokenFromExistingSecret.enabled) }}
checksum/secrets-influxdb-external: {{ include (print $.Template.BasePath "/secrets-influxdb-external.yaml") . | sha256sum }}
{{- end }}
{{- if and .Values.api.influxdbSetup.enabled }}
checksum/configmap-influxdb-setup: {{ include (print $.Template.BasePath "/configmap-influxdb-setup.yaml") . | sha256sum }}
{{- end }}
{{- if .Values.api.podAnnotations }}
{{ toYaml .Values.api.podAnnotations | nindent 8 }}
{{- end }}
Expand Down Expand Up @@ -76,6 +79,18 @@ spec:
imagePullPolicy: {{ .Values.api.image.imagePullPolicy }}
args: ["migrate"]
env: {{ include (print $.Template.BasePath "/_api_environment.yaml") . | nindent 8 }}
{{- if .Values.api.influxdbSetup.enabled }}
- name: influxdb-setup
image: {{ .Values.api.image.repository }}:{{ .Values.api.image.tag | default (printf "%s" .Chart.AppVersion) }}
imagePullPolicy: {{ .Values.api.image.imagePullPolicy }}
command:
- python
- /influxdb_setup/influxdb_setup.py
env: {{ include (print $.Template.BasePath "/_api_environment.yaml") . | nindent 8 }}
volumeMounts:
- name: influxdb-setup
mountPath: /influxdb_setup/
{{- end }}
containers:
- name: {{ .Chart.Name }}-api
image: {{ .Values.api.image.repository }}:{{ .Values.api.image.tag | default (printf "%s" .Chart.AppVersion) }}
Expand Down Expand Up @@ -107,3 +122,9 @@ spec:
timeoutSeconds: {{ .Values.api.readinessProbe.timeoutSeconds }}
resources:
{{ toYaml .Values.api.resources | indent 10 }}
{{- if .Values.api.influxdbSetup.enabled }}
volumes:
- name: influxdb-setup
configMap:
name: {{ template "flagsmith.fullname" . }}-influxdb-setup
{{- end }}
2 changes: 2 additions & 0 deletions charts/flagsmith/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ api:
hostFromNodeIp: false
port: 8125
prefix: flagsmith.api
influxdbSetup:
enabled: false

frontend:
# Set this to `false` to switch off the frontend (deployment,
Expand Down

0 comments on commit 41af34c

Please sign in to comment.