Skip to content

Commit 41af34c

Browse files
authored
Automated InfluxDB setup steps (#97)
1 parent 4cec00c commit 41af34c

File tree

6 files changed

+179
-1
lines changed

6 files changed

+179
-1
lines changed

charts/flagsmith/Chart.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: v2
22
name: flagsmith
33
description: Flagsmith
44
type: application
5-
version: 0.13.0
5+
version: 0.14.0
66
appVersion: 2.34.0
77
dependencies:
88
- name: postgresql
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests:
2+
enabled: true
3+
4+
api:
5+
extraEnv:
6+
ENABLE_INFLUXDB_FEATURES: 'true'
7+
influxdbSetup:
8+
enabled: true
9+
10+
influxdb2:
11+
enabled: true
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# File extension is .txt not .py just because helm's linting complains
2+
# about non txt/tpl/yaml/yml extensions.
3+
4+
import os
5+
import sys
6+
7+
from influxdb_client import InfluxDBClient
8+
9+
influxdb_url = os.environ["INFLUXDB_URL"]
10+
influxdb_token = os.environ["INFLUXDB_TOKEN"]
11+
influxdb_organization_name = os.environ["INFLUXDB_ORG"]
12+
influxdb_setup_ping_retries = int(os.environ.get("INFLUXDB_SETUP_PING_RETRIES", 30))
13+
influxdb_setup_ping_delay_seconds = int(os.environ.get("INFLUXDB_SETUP_PING_DELAY_SECONDS", 2))
14+
15+
print("Configuring InfluxDB at {}".format(influxdb_url))
16+
17+
client = InfluxDBClient(url=influxdb_url, token=influxdb_token)
18+
print("Checking for ping...")
19+
for attempt in range(1, influxdb_setup_ping_retries+1):
20+
if client.ping():
21+
break
22+
else:
23+
print(f"Failed to ping after {influxdb_setup_ping_retries} retries (with {influxdb_setup_ping_delay_seconds}s delay between each retry)")
24+
sys.exit(1)
25+
26+
print("Successfully pinged influxdb")
27+
28+
matching_organizations = client.organizations_api().find_organizations(org=influxdb_organization_name)
29+
30+
if not matching_organizations:
31+
print("No organizations found, not creating")
32+
sys.exit(1)
33+
34+
if len(matching_organizations) > 1:
35+
print(f"Found multiple organizations with name {influxdb_organization_name}. This should not happen.")
36+
sys.exit(1)
37+
38+
organization = matching_organizations[0]
39+
40+
buckets_to_ensure_exist = ["default", "default_downsampled_15m", "default_downsampled_1h"]
41+
buckets_api = client.buckets_api()
42+
print("Creating buckets if needed...")
43+
for bucket_name in buckets_to_ensure_exist:
44+
existing_bucket = buckets_api.find_bucket_by_name(bucket_name)
45+
if not existing_bucket:
46+
print(f"Bucket {bucket_name} does not exist. Creating...")
47+
buckets_api.create_bucket(bucket_name=bucket_name, org_id=organization.id)
48+
print(f"Created bucket {bucket_name}.")
49+
else:
50+
print(f"Bucket {bucket_name} already exists. Nothing to do.")
51+
print("Finished creating buckets if needed.")
52+
53+
54+
tasks_to_ensure_exist = [{
55+
"name": "Downsample (API Requests)",
56+
"flux": """
57+
data = from(bucket: "default")
58+
|> range(start: -duration(v: int(v: task.every) * 2))
59+
|> filter(fn: (r) =>
60+
(r._measurement == "api_call"))
61+
62+
data
63+
|> aggregateWindow(fn: sum, every: 15m)
64+
|> filter(fn: (r) =>
65+
(exists r._value))
66+
|> to(bucket: "default_downsampled_15m")
67+
""",
68+
"every": "15m",
69+
}, {
70+
"name": "Downsample (Flag Evaluations)",
71+
"flux": """
72+
data = from(bucket: "default")
73+
|> range(start: -duration(v: int(v: task.every) * 2))
74+
|> filter(fn: (r) =>
75+
(r._measurement == "feature_evaluation"))
76+
77+
data
78+
|> aggregateWindow(fn: sum, every: 15m)
79+
|> filter(fn: (r) =>
80+
(exists r._value))
81+
|> to(bucket: "default_downsampled_15m")
82+
""",
83+
"every": "15m",
84+
}, {
85+
"name": "Downsample API 1h",
86+
"flux": """
87+
data = from(bucket: "default")
88+
|> range(start: -duration(v: int(v: task.every) * 2))
89+
|> filter(fn: (r) =>
90+
(r._measurement == "api_call"))
91+
92+
data
93+
|> aggregateWindow(fn: sum, every: 1h)
94+
|> filter(fn: (r) =>
95+
(exists r._value))
96+
|> to(bucket: "default_downsampled_1h")
97+
""",
98+
"every": "1h",
99+
}, {
100+
"name": "Downsample API 1h - Flag Analytics",
101+
"flux": """
102+
data = from(bucket: "default")
103+
|> range(start: -duration(v: int(v: task.every) * 2))
104+
|> filter(fn: (r) =>
105+
(r._measurement == "feature_evaluation"))
106+
|> filter(fn: (r) =>
107+
(r._field == "request_count"))
108+
|> group(columns: ["feature_id", "environment_id"])
109+
110+
data
111+
|> aggregateWindow(fn: sum, every: 1h)
112+
|> filter(fn: (r) =>
113+
(exists r._value))
114+
|> set(key: "_measurement", value: "feature_evaluation")
115+
|> set(key: "_field", value: "request_count")
116+
|> to(bucket: "default_downsampled_1h")
117+
""",
118+
"every": "1h",
119+
}]
120+
121+
print("Creating tasks if needed...")
122+
tasks = client.tasks_api()
123+
for task_definition in tasks_to_ensure_exist:
124+
if not tasks.find_tasks(name=task_definition["name"], org_id=organization.id):
125+
print("Task {} does not exist. Creating...".format(task_definition["name"]))
126+
tasks.create_task_every(task_definition["name"], task_definition["flux"], task_definition["every"], organization)
127+
print("Created task {}.".format(task_definition["name"]))
128+
else:
129+
print("Task {} already exists. Nothing to do.".format(task_definition["name"]))
130+
print("Finished creating tasks if needed.")
131+
132+
print("Finished configuring InfluxDB at {}".format(influxdb_url))
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{{- if .Values.api.influxdbSetup.enabled }}
2+
apiVersion: v1
3+
kind: ConfigMap
4+
metadata:
5+
name: {{ template "flagsmith.fullname" . }}-influxdb-setup
6+
labels:
7+
{{- include "flagsmith.labels" . | nindent 4 }}
8+
app.kubernetes.io/component: influxdb-setup
9+
data:
10+
influxdb_setup.py: |
11+
{{ include (print $.Template.BasePath "/_influxdb_setup.txt") . | indent 4 }}
12+
{{- end }}

charts/flagsmith/templates/deployment-api.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ spec:
2121
{{- if and .Values.influxdbExternal.enabled (not .Values.influxdbExternal.tokenFromExistingSecret.enabled) }}
2222
checksum/secrets-influxdb-external: {{ include (print $.Template.BasePath "/secrets-influxdb-external.yaml") . | sha256sum }}
2323
{{- end }}
24+
{{- if and .Values.api.influxdbSetup.enabled }}
25+
checksum/configmap-influxdb-setup: {{ include (print $.Template.BasePath "/configmap-influxdb-setup.yaml") . | sha256sum }}
26+
{{- end }}
2427
{{- if .Values.api.podAnnotations }}
2528
{{ toYaml .Values.api.podAnnotations | nindent 8 }}
2629
{{- end }}
@@ -76,6 +79,18 @@ spec:
7679
imagePullPolicy: {{ .Values.api.image.imagePullPolicy }}
7780
args: ["migrate"]
7881
env: {{ include (print $.Template.BasePath "/_api_environment.yaml") . | nindent 8 }}
82+
{{- if .Values.api.influxdbSetup.enabled }}
83+
- name: influxdb-setup
84+
image: {{ .Values.api.image.repository }}:{{ .Values.api.image.tag | default (printf "%s" .Chart.AppVersion) }}
85+
imagePullPolicy: {{ .Values.api.image.imagePullPolicy }}
86+
command:
87+
- python
88+
- /influxdb_setup/influxdb_setup.py
89+
env: {{ include (print $.Template.BasePath "/_api_environment.yaml") . | nindent 8 }}
90+
volumeMounts:
91+
- name: influxdb-setup
92+
mountPath: /influxdb_setup/
93+
{{- end }}
7994
containers:
8095
- name: {{ .Chart.Name }}-api
8196
image: {{ .Values.api.image.repository }}:{{ .Values.api.image.tag | default (printf "%s" .Chart.AppVersion) }}
@@ -107,3 +122,9 @@ spec:
107122
timeoutSeconds: {{ .Values.api.readinessProbe.timeoutSeconds }}
108123
resources:
109124
{{ toYaml .Values.api.resources | indent 10 }}
125+
{{- if .Values.api.influxdbSetup.enabled }}
126+
volumes:
127+
- name: influxdb-setup
128+
configMap:
129+
name: {{ template "flagsmith.fullname" . }}-influxdb-setup
130+
{{- end }}

charts/flagsmith/values.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ api:
6767
hostFromNodeIp: false
6868
port: 8125
6969
prefix: flagsmith.api
70+
influxdbSetup:
71+
enabled: false
7072

7173
frontend:
7274
# Set this to `false` to switch off the frontend (deployment,

0 commit comments

Comments
 (0)