Skip to content
Merged
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
37 changes: 37 additions & 0 deletions .devcontainer/00-blind-by-design_03-expert/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
{
"name": "πŸ§ͺ Adventure 00 | πŸ”΄ Expert (Read the chart)",
"dockerComposeFile": "docker-compose.yml",
"service": "workspace",
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}/adventures/planned/00-blind-by-design/expert",
"postCreateCommand": "bash /workspaces/${localWorkspaceFolderBasename}/.devcontainer/00-blind-by-design_03-expert/post-create.sh",
"postStartCommand": "bash /workspaces/${localWorkspaceFolderBasename}/.devcontainer/00-blind-by-design_03-expert/post-start.sh",
"customizations": {
"vscode": {
"extensions": [
"vscjava.vscode-java-pack",
"redhat.vscode-yaml",
"ms-azuretools.vscode-docker"
]
},
"codespaces": {
"openFiles": [
"adventures/planned/00-blind-by-design/docs/expert.md",
"adventures/planned/00-blind-by-design/expert/otel.properties",
"adventures/planned/00-blind-by-design/expert/src/main/java/dev/openfeature/demo/java/demo/OpenFeatureConfig.java",
"adventures/planned/00-blind-by-design/expert/flags.json"
]
}
},
"forwardPorts": [8080, 3000, 4317, 4318, 9090, 3200],
"portsAttributes": {
"8080": { "label": "Spring Boot lab", "onAutoForward": "notify" },
"3000": { "label": "Grafana", "onAutoForward": "notify" },
"4317": { "label": "OTLP gRPC", "onAutoForward": "ignore" },
"4318": { "label": "OTLP HTTP", "onAutoForward": "ignore" },
"9090": { "label": "Prometheus", "onAutoForward": "ignore" },
"3200": { "label": "Tempo HTTP API", "onAutoForward": "ignore" }
},
"otherPortsAttributes": {
"onAutoForward": "ignore"
}
}
75 changes: 75 additions & 0 deletions .devcontainer/00-blind-by-design_03-expert/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Multi-container devcontainer for Expert. The lab itself runs in
# `workspace`; flagd, the Grafana LGTM stack, and the k6 loadgen run as
# sibling services. No Docker-in-Docker β€” the devcontainer attaches to
# `workspace` and the rest of the stack is already up.
#
# Inside `workspace`, services are reachable by service name
# (flagd:8013, lgtm:4317, etc.). FLAGD_HOST and OTEL_EXPORTER_OTLP_ENDPOINT
# are pre-set so the participant does not have to hard-code hostnames.
# Codespaces also forwards each port to localhost on the host so verify.sh
# and curl can keep using localhost:NNNN unchanged.

services:
workspace:
image: mcr.microsoft.com/devcontainers/java:1-21
volumes:
- ../..:/workspaces/${localWorkspaceFolderBasename:-open-ecosystem-challenges}:cached
command: sleep infinity
environment:
- FLAGD_HOST=flagd
- FLAGD_PORT=8013
# OpenTelemetry Java Agent. post-create.sh downloads the jar; the
# spring-boot-maven-plugin reads OTEL_JAVAAGENT_JAR for its <jvmArguments>
# so only the forked lab JVM is agent-attached (not Maven itself).
# Agent config lives in expert/otel.properties β€” that's the file
# players edit to toggle the metrics exporter.
- OTEL_JAVAAGENT_JAR=/workspaces/${localWorkspaceFolderBasename:-open-ecosystem-challenges}/tools/opentelemetry-javaagent.jar
- OTEL_JAVAAGENT_CONFIGURATION_FILE=/workspaces/${localWorkspaceFolderBasename:-open-ecosystem-challenges}/adventures/planned/00-blind-by-design/expert/otel.properties
# Trial country of registration. Read by OpenFeatureConfig via
# System.getenv("COUNTRY") and put on the global eval context.
- COUNTRY=de

flagd:
image: ghcr.io/open-feature/flagd:v0.15.4
volumes:
- ../..:/workspaces/${localWorkspaceFolderBasename:-open-ecosystem-challenges}:ro
command:
- start
- --uri
- file:/workspaces/${localWorkspaceFolderBasename:-open-ecosystem-challenges}/adventures/planned/00-blind-by-design/expert/flags.json
# No `ports:` block β€” the lab and loadgen reach flagd on the
# docker-internal network as `flagd:8013`. Forwarding the flagd
# ports onto the Codespace host is not needed to play the level.

lgtm:
image: grafana/otel-lgtm:0.26.0
ports:
- "3000:3000" # Grafana UI (admin / admin)
- "4317:4317" # OTLP gRPC
- "4318:4318" # OTLP HTTP
- "9090:9090" # Prometheus query API (verify.sh)
- "3200:3200" # Tempo HTTP API (verify.sh)
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- ../..:/workspaces/${localWorkspaceFolderBasename:-open-ecosystem-challenges}:ro
# Dashboard auto-provisioning: otel-lgtm scans /otel-lgtm/grafana/conf/provisioning/dashboards/
# for provider YAMLs, then loads dashboard JSONs from whatever path
# the provider references. We point at .../custom for both.
- ../../adventures/planned/00-blind-by-design/expert/dashboards/provisioning.yaml:/otel-lgtm/grafana/conf/provisioning/dashboards/fun-with-flags.yaml:ro
- ../../adventures/planned/00-blind-by-design/expert/dashboards:/otel-lgtm/grafana/conf/provisioning/dashboards/custom:ro

