Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion artifacts/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Services: adminer, cloudflared, portainer, portainer-agent, postgraphile, postgr

### event-streaming

Services: debezium, debezium-postgres-connector, postgres, redpanda, redpanda-console, sqitch, traefik
Services: debezium, debezium-postgres-connector, gizmosql, postgres, redpanda, redpanda-connect, redpanda-console, sqitch, traefik

### recommendation

Expand Down Expand Up @@ -73,6 +73,10 @@ You cannot access the search engine via a web interface.

You cannot access the ip geolocator via a web interface.

### gizmosql

You can query the event stream's parquet lakehouse using `grafana`.

### grafana

You can access the observation dashboard at [grafana.app.localhost](https://grafana.app.localhost/).
Expand Down Expand Up @@ -142,6 +146,10 @@ You cannot access the caching system via a web interface.

You can access the event streaming platform's ui as described under `redpanda-console`.

### redpanda-connect

You cannot access the event stream connector directly.

### redpanda-console

You can access the event streaming platform's ui at [redpanda.app.localhost](https://redpanda.app.localhost/).
Expand Down
1 change: 1 addition & 0 deletions src/development/.env.template
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
RECCOOM_ADMIN_ACCOUNT_IDS=
S3_ENDPOINT_URL=
TUSD_BUCKET=vibetype-images
TUSD_ENDPOINT=http://minio:9000
TUSD_MAX_SIZE=10485760
Expand Down
18 changes: 18 additions & 0 deletions src/development/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,21 @@ volumes:
pnpm-data:
# The node package manager's data.
{}
secrets:
s3-account-id:
# The event stream analytics' cloud storage account identifier.
file: ~~/artifacts/secrets/s3-account-id.secret
s3-aws-credentials-access-key:
# The event stream analytics' cloud storage secret access key.
file: ~~/artifacts/secrets/s3-aws-credentials-access-key.secret
s3-aws-credentials-access-key-id:
# The event stream analytics' cloud storage access key identifier.
file: ~~/artifacts/secrets/s3-aws-credentials-access-key-id.secret
x-dargstack:
secrets:
s3-account-id:
type: third_party
s3-aws-credentials-access-key:
type: third_party
s3-aws-credentials-access-key-id:
type: third_party
41 changes: 41 additions & 0 deletions src/development/gizmosql/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
secrets:
gizmosql-password:
# The gizmosql server's password.
file: ~~/artifacts/secrets/gizmosql-password.secret
services:
gizmosql:
# You can query the event stream's parquet lakehouse using `grafana`.
command: /run/entrypoint.sh
deploy:
labels:
- dargstack.profiles=event-streaming
entrypoint: sh
environment:
GIZMOSQL_USERNAME: gizmosql
INIT_SQL_COMMANDS_FILE: /tmp/gizmosql-init.sql
PRINT_QUERIES: "1"
TLS_ENABLED: "0"
healthcheck:
test: ["CMD-SHELL", "GIZMOSQL_PASSWORD=$$(cat /run/environment-variables/GIZMOSQL_PASSWORD) gizmosql_client --host 127.0.0.1 --port 31337 --username gizmosql --command 'SELECT 1'"]
interval: 30s
timeout: 10s
retries: 3
start_period: 60s
image: gizmodata/gizmosql:v1.35.1
secrets:
- source: gizmosql-password
target: /run/environment-variables/GIZMOSQL_PASSWORD
- source: s3-account-id
target: /run/environment-variables/S3_ACCOUNT_ID
- source: s3-aws-credentials-access-key-id
target: /run/environment-variables/S3_ACCESS_KEY_ID
- source: s3-aws-credentials-access-key
target: /run/environment-variables/S3_SECRET_ACCESS_KEY
volumes:
- ./configurations/entrypoint.sh:/run/entrypoint.sh:ro
- ./configurations/init.sql.template:/run/init.sql.template:ro
x-dargstack:
secrets:
gizmosql-password:
special_characters: false
type: random_string
51 changes: 51 additions & 0 deletions src/development/gizmosql/configurations/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/bin/sh
set -eu

# START of maevsi entrypoint script customization
ENVIRONMENT_VARIABLES_PATH="/run/environment-variables"

is_valid_var_name() {
case "$1" in
''|[!a-zA-Z_]*|*[!a-zA-Z0-9_]*) return 1 ;;
*) return 0 ;;
esac
}

