diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..7c47f24 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +ARG GO_VERSION=1.22.4 +ARG VARIANT=bookworm +FROM golang:${GO_VERSION}-${VARIANT} as builder + +WORKDIR /build + +COPY . . + +ARG GOFLAGS="-ldflags=-w -ldflags=-s" +RUN CGO_ENABLED=0 go build -o k6build -trimpath ./cmd/k6build/main.go + +# k6build server requires golang toolchain +FROM golang:${GO_VERSION}-${VARIANT} + +RUN addgroup --gid 1000 k6build && \ + adduser --uid 1000 --ingroup k6build \ + --home /home/k6build --shell /bin/sh \ + --disabled-password --gecos "" k6build + +COPY --from=builder /build/k6build /usr/local/bin/ + +WORKDIR /home/k6build + +USER k6build + +ENTRYPOINT ["/usr/local/bin/k6build"] \ No newline at end of file diff --git a/README.md b/README.md index 4f98c84..3ec4743 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,19 @@ +# k6build + +k6build builds custom k6 binaries with extensions + +## Examples + +The following sections describe different usage scenarios. + +### kubernetes + +[examples/kubernetes](examples/kubernetes/) describes how to run `k6build` in a kubernetes cluster and execute `k6` tests in a pod using [k6exec](https://github.com/grafana/k6exec). + +### k6-operator + +TODO: use [k6-operator](https://github.com/grafana/k6-operator) for running the tests using a custom image. + # k6build diff --git a/examples/kubernetes/README.md b/examples/kubernetes/README.md new file mode 100644 index 0000000..2d6ad48 --- /dev/null +++ b/examples/kubernetes/README.md @@ -0,0 +1,127 @@ +# Running k6build in Kubernetes + +This example shows how to deploy k6build as a service in Kubernetes and use [k6exec](https://github.com/grafana/k6exec) for running tests using extensions. + +![Fig. Architecture](images/architecture.png) + + +## Requirements + +This example requires access to a Kubernetes cluster and rights to deploy a service and create secrets. + +For testing, you can use [minikube](https://minikube.sigs.k8s.io/docs/) or [k3d](https://k3d.io/). + +### Build the image + +Build the [k6build image](/Dockerfile) from this project's root directory: + +``` +docker build -t grafana/k6build . +``` + +Make the image available to your Kubernetes cluster by loading it into a repository. + +This process depends on your cluster's setup. Following sections explain the process for common test cluster environments. + +#### Minikube + +If you are using minikube, you can use the following command: + +``` +minikube image load grafana/k6build +``` + +#### k3d + +If you are using k3d, you can use the following command: + +``` +k3d image import grafana/k6build +``` + +### Create the dependencies catalog + +k6build uses a [catalog](https://github.com/grafana/k6catalog) that specifies the versions supported for `k6` and the supported extensions. + +The `k6build` service expects this catalog to be in the `k6build-catalog` [configmap](https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/). + +The [deployment/catalog.json](deployment/catalog.json) file contains a sample catalog. + +Edit it to your needs (e.g. supported k6 versions) and create a configmap: + +``` +kubectl create configmap k6build-catalog --from-file deployment/catalog.json +configmap/k6build-catalog created +``` + +### Deploy service + +The [deployment/k6build.yaml](deployment/k6build.yaml) file contains the manifests for deploying as a service. It also creates a cache server to support the downloading of custom `k6` binaries. + +Deploy these components with the following command: + +``` +kubectl apply -f deployment/k6build.yaml +pod/cachesrv created +service/cachesrv created +pod/k6build created +service/k6build created +``` + +### Upload the test + +The test must be available as a config map. + +``` +kubectl create configmap k6test --from-file tests/sqlite.js +configmap/k6test created + +``` + +### Run test using k6exec + +The [deployment/k6exec.yaml](deployment/k6exec.yaml) file contains the manifest for running a job that executes the test from the `k6test` configmap. + +``` +kubectl create -f deployment/k6exec.yaml +pod/k6exec-2tr2j created + +``` + +> Notice that each type a pod is created using the `deployment/k6exec.yaml` manifest, it is given a different name. + +Get test results with the following command: + +``` +kubectl logs k6exec-2tr2j -f + + /\ |‾‾| /‾‾/ /‾‾/ + /\ / \ | |/ / / / + / \/ \ | ( / ‾‾\ + / \ | |\ \ | (‾) | + / __________ \ |__| \__\ \_____/ .io + + execution: local + script: test/sqlite.js + output: - + + scenarios: (100.00%) 1 scenario, 1 max VUs, 10m30s max duration (incl. graceful stop): + * default: 1 iterations for each of 1 VUs (maxDuration: 10m0s, gracefulStop: 30s) + +time="2024-08-28T12:09:23Z" level=info msg="key: plugin-name, value: k6-plugin-sql" source=console + + █ setup + + █ teardown + + data_received........: 0 B 0 B/s + data_sent............: 0 B 0 B/s + iteration_duration...: avg=7.16ms min=27.68µs med=10.56ms max=10.91ms p(90)=10.84ms p(95)=10.87ms + iterations...........: 1 44.591994/s + + +running (00m00.0s), 0/1 VUs, 1 complete and 0 interrupted iterations +default ✓ [ 100% ] 1 VUs 00m00.0s/10m0s 1/1 iters, 1 per VU +``` + +> The first time you run the test this command may take time to show any result while the binary is compiled. Subsequent executions should run almost immediately. \ No newline at end of file diff --git a/examples/kubernetes/deployment/catalog.json b/examples/kubernetes/deployment/catalog.json new file mode 100644 index 0000000..1dcb3a4 --- /dev/null +++ b/examples/kubernetes/deployment/catalog.json @@ -0,0 +1,6 @@ +{ + "k6": {"module": "go.k6.io/k6", "versions": ["v0.50.0", "v0.51.0"]}, + "k6/x/kubernetes": {"module": "github.com/grafana/xk6-kubernetes", "versions": ["v0.8.0","v0.9.0"]}, + "k6/x/sql": {"module": "github.com/grafana/xk6-sql", "versions": ["v0.4.0"]}, + "k6/x/output-kafka": {"module": "github.com/grafana/xk6-output-kafka", "versions": ["v0.7.0"]} +} diff --git a/examples/kubernetes/deployment/k6build.yaml b/examples/kubernetes/deployment/k6build.yaml new file mode 100644 index 0000000..d0182bb --- /dev/null +++ b/examples/kubernetes/deployment/k6build.yaml @@ -0,0 +1,71 @@ +kind: Pod +apiVersion: v1 +metadata: + name: cachesrv + labels: + app: cachesrv +spec: + containers: + - name: cachesrv + image: grafana/k6build + imagePullPolicy: Never + command: ["k6build", "cache", "--log-level", "DEBUG", "--download-url", "http://cachesrv:9000/cache"] + +--- +kind: Service +apiVersion: v1 +metadata: + name: cachesrv +spec: + selector: + app: cachesrv + type: LoadBalancer + ports: + - port: 9000 + +--- +kind: Pod +apiVersion: v1 +metadata: + name: k6build + labels: + app: k6build +spec: + containers: + - name: buildsrv + image: grafana/k6build + imagePullPolicy: Never + command: + - "k6build" + - "server" + - "--verbose" + - "--log-level" + - "DEBUG" + - "--cache-url" + - "http://cachesrv:9000/cache" + - "-e" + - "CGO_ENABLED=1" + volumeMounts: + - mountPath: "/home/k6build" + name: catalog + readOnly: true + - mountPath: "/home/k6build/.cache" + name: gocache + volumes: + - name: catalog + configMap: + name: k6build-catalog + - name: gocache + emptyDir: {} + +--- +kind: Service +apiVersion: v1 +metadata: + name: k6build +spec: + selector: + app: k6build + type: LoadBalancer + ports: + - port: 8000 diff --git a/examples/kubernetes/deployment/k6exec.yaml b/examples/kubernetes/deployment/k6exec.yaml new file mode 100644 index 0000000..398964c --- /dev/null +++ b/examples/kubernetes/deployment/k6exec.yaml @@ -0,0 +1,20 @@ +kind: Pod +apiVersion: v1 +metadata: + generateName: k6exec- + labels: + app: k6exec +spec: + restartPolicy: Never + containers: + - name: k6exec + image: ghcr.io/grafana/k6exec:latest + imagePullPolicy: IfNotPresent + command: ["k6exec", "--build-service-url", "http://k6build:8000", "run", "test/sqlite.js"] + volumeMounts: + - mountPath: "/home/k6exec/test" + name: test + volumes: + - name: test + configMap: + name: k6test diff --git a/examples/kubernetes/images/architecture.excalidraw b/examples/kubernetes/images/architecture.excalidraw new file mode 100644 index 0000000..c1d3753 --- /dev/null +++ b/examples/kubernetes/images/architecture.excalidraw @@ -0,0 +1,1235 @@ +{ + "type": "excalidraw", + "version": 2, + "source": "https://excalidraw.com", + "elements": [ + { + "id": "Rt4GphvHU5795MJMiO9Xp", + "type": "rectangle", + "x": 325.73062884807587, + "y": -134.74151398738218, + "width": 138, + "height": 120, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a0", + "roundness": { + "type": 3 + }, + "seed": 967843734, + "version": 89, + "versionNonce": 2144908374, + "isDeleted": false, + "boundElements": [ + { + "type": "text", + "id": "8mmsatPcZx4qLLtYYlbs1" + } + ], + "updated": 1724848321765, + "link": null, + "locked": false + }, + { + "id": "8mmsatPcZx4qLLtYYlbs1", + "type": "text", + "x": 366.29312884807587, + "y": -84.34151398738217, + "width": 56.875, + "height": 19.2, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a1", + "roundness": null, + "seed": 247552918, + "version": 32, + "versionNonce": 313244054, + "isDeleted": false, + "boundElements": null, + "updated": 1724848321765, + "link": null, + "locked": false, + "text": "script", + "fontSize": 16, + "fontFamily": 3, + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "Rt4GphvHU5795MJMiO9Xp", + "originalText": "script", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "id": "0D9YgqACS6le7AjyInh_G", + "type": "rectangle", + "x": 309.73062884807587, + "y": -163.74151398738218, + "width": 171.99999999999997, + "height": 167, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a2", + "roundness": null, + "seed": 1171025814, + "version": 259, + "versionNonce": 2003572438, + "isDeleted": false, + "boundElements": [ + { + "id": "iJbyBwrA-kdllHKJYkOHX", + "type": "arrow" + } + ], + "updated": 1724848321765, + "link": null, + "locked": false + }, + { + "id": "XwMQCeOKuRw1mKbVcAgVj", + "type": "text", + "x": 318.73062884807587, + "y": -159.74151398738218, + "width": 85, + "height": 19.2, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a3", + "roundness": null, + "seed": 1564717962, + "version": 82, + "versionNonce": 2120800598, + "isDeleted": false, + "boundElements": null, + "updated": 1724848321765, + "link": null, + "locked": false, + "text": "configmap", + "fontSize": 16, + "fontFamily": 3, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "configmap", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "id": "AxzBh-hgEypUvoUO8OaT8", + "type": "rectangle", + "x": 571.7306288480759, + "y": -168.74151398738218, + "width": 174, + "height": 176, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "a4", + "roundness": null, + "seed": 944721110, + "version": 144, + "versionNonce": 1303491798, + "isDeleted": false, + "boundElements": null, + "updated": 1724848051543, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 108, + "versionNonce": 1331765962, + "index": "a5", + "isDeleted": false, + "id": "MrrTcDt1tHhlgya7fYE5Y", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 590.7306288480759, + "y": -136.74151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 138, + "height": 120, + "seed": 354035286, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "8GkzOzp-CTy104tQxHNaY" + }, + { + "id": "SeJXS2JTLx_kG3Z7UB3l4", + "type": "arrow" + }, + { + "id": "dy0GU6SqJfke2ziAxXzbd", + "type": "arrow" + }, + { + "id": "iJbyBwrA-kdllHKJYkOHX", + "type": "arrow" + }, + { + "id": "vNjC-PnYoiSspAIGw3VzR", + "type": "arrow" + } + ], + "updated": 1724848381083, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 53, + "versionNonce": 1266895510, + "index": "a6", + "isDeleted": false, + "id": "8GkzOzp-CTy104tQxHNaY", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 631.2931288480759, + "y": -86.34151398738217, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 56.875, + "height": 19.2, + "seed": 586083222, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848009384, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "k6exec", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "MrrTcDt1tHhlgya7fYE5Y", + "originalText": "k6exec", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "text", + "version": 118, + "versionNonce": 1260843734, + "index": "a7", + "isDeleted": false, + "id": "62HHH2UnAEuFHSM9yMQEN", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 582.2306288480759, + "y": -164.3415139873822, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 28.75, + "height": 19.2, + "seed": 1212083722, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848024641, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "Pod", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Pod", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "rectangle", + "version": 211, + "versionNonce": 978207126, + "index": "aA", + "isDeleted": false, + "id": "i0gHncyuhEp5QgcgP36UW", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 947.7306288480759, + "y": -143.74151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 138, + "height": 120, + "seed": 154260234, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "HueqLYsJaJ0vgi8THsgqd" + }, + { + "id": "SeJXS2JTLx_kG3Z7UB3l4", + "type": "arrow" + }, + { + "id": "za6EUjImrkawN35sH-CRV", + "type": "arrow" + }, + { + "id": "vNjC-PnYoiSspAIGw3VzR", + "type": "arrow" + } + ], + "updated": 1724848375223, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 171, + "versionNonce": 551676950, + "index": "aB", + "isDeleted": false, + "id": "HueqLYsJaJ0vgi8THsgqd", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 979.2306288480759, + "y": -102.94151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 75, + "height": 38.4, + "seed": 911663562, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848351610, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "k6build \nserver", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "i0gHncyuhEp5QgcgP36UW", + "originalText": "k6build server", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "text", + "version": 186, + "versionNonce": 1978281802, + "index": "aC", + "isDeleted": false, + "id": "2kU1RYhf56l6EgXUHPVUw", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 938.2306288480759, + "y": -168.3415139873822, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 28.75, + "height": 19.2, + "seed": 23861386, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848385518, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "Pod", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Pod", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "rectangle", + "version": 339, + "versionNonce": 1147609098, + "index": "aD", + "isDeleted": false, + "id": "u4uDSiMCAkH7knEgUJuZT", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 930.7306288480759, + "y": 65.25848601261782, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 174, + "height": 176, + "seed": 2872854, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "za6EUjImrkawN35sH-CRV", + "type": "arrow" + } + ], + "updated": 1724848355893, + "link": null, + "locked": false + }, + { + "type": "rectangle", + "version": 330, + "versionNonce": 1966602582, + "index": "aE", + "isDeleted": false, + "id": "zUtiT7wYWYVxufAurYZnN", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 952.7306288480759, + "y": 98.25848601261782, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 138, + "height": 120, + "seed": 1739891542, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "1t9HwU4dkeef5nWtCfh1Z" + }, + { + "id": "dy0GU6SqJfke2ziAxXzbd", + "type": "arrow" + } + ], + "updated": 1724848351610, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 296, + "versionNonce": 931011542, + "index": "aF", + "isDeleted": false, + "id": "1t9HwU4dkeef5nWtCfh1Z", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 988.6056288480759, + "y": 139.05848601261783, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 66.25, + "height": 38.4, + "seed": 389138582, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848351610, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "k6build\ncache", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "zUtiT7wYWYVxufAurYZnN", + "originalText": "k6build\ncache", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "text", + "version": 343, + "versionNonce": 272118038, + "index": "aG", + "isDeleted": false, + "id": "oBJrWz8-au44FGp1jSbS1", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 944.2306288480759, + "y": 70.6584860126178, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 28.75, + "height": 19.2, + "seed": 1045972438, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848351610, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "Pod", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Pod", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "id": "SeJXS2JTLx_kG3Z7UB3l4", + "type": "arrow", + "x": 728.7306288480759, + "y": -103.74151398738218, + "width": 195, + "height": 0, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aH", + "roundness": { + "type": 2 + }, + "seed": 773445194, + "version": 187, + "versionNonce": 290314582, + "isDeleted": false, + "boundElements": null, + "updated": 1724848393628, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 195, + 0 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "MrrTcDt1tHhlgya7fYE5Y", + "focus": -0.45, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "i0gHncyuhEp5QgcgP36UW", + "focus": 0.3333333333333333, + "gap": 24, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "za6EUjImrkawN35sH-CRV", + "type": "arrow", + "x": 1022.7306288480759, + "y": 1.2584860126178228, + "width": 1.1572908078342152, + "height": 64, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aI", + "roundness": { + "type": 2 + }, + "seed": 1738840918, + "version": 246, + "versionNonce": 328991638, + "isDeleted": false, + "boundElements": null, + "updated": 1724848362713, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 1.1572908078342152, + 64 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "i0gHncyuhEp5QgcgP36UW", + "focus": -0.06367947042300588, + "gap": 25, + "fixedPoint": null + }, + "endBinding": { + "elementId": "u4uDSiMCAkH7knEgUJuZT", + "focus": 0.08746420774262165, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "type": "arrow", + "version": 316, + "versionNonce": 714291978, + "index": "aJ", + "isDeleted": false, + "id": "vNjC-PnYoiSspAIGw3VzR", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 925.2306288480759, + "y": -67.74151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 194, + "height": 1, + "seed": 567899018, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 2 + }, + "boundElements": [], + "updated": 1724848397476, + "link": null, + "locked": false, + "startBinding": { + "elementId": "i0gHncyuhEp5QgcgP36UW", + "focus": -0.2572807242292254, + "gap": 22.5, + "fixedPoint": null + }, + "endBinding": { + "elementId": "MrrTcDt1tHhlgya7fYE5Y", + "focus": 0.17179093005380477, + "gap": 2.5, + "fixedPoint": null + }, + "lastCommittedPoint": null, + "startArrowhead": null, + "endArrowhead": "arrow", + "points": [ + [ + 0, + 0 + ], + [ + -194, + 1 + ] + ], + "elbowed": false + }, + { + "id": "dy0GU6SqJfke2ziAxXzbd", + "type": "arrow", + "x": 659.7306288480759, + "y": -15.741513987382177, + "width": 270, + "height": 181.60926811129977, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aK", + "roundness": { + "type": 2 + }, + "seed": 671594122, + "version": 300, + "versionNonce": 98197142, + "isDeleted": false, + "boundElements": [], + "updated": 1724848351610, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 22, + 172 + ], + [ + 270, + 181.60926811129977 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "MrrTcDt1tHhlgya7fYE5Y", + "focus": 0.10175917500758265, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "zUtiT7wYWYVxufAurYZnN", + "focus": -0.17828888345159447, + "gap": 23, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "iJbyBwrA-kdllHKJYkOHX", + "type": "arrow", + "x": 585.7306288480759, + "y": -84.74151398738218, + "width": 103, + "height": 1.5855071562340726, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aM", + "roundness": null, + "seed": 1797640010, + "version": 85, + "versionNonce": 917425174, + "isDeleted": false, + "boundElements": null, + "updated": 1724848321765, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + -103, + -1.5855071562340726 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "MrrTcDt1tHhlgya7fYE5Y", + "focus": 0.11211924821775762, + "gap": 20, + "fixedPoint": null + }, + "endBinding": { + "elementId": "0D9YgqACS6le7AjyInh_G", + "focus": -0.08753109452736318, + "gap": 1, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "id": "Zvs_4tbVy7IU942G8SqZq", + "type": "text", + "x": 758.9539361397427, + "y": -150.74151398738218, + "width": 138.74348958333317, + "height": 20.199999999999974, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aO", + "roundness": null, + "seed": 23552214, + "version": 56, + "versionNonce": 1008913866, + "isDeleted": false, + "boundElements": null, + "updated": 1724848344150, + "link": null, + "locked": false, + "text": "Request binary", + "fontSize": 16.833333333333307, + "fontFamily": 3, + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Request binary", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "text", + "version": 110, + "versionNonce": 15504854, + "index": "aP", + "isDeleted": false, + "id": "Abdt6NTcxxPX_6tHxKcU2", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 729.3588840564095, + "y": 124.1584860126178, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 149.043212890625, + "height": 20.199999999999967, + "seed": 2058424918, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848409995, + "link": null, + "locked": false, + "fontSize": 16.833333333333307, + "fontFamily": 3, + "text": "Download binary", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "Download binary", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "rectangle", + "version": 215, + "versionNonce": 164811222, + "index": "aQ", + "isDeleted": false, + "id": "ri7uncm2rJ0OlmerVVtyr", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1185.2306288480759, + "y": -137.24151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 138, + "height": 120, + "seed": 471122442, + "groupIds": [], + "frameId": null, + "roundness": { + "type": 3 + }, + "boundElements": [ + { + "type": "text", + "id": "mxzqiC7aUkouTIfhrR6lb" + } + ], + "updated": 1724848450405, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 166, + "versionNonce": 1270763082, + "index": "aR", + "isDeleted": false, + "id": "mxzqiC7aUkouTIfhrR6lb", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "solid", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1221.1056288480759, + "y": -86.84151398738217, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 66.25, + "height": 19.2, + "seed": 1828974794, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848483012, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "catalog", + "textAlign": "center", + "verticalAlign": "middle", + "containerId": "ri7uncm2rJ0OlmerVVtyr", + "originalText": "catalog", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "rectangle", + "version": 366, + "versionNonce": 1174829450, + "index": "aT", + "isDeleted": false, + "id": "muEoqEM-0GiayzVn9u8sH", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1166.7306288480759, + "y": -175.24151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 171.99999999999997, + "height": 167, + "seed": 1289633930, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "0JjTVJ_LkCevqE1iFRm2e", + "type": "arrow" + } + ], + "updated": 1724848478824, + "link": null, + "locked": false + }, + { + "type": "text", + "version": 188, + "versionNonce": 837540246, + "index": "aU", + "isDeleted": false, + "id": "vkq9LKOjfxrpyKQiYiq1t", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1175.7306288480759, + "y": -171.24151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 85, + "height": 19.2, + "seed": 1964613450, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848450405, + "link": null, + "locked": false, + "fontSize": 16, + "fontFamily": 3, + "text": "configmap", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "configmap", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "rectangle", + "version": 405, + "versionNonce": 440431626, + "index": "aW", + "isDeleted": false, + "id": "Oxt7wvWPZxPRJEkCGRpGP", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 928.7306288480759, + "y": -169.24151398738218, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 171.99999999999997, + "height": 167, + "seed": 172553750, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [ + { + "id": "0JjTVJ_LkCevqE1iFRm2e", + "type": "arrow" + } + ], + "updated": 1724848478824, + "link": null, + "locked": false + }, + { + "id": "0JjTVJ_LkCevqE1iFRm2e", + "type": "arrow", + "x": 1100.7306288480759, + "y": -84.74151398738218, + "width": 62, + "height": 1, + "angle": 0, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "groupIds": [], + "frameId": null, + "index": "aX", + "roundness": null, + "seed": 1494732170, + "version": 27, + "versionNonce": 1323918026, + "isDeleted": false, + "boundElements": null, + "updated": 1724848478824, + "link": null, + "locked": false, + "points": [ + [ + 0, + 0 + ], + [ + 62, + 1 + ] + ], + "lastCommittedPoint": null, + "startBinding": { + "elementId": "Oxt7wvWPZxPRJEkCGRpGP", + "focus": -0.004560136804104123, + "gap": 1, + "fixedPoint": null + }, + "endBinding": { + "elementId": "muEoqEM-0GiayzVn9u8sH", + "focus": -0.111343340300209, + "gap": 4, + "fixedPoint": null + }, + "startArrowhead": null, + "endArrowhead": "arrow", + "elbowed": false + }, + { + "type": "text", + "version": 134, + "versionNonce": 279123594, + "index": "aY", + "isDeleted": false, + "id": "GgMGZ-xowRwFH-nG3mcTU", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 764.3588840564095, + "y": -53.8415139873822, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 149.043212890625, + "height": 20.199999999999967, + "seed": 743160458, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848511549, + "link": null, + "locked": false, + "fontSize": 16.833333333333307, + "fontFamily": 3, + "text": "binary metadata", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "binary metadata", + "autoResize": true, + "lineHeight": 1.2 + }, + { + "type": "text", + "version": 100, + "versionNonce": 1817254538, + "index": "aZ", + "isDeleted": false, + "id": "Pel8YL7lCkgatpemc44Wz", + "fillStyle": "hachure", + "strokeWidth": 1, + "strokeStyle": "dashed", + "roughness": 0, + "opacity": 100, + "angle": 0, + "x": 1043.3588840564094, + "y": 18.1584860126178, + "strokeColor": "#364fc7", + "backgroundColor": "transparent", + "width": 119.4625244140625, + "height": 20.199999999999967, + "seed": 702972298, + "groupIds": [], + "frameId": null, + "roundness": null, + "boundElements": [], + "updated": 1724848534501, + "link": null, + "locked": false, + "fontSize": 16.833333333333307, + "fontFamily": 3, + "text": "store binary", + "textAlign": "left", + "verticalAlign": "top", + "containerId": null, + "originalText": "store binary", + "autoResize": true, + "lineHeight": 1.2 + } + ], + "appState": { + "gridSize": 20, + "gridStep": 5, + "gridModeEnabled": false, + "viewBackgroundColor": "#ffffff" + }, + "files": {} +} \ No newline at end of file diff --git a/examples/kubernetes/images/architecture.png b/examples/kubernetes/images/architecture.png new file mode 100644 index 0000000..fbbfeaf Binary files /dev/null and b/examples/kubernetes/images/architecture.png differ diff --git a/examples/kubernetes/tests/sqlite.js b/examples/kubernetes/tests/sqlite.js new file mode 100644 index 0000000..c17f93e --- /dev/null +++ b/examples/kubernetes/tests/sqlite.js @@ -0,0 +1,24 @@ +// source: https://github.com/grafana/xk6-sql/blob/v0.4.0/examples/sqlite3_test.js +import sql from "k6/x/sql"; + +const db = sql.open("sqlite3", "./test.db"); + +export function setup() { + db.exec(`CREATE TABLE IF NOT EXISTS keyvalues ( + id integer PRIMARY KEY AUTOINCREMENT, + key varchar NOT NULL, + value varchar);`); +} + +export function teardown() { + db.close(); +} + +export default function () { + db.exec("INSERT INTO keyvalues (key, value) VALUES('plugin-name', 'k6-plugin-sql');"); + + let results = sql.query(db, "SELECT * FROM keyvalues WHERE key = $1;", "plugin-name"); + for (const row of results) { + console.log(`key: ${row.key}, value: ${row.value}`); + } +}