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
50 changes: 50 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: CI

on:
push:
branches: ["main"]
pull_request:
branches: ["main"]

permissions:
contents: read

jobs:
frontend:
name: Frontend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: "20"
cache: npm
- run: npm ci
- run: npm run build

backend:
name: Backend
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version: "1.22"
cache-dependency-path: backend/go.mod
- name: Download modules
run: cd backend && go mod download
- name: Create frontend embed placeholder
run: mkdir -p backend/dist && touch backend/dist/main.js
- run: cd backend && go vet ./...
- run: cd backend && go test ./...
- run: cd backend && go build -o /dev/null .

helm-lint:
name: Helm lint
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: azure/setup-helm@1a275c3b69536ee54be43f2070a358922e12c8d4 # v4.3.1
with:
version: "3.14.0"
- run: helm lint charts/plugin-bench/
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
node_modules/
dist/
backend/dist/main.js
backend/plugin-bench
*.tgz
20 changes: 20 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
FROM golang:1.22-alpine AS backend-builder

WORKDIR /app

COPY backend/go.mod backend/go.sum* ./
RUN go mod download

COPY backend/ ./
COPY dist/main.js ./dist/main.js

RUN CGO_ENABLED=0 GOOS=linux go build -trimpath -ldflags="-s -w" -o server .

FROM alpine:3.19

RUN apk --no-cache add ca-certificates

COPY --from=backend-builder /app/server /usr/local/bin/server

EXPOSE 8080
ENTRYPOINT ["server"]
14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.PHONY: help frontend backend helm-lint

help: ## Display available commands.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make <target>\n\n"} /^[a-zA-Z_-]+:.*##/ { printf " %-16s %s\n", $$1, $$2 }' $(MAKEFILE_LIST)

frontend: ## Type-check and build the frontend bundle.
npm run build