loadgen:
image: grafana/k6:1.7.1
command: ["run", "--quiet", "/scripts/script.js"]
volumes:
- ../../adventures/planned/00-blind-by-design/expert/loadgen/k6:/scripts:ro
environment:
# The script idles while loadgen_active is "off". Flip it in flags.json
# to start hammering the lab.
- BASE_URL=http://workspace:8080
- FLAGD_URL=http://flagd:8013
restart: unless-stopped
depends_on:
- flagd
46 changes: 46 additions & 0 deletions .devcontainer/00-blind-by-design_03-expert/post-create.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env bash
set -e

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"

# shellcheck disable=SC1091
source "$REPO_ROOT/lib/scripts/tracker.sh"
set_tracking_context "00-blind-by-design" "expert"
track_codespace_created

# gum is used by the verify.sh / output.sh helpers
"$REPO_ROOT/lib/shared/init.sh" --version v0.17.0 # https://github.com/charmbracelet/gum/releases

# jq is needed by verify.sh; the Java devcontainer image is debian-based.
if ! command -v jq >/dev/null 2>&1; then
sudo apt-get update -y
sudo apt-get install -y --no-install-recommends jq
fi

CHALLENGE_DIR="$REPO_ROOT/adventures/planned/00-blind-by-design/expert"

# Make the Maven wrapper executable so the participant can just `./mvnw ...`
if [[ -f "$CHALLENGE_DIR/mvnw" ]]; then
chmod +x "$CHALLENGE_DIR/mvnw"
fi

# Download the OpenTelemetry Java Agent. The Spring Boot Maven Plugin
# attaches it via -javaagent (see expert/pom.xml). One jar per Codespace
# β€” skip if already present so re-runs are cheap.
OTEL_AGENT_VERSION="v2.27.0"
OTEL_AGENT_DIR="$REPO_ROOT/tools"
OTEL_AGENT_JAR="$OTEL_AGENT_DIR/opentelemetry-javaagent.jar"
mkdir -p "$OTEL_AGENT_DIR"
if [[ ! -f "$OTEL_AGENT_JAR" ]]; then
echo "⬇️ Downloading OpenTelemetry Java Agent $OTEL_AGENT_VERSION..."
curl -fsSL \
-o "$OTEL_AGENT_JAR" \
"https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/download/$OTEL_AGENT_VERSION/opentelemetry-javaagent.jar" \
|| echo "⚠️ Failed to fetch the OpenTelemetry Java Agent β€” traces and metrics will not flow until the jar is present at $OTEL_AGENT_JAR"
fi

echo "✨ Pre-warming the Maven dependency cache so the first ./mvnw is fast..."
( cd "$CHALLENGE_DIR" && ./mvnw -q -DskipTests dependency:go-offline ) || \
echo "⚠️ Dependency pre-warm skipped (network or wrapper not ready yet)"

echo "βœ… Phase 3 toolchain ready (gum + Java 21). flagd / lgtm / loadgen run as sibling devcontainer services."
52 changes: 52 additions & 0 deletions .devcontainer/00-blind-by-design_03-expert/post-start.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -e

REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
CHALLENGE_DIR="$REPO_ROOT/adventures/planned/00-blind-by-design/expert"

cat <<EOF

✨ Adventure 00 β€” Level 3 (πŸ”΄ Expert): Read the chart

πŸ“‚ Challenge directory:
$CHALLENGE_DIR

πŸ§ͺ Sibling services already running (managed by devcontainer compose):
- flagd β†’ flagd:8013 (gRPC eval) / flagd:8016 (OFREP HTTP)
Management/metrics on :8014, sync stream on :8015.
- lgtm β†’ lgtm:4317 (OTLP) / Grafana on http://localhost:3000 (admin / admin)
- loadgen β†’ idles until loadgen_active flag flips to "on"

All ports are forwarded to localhost on the host, so curl, verify.sh,
and the browser can keep using localhost:NNNN.

β–Ά Run the lab β€” one launch config in .vscode/launch.json:
πŸ§ͺ Run the Phase 3 Lab
Open the Run and Debug view (Ctrl/Cmd + Shift + D) and hit β–Ά.

Or from the terminal:
./mvnw spring-boot:run

βœ… Run the verification when you're ready:
./verify.sh
or use the πŸ§ͺ Verify Solution task: Tasks β†’ Run Test Task.

EOF

# Track that the environment is ready
# shellcheck disable=SC1091
source "$REPO_ROOT/lib/scripts/tracker.sh"
set_tracking_context "blind-by-design" "expert"
track_codespace_initialized

# Open the relevant files in the connected editor. customizations.codespaces.openFiles
# is unreliable for dockerComposeFile-based devcontainers (the orchestrator merges
# devcontainer.json and the field is sometimes dropped). `code` is the same CLI the
# editor uses internally and works against either the web or desktop client.
if command -v code >/dev/null 2>&1; then
code "$REPO_ROOT/adventures/planned/00-blind-by-design/docs/expert.md" \
"$CHALLENGE_DIR/otel.properties" \
"$CHALLENGE_DIR/src/main/java/dev/openfeature/demo/java/demo/OpenFeatureConfig.java" \
"$CHALLENGE_DIR/flags.json" \
2>/dev/null || true
fi
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,11 @@ venv/
.pytest_cache/
.mypy_cache/

# Maven build artifacts
target/

# OpenTelemetry Java Agent (downloaded per-Codespace by post-create.sh)
tools/

# Custom ignores/includes
.prompts
Loading
Loading