load_env_file() {
file="$1"
name=$(basename "$file")
is_valid_var_name "$name" || return 0
value=$(cat "$file")
export "$name=$value"
}

load_environment_variables() {
[ -d "$ENVIRONMENT_VARIABLES_PATH" ] || return 0
set -- "$ENVIRONMENT_VARIABLES_PATH"/*
[ -e "$1" ] || return 0

for file in "$ENVIRONMENT_VARIABLES_PATH"/*; do
[ -f "$file" ] && load_env_file "$file"
done
}

load_environment_variables
# END of maevsi entrypoint script customization

# DuckDB in this image has no getenv() function, so the S3 values are rendered
# into init.sql. sed treats `&` and `\` specially in replacements, so escape
# them first (S3 keys are hex today, but this keeps arbitrary values safe).
escape_sed_replacement() {
printf '%s\n' "$1" | sed 's/[&\\]/\\&/g'
}

S3_ACCOUNT_ID="$(escape_sed_replacement "${S3_ACCOUNT_ID}")"
S3_ACCESS_KEY_ID="$(escape_sed_replacement "${S3_ACCESS_KEY_ID}")"
S3_SECRET_ACCESS_KEY="$(escape_sed_replacement "${S3_SECRET_ACCESS_KEY}")"

sed -e "s|__S3_ACCOUNT_ID__|${S3_ACCOUNT_ID}|g" \
-e "s|__S3_ACCESS_KEY_ID__|${S3_ACCESS_KEY_ID}|g" \
-e "s|__S3_SECRET_ACCESS_KEY__|${S3_SECRET_ACCESS_KEY}|g" \
/run/init.sql.template > /tmp/gizmosql-init.sql

exec /opt/gizmosql/scripts/start_gizmosql.sh
38 changes: 38 additions & 0 deletions src/development/gizmosql/configurations/init.sql.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
INSTALL httpfs;
LOAD httpfs;

CREATE SECRET s3_secret (TYPE r2, KEY_ID '__S3_ACCESS_KEY_ID__', SECRET '__S3_SECRET_ACCESS_KEY__', ACCOUNT_ID '__S3_ACCOUNT_ID__');

CREATE SCHEMA IF NOT EXISTS analytics;

-- The event stream's parquet lakehouse, written by redpanda-connect to S3
-- (bucket "test", prefix "events/"). The raw parquet columns are strings, so
-- ids and timestamps are cast to proper types (try_cast keeps bad values NULL).
CREATE OR REPLACE VIEW analytics.events AS
SELECT
try_cast(id AS UUID) AS id,
name,
slug,
try_cast(start AS TIMESTAMPTZ) AS start,
try_cast("end" AS TIMESTAMPTZ) AS "end",
visibility,
is_archived,
is_in_person,
is_remote,
language,
url,
try_cast(address_id AS UUID) AS address_id,
guest_count_maximum,
try_cast(created_at AS TIMESTAMPTZ) AS created_at,
try_cast(created_by AS UUID) AS created_by,
operation
FROM read_parquet('r2://test/events/*.parquet');

-- Example aggregate over the lakehouse.
CREATE OR REPLACE VIEW analytics.events_daily AS
SELECT
try_cast(created_at AS DATE) AS day,
count(*) AS events
FROM read_parquet('r2://test/events/*.parquet')
GROUP BY 1
ORDER BY 1;
2 changes: 2 additions & 0 deletions src/development/grafana/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ services:
GF_DATABASE_PASSWORD__FILE: /run/secrets/postgres-role-service-grafana-password
GF_DATABASE_TYPE: postgres
GF_DATABASE_USER__FILE: /run/secrets/postgres-role-service-grafana-username
GF_INSTALL_PLUGINS: gizmodata-gizmosql-datasource

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think about removing all the provisioning code for Grafana and instead configure it in the live system. Provisioning codifies the initial setup and makes it more explicit in that sense but also is quite rigid and disallows changing the config in the live Grafana instance. As we want to persist configurations done in the Grafana UI anyway, we can safe ourselves from config being too rigid and extensive and just configure those connectors in the UI, I'd say.

GF_SECURITY_ADMIN_EMAIL__FILE: /run/secrets/grafana-admin-email
GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana-admin-password
GF_SECURITY_ADMIN_USER__FILE: /run/secrets/grafana-admin-user
Expand All @@ -46,6 +47,7 @@ services:
- grafana-admin-password
- grafana-admin-user
- grafana-discord-webhook
- gizmosql-password
- postgres-db
- postgres-role-service-grafana-password
- postgres-role-service-grafana-username
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: 1

datasources:
- access: proxy
editable: true
jsonData:
host: gizmosql
port: 31337
useTLS: false
username: gizmosql
name: GizmoSQL
secureJsonData:
password: $__file{/run/secrets/gizmosql-password}
type: gizmodata-gizmosql-datasource
30 changes: 30 additions & 0 deletions src/development/redpanda-connect/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
secrets:
s3-aws-credentials:
# The event stream ingestion's s3 credentials file.
file: ~~/artifacts/secrets/s3-aws-credentials.secret
services:
redpanda-connect:
# You cannot access the event stream connector directly.
deploy:
labels:
- dargstack.profiles=event-streaming
environment:
AWS_SHARED_CREDENTIALS_FILE: /run/secrets/s3-aws-credentials
healthcheck:
test: ["CMD-SHELL", "wget -q --spider http://127.0.0.1:4195/ready"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
image: redpandadata/connect:4.103.1
secrets:
- s3-aws-credentials
volumes:
- ./configurations/config.yaml:/connect.yaml:ro
x-dargstack:
secrets:
s3-aws-credentials:
template: |
[default]
aws_access_key_id = {{secret:s3-aws-credentials-access-key-id}}
aws_secret_access_key = {{secret:s3-aws-credentials-access-key}}
77 changes: 77 additions & 0 deletions src/development/redpanda-connect/configurations/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
input:
kafka_franz:
seed_brokers: ["redpanda:9092"]
topics: ["vibetype.vibetype.event"]
consumer_group: "rp_connect_s3_ingest"
pipeline:
processors:
# Tombstone messages (Debezium deletes) carry no payload and must be dropped.
- bloblang: |
root = if this.payload.after.or(this.after) == null { deleted() }
- mapping: |
root = this.payload.after.or(this.after)
root.operation = this.payload.op.or(this.op)
Comment on lines +8 to +13

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if this handles all tombstone messages correctly, I'd need to research a bit more.

output:
aws_s3:
bucket: test
endpoint: ${S3_ENDPOINT_URL}
Comment thread
HMDank marked this conversation as resolved.
region: weur
force_path_style_urls: true
credentials:
profile: default
path: 'events/${! timestamp_unix_nano() }-${! uuid_v4() }.parquet'
batching:
count: 10000
period: 15s
processors:
- parquet_encode:
schema:
- name: id
type: UTF8
optional: true
- name: name
type: UTF8
optional: true
- name: slug
type: UTF8
optional: true
- name: start
type: UTF8
optional: true
- name: end
type: UTF8
optional: true
- name: visibility
type: UTF8
optional: true
- name: is_archived
type: BOOLEAN
optional: true
- name: is_in_person
type: BOOLEAN
optional: true
- name: is_remote
type: BOOLEAN
optional: true
- name: language
type: UTF8
optional: true
- name: url
type: UTF8
optional: true
- name: address_id
type: UTF8
optional: true
- name: guest_count_maximum
type: INT64
optional: true
- name: created_at
type: UTF8
optional: true
- name: created_by
type: UTF8
optional: true
- name: operation
type: UTF8
optional: true
default_compression: zstd
5 changes: 5 additions & 0 deletions src/production/gizmosql/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
gizmosql:
deploy:
update_config:
order: stop-first
5 changes: 5 additions & 0 deletions src/production/redpanda-connect/compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
services:
redpanda-connect:
deploy:
update_config:
order: stop-first
Comment thread
dargmuesli marked this conversation as resolved.
Loading