backend: ## Run backend formatting, vetting, tests, and build.
gofmt -w backend/*.go
cd backend && go vet ./... && go test ./... && go build -o /dev/null .

helm-lint: ## Lint the Helm chart.
helm lint charts/plugin-bench/
3 changes: 3 additions & 0 deletions backend/go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/openeverest/plugin-bench/backend

go 1.22
86 changes: 86 additions & 0 deletions backend/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package main

import (
"embed"
"encoding/json"
"log"
"net/http"
"os"
"time"
)

// The frontend bundle is copied here by the Docker build. CI creates a
// placeholder so the backend can be checked before the frontend is built.
//
//go:embed dist/main.js
var distFS embed.FS

type runSummary struct {
ID string `json:"id"`
Status string `json:"status"`
Profile string `json:"profile"`
CreatedAt time.Time `json:"createdAt"`
}

func writeJSON(w http.ResponseWriter, status int, value any) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
if err := json.NewEncoder(w).Encode(value); err != nil {
log.Printf("writeJSON: %v", err)
}
}

func handleBundle(w http.ResponseWriter, _ *http.Request) {
bundle, err := distFS.ReadFile("dist/main.js")
if err != nil {
http.Error(w, "frontend bundle not found", http.StatusNotFound)
return
}
w.Header().Set("Content-Type", "application/javascript; charset=utf-8")
w.Header().Set("Cache-Control", "no-store")
_, _ = w.Write(bundle)
}

func handleHealth(w http.ResponseWriter, _ *http.Request) {
writeJSON(w, http.StatusOK, map[string]string{"status": "ok"})
}

func handleStatus(w http.ResponseWriter, _ *http.Request) {
writeJSON(w, http.StatusOK, map[string]any{
"status": "scaffold",
"database": "postgresql",
"runnerReady": false,
"storage": "ephemeral",
"message": "Benchmark orchestration is not implemented yet.",
})
}

func handleRuns(w http.ResponseWriter, r *http.Request) {
switch r.Method {
case http.MethodGet:
writeJSON(w, http.StatusOK, map[string]any{"runs": []runSummary{}})
case http.MethodPost:
writeJSON(w, http.StatusNotImplemented, map[string]string{
"error": "benchmark execution is not implemented in the scaffold",
})
default:
w.WriteHeader(http.StatusMethodNotAllowed)
}
}

func main() {
mux := http.NewServeMux()
mux.HandleFunc("GET /main.js", handleBundle)
mux.HandleFunc("GET /healthz", handleHealth)
mux.HandleFunc("GET /api/status", handleStatus)
mux.HandleFunc("/api/runs", handleRuns)

port := os.Getenv("PORT")
if port == "" {
port = "8080"
}
log.Printf("plugin-bench backend listening on :%s", port)
if err := http.ListenAndServe(":"+port, mux); err != nil {
log.Fatal(err)
}
}
6 changes: 6 additions & 0 deletions charts/plugin-bench/Chart.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
name: plugin-bench
description: Helm chart for the OpenEverest Performance Benchmark plugin
type: application
version: 0.1.0
appVersion: "0.1.0"
39 changes: 39 additions & 0 deletions charts/plugin-bench/templates/_helpers.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{{/* Expand the name of the chart. */}}
{{- define "plugin-bench.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/* Create a default fully qualified app name. */}}
{{- define "plugin-bench.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/* Chart label. */}}
{{- define "plugin-bench.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/* Common labels. */}}
{{- define "plugin-bench.labels" -}}
helm.sh/chart: {{ include "plugin-bench.chart" . }}
{{ include "plugin-bench.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/* Selector labels. */}}
{{- define "plugin-bench.selectorLabels" -}}
app.kubernetes.io/name: {{ include "plugin-bench.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
49 changes: 49 additions & 0 deletions charts/plugin-bench/templates/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "plugin-bench.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "plugin-bench.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "plugin-bench.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "plugin-bench.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
protocol: TCP
env:
- name: PORT
value: {{ .Values.service.port | quote }}
{{- if .Values.everestAPIURL }}
- name: EVEREST_API_URL
value: {{ .Values.everestAPIURL | quote }}
{{- end }}
livenessProbe:
httpGet:
path: /healthz
port: {{ .Values.service.port }}
initialDelaySeconds: 5
periodSeconds: 15
readinessProbe:
httpGet:
path: /healthz
port: {{ .Values.service.port }}
initialDelaySeconds: 3
periodSeconds: 10
resources:
{{- toYaml .Values.resources | nindent 12 }}
24 changes: 24 additions & 0 deletions charts/plugin-bench/templates/plugin-cr.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
apiVersion: extensions.openeverest.io/v1alpha1
kind: Plugin
metadata:
name: {{ .Release.Name }}
spec:
displayName: {{ .Values.plugin.displayName | quote }}
description: {{ .Values.plugin.description | quote }}
version: {{ .Chart.AppVersion | quote }}
vendor: {{ .Values.plugin.vendor | quote }}
enabled: {{ .Values.plugin.enabled }}
backend:
serviceRef:
namespace: {{ .Release.Namespace }}
name: {{ include "plugin-bench.fullname" . }}
port: {{ .Values.service.port }}
frontend:
bundlePath: {{ .Values.plugin.bundlePath | quote }}
extensionPoints:
{{- toYaml .Values.plugin.extensionPoints | nindent 6 }}
permissions:
- verb: read
resource: database-clusters
- verb: read
resource: database-cluster-connection-details
14 changes: 14 additions & 0 deletions charts/plugin-bench/templates/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "plugin-bench.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "plugin-bench.labels" . | nindent 4 }}
spec:
selector:
{{- include "plugin-bench.selectorLabels" . | nindent 4 }}
ports:
- port: {{ .Values.service.port }}
targetPort: {{ .Values.service.port }}
protocol: TCP
40 changes: 40 additions & 0 deletions charts/plugin-bench/values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
replicaCount: 1

image:
repository: ghcr.io/openeverest/plugin-bench
pullPolicy: IfNotPresent
tag: ""

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

service:
port: 8080

plugin:
displayName: "Performance Benchmark"
description: "Run and inspect PostgreSQL benchmarks for OpenEverest database clusters."
vendor: "OpenEverest"
enabled: true
bundlePath: "/main.js"
extensionPoints:
- type: route
path: /performance-benchmark
label: Performance Benchmark
- type: clusterDetailTab
path: performance-benchmark
label: Performance Benchmark
providers:
- provider-cloudnative-pg
- provider-percona-postgresql

everestAPIURL: ""

resources:
limits:
cpu: 200m
memory: 128Mi
requests:
cpu: 50m
memory: 64Mi
Loading
Loading