├── VERSION ├── examples ├── apps │ ├── fio │ │ ├── values.yaml │ │ ├── README.md │ │ ├── .gitignore │ │ ├── examples │ │ │ ├── 1.ephemeral-volume.yml │ │ │ ├── 0.no-storage.yml │ │ │ ├── 3.raw-device.yml │ │ │ ├── 2.formatted-device.yml │ │ │ └── 4.shared-fs.yml │ │ ├── .helmignore │ │ ├── scripts │ │ │ └── fio.sh │ │ ├── templates │ │ │ ├── 0.default.yml │ │ │ └── 4.shared-fs.yml │ │ └── Chart.yaml │ ├── flower │ │ ├── values.yaml │ │ ├── .helmignore │ │ ├── README.md │ │ ├── containers │ │ │ ├── README.md │ │ │ ├── advanced_tensorflow.Dockerfile │ │ │ └── advanced_pytorch.Dockerfile │ │ ├── example.yaml │ │ ├── templates │ │ │ ├── advanced_pytorch.yaml │ │ │ └── advanced_tensorflow.yaml │ │ └── Chart.yaml │ ├── h5py │ │ ├── values.yaml │ │ ├── README.md │ │ ├── scripts │ │ │ ├── collective_io │ │ │ │ └── README.md │ │ │ ├── concatenation │ │ │ │ ├── README.md │ │ │ │ └── create.py │ │ │ ├── bytesio │ │ │ │ ├── README.md │ │ │ │ └── bytesio.py │ │ │ └── multiprocessing │ │ │ │ ├── README.md │ │ │ │ └── image-visualizer.py │ │ ├── .gitignore │ │ ├── .helmignore │ │ ├── examples │ │ │ ├── 0.sources.yml │ │ │ └── 1.pipeline.yml │ │ ├── Chart.yaml │ │ └── templates │ │ │ └── multiprocessing.yml │ ├── iperf2 │ │ ├── values.yaml │ │ ├── .gitignore │ │ ├── .helmignore │ │ ├── templates │ │ │ ├── server.yml │ │ │ └── client.yml │ │ ├── examples │ │ │ ├── 0.server-client.yml │ │ │ ├── 5.assertions.yml │ │ │ ├── 1.scheduled-clients.yml │ │ │ ├── 6.deletions.yml │ │ │ ├── 3.create-until.yml │ │ │ ├── 8.time-driven-partition.yml │ │ │ ├── 11.time-driven-delay.yml │ │ │ ├── 4.create-when.yml │ │ │ ├── 2.advanced-placement.yml │ │ │ ├── 7.failure-toleration.yml │ │ │ └── 9.state-driven-partition.yml │ │ └── Chart.yaml │ ├── iperf3 │ │ ├── values.yaml │ │ ├── .gitignore │ │ ├── templates │ │ │ ├── server.yml │ │ │ └── client.yml │ │ ├── .helmignore │ │ ├── examples │ │ │ └── 0.server-client.yml │ │ └── Chart.yaml │ ├── mongodb │ │ ├── values.yaml │ │ ├── .gitignore │ │ ├── README.md │ │ ├── .helmignore │ │ ├── Chart.yaml │ │ └── examples │ │ │ └── README.md │ ├── redis │ │ ├── values.yaml │ │ ├── .gitignore │ │ ├── .helmignore │ │ ├── templates │ │ │ └── telemetry.yml │ │ ├── Chart.yaml │ │ └── examples │ │ │ └── 5.scaleup-scheduled.yml │ ├── ycsb │ │ ├── values.yaml │ │ ├── README.md │ │ ├── .gitignore │ │ ├── .helmignore │ │ └── Chart.yaml │ ├── datasets │ │ ├── values.yaml │ │ ├── README.md │ │ ├── .gitignore │ │ └── Chart.yaml │ ├── tikv │ │ ├── examples │ │ │ ├── README.md │ │ │ └── plan.scaleout.yml │ │ ├── .gitignore │ │ ├── values.yaml │ │ ├── .helmignore │ │ └── Chart.yaml │ ├── flower-custom │ │ ├── values.yaml │ │ ├── README.md │ │ ├── .gitignore │ │ ├── .helmignore │ │ ├── templates │ │ │ ├── server-with-logs.yml │ │ │ ├── datasets.yml │ │ │ └── server.yml │ │ ├── Chart.yaml │ │ └── examples │ │ │ ├── 1.baseline.yml │ │ │ ├── 2.throttle-server.yml │ │ │ ├── 10.scheduled-join.yml │ │ │ └── 11.scaled-baseline.yml │ ├── parallax │ │ ├── values.yaml │ │ ├── README.md │ │ ├── .gitignore │ │ ├── Chart.yaml │ │ ├── .helmignore │ │ └── templates │ │ │ └── benchmark.yml │ ├── tebis │ │ ├── values.yaml │ │ ├── .gitignore │ │ ├── Chart.yaml │ │ ├── .helmignore │ │ ├── build │ │ │ └── init.Dockerfile │ │ └── examples │ │ │ └── normal-execution.yml │ ├── virtual-slurm │ │ ├── values.yaml │ │ ├── .gitignore │ │ ├── scripts │ │ │ └── test.py │ │ ├── .helmignore │ │ ├── templates │ │ │ └── storage.yml │ │ ├── README.md │ │ ├── examples │ │ │ └── normal-execution.yml │ │ └── Chart.yaml │ ├── fedbed │ │ ├── README.md │ │ ├── values.yaml │ │ ├── examples │ │ │ └── resource-distribution.yml │ │ └── Chart.yaml │ ├── cockroachdb │ │ ├── .gitignore │ │ ├── Chart.yaml │ │ ├── .helmignore │ │ └── values.yaml │ ├── opengadget3 │ │ ├── .gitignore │ │ ├── values.yaml │ │ ├── README.md │ │ ├── .helmignore │ │ ├── examples │ │ │ └── gadget.yml │ │ ├── templates │ │ │ └── ssh.yml │ │ └── Chart.yaml │ ├── README.md │ └── debugger │ │ └── tools │ │ └── docker.yml ├── patterns │ ├── ci │ │ └── README.md │ ├── databases │ │ ├── elasticity │ │ │ └── install.sh │ │ ├── ycsb-sequence │ │ │ └── install.sh │ │ ├── network-partition │ │ │ └── install.sh │ │ ├── sstable-bitrot │ │ │ └── install.sh │ │ └── normal-load │ │ │ ├── install.sh │ │ │ ├── manifest.yml │ │ │ └── manifest-by-time.yml │ └── federated-learning │ │ ├── ml-backend │ │ ├── install.sh │ │ └── manifest.yml │ │ ├── crash-on-epoch │ │ └── install.sh │ │ ├── node-placement │ │ └── install.sh │ │ ├── resource-distribution │ │ └── install.sh │ │ └── parallel-workflows │ │ └── install.sh └── tutorial │ ├── 1.hello-world.yml │ ├── 2.parameters.yml │ ├── 14b.delete-cluster-with-tolerance.yml │ ├── 3.execution-order.yml │ └── 4.dependency-order.yml ├── docs ├── logo.jpg └── readme.assets │ ├── cli-get.png │ ├── grafana.png │ ├── grafana2.png │ ├── cli-inspect.png │ ├── cli-submit.png │ ├── inspect-failed.png │ ├── kubect-frisbee.png │ ├── submit-dependencies.png │ └── contextualized-visualization.png ├── charts ├── system │ ├── .gitignore │ ├── .helmignore │ ├── templates │ │ ├── chaos │ │ │ ├── pod-kill.yml │ │ │ ├── network-loss.yml │ │ │ ├── network-duplicate.yml │ │ │ └── network-delay.yml │ │ └── telemetry │ │ │ └── dataviewer │ │ │ └── dataviewer.yml │ └── Chart.yaml └── platform │ ├── charts │ ├── openebs-3.2.0.tgz │ ├── chaos-mesh-2.1.2.tgz │ └── kubernetes-dashboard-5.7.0.tgz │ ├── templates │ ├── NOTES.txt │ ├── configuration.yaml │ ├── webhook │ │ ├── admission │ │ │ └── certificate.yaml │ │ └── alerts │ │ │ └── proxy.yaml │ └── deployment │ │ └── clusterrolebinding.yaml │ ├── .helmignore │ └── Chart.lock ├── images ├── annotator │ ├── Dockerfile │ └── builder.sh ├── prometheus │ ├── builder.sh │ └── Dockerfile ├── cadvisor │ ├── builder.sh │ └── Dockerfile └── ci-environment │ └── Dockerfile ├── hack ├── README.md ├── api-docs │ ├── template │ │ ├── placeholder.go │ │ ├── members.tpl │ │ └── pkg.tpl │ └── config.json ├── remove_k8s_finalizers.sh ├── remove_k8s_ns_finalizer.sh └── boilerplate.go.txt ├── .dockerignore ├── api └── v1alpha1 │ ├── doc.go │ ├── type_tolerations.go │ └── register.go ├── cmd ├── README.md └── kubectl-frisbee │ ├── main.go │ ├── env │ ├── logo.go │ └── root_unix.go │ └── commands │ ├── common │ ├── constants.go │ └── kubectl-wrapper_test.go │ ├── install.go │ ├── root.go │ ├── delete.go │ ├── validate.go │ └── report.go ├── .builds-linux.goreleaser.yml ├── CONTRIBUTORS.md ├── CITATION.cff ├── .gitignore ├── .github ├── ISSUE_TEMPLATE │ ├── question.md │ ├── feature_request.md │ └── bug_report.md ├── workflows │ ├── repo-stats.yml │ ├── generate-api-docs.yaml │ ├── test-unit.yml │ ├── release-docker-images.yml │ └── release-kubectl-frisbee.yml └── pull_request_template.md ├── pkg ├── home │ ├── lazypath_windows.go │ ├── lazypath_darwin.go │ ├── home_windows_test.go │ ├── xdg │ │ └── xdg.go │ └── home_unix_test.go ├── structure │ ├── map.go │ ├── slice.go │ └── structs.go ├── distributions │ ├── number.go │ ├── constant.go │ ├── pareto.go │ ├── uniform.go │ └── normal.go ├── debug │ └── debug.go ├── configuration │ └── references.go ├── grafana │ └── lister.go └── client │ └── api.go ├── controllers ├── common │ ├── watchers │ │ └── interface.go │ └── endpoints.go ├── call │ └── utils │ │ └── timeline.go ├── cascade │ └── utils │ │ └── timeline.go ├── chaos │ └── jobs.go └── cluster │ └── utils │ └── timeline.go └── Dockerfile /VERSION: -------------------------------------------------------------------------------- 1 | v1.0.43 2 | -------------------------------------------------------------------------------- /examples/apps/fio/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/flower/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/h5py/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/iperf2/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/iperf3/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/mongodb/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/redis/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/ycsb/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/datasets/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/tikv/examples/README.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/fio/README.md: -------------------------------------------------------------------------------- 1 | ## Parameters -------------------------------------------------------------------------------- /examples/apps/flower-custom/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/flower/.helmignore: -------------------------------------------------------------------------------- 1 | containers -------------------------------------------------------------------------------- /examples/apps/h5py/README.md: -------------------------------------------------------------------------------- 1 | ## Parameters -------------------------------------------------------------------------------- /examples/apps/parallax/values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | -------------------------------------------------------------------------------- /examples/apps/tebis/values.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/values.yaml: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/apps/ycsb/README.md: -------------------------------------------------------------------------------- 1 | ## Parameters 2 | -------------------------------------------------------------------------------- /examples/apps/fedbed/README.md: -------------------------------------------------------------------------------- 1 | # FedBed 2 | 3 | 4 | ## Parameters 5 | -------------------------------------------------------------------------------- /examples/apps/flower/README.md: -------------------------------------------------------------------------------- 1 | # Flower 2 | 3 | 4 | ## Parameters 5 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/README.md: -------------------------------------------------------------------------------- 1 | # Flower 2 | 3 | 4 | ## Parameters 5 | -------------------------------------------------------------------------------- /examples/apps/parallax/README.md: -------------------------------------------------------------------------------- 1 | # Parallax 2 | 3 | 4 | ## Parameters 5 | -------------------------------------------------------------------------------- /examples/apps/h5py/scripts/collective_io/README.md: -------------------------------------------------------------------------------- 1 | Test collective io in h5py 2 | -------------------------------------------------------------------------------- /docs/logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/logo.jpg -------------------------------------------------------------------------------- /charts/system/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/datasets/README.md: -------------------------------------------------------------------------------- 1 | # Federated Learning Datasets 2 | 3 | 4 | ## Parameters 5 | -------------------------------------------------------------------------------- /examples/apps/fio/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/h5py/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/iperf2/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/iperf3/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/mongodb/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/redis/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/tebis/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/tikv/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/ycsb/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/cockroachdb/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/datasets/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/h5py/scripts/concatenation/README.md: -------------------------------------------------------------------------------- 1 | Concatenate multiple files into a single virtual dataset -------------------------------------------------------------------------------- /examples/apps/opengadget3/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/parallax/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /images/annotator/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM alpine:3.18 2 | 3 | RUN apk update && apk add curl bash grep 4 | 5 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/.gitignore: -------------------------------------------------------------------------------- 1 | # ignore local charts (used for testing) 2 | charts 3 | Chart.lock 4 | -------------------------------------------------------------------------------- /hack/README.md: -------------------------------------------------------------------------------- 1 | Contains utility files, e.g. the file used to scaffold the license header for your project files. -------------------------------------------------------------------------------- /docs/readme.assets/cli-get.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/cli-get.png -------------------------------------------------------------------------------- /docs/readme.assets/grafana.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/grafana.png -------------------------------------------------------------------------------- /docs/readme.assets/grafana2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/grafana2.png -------------------------------------------------------------------------------- /docs/readme.assets/cli-inspect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/cli-inspect.png -------------------------------------------------------------------------------- /docs/readme.assets/cli-submit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/cli-submit.png -------------------------------------------------------------------------------- /docs/readme.assets/inspect-failed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/inspect-failed.png -------------------------------------------------------------------------------- /docs/readme.assets/kubect-frisbee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/kubect-frisbee.png -------------------------------------------------------------------------------- /charts/platform/charts/openebs-3.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/charts/platform/charts/openebs-3.2.0.tgz -------------------------------------------------------------------------------- /images/prometheus/builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build . -t icsforth/prometheus 4 | 5 | docker push icsforth/prometheus:latest -------------------------------------------------------------------------------- /docs/readme.assets/submit-dependencies.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/submit-dependencies.png -------------------------------------------------------------------------------- /charts/platform/charts/chaos-mesh-2.1.2.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/charts/platform/charts/chaos-mesh-2.1.2.tgz -------------------------------------------------------------------------------- /images/cadvisor/builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build . -t icsforth/cadvisor --network=host 4 | 5 | docker push icsforth/cadvisor:latest 6 | -------------------------------------------------------------------------------- /hack/api-docs/template/placeholder.go: -------------------------------------------------------------------------------- 1 | // Package template keeps a placeholder file to make Go vendor this directory properly. 2 | package template 3 | -------------------------------------------------------------------------------- /images/annotator/builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | docker build . -t icsforth/annotator --network host 4 | 5 | docker push icsforth/annotator:latest 6 | -------------------------------------------------------------------------------- /docs/readme.assets/contextualized-visualization.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/docs/readme.assets/contextualized-visualization.png -------------------------------------------------------------------------------- /charts/platform/charts/kubernetes-dashboard-5.7.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CARV-ICS-FORTH/frisbee/HEAD/charts/platform/charts/kubernetes-dashboard-5.7.0.tgz -------------------------------------------------------------------------------- /examples/apps/tikv/values.yaml: -------------------------------------------------------------------------------- 1 | ## @section Common Parameters 2 | ## 3 | 4 | ## @param nameOverride String to partially override common.names.fullname 5 | ### 6 | nameOverride: "" 7 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore all files which are not go type 3 | !**/*.go 4 | !**/*.mod 5 | !**/*.sum 6 | -------------------------------------------------------------------------------- /examples/apps/h5py/scripts/bytesio/README.md: -------------------------------------------------------------------------------- 1 | Create an HDF5 file in memory and retrieve the raw bytes 2 | This could be used, for instance, in a server producing small HDF5 3 | files on demand. -------------------------------------------------------------------------------- /api/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | // Package v1alpha1 contains API Schema definitions for the Frisbee v1alpha1 API group 2 | // +kubebuilder:object:generate=true 3 | // +groupName=frisbee.dev 4 | package v1alpha1 5 | -------------------------------------------------------------------------------- /examples/apps/opengadget3/values.yaml: -------------------------------------------------------------------------------- 1 | ## @section OpenGadget3 Configuration parameters 2 | 3 | ## @param datasetPath The local path to get the dataset from. 4 | datasetPath: /home/fnikol/Workspace/projects/OpenGadget3/dataset -------------------------------------------------------------------------------- /charts/platform/templates/NOTES.txt: -------------------------------------------------------------------------------- 1 | Thank you for installing {{ .Chart.Name }}. 2 | 3 | Your release is named {{ .Release.Name }}. 4 | 5 | To learn more about the release, try: 6 | 7 | $ helm status {{ .Release.Name }} 8 | $ helm get all {{ .Release.Name }} -------------------------------------------------------------------------------- /cmd/README.md: -------------------------------------------------------------------------------- 1 | The plugin 2 | 3 | Example: 4 | https://github.com/kubernetes/sample-cli-plugin 5 | 6 | The plugin should be placed in 7 | /usr/local/bin 8 | ~/.local/bin 9 | $GOPATH/bin 10 | 11 | In order to be detectable by kubectil is must be named `kubectl-frisbee`. -------------------------------------------------------------------------------- /examples/apps/h5py/scripts/bytesio/bytesio.py: -------------------------------------------------------------------------------- 1 | import io 2 | 3 | import h5py 4 | 5 | bio = io.BytesIO() 6 | with h5py.File(bio, 'w') as f: 7 | f['dataset'] = range(10) 8 | 9 | data = bio.getvalue() # data is a regular Python bytes object. 10 | print("Total size:", len(data)) 11 | print("First bytes:", data[:10]) 12 | -------------------------------------------------------------------------------- /examples/apps/mongodb/README.md: -------------------------------------------------------------------------------- 1 | MongoDB is a source-available cross-platform document-oriented database program. Classified as a NoSQL database program, 2 | MongoDB uses JSON-like documents with optional schemas. 3 | 4 | https://www.serverlab.ca/tutorials/linux/database-servers/how-to-create-mongodb-replication-clusters/ 5 | 6 | ## Parameters 7 | -------------------------------------------------------------------------------- /examples/apps/opengadget3/README.md: -------------------------------------------------------------------------------- 1 | # Run MPI Jobs using the MPI-Operator 2 | 3 | This experiment aims to run MPI jobs on Kubernetes using the MPI-Operator of Kubeflow 4 | 5 | https://github.com/kubeflow/mpi-operator 6 | 7 | kubectl apply -f https://raw.githubusercontent.com/kubeflow/mpi-operator/master/deploy/v2beta1/mpi-operator.yaml 8 | 9 | ## Parameters -------------------------------------------------------------------------------- /images/cadvisor/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM gcr.io/cadvisor/cadvisor:v0.46.0 2 | 3 | # Needed to fix DNS issues 4 | #COPY /etc/resolv.conf /etc/resolv.conf.override 5 | #RUN echo "$( cat /etc/resolv.conf | sed 's/ndots:5/ndots:1/')" > /etc/resolv.conf 6 | 7 | # Add a newer version of nsenter that supports cgroup 8 | RUN apk add --no-cache util-linux inotify-tools 9 | -------------------------------------------------------------------------------- /.builds-linux.goreleaser.yml: -------------------------------------------------------------------------------- 1 | before: 2 | hooks: 3 | - go mod tidy 4 | 5 | dist: linux 6 | builds: 7 | - main: ./cmd/kubectl-frisbee 8 | binary: kubectl-frisbee 9 | env: 10 | - CGO_ENABLED=0 11 | goos: 12 | - linux 13 | goarch: 14 | - amd64 15 | - arm64 16 | - 386 17 | archives: 18 | - format: binary 19 | -------------------------------------------------------------------------------- /hack/remove_k8s_finalizers.sh: -------------------------------------------------------------------------------- 1 | set -em 2 | 3 | # For more explanation check https://www.crybit.com/kubernetes-objects-deleting-stuck-in-terminating-state/ 4 | 5 | names=("$@") 6 | 7 | echo "Expected format ./remove_k8s_finalizers.sh kind name0 name1 ..." 8 | 9 | echo kubectl patch ${names[@]} --type json --patch=\'[ { "op": "remove", "path": "/metadata/finalizers" } ]\' -------------------------------------------------------------------------------- /examples/apps/fedbed/values.yaml: -------------------------------------------------------------------------------- 1 | ## @section Fedbed Configuration parameters 2 | 3 | ## @param server.image Fedbed server's image version. 4 | server: 5 | image: fogemulator/testfedbed:latest # alt: icsforth/fedbed:latest 6 | 7 | 8 | ## @param client.image Fedbed client's image version. 9 | client: 10 | image: fogemulator/testfedbed:latest # alt: icsforth/fedbed:latest -------------------------------------------------------------------------------- /examples/patterns/ci/README.md: -------------------------------------------------------------------------------- 1 | 2 | ## Sequential Tests 3 | This examples demonstrates how to use frisbee as a CI. The experiment consists of multiple tests 4 | that run sequentially (on different pods) and stress the Parallax key/value store. 5 | 6 | ```shell 7 | kubectl frisbee submit test parallax- examples/ci/sequential-tests.yaml charts/databases/parallax/ charts/system/ 8 | ``` -------------------------------------------------------------------------------- /images/ci-environment/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM jrei/systemd-ubuntu:22.04 2 | 3 | SHELL ["/bin/bash", "-c"] 4 | 5 | RUN apt-get update 6 | 7 | # Install snap and make it support --classic deployments 8 | RUN apt-get install -y snapd sudo curl 9 | 10 | RUN ln -s /var/lib/snapd/snap /snap 11 | 12 | ENV PATH="${PATH}:/snap/bin" 13 | 14 | ENV LC_ALL=C.UTF-8 15 | ENV LANG=C.UTF-8 16 | -------------------------------------------------------------------------------- /examples/apps/flower/containers/README.md: -------------------------------------------------------------------------------- 1 | == Advanced Pytorch == 2 | ``` shell 3 | docker build -t icsforth/advanced_pytorch -f advanced_pytorch.Dockerfile . 4 | docker push icsforth/advanced_pytorch 5 | ``` 6 | 7 | == Advanced Tensorflow == 8 | ``` shell 9 | docker build -t icsforth/advanced_tensorflow -f advanced_tensorflow.Dockerfile . 10 | docker push icsforth/advanced_tensorflow 11 | ``` -------------------------------------------------------------------------------- /examples/apps/parallax/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | appVersion: "1.16.0" 4 | description: "Parallax is an embedded key value store for fast storage devices" 5 | 6 | name: parallax 7 | type: application 8 | 9 | maintainers: 10 | - name: Fotis Nikolaidis 11 | email: nikolaidis.fotis@gmail.com 12 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 13 | 14 | version: 0.0.0 -------------------------------------------------------------------------------- /examples/apps/tebis/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | appVersion: "1.16.0" 4 | description: "Tebis is a rack-scale key/value store optimized for replication over RDMA" 5 | 6 | name: tebis 7 | type: application 8 | 9 | maintainers: 10 | - name: Fotis Nikolaidis 11 | email: nikolaidis.fotis@gmail.com 12 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 13 | 14 | version: 0.0.0 -------------------------------------------------------------------------------- /images/prometheus/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM prom/prometheus 2 | 3 | USER root 4 | 5 | # Use envsubst to replace ${var} or $var according to the values of the current environment variables. 6 | RUN wget -O /bin/envsubst https://github.com/a8m/envsubst/releases/download/v1.2.0/envsubst-`uname -s`-`uname -m` 7 | 8 | RUN chmod +X /bin/envsubst && chmod 777 /bin/envsubst 9 | 10 | USER nobody 11 | WORKDIR /prometheus 12 | -------------------------------------------------------------------------------- /CONTRIBUTORS.md: -------------------------------------------------------------------------------- 1 | Contributors to Frisbee 2 | Maintainers 3 | 4 | The SingularityCE maintainers are responsible for stewardship of the project, and maintaining the repository and infrastructure. 5 | 6 | - Fotis Nikolaidis 7 | 8 | Contributors 9 | 10 | The following have contributed code and/or documentation to this repository. 11 | 12 | - Fotis Nikolaidis 13 | -------------------------------------------------------------------------------- /examples/apps/cockroachdb/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | appVersion: "1.16.0" 4 | description: "CockroachDB is a distributed database with standard SQL for cloud 5 | applications." 6 | 7 | name: cockroachdb 8 | type: application 9 | 10 | maintainers: 11 | - name: Fotis Nikolaidis 12 | email: nikolaidis.fotis@gmail.com 13 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 14 | 15 | version: 0.0.0 16 | -------------------------------------------------------------------------------- /charts/platform/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/scripts/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import socket 5 | import time 6 | from datetime import datetime as dt 7 | 8 | if __name__ == '__main__': 9 | print('Process started {}'.format(dt.now())) 10 | print('NODE : {}'.format(socket.gethostname())) 11 | print('PID : {}'.format(os.getpid())) 12 | print('Executing for 15 secs') 13 | time.sleep(15) 14 | print('Process finished {}\n'.format(dt.now())) 15 | -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.1.0 2 | message: "If you use this software, please cite it as below." 3 | authors: 4 | - family-names: "Nikolaidis" 5 | given-names: "Fotis" 6 | orcid: "https://orcid.org/0000-0002-9379-6233" 7 | title: "frisbee: a Kubernetes-native platform for exploring, testing, and benchmarking distributed applications" 8 | version: 1.0.0 9 | doi: 10.5281/zenodo.5566624 10 | date-released: 2021-11-08 11 | url: "https://github.com/CARV-ICS-FORTH/frisbee" 12 | -------------------------------------------------------------------------------- /charts/platform/Chart.lock: -------------------------------------------------------------------------------- 1 | dependencies: 2 | - name: openebs 3 | repository: https://openebs.github.io/charts 4 | version: 3.2.0 5 | - name: chaos-mesh 6 | repository: https://charts.chaos-mesh.org 7 | version: 2.1.2 8 | - name: kubernetes-dashboard 9 | repository: https://kubernetes.github.io/dashboard/ 10 | version: 5.7.0 11 | digest: sha256:e653a9bc4bc395642be6e4156fae941eaeda8a52b1061cbb520bd279859818d0 12 | generated: "2022-07-16T01:01:13.277059714+03:00" 13 | -------------------------------------------------------------------------------- /examples/apps/tikv/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /examples/apps/ycsb/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/system/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/fio/examples/1.ephemeral-volume.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: bind-fs 6 | spec: 7 | actions: 8 | - action: Service 9 | name: fio 10 | service: 11 | templateRef: frisbee.apps.fio.ephemeral 12 | inputs: 13 | - { direct: "1" } 14 | 15 | # Teardown 16 | - action: Delete 17 | name: teardown 18 | depends: { success: [ fio ] } 19 | delete: 20 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/flower/example.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: advanced-pytorch 6 | spec: 7 | actions: 8 | # Run the default script 9 | - action: Service 10 | name: script 11 | service: 12 | templateRef: frisbee.apps.flower.advanced-pytorch 13 | 14 | # Teardown 15 | - action: Delete 16 | name: teardown 17 | depends: { success: [ script ] } 18 | delete: 19 | jobs: [ ] 20 | 21 | -------------------------------------------------------------------------------- /examples/apps/iperf3/templates/server.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.apps.iperf3.server 6 | spec: 7 | service: 8 | decorators: 9 | telemetry: 10 | - frisbee.system.telemetry.resources 11 | 12 | containers: # Container 13 | - name: main 14 | image: "networkstatic/iperf3" 15 | ports: 16 | - name: tcp 17 | containerPort: 5201 18 | args: [ "-s", "-f", "m" ] 19 | -------------------------------------------------------------------------------- /examples/apps/fio/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/fio/examples/0.no-storage.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: default-fs 6 | spec: 7 | actions: 8 | - action: Service 9 | name: fio 10 | service: 11 | templateRef: frisbee.apps.fio.builtin 12 | inputs: 13 | - { direct: "0" } 14 | 15 | 16 | # Teardown 17 | - action: Delete 18 | name: teardown 19 | depends: { success: [ fio ] } 20 | delete: 21 | jobs: [ ] 22 | -------------------------------------------------------------------------------- /examples/apps/fio/examples/3.raw-device.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: raw-device 6 | spec: 7 | actions: 8 | - action: Service 9 | name: fio 10 | service: 11 | templateRef: frisbee.apps.fio.raw-device 12 | inputs: 13 | - { direct: "0" } 14 | 15 | 16 | # Teardown 17 | - action: Delete 18 | name: teardown 19 | depends: { success: [ fio ] } 20 | delete: 21 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/h5py/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/redis/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/iperf2/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/iperf3/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/mongodb/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/fio/examples/2.formatted-device.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: formatted-device 6 | spec: 7 | actions: 8 | - action: Service 9 | name: fio 10 | service: 11 | templateRef: frisbee.apps.fio.formatted-device 12 | inputs: 13 | - { direct: "0" } 14 | 15 | # Teardown 16 | - action: Delete 17 | name: teardown 18 | depends: { success: [ fio ] } 19 | delete: 20 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/opengadget3/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md -------------------------------------------------------------------------------- /examples/apps/tebis/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md 27 | 28 | # Tools 29 | build -------------------------------------------------------------------------------- /examples/apps/parallax/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md 27 | 28 | # Tools 29 | build -------------------------------------------------------------------------------- /hack/remove_k8s_ns_finalizer.sh: -------------------------------------------------------------------------------- 1 | set -eou pipefail 2 | namespace=$1 3 | if [ -z "$namespace" ] 4 | then 5 | echo "This script requires a namespace argument input. None found. Exiting." 6 | exit 1 7 | fi 8 | 9 | kubectl get namespace $namespace -o json | jq '.spec = {"finalizers":[]}' > rknf_tmp.json 10 | kubectl proxy & 11 | 12 | sleep 5 13 | curl -H "Content-Type: application/json" -X PUT --data-binary @rknf_tmp.json http://localhost:8001/api/v1/namespaces/$namespace/finalize 14 | pkill -9 -f "kubectl proxy" 15 | rm rknf_tmp.json 16 | -------------------------------------------------------------------------------- /charts/system/templates/chaos/pod-kill.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.system.chaos.pod.kill 6 | spec: 7 | inputs: 8 | parameters: 9 | target: localhost 10 | chaos: 11 | raw: | 12 | apiVersion: chaos-mesh.org/v1alpha1 13 | kind: PodChaos 14 | spec: 15 | action: pod-kill 16 | mode: one 17 | selector: 18 | pods: 19 | {{.Release.Namespace}}: 20 | - {{"{{.inputs.parameters.target}}"}} -------------------------------------------------------------------------------- /examples/apps/tebis/build/init.Dockerfile: -------------------------------------------------------------------------------- 1 | # Create the SDK layers 2 | FROM alpine/git as builder 3 | 4 | WORKDIR / 5 | 6 | # Fetch Tebis 7 | RUN git clone --branch master "https://tebis-docker-container:kEmvUT1ZaceUsad6usGF@carvgit.ics.forth.gr/storage/tebis.git" 8 | 9 | 10 | # Create the manager container 11 | FROM python:3.6-alpine as tebis-manager 12 | 13 | # Install Zookeeper dependency 14 | RUN pip3 install kazoo 15 | 16 | WORKDIR / 17 | COPY --from=builder /tebis/scripts/kreonR/ . 18 | 19 | 20 | ENTRYPOINT ["python"] 21 | CMD ["/tebis_zk_init.py"] 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | testbin/* 10 | 11 | # Test binary, build with `go test -c` 12 | *.test 13 | 14 | # Output of the go coverage tool, specifically when used with LiteIDE 15 | *.out 16 | 17 | # Kubernetes Generated files - skip generated files, except for vendored files 18 | 19 | !vendor/**/zz_generated.* 20 | 21 | # editor and IDE paraphernalia 22 | .idea 23 | *.swp 24 | *.swo 25 | *~ 26 | 27 | # Ignore any accidently generated main 28 | ./main 29 | ./kubectl-frisbee 30 | -------------------------------------------------------------------------------- /examples/apps/cockroachdb/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md 27 | 28 | # Ignore any figures used in the README.md 29 | examples/README.assets -------------------------------------------------------------------------------- /examples/apps/flower-custom/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | 25 | # Docs 26 | *.md 27 | 28 | # Ignore any figures used in the README.md 29 | examples/README.assets -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/templates/storage.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # In order to have shared data environment, we must first create a network volume. 3 | # This volume will then be mounted across slurm nodes. 4 | # This is an adaptation of https://medium.com/analytics-vidhya/slurm-cluster-with-docker-9f242deee601 5 | apiVersion: v1 6 | kind: PersistentVolumeClaim 7 | metadata: 8 | name: shared-storage 9 | spec: 10 | storageClassName: platform.storageclass.network 11 | volumeMode: Filesystem 12 | accessModes: 13 | - ReadWriteMany 14 | resources: 15 | requests: 16 | storage: 2Gi 17 | -------------------------------------------------------------------------------- /examples/apps/README.md: -------------------------------------------------------------------------------- 1 | # The Frisbee Library 2 | 3 | Popular applications, provided by Frisbee, ready to launch on Kubernetes 4 | using [Kubernetes Helm](https://github.com/helm/helm). 5 | 6 | ## TL;DR 7 | 8 | ```bash 9 | # Add Frisbee repo in Helm 10 | $ helm repo add frisbee https://carv-ics-forth.github.io/frisbee/charts 11 | 12 | # Install the Frisbee platform 13 | $ helm install my-frisbee charts/frisbee 14 | 15 | # Install the default system templates 16 | $ helm install my-system charts/system 17 | 18 | # Install the any of the available charts. 19 | $ helm install my-example charts/iperf-2 20 | ``` 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F914 Question" 3 | about: Usage question that isn't answered in docs or discussion 4 | 5 | --- 6 | 7 | ## Question 8 | 9 | Before asking a question, make sure you have: 10 | 11 | - Reviewed relevant Kubernetes information: Google your error messages and look at K8s docs. 12 | - Searched open and closed [GitHub issues](https://github.com/CARV-ICS-FORTH/frisbee/issues) 13 | - Read the documentation: 14 | - [Frisbee Readme](https://github.com/CARV-ICS-FORTH/frisbee/blob/main/README.md) 15 | - [Frisbee Doc](https://github.com/CARV-ICS-FORTH/frisbee/tree/main/docs) 16 | -------------------------------------------------------------------------------- /charts/platform/templates/configuration.yaml: -------------------------------------------------------------------------------- 1 | # Maintain a list of installation variables that need to be passed to the controller. 2 | # See utils.Configuration 3 | --- 4 | apiVersion: v1 5 | kind: ConfigMap 6 | metadata: 7 | name: system.controller.configuration 8 | labels: 9 | discover.frisbee.dev/name: system.controller.configuration 10 | data: 11 | DeveloperMode: {{not .Values.operator.enabled | quote}} 12 | 13 | Namespace: {{.Release.Namespace}} 14 | 15 | DomainName: {{.Values.global.domainName}} 16 | 17 | IngressClassName: {{.Values.global.ingressClass}} 18 | 19 | ControllerName: {{.Values.operator.name}} -------------------------------------------------------------------------------- /.github/workflows/repo-stats.yml: -------------------------------------------------------------------------------- 1 | name: GitHub Repo Statistics 2 | 3 | on: 4 | schedule: 5 | # Run this once per day, towards the end of the day for keeping the most 6 | # recent data point most meaningful (hours are interpreted in UTC). 7 | - cron: "0 23 * * *" 8 | workflow_dispatch: # Allow for running this manually. 9 | 10 | jobs: 11 | j1: 12 | name: github-repo-stats 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: run-ghrs 16 | # Use latest release. 17 | uses: jgehrcke/github-repo-stats@v1.4.0 18 | with: 19 | ghtoken: ${{ secrets.ghrs_github_api_token }} 20 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | What problem does this PR solve? 2 | 3 | Issue Number: close #xxx 4 | 5 | Problem Summary: 6 | What is changed and how it works? 7 | 8 | Proposal: xxx 9 | 10 | What's Changed: 11 | Related changes 12 | 13 | Need to update Frisbee Dashboard component, related issue: 14 | Need to cheery-pick to the release branch 15 | 16 | Checklist 17 | 18 | Tests 19 | 20 | Unit test 21 | E2E test 22 | Manual test (add detailed scripts or steps below) 23 | No code 24 | 25 | Side effects 26 | 27 | Breaking backward compatibility 28 | 29 | Release note 30 | 31 | Please add a release note. If you don't think this PR needs a release note then fill it with None. 32 | -------------------------------------------------------------------------------- /examples/apps/flower/templates/advanced_pytorch.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.apps.flower.advanced-pytorch 6 | spec: 7 | service: 8 | decorators: 9 | telemetry: [ frisbee.system.telemetry.resources ] 10 | 11 | containers: 12 | - name: main 13 | image: icsforth/advanced_pytorch 14 | command: 15 | - /bin/sh # Run shell 16 | - -c # Read from string 17 | - | # Multi-line str 18 | set -eum 19 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 20 | 21 | poetry run ./run.sh -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F680 Feature Request" 3 | about: I have a suggestion 4 | 5 | --- 6 | 7 | ## Feature Request 8 | 9 | **Is your feature request related to a problem? Please describe.** 10 | A clear and concise description of what the issue is. Ex. I'm always frustrated when [...] 11 | 12 | **Describe the solution you'd like** 13 | A clear and concise description of what you want to happen. 14 | 15 | **Describe alternatives you've considered** 16 | A clear and concise description of any alternative solutions or features you've considered. 17 | 18 | **Additional context** 19 | Add any other context or screenshots about the feature request here. 20 | -------------------------------------------------------------------------------- /examples/apps/flower/templates/advanced_tensorflow.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.apps.flower.advanced-tensorflow 6 | spec: 7 | service: 8 | decorators: 9 | telemetry: [ frisbee.system.telemetry.resources ] 10 | 11 | containers: 12 | - name: main 13 | image: icsforth/advanced_tensorflow 14 | command: 15 | - /bin/sh # Run shell 16 | - -c # Read from string 17 | - | # Multi-line str 18 | set -eum 19 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 20 | 21 | poetry run ./run.sh -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/README.md: -------------------------------------------------------------------------------- 1 | # Virtual Slurm Cluster 2 | 3 | The aim is to give an environment to test, introduce and practice the use and development over a Slurm Cluster (this is not an environment for production). 4 | 5 | 6 | This is an adaptation of https://medium.com/analytics-vidhya/slurm-cluster-with-docker-9f242deee601 7 | 8 | ``` 9 | kubectl frisbee submit test demo ./examples/slurm-jupyter.yml ./ charts/system/ 10 | ``` 11 | 12 | The ./examples/slurm-jupyter.yml is the scenario to run. 13 | The `.` install dependencies to the templates of this chart/package. 14 | The `../chart/system` install dependencies to the template of an external chart/package. 15 | 16 | 17 | ## Parameters -------------------------------------------------------------------------------- /examples/apps/cockroachdb/values.yaml: -------------------------------------------------------------------------------- 1 | ## @section Cockroach Configuration parameters 2 | 3 | ## @param server.image CockroachDB's image version. 4 | ## @param server.port CockroachDB's port to listen to inter-communications and client connections. 5 | ## @param server.webPort CockroachDB's port to Web Interface. 6 | ## @param server.cpu The number of CPUs that will be allocated to each server. 7 | ## @param server.memory The size of memory that will be allocated to each server. 8 | ## @param server.storage The size of available space that will be allocated to each server. 9 | 10 | server: 11 | image: cockroachdb/cockroach:v22.1.2 12 | port: 26257 13 | webPort: 8080 14 | cpu: 0.5 15 | memory: 3Gi 16 | storage: 15Gi -------------------------------------------------------------------------------- /examples/apps/opengadget3/examples/gadget.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: mpi 6 | spec: 7 | actions: 8 | - action: Cluster 9 | name: workers 10 | cluster: 11 | templateRef: frisbee.apps.mpi-worker 12 | instances: 4 # Must match 13 | 14 | - action: Service 15 | name: launcher 16 | depends: { running: [ workers ] } 17 | service: 18 | templateRef: frisbee.apps.mpi-launcher 19 | inputs: 20 | - {numOfWorkers: 4} # Must match 21 | 22 | # Teardown 23 | - action: Delete 24 | name: teardown 25 | depends: { success: [ launcher ] } 26 | delete: 27 | jobs: [ workers ] -------------------------------------------------------------------------------- /examples/apps/iperf2/templates/server.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.apps.iperf2.server 6 | spec: 7 | service: 8 | decorators: 9 | telemetry: 10 | - frisbee.system.telemetry.resources 11 | containers: 12 | - name: main 13 | image: "czero/iperf2" 14 | ports: 15 | - name: tcp 16 | containerPort: 5001 17 | command: 18 | - /bin/sh # Run shell 19 | - -c # Read from string 20 | - | # Multi-line str 21 | set -eum 22 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 23 | 24 | iperf -s -f m -i 5 -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: "\U0001F41B Bug Report" 3 | about: Something isn't working as expected 4 | 5 | --- 6 | 7 | ## Bug Report 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **To Reproduce** 13 | Steps to reproduce the behavior: 14 | 15 | 1. Attach the template specification. 16 | 2. Attach the scenario specification. 17 | 3. Attach the output log. 18 | 4. Highlight the error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **What version of Kubernetes are you using?** 27 | 28 | -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/0.server-client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: server-client 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create an iperf client 15 | - action: Service 16 | name: client 17 | depends: { running: [ server ] } 18 | service: 19 | templateRef: frisbee.apps.iperf2.client 20 | inputs: 21 | - { server: server, seconds: "300" } 22 | 23 | 24 | # Teardown 25 | - action: Delete 26 | name: teardown 27 | depends: { running: [ server ], success: [ client ] } 28 | delete: 29 | jobs: [ server ] 30 | -------------------------------------------------------------------------------- /examples/apps/flower/containers/advanced_tensorflow.Dockerfile: -------------------------------------------------------------------------------- 1 | # Build container for the advanced_pytorch example according to the following instructions: 2 | # https://github.com/adap/flower/tree/main/examples/advanced_tensorflow 3 | FROM tensorflow/tensorflow 4 | 5 | USER root 6 | 7 | RUN apt-get update && apt-get install -y git 8 | 9 | # Install dependencies 10 | RUN pip install poetry 11 | 12 | # Clone the example project 13 | RUN git clone --depth=1 https://github.com/adap/flower.git \ 14 | && mv flower/examples/advanced_tensorflow . \ 15 | && rm -rf flower 16 | 17 | WORKDIR ./advanced_tensorflow 18 | 19 | # Download Flower dependencies 20 | RUN poetry install 21 | 22 | # Download the CIFAR-10 dataset 23 | RUN python -c "import tensorflow as tf; tf.keras.datasets.cifar10.load_data()" -------------------------------------------------------------------------------- /examples/apps/fio/examples/4.shared-fs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: fs 6 | spec: 7 | storageClassName: platform.storageclass.network 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadWriteMany 11 | resources: 12 | requests: 13 | storage: 512Mi 14 | 15 | --- 16 | apiVersion: frisbee.dev/v1alpha1 17 | kind: Scenario 18 | metadata: 19 | name: shared-fs 20 | spec: 21 | actions: 22 | - action: Cluster 23 | name: fio 24 | cluster: 25 | templateRef: frisbee.apps.fio.shared-fs 26 | instances: 2 27 | inputs: 28 | - { direct: "0", claimName: fs } 29 | 30 | # Teardown 31 | - action: Delete 32 | name: teardown 33 | depends: { success: [ fio ] } 34 | delete: 35 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/h5py/scripts/multiprocessing/README.md: -------------------------------------------------------------------------------- 1 | Demonstrates how to use h5py with the multiprocessing module. 2 | This module implements a simple multiprocess program to generate 3 | Mandelbrot set images. It uses a process pool to do the computations, 4 | and a single process to save the results to file. 5 | Importantly, only one process actually reads/writes the HDF5 file. 6 | Remember that when a process is fork()ed, the child inherits the HDF5 7 | state from its parent, which can be dangerous if you already have a file 8 | open. Trying to interact with the same file on disk from multiple 9 | processes results in undefined behavior. 10 | If matplotlib is available, the program will read from the HDF5 file and 11 | display an image of the fractal in a window. To re-run the calculation, 12 | delete the file "mandelbrot.hdf5". -------------------------------------------------------------------------------- /examples/patterns/databases/elasticity/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | 8 | export NAMESPACE=elasticity 9 | export SCENARIO=$(dirname -- "$0")/manifest.yml 10 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 11 | export DEPENDENCIES=(./charts/system/ ./examples/apps/cockroachdb ./examples/apps/ycsb) 12 | 13 | # Prepare the Reporting folder 14 | mkdir -p "${REPORTS}" 15 | 16 | # Copy the manifest 17 | cp "${SCENARIO}" "${REPORTS}" 18 | 19 | # Submit the scenario and follow logs 20 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" 21 | 22 | # Give a headstart 23 | sleep 10 24 | 25 | # Report the scenario 26 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait -------------------------------------------------------------------------------- /examples/patterns/databases/ycsb-sequence/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=ycsb-sequence 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/cockroachdb ./examples/apps/ycsb) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Report the scenario 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait -------------------------------------------------------------------------------- /examples/patterns/databases/network-partition/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=network-partition 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/cockroachdb ./examples/apps/ycsb) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Report the scenario 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait -------------------------------------------------------------------------------- /examples/patterns/databases/sstable-bitrot/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=sstable-bitrot 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/cockroachdb ./examples/apps/ycsb) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow the failing client's logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Download test report 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait -------------------------------------------------------------------------------- /charts/system/templates/chaos/network-loss.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.system.chaos.network.loss 6 | spec: 7 | inputs: 8 | parameters: 9 | source: localhost 10 | duration: "2m" 11 | loss: "25" 12 | correlation: "25" 13 | chaos: 14 | raw: | 15 | apiVersion: chaos-mesh.org/v1alpha1 16 | kind: NetworkChaos 17 | spec: 18 | action: loss 19 | mode: all 20 | duration: {{"{{.inputs.parameters.duration}}" | quote}} 21 | selector: 22 | pods: 23 | {{.Release.Namespace}}: 24 | - {{"{{.inputs.parameters.source}}" | quote}} 25 | loss: 26 | loss: {{"{{.inputs.parameters.loss}}" | quote}} 27 | correlation: {{"{{.inputs.parameters.correlation}}" | quote}} -------------------------------------------------------------------------------- /examples/patterns/federated-learning/ml-backend/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=ml-backend 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/fedbed/) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow server's logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" --logs server |& tee "${REPORTS}"/logs & 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Report the scenario 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait -------------------------------------------------------------------------------- /examples/patterns/federated-learning/crash-on-epoch/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=crash-on-epoch 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/fedbed/) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow server's logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" --logs server |& tee "${REPORTS}"/logs & 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Report the scenario 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait 26 | -------------------------------------------------------------------------------- /examples/patterns/federated-learning/node-placement/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=node-placement 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/fedbed/) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow server logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" --logs server |& tee "${REPORTS}"/logs & 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Report the scenario 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait 26 | -------------------------------------------------------------------------------- /examples/tutorial/1.hello-world.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template # new type of k8s spec 4 | metadata: 5 | name: whalesay # name of the template spec 6 | spec: 7 | service: 8 | containers: # application container 9 | - name: main 10 | image: docker/whalesay 11 | command: [ cowsay ] 12 | args: [ "hello-world" ] 13 | 14 | --- 15 | apiVersion: frisbee.dev/v1alpha1 16 | kind: Scenario 17 | metadata: 18 | name: hello-world 19 | spec: 20 | actions: 21 | # create a service using the whalesay template 22 | - action: Service 23 | name: whalesay 24 | service: 25 | templateRef: whalesay 26 | 27 | 28 | # Teardown 29 | - action: Delete 30 | name: teardown 31 | depends: { success: [ whalesay ] } 32 | delete: 33 | jobs: [ ] 34 | -------------------------------------------------------------------------------- /hack/api-docs/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "hideMemberFields": [ 3 | "TypeMeta" 4 | ], 5 | "hideTypePatterns": [ 6 | "ParseError$", 7 | "List$" 8 | ], 9 | "externalPackages": [ 10 | { 11 | "typeMatchPrefix": "^k8s\\.io/apimachinery/pkg/apis/meta/v1\\.Duration$", 12 | "docsURLTemplate": "https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1#Duration" 13 | }, 14 | { 15 | "typeMatchPrefix": "^k8s\\.io/(api|apimachinery/pkg/apis)/", 16 | "docsURLTemplate": "https://v1-20.docs.kubernetes.io/docs/reference/generated/kubernetes-api/v1.20/#{{lower .TypeIdentifier}}-{{arrIndex .PackageSegments -1}}-{{arrIndex .PackageSegments -2}}" 17 | } 18 | ], 19 | "typeDisplayNamePrefixOverrides": { 20 | "k8s.io/api/": "Kubernetes ", 21 | "k8s.io/apimachinery/pkg/apis/": "Kubernetes " 22 | }, 23 | "markdownDisabled": false 24 | } -------------------------------------------------------------------------------- /examples/patterns/federated-learning/resource-distribution/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=resource-distribution 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/fedbed/) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow server logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" --logs server |& tee "${REPORTS}"/logs & 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Report the scenario 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait 26 | -------------------------------------------------------------------------------- /examples/patterns/federated-learning/parallel-workflows/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | export NAMESPACE=parallel-workflows 8 | export SCENARIO=$(dirname -- "$0")/manifest.yml 9 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 10 | export DEPENDENCIES=(./charts/system/ ./examples/apps/fedbed/) 11 | 12 | # Prepare the Reporting folder 13 | mkdir -p "${REPORTS}" 14 | 15 | # Copy the manifest 16 | cp "${SCENARIO}" "${REPORTS}" 17 | 18 | # Submit the scenario and follow server logs 19 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" --logs wfa-server,wfb-server |& tee "${REPORTS}"/logs & 20 | 21 | # Give a headstart 22 | sleep 10 23 | 24 | # Download test report 25 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait 26 | -------------------------------------------------------------------------------- /charts/system/templates/chaos/network-duplicate.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.system.chaos.network.duplicate 6 | spec: 7 | inputs: 8 | parameters: 9 | source: localhost 10 | duration: "2m" 11 | duplicate: "40" 12 | correlation: "25" 13 | chaos: 14 | raw: | 15 | apiVersion: chaos-mesh.org/v1alpha1 16 | kind: NetworkChaos 17 | spec: 18 | action: duplicate 19 | mode: all 20 | duration: {{"{{.inputs.parameters.duration}}" | quote}} 21 | selector: 22 | pods: 23 | {{.Release.Namespace}}: 24 | - {{"{{.inputs.parameters.source}}" | quote}} 25 | duplicate: 26 | duplicate: {{"{{.inputs.parameters.duplicate}}" | quote}} 27 | correlation: {{"{{.inputs.parameters.correlation}}" |quote}} 28 | 29 | -------------------------------------------------------------------------------- /charts/platform/templates/webhook/admission/certificate.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: cert-manager.io/v1 3 | kind: Certificate 4 | metadata: 5 | name: webhook-tls 6 | namespace: {{.Release.Namespace}} 7 | spec: 8 | secretName: webhook-tls 9 | duration: 87600h 10 | commonName: webhook-service.{{.Release.Namespace}}.svc 11 | dnsNames: 12 | - webhook-service.{{.Release.Namespace}}.svc 13 | privateKey: 14 | algorithm: RSA 15 | size: 2048 16 | issuerRef: 17 | name: my-issuer 18 | subject: 19 | organizations: [ "FORTH" ] 20 | countries: [ "GR" ] 21 | provinces: [ "Crete" ] 22 | localities: [ "Heraklion" ] 23 | organizationalUnits: [ "CARV" ] 24 | postalCodes: [ "71300" ] 25 | streetAddresses: [ "N. Plastira 100" ] 26 | 27 | --- 28 | apiVersion: cert-manager.io/v1 29 | kind: Issuer 30 | metadata: 31 | name: my-issuer 32 | spec: 33 | selfSigned: { } 34 | -------------------------------------------------------------------------------- /examples/patterns/databases/normal-load/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -eu 4 | set -o pipefail 5 | trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT 6 | 7 | 8 | export NAMESPACE=normal-load 9 | export SCENARIO=$(dirname -- "$0")/manifest.yml 10 | export REPORTS=${HOME}/frisbee-reports/${NAMESPACE}/ 11 | export DEPENDENCIES=(./charts/system/ ./examples/apps/cockroachdb ./examples/apps/ycsb) 12 | export DASHBOARDS=(summary ingleton ycsb) 13 | 14 | # Prepare the Reporting folder 15 | mkdir -p "${REPORTS}" 16 | 17 | # Copy the manifest 18 | cp "${SCENARIO}" "${REPORTS}" 19 | 20 | # Submit the scenario and follow logs 21 | kubectl-frisbee submit test "${NAMESPACE}" "${SCENARIO}" "${DEPENDENCIES[@]}" 22 | 23 | # Give a headstart 24 | sleep 10 25 | 26 | # Report the scenario 27 | kubectl-frisbee report test "${NAMESPACE}" "${REPORTS}" --pdf --data --aggregated-pdf --wait --dashboard "${DASHBOARDS}" -------------------------------------------------------------------------------- /pkg/home/lazypath_windows.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | /* 4 | Copyright 2022-2023 ICS-FORTH. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package home 20 | 21 | import "os" 22 | 23 | func dataHome() string { return configHome() } 24 | 25 | func configHome() string { return os.Getenv("APPDATA") } 26 | 27 | func cacheHome() string { return os.Getenv("TEMP") } 28 | -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/5.assertions.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: assertions 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create an iperf client 15 | - action: Service 16 | name: client 17 | depends: { running: [ server ] } 18 | assert: 19 | state: '{{.NumFailedJobs}} >= 1' 20 | metrics: 'max() of query(wpFnYRwGk/2/bitrate, 5m, now) is below(1000)' 21 | service: 22 | templateRef: frisbee.apps.iperf2.client 23 | inputs: 24 | - { server: server, seconds: "800" } 25 | 26 | - action: Delete 27 | name: teardown 28 | depends: { running: [ server ], success: [ client ] } 29 | delete: 30 | jobs: [ server ] -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands" 21 | "github.com/kubeshop/testkube/pkg/ui" 22 | ) 23 | 24 | func main() { 25 | if err := commands.NewRootCmd().Execute(); err != nil { 26 | ui.Fail(err) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /examples/apps/iperf2/templates/client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.apps.iperf2.client 6 | spec: 7 | inputs: 8 | parameters: 9 | server: localhost 10 | seconds: "60" 11 | service: 12 | decorators: 13 | telemetry: 14 | - frisbee.system.telemetry.resources 15 | - frisbee.apps.iperf2.client.telemetry 16 | 17 | containers: 18 | - name: main 19 | image: "czero/iperf2" 20 | command: 21 | - /bin/sh # Run shell 22 | - -c # Read from string 23 | - | # Multi-line str 24 | set -eum 25 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 26 | 27 | server={{"{{.inputs.parameters.server}}"}} 28 | 29 | iperf -c ${server} -t {{"{{.inputs.parameters.seconds}}"}} -f m -i 5 > /dev/shm/pipe 30 | -------------------------------------------------------------------------------- /examples/apps/iperf3/examples/0.server-client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: validate-network 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf3.server 13 | 14 | # Create an iperf client 15 | - action: Service 16 | name: client 17 | depends: { running: [ server ] } 18 | assert: 19 | state: '{{.IsSuccessful "client"}} == true' 20 | metrics: 'avg() of query(wpFnYRwGk/2/bitrate, 5m, now) is below(1000)' 21 | service: 22 | templateRef: frisbee.apps.iperf3.client 23 | inputs: 24 | - { server: server, seconds: "600" } 25 | 26 | - action: Delete 27 | name: teardown 28 | depends: { running: [ server ], success: [ client ] } 29 | delete: 30 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/1.scheduled-clients.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: scheduled-clients 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create a cluster of iperf clients 15 | - action: Cluster 16 | name: clients 17 | depends: { running: [ server ] } 18 | cluster: 19 | templateRef: frisbee.apps.iperf2.client 20 | instances: 10 21 | inputs: 22 | - { server: server, seconds: "120" } 23 | - { server: server, seconds: "60" } 24 | schedule: 25 | cron: "@every 1m" 26 | 27 | # Teardown 28 | - action: Delete 29 | name: teardown 30 | depends: { running: [ server ], success: [ clients ] } 31 | delete: 32 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/6.deletions.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: failure-toleration 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create an iperf client 15 | - action: Service 16 | name: client 17 | depends: { running: [ server ] } 18 | service: 19 | templateRef: frisbee.apps.iperf2.client 20 | inputs: 21 | - { server: server, seconds: "300" } 22 | 23 | # Delete the iperf client 24 | - action: Delete 25 | name: delete-client 26 | depends: { after: "2m" } 27 | delete: 28 | jobs: [ client ] 29 | 30 | 31 | - action: Delete 32 | name: teardown 33 | depends: { running: [ server ], success: [ delete-client ] } 34 | delete: 35 | jobs: [ server ] -------------------------------------------------------------------------------- /charts/system/templates/chaos/network-delay.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.system.chaos.network.delay 6 | spec: 7 | inputs: 8 | parameters: 9 | source: localhost 10 | duration: "2m" 11 | latency: "90ms" 12 | correlation: "25" 13 | jitter: "90ms" 14 | chaos: 15 | raw: | 16 | apiVersion: chaos-mesh.org/v1alpha1 17 | kind: NetworkChaos 18 | spec: 19 | action: delay 20 | mode: all 21 | duration: {{"{{.inputs.parameters.duration}}" | quote}} 22 | selector: 23 | pods: 24 | {{.Release.Namespace}}: 25 | - {{"{{.inputs.parameters.source}}" | quote}} 26 | delay: 27 | latency: {{"{{.inputs.parameters.latency}}" | quote}} 28 | correlation: {{"{{.inputs.parameters.correlation}}" | quote}} 29 | jitter: {{"{{.inputs.parameters.jitter}}" | quote}} 30 | 31 | -------------------------------------------------------------------------------- /controllers/common/watchers/interface.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package watchers 18 | 19 | import ( 20 | "sigs.k8s.io/controller-runtime/pkg/event" 21 | ) 22 | 23 | type ( 24 | CreateFunc func(e event.CreateEvent) bool 25 | UpdateFunc func(e event.UpdateEvent) bool 26 | DeleteFunc func(e event.DeleteEvent) bool 27 | GenericFunc func(e event.GenericEvent) bool 28 | ) 29 | -------------------------------------------------------------------------------- /examples/apps/h5py/scripts/multiprocessing/image-visualizer.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import h5py 4 | 5 | 6 | def visualize_file(): 7 | """ Open the HDF5 file and display the result """ 8 | try: 9 | import matplotlib.pyplot as plt 10 | except ImportError: 11 | print("Whoops! Matplotlib is required to view the fractal.") 12 | raise 13 | 14 | f = h5py.File('/testdata/mandelbrot.hdf5', 'r') 15 | dset = f['mandelbrot'] 16 | a = dset[...] 17 | plt.imshow(a.transpose()) 18 | 19 | print("Saving fractal at /testdata/mygraph.png.") 20 | plt.savefig("/testdata/mygraph.png") 21 | 22 | print("Displaying fractal. Close window to exit program.") 23 | try: 24 | plt.show() 25 | finally: 26 | f.close() 27 | 28 | 29 | if __name__ == '__main__': 30 | if not h5py.is_hdf5('/testdata/mandelbrot.hdf5'): 31 | print('Not an HDF5 file') 32 | sys.exit(-1) 33 | else: 34 | visualize_file() 35 | -------------------------------------------------------------------------------- /examples/apps/iperf3/templates/client.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.apps.iperf3.client 6 | spec: 7 | inputs: 8 | parameters: 9 | server: localhost 10 | seconds: "60" 11 | service: 12 | decorators: 13 | telemetry: 14 | - frisbee.system.telemetry.resources 15 | - frisbee.apps.iperf3.client.telemetry 16 | 17 | containers: 18 | - name: main 19 | image: "networkstatic/iperf3" 20 | ports: 21 | - name: tcp 22 | containerPort: 5201 23 | command: 24 | - /bin/sh # Run shell 25 | - -c # Read from string 26 | - | # Multi-line str 27 | set -eum 28 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 29 | 30 | server={{"{{.inputs.parameters.server}}"}} 31 | 32 | iperf3 -c ${server} -t {{"{{.inputs.parameters.seconds}}"}} -f m > /dev/shm/pipe 33 | -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/3.create-until.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: create-until 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create a cluster of iperf clients 15 | - action: Cluster 16 | name: clients 17 | depends: { running: [ server ] } 18 | cluster: 19 | templateRef: frisbee.apps.iperf2.client 20 | instances: 100 21 | inputs: 22 | - { server: server, seconds: "160" } 23 | - { server: server, seconds: "60" } 24 | schedule: 25 | cron: "@every 1m" 26 | suspendWhen: 27 | metrics: 'avg() of query(wpFnYRwGk/2/bitrate, 5m, now) is below(500)' 28 | 29 | - action: Delete 30 | name: teardown 31 | depends: { running: [ server ], success: [ clients ] } 32 | delete: 33 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/fio/scripts/fio.sh: -------------------------------------------------------------------------------- 1 | cat > fio.conf <> /dev/shm/pipe 21 | 22 | echo 23 | echo 24 | echo 25 | done 26 | done 27 | done 28 | 29 | for rw in read write; do 30 | for numjobs in 1; do 31 | for iodepth in 1 4 32 128 256; do 32 | cmd="fio --rw=$$rw --bs=1M --numjobs=$$numjobs --iodepth=$$iodepth fio.conf" 33 | echo $$cmd 34 | $$cmd >> /dev/shm/pipe 35 | 36 | echo 37 | echo 38 | echo 39 | done 40 | done 41 | done 42 | -------------------------------------------------------------------------------- /pkg/structure/map.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package structure 18 | 19 | import ( 20 | "reflect" 21 | "sort" 22 | ) 23 | 24 | func SortedMapKeys(m interface{}) []string { 25 | keyVals := reflect.ValueOf(m).MapKeys() 26 | 27 | keys := make([]string, 0, len(keyVals)) 28 | 29 | for _, key := range keyVals { 30 | keys = append(keys, key.String()) 31 | } 32 | 33 | sort.Strings(keys) 34 | 35 | return keys 36 | } 37 | -------------------------------------------------------------------------------- /examples/apps/h5py/examples/0.sources.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Create an HDF5 file in memory and retrieve the raw bytes 3 | # This could be used, for instance, in a server producing small HDF5 4 | # files on demand. 5 | apiVersion: frisbee.dev/v1alpha1 6 | kind: Scenario 7 | metadata: 8 | name: sources 9 | spec: 10 | actions: 11 | - action: Service 12 | name: bytesio-embedded 13 | service: 14 | templateRef: h5py.bytesio.embedded 15 | 16 | - action: Service 17 | name: bytesio-from-script 18 | service: 19 | templateRef: h5py.bytesio.from-script 20 | 21 | 22 | - action: Service 23 | name: bytesio-from-web 24 | service: 25 | templateRef: h5py.bytesio.from-web 26 | inputs: 27 | - { source: "https://raw.githubusercontent.com/h5py/h5py/master/examples/bytesio.py" } 28 | 29 | 30 | - action: Delete 31 | name: teardown 32 | depends: { success: [ bytesio-embedded, bytesio-from-script, bytesio-from-web ] } 33 | delete: 34 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/flower/containers/advanced_pytorch.Dockerfile: -------------------------------------------------------------------------------- 1 | # Build container for the advanced_pytorch example according to the following instructions: 2 | # https://github.com/adap/flower/tree/main/examples/advanced_pytorch 3 | FROM bitnami/pytorch 4 | 5 | USER root 6 | 7 | RUN apt-get update && apt-get install -y git 8 | 9 | # Install dependencies 10 | RUN pip install poetry 11 | 12 | # Clone the example project 13 | RUN git clone --depth=1 https://github.com/adap/flower.git \ 14 | && mv flower/examples/advanced_pytorch . \ 15 | && rm -rf flower 16 | 17 | WORKDIR ./advanced_pytorch 18 | 19 | # Download Flower dependencies 20 | RUN poetry install 21 | 22 | # Download the EfficientNetB0 model 23 | RUN python -c "import torch; torch.hub.load( \ 24 | 'NVIDIA/DeepLearningExamples:torchhub', \ 25 | 'nvidia_efficientnet_b0', pretrained=True)" 26 | 27 | # Download the CIFAR-10 dataset 28 | RUN python -c "from torchvision.datasets import CIFAR10; CIFAR10('./dataset', download=True)" 29 | 30 | -------------------------------------------------------------------------------- /pkg/distributions/number.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package distributions 18 | 19 | // Number is a common generator. 20 | type Number struct { 21 | LastValue float64 22 | } 23 | 24 | // SetLastValue sets the last value generated. 25 | func (n *Number) SetLastValue(value float64) { 26 | n.LastValue = value 27 | } 28 | 29 | // Last implements the Generator Last interface. 30 | func (n *Number) Last() float64 { 31 | return n.LastValue 32 | } 33 | -------------------------------------------------------------------------------- /pkg/distributions/constant.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package distributions 18 | 19 | // Constant represents a Constant distribution 20 | type Constant struct { 21 | Number 22 | } 23 | 24 | // NewConstant creates a new Constant distribution. 25 | func NewConstant() *Constant { 26 | return &Constant{} 27 | } 28 | 29 | // Next computes the value of the probability density function at x. 30 | func (u *Constant) Next() float64 { 31 | return 1 32 | } 33 | -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/8.time-driven-partition.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: time-driven-delay 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create an iperf client 15 | - action: Service 16 | name: client 17 | depends: { running: [ server ] } 18 | service: 19 | templateRef: frisbee.apps.iperf2.client 20 | inputs: 21 | - { server: server, seconds: "800" } 22 | 23 | # After a while, inject a network failure 24 | - action: Chaos 25 | name: partition0 26 | depends: { running: [ server ], after: "3m" } 27 | chaos: 28 | templateRef: frisbee.system.chaos.network.delay 29 | inputs: 30 | - { source: server, duration: "2m" } 31 | 32 | - action: Delete 33 | name: teardown 34 | depends: { running: [ server ], success: [ partition0, client ] } 35 | delete: 36 | jobs: [ server ] -------------------------------------------------------------------------------- /pkg/home/lazypath_darwin.go: -------------------------------------------------------------------------------- 1 | //go:build darwin 2 | 3 | /* 4 | Copyright 2022-2023 ICS-FORTH. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package home 20 | 21 | import ( 22 | "path/filepath" 23 | 24 | "k8s.io/client-go/util/homedir" 25 | ) 26 | 27 | func dataHome() string { 28 | return filepath.Join(homedir.HomeDir(), "Library") 29 | } 30 | 31 | func configHome() string { 32 | return filepath.Join(homedir.HomeDir(), "Library", "Preferences") 33 | } 34 | 35 | func cacheHome() string { 36 | return filepath.Join(homedir.HomeDir(), "Library", "Caches") 37 | } 38 | -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/11.time-driven-delay.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: time-driven-delay 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create an iperf client 15 | - action: Service 16 | name: client 17 | depends: { running: [ server ] } 18 | service: 19 | templateRef: frisbee.apps.iperf2.client 20 | inputs: 21 | - { server: server, seconds: "800" } 22 | 23 | # After a while, inject a network failure 24 | - action: Chaos 25 | name: partition0 26 | depends: { running: [ server ], after: "3m" } 27 | chaos: 28 | templateRef: frisbee.system.chaos.network.delay 29 | inputs: 30 | - { source: server, duration: "2m" } 31 | 32 | # Teardown 33 | - action: Delete 34 | name: teardown 35 | depends: { running: [ server ], success: [ partition0, client ] } 36 | delete: 37 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/patterns/federated-learning/ml-backend/manifest.yml: -------------------------------------------------------------------------------- 1 | # This experiment is designed for the evaluation of various ML frameworks on the client. 2 | # For this purpose, we use a single client, and we change its backend. 3 | --- 4 | apiVersion: frisbee.dev/v1alpha1 5 | kind: Scenario 6 | metadata: 7 | name: backend 8 | spec: 9 | actions: 10 | # Step 1: Create FedBed server 11 | - action: Service 12 | name: server 13 | service: 14 | templateRef: frisbee.apps.fedbed.server 15 | inputs: 16 | - { dataset: "MNIST", backend: "pytorch", dataset_eval: "false" } # Change values here 17 | 18 | # Step 2: Create FedBed clients 19 | - action: Cluster 20 | name: clients 21 | depends: { running: [ server ] } 22 | cluster: 23 | templateRef: frisbee.apps.fedbed.client 24 | inputs: 25 | - { fl_server: server, dataset: "MNIST", backend: "pytorch" } # Change values here 26 | 27 | # Teardown 28 | - action: Delete 29 | name: teardown 30 | depends: { success: [ clients ] } 31 | delete: 32 | jobs: [ server ] 33 | -------------------------------------------------------------------------------- /charts/platform/templates/deployment/clusterrolebinding.yaml: -------------------------------------------------------------------------------- 1 | #--- 2 | #apiVersion: v1 3 | #kind: ServiceAccount 4 | #metadata: 5 | # name: {{.Values.operator.name}}-account 6 | 7 | 8 | --- 9 | # Glue between the rbac role and the Frisbee deployment's Account. 10 | # If the operator runs internal to the cluster, use the Frisbee account. 11 | # If the operator runs externally to the cluster, use the default account 12 | # This is because accounting requires mounting a token to the pod, which is not feasible 13 | # for externally running controllers. 14 | apiVersion: rbac.authorization.k8s.io/v1 15 | kind: ClusterRoleBinding 16 | metadata: 17 | name: frisbee 18 | namespace: {{.Release.Namespace}} 19 | roleRef: 20 | apiGroup: rbac.authorization.k8s.io 21 | kind: ClusterRole 22 | name: frisbee # This is fixed because it is autogenerated in the Makefile 23 | subjects: 24 | - kind: ServiceAccount 25 | name: default 26 | namespace: {{.Release.Namespace}} 27 | # {{if .Values.operator.enabled}} 28 | # name: {{.Values.operator.name}}-account 29 | # {{ else }} 30 | # name: default 31 | # {{ end }} -------------------------------------------------------------------------------- /examples/tutorial/2.parameters.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: whalesay 6 | spec: 7 | # invoke the whalesay template with 8 | # "hello world" as the default argument 9 | # to the message parameter 10 | inputs: 11 | parameters: 12 | message: "hello-world" 13 | service: 14 | containers: 15 | - name: main 16 | image: docker/whalesay 17 | command: [ cowsay ] 18 | args: [ "{{.inputs.parameters.message}}" ] 19 | 20 | --- 21 | apiVersion: frisbee.dev/v1alpha1 22 | kind: Scenario 23 | metadata: 24 | name: parameters 25 | spec: 26 | actions: 27 | - action: Service 28 | name: default-parameters 29 | service: 30 | templateRef: whalesay 31 | 32 | - action: Service 33 | name: custom-parameters 34 | service: 35 | templateRef: whalesay 36 | inputs: 37 | - { message: "Thanks for all the fish!" } 38 | 39 | 40 | # Teardown 41 | - action: Delete 42 | name: teardown 43 | depends: { success: [ default-parameters, custom-parameters ] } 44 | delete: 45 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/examples/normal-execution.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: virtual-slurm 6 | spec: 7 | testData: 8 | volume: { claimName: shared-storage } 9 | globalNamespace: true 10 | 11 | actions: 12 | - action: Service 13 | name: slurmmaster # Fixed reference in the slurm-node's configuration. 14 | service: 15 | templateRef: slurm-master 16 | inputs: 17 | - nodes: 3 18 | 19 | - action: Cluster 20 | name: slurmnode 21 | depends: { running: [ slurmmaster ] } 22 | cluster: 23 | templateRef: slurm-node # Fixed prefix in the slurm.conf 24 | instances: 3 25 | inputs: 26 | - nodes: 3 27 | 28 | - action: Service 29 | name: slurm-jupyter 30 | depends: { running: [ slurmmaster, slurmnode ] } 31 | service: 32 | templateRef: slurm-jupyter 33 | inputs: 34 | - nodes: 3 35 | 36 | # Teardown 37 | - action: Delete 38 | name: teardown 39 | depends: { success: [ slurm-jupyter, slurmmaster, slurmnode ] } 40 | delete: 41 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/h5py/examples/1.pipeline.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # In order to have shared logs, we must first create a network volume. 3 | # This volume will then be mounted across the various containers. 4 | apiVersion: v1 5 | kind: PersistentVolumeClaim 6 | metadata: 7 | name: shared-storage 8 | spec: 9 | storageClassName: platform.storageclass.network 10 | volumeMode: Filesystem 11 | accessModes: 12 | - ReadWriteMany 13 | resources: 14 | requests: 15 | storage: 500Mi 16 | 17 | --- 18 | apiVersion: frisbee.dev/v1alpha1 19 | kind: Scenario 20 | metadata: 21 | name: pipeline 22 | spec: 23 | testData: 24 | volume: { claimName: shared-storage } 25 | globalNamespace: true 26 | 27 | actions: 28 | - action: Service 29 | name: generator 30 | service: 31 | templateRef: h5py.pipeline.image-generator 32 | 33 | - action: Service 34 | name: visualizer 35 | # depends: { success: [generator]} 36 | service: 37 | templateRef: h5py.pipeline.image-visualizer 38 | 39 | 40 | - action: Delete 41 | name: teardown 42 | depends: { success: [ generator, visualizer ] } 43 | delete: 44 | jobs: [ ] -------------------------------------------------------------------------------- /examples/apps/fio/templates/0.default.yml: -------------------------------------------------------------------------------- 1 | # Add monitoring # https://github.com/fritchie/fio_benchmark_exporter 2 | --- 3 | apiVersion: frisbee.dev/v1alpha1 4 | kind: Template 5 | metadata: 6 | name: frisbee.apps.fio.builtin 7 | spec: 8 | inputs: 9 | parameters: 10 | size: "10M" 11 | direct: "0" 12 | ioengine: libaio 13 | service: 14 | decorators: # decorators 15 | telemetry: 16 | - frisbee.system.telemetry.resources 17 | 18 | containers: # Container 19 | - name: main 20 | image: xridge/fio 21 | command: 22 | - /bin/sh # Run shell 23 | - -c # Read from string 24 | - | # Multi-line str 25 | set -eum 26 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 27 | 28 | mkdir /scratch 29 | 30 | DEVICE=/scratch 31 | SIZE={{"{{.inputs.parameters.size}}"}} 32 | DIRECT={{"{{.inputs.parameters.direct}}"}} 33 | IOENGINE={{"{{.inputs.parameters.ioengine}}"}} 34 | 35 | {{ range .Files.Lines "scripts/fio.sh" }} 36 | {{ . }} 37 | {{ end }} -------------------------------------------------------------------------------- /examples/apps/debugger/tools/docker.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: system.tools.docker 6 | spec: 7 | service: 8 | decorators: 9 | labels: 10 | scenario.frisbee.dev/component: SYS 11 | 12 | volumes: 13 | - name: docker-sock 14 | hostPath: 15 | path: /var/run 16 | - name: docker-graph-storage 17 | emptyDir: { } 18 | containers: # Container(s) 19 | - name: main 20 | image: 192.168.1.213:5000/docker:latest 21 | securityContext: 22 | privileged: true 23 | volumeMounts: 24 | - name: docker-sock 25 | mountPath: /var/run 26 | - name: docker-graph-storage 27 | mountPath: /var/lib/docker 28 | env: 29 | - name: DOCKER_HOST 30 | value: tcp://localhost:2375 31 | command: 32 | - /bin/sh # Run shell 33 | - -c # Read from string 34 | - | # Multi-line str 35 | set -eum 36 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 37 | 38 | tail -f /dev/null -------------------------------------------------------------------------------- /.github/workflows/generate-api-docs.yaml: -------------------------------------------------------------------------------- 1 | name: Generate API Docs 2 | 3 | on: 4 | workflow_dispatch: 5 | pull_request_target: 6 | paths: 7 | - 'api/**/*.go' 8 | 9 | jobs: 10 | check-docs: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v3 15 | with: 16 | ref: ${{github.event.pull_request.head.ref}} 17 | repository: ${{github.event.pull_request.head.repo.full_name}} 18 | 19 | - name: Setup Go 20 | uses: actions/setup-go@v3 21 | with: 22 | go-version: '^1.18.3' 23 | 24 | - name: Execute api-docs generator 25 | run: make api-docs # will write to .docs/api.html 26 | 27 | - name: Configure Git 28 | run: | 29 | git config user.name "$GITHUB_ACTOR" 30 | git config user.email "$GITHUB_ACTOR@users.noreply.github.com" 31 | 32 | - name: Push changes 33 | run: | 34 | # Push all the changes 35 | cd docs 36 | 37 | git status -s 38 | if git status -s | grep charts; then 39 | git add . && git commit -am "Update API docs" --signoff && git push 40 | fi -------------------------------------------------------------------------------- /charts/system/templates/telemetry/dataviewer/dataviewer.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: frisbee.system.telemetry.dataviewer 6 | spec: 7 | service: 8 | decorators: 9 | labels: 10 | scenario.frisbee.dev/component: SYS 11 | 12 | ingressPort: 13 | name: http 14 | 15 | # Do a nasty touch to sync/populate the volume. 16 | initContainers: 17 | - name: wait-for-volume 18 | image: busybox 19 | command: [ "touch", "/testdata/init" ] 20 | 21 | containers: # Expose collected logs 22 | - name: main 23 | image: filebrowser/filebrowser 24 | command: [ "/filebrowser" ] 25 | args: [ "-r", "/testdata" ] 26 | ports: 27 | - name: http 28 | containerPort: {{.Values.telemetry.dataviewer.port}} 29 | 30 | callables: 31 | num-of-files: 32 | container: main 33 | command: 34 | - /bin/sh 35 | - -c 36 | - | 37 | ls /testdata | wc -l 38 | 39 | list-files: 40 | container: main 41 | command: 42 | - /bin/sh 43 | - -c 44 | - | 45 | ls -l /testdata -------------------------------------------------------------------------------- /examples/apps/fedbed/examples/resource-distribution.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: resource-distribution 6 | spec: 7 | actions: 8 | # Step 1: Create FedBed server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.fedbed.server 13 | inputs: 14 | - { min_fit_clients: 3 } 15 | 16 | # Step 2: Create FedBed clients 17 | - action: Cluster 18 | name: clients 19 | depends: { running: [ server ]} 20 | cluster: 21 | templateRef: frisbee.apps.fedbed.client 22 | inputs: 23 | - { fl_server: server, dataset: "MNIST", backend: "pytorch", total_nodes: 3, node_id: 0 } 24 | - { fl_server: server, dataset: "MNIST", backend: "pytorch", total_nodes: 3, node_id: 1 } 25 | - { fl_server: server, dataset: "MNIST", backend: "pytorch", total_nodes: 3, node_id: 2 } 26 | resources: 27 | total: { memory: 500Mi } 28 | distribution: { name: uniform } 29 | 30 | # Teardown 31 | - action: Delete 32 | name: teardown 33 | depends: { success: [ clients ] } 34 | delete: 35 | jobs: [ server ] 36 | -------------------------------------------------------------------------------- /pkg/debug/debug.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package debug 18 | 19 | import ( 20 | "fmt" 21 | "path" 22 | "path/filepath" 23 | "runtime" 24 | ) 25 | 26 | func GetCallerInfo(skip int) (fileName, funcName string, line int) { 27 | programCounter, file, line, ok := runtime.Caller(skip) 28 | if !ok { 29 | return 30 | } 31 | 32 | fileName = path.Base(file) 33 | funcName = runtime.FuncForPC(programCounter).Name() 34 | 35 | return 36 | } 37 | 38 | func GetCallerLine() string { 39 | fileName, funcName, line := GetCallerInfo(3) 40 | 41 | _ = fileName 42 | 43 | return fmt.Sprintf("%s:%d", filepath.Base(funcName), line) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/configuration/references.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package configuration 18 | 19 | // References are defined separately in order to facilitate the matching between Yaml configuration (of kubernetes) 20 | // and Go code of the controller. 21 | const ( 22 | // PlatformConfigurationName points to a configmap that maintain information about the installation. 23 | PlatformConfigurationName = "system.controller.configuration" 24 | 25 | PrometheusTemplate = "frisbee.system.telemetry.prometheus" 26 | 27 | GrafanaTemplate = "frisbee.system.telemetry.grafana" 28 | 29 | DataviewerTemplate = "frisbee.system.telemetry.dataviewer" 30 | ) 31 | -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/env/logo.go: -------------------------------------------------------------------------------- 1 | package env 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | 7 | "github.com/dimiro1/banner" 8 | "github.com/kubeshop/testkube/pkg/ui" 9 | ) 10 | 11 | func logo() string { 12 | buf := bytes.NewBuffer(nil) 13 | 14 | /* 15 | templ := `{{ .Title "Frisbee" "" 4 }} 16 | {{ .AnsiColor.BrightCyan }}The title will be ascii and indented 4 spaces{{ .AnsiColor.Default }} 17 | GoVersion: {{ .GoVersion }} 18 | GOOS: {{ .GOOS }} 19 | GOARCH: {{ .GOARCH }} 20 | NumCPU: {{ .NumCPU }} 21 | GOPATH: {{ .GOPATH }} 22 | GOROOT: {{ .GOROOT }} 23 | Compiler: {{ .Compiler }} 24 | ENV: {{ .Env "GOPATH" }} 25 | Now: {{ .Now "Monday, 2 Jan 2006" }} 26 | {{ .AnsiColor.BrightGreen }}This text will appear in Green 27 | {{ .AnsiColor.BrightRed }}This text will appear in Red{{ .AnsiColor.Default }}` 28 | */ 29 | 30 | templ := ` 31 | {{ .AnsiColor.BrightRed }} 32 | {{ .Title "Frisbee" "" 4 }} 33 | {{ .AnsiColor.BrightGreen }} 34 | ` 35 | 36 | banner.InitString(buf, true, true, templ) 37 | 38 | return buf.String() 39 | } 40 | 41 | func Logo() { 42 | fmt.Fprint(ui.Writer, ui.Blue(logo())) 43 | fmt.Fprintln(ui.Writer) 44 | 45 | ui.Success("Kubernetes API:", Default.KubeConfig.Host) 46 | } 47 | -------------------------------------------------------------------------------- /examples/apps/opengadget3/templates/ssh.yml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: ssh-config 5 | data: 6 | sshd_config: | 7 | PidFile /home/mpiuser/sshd.pid 8 | HostKey /home/mpiuser/.ssh/id_rsa 9 | StrictModes no 10 | Port 2222 11 | id_rsa: | 12 | -----BEGIN EC PRIVATE KEY----- 13 | MIHcAgEBBEIAmzcWt1r1eqapBzFSvmyo4CkwlTfoDdj2EJB8kBNm4xoNfc7XNIa+ 14 | DvzgMAcCFmnMa87b3tvCPManAI+F6Ly9r7KgBwYFK4EEACOhgYkDgYYABAAsy5YZ 15 | uCEstHwZXepXcZ0II0bbeJp/N1qUPjTF7h79/ca31qtAzDolgpJjaFCFtuX3cCQt 16 | O9I4zHcGmPoapZ3VjAHi8LMP8MmyROwLcZCLpcS2pjlnRfytmFWipmqD8O0zl2NQ 17 | C7LyWNexA+Z2n+QfUkzQ8ufyohPPzC7PmbXKR0EqhQ== 18 | -----END EC PRIVATE KEY----- 19 | id_rsa.pub: | 20 | ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAsy5YZuCEstHwZXepXcZ0II0bbeJp/N1qUPjTF7h79/ca31qtAzDolgpJjaFCFtuX3cCQtO9I4zHcGmPoapZ3VjAHi8LMP8MmyROwLcZCLpcS2pjlnRfytmFWipmqD8O0zl2NQC7LyWNexA+Z2n+QfUkzQ8ufyohPPzC7PmbXKR0EqhQ== 21 | authorized_keys: | 22 | ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAsy5YZuCEstHwZXepXcZ0II0bbeJp/N1qUPjTF7h79/ca31qtAzDolgpJjaFCFtuX3cCQtO9I4zHcGmPoapZ3VjAHi8LMP8MmyROwLcZCLpcS2pjlnRfytmFWipmqD8O0zl2NQC7LyWNexA+Z2n+QfUkzQ8ufyohPPzC7PmbXKR0EqhQ== 23 | -------------------------------------------------------------------------------- /controllers/call/utils/timeline.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package utils 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/api/v1alpha1" 21 | "github.com/carv-ics-forth/frisbee/pkg/distributions" 22 | ) 23 | 24 | func SetTimeline(call *v1alpha1.Call) { 25 | if call.Spec.Schedule == nil || call.Spec.Schedule.Timeline == nil { 26 | return 27 | } 28 | 29 | probabilitySlice := distributions.GenerateProbabilitySliceFromSpec(int64(len(call.Spec.Services)), 30 | call.Spec.Schedule.Timeline.DistributionSpec) 31 | 32 | call.Status.ExpectedTimeline = probabilitySlice.ApplyToTimeline( 33 | call.GetCreationTimestamp(), 34 | *call.Spec.Schedule.Timeline.TotalDuration, 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/templates/server-with-logs.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: fl.quickstart.server-logs 6 | spec: 7 | inputs: 8 | parameters: 9 | logClaimName: "" 10 | 11 | service: 12 | decorators: 13 | telemetry: 14 | - frisbee.system.telemetry.resources 15 | 16 | volumes: 17 | - name: logs 18 | persistentVolumeClaim: 19 | claimName: {{"{{.inputs.parameters.logClaimName}}" | quote}} 20 | 21 | containers: # Container 22 | - name: main 23 | image: icsforth/fl-demo:latest 24 | ports: 25 | - name: tcp 26 | containerPort: 8080 27 | volumeMounts: 28 | - name: logs 29 | mountPath: /logs 30 | command: 31 | - /bin/sh # Run shell 32 | - -c # Read from string 33 | - | # Multi-line str 34 | set -eum 35 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 36 | 37 | export logDir=/logs/${HOSTNAME} 38 | 39 | python3 server.py &> ${logDir} & 40 | processnumber=$! 41 | 42 | tail -F ${logDir} | awk '/History (loss, distributed):/ { system("kill '$processnumber'") }' -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/4.create-when.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: create-when 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create an iperf client to generate background noise 15 | - action: Service 16 | name: noise 17 | depends: { running: [ server ] } 18 | service: 19 | templateRef: frisbee.apps.iperf2.client 20 | inputs: 21 | - { server: server, seconds: "800" } 22 | 23 | # Create a cluster of iperf clients 24 | - action: Cluster 25 | name: clients 26 | depends: { running: [ server ] } 27 | cluster: 28 | templateRef: frisbee.apps.iperf2.client 29 | instances: 100 30 | inputs: 31 | - { server: server, seconds: "160" } 32 | - { server: server, seconds: "60" } 33 | schedule: 34 | event: 35 | metrics: 'avg() of query(wpFnYRwGk/2/bitrate, 5m, now) is above(100)' 36 | 37 | - action: Delete 38 | name: teardown 39 | depends: { running: [ server, noise ], success: [ clients ] } 40 | delete: 41 | jobs: [ server, noise ] -------------------------------------------------------------------------------- /controllers/cascade/utils/timeline.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package utils 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/api/v1alpha1" 21 | "github.com/carv-ics-forth/frisbee/pkg/distributions" 22 | ) 23 | 24 | func SetTimeline(cascade *v1alpha1.Cascade) { 25 | if cascade.Spec.Schedule == nil || cascade.Spec.Schedule.Timeline == nil { 26 | return 27 | } 28 | 29 | probabilitySlice := distributions.GenerateProbabilitySliceFromSpec(int64(cascade.Spec.MaxInstances), 30 | cascade.Spec.Schedule.Timeline.DistributionSpec) 31 | 32 | cascade.Status.ExpectedTimeline = probabilitySlice.ApplyToTimeline( 33 | cascade.GetCreationTimestamp(), 34 | *cascade.Spec.Schedule.Timeline.TotalDuration, 35 | ) 36 | } 37 | -------------------------------------------------------------------------------- /examples/apps/redis/templates/telemetry.yml: -------------------------------------------------------------------------------- 1 | apiVersion: frisbee.dev/v1alpha1 2 | kind: Template 3 | metadata: 4 | name: redis.telemetry.server 5 | spec: 6 | service: 7 | decorators: 8 | annotations: # Declare the container explicitly as sidecar. 9 | "sidecar.frisbee.dev/telemetry": telegraf 10 | 11 | containers: 12 | - name: telegraf 13 | image: telegraf:1.20.3 14 | ports: 15 | - name: tel-red 16 | containerPort: 9443 17 | command: 18 | - /bin/bash # Run shell 19 | - -c # Read from string 20 | - | # Multi-line str 21 | #!/bin/sh 22 | set -eum 23 | 24 | cat > /tmp/prometheus.conf < 6 | 7 | {{ fieldName . }}
8 | 9 | {{ if linkForType .Type }} 10 | 11 | {{ typeDisplayName .Type }} 12 | 13 | {{ else }} 14 | {{ typeDisplayName .Type }} 15 | {{ end }} 16 | 17 | 18 | 19 | {{ if fieldEmbedded . }} 20 |

21 | (Members of {{ fieldName . }} are embedded into this type.) 22 |

23 | {{ end}} 24 | 25 | {{ if isOptionalMember .}} 26 | (Optional) 27 | {{ end }} 28 | 29 | {{ safe (renderComments .CommentLines) }} 30 | 31 | {{ if and (eq (.Type.Name.Name) "ObjectMeta") }} 32 | Refer to the Kubernetes API documentation for the fields of the 33 | metadata field. 34 | {{ end }} 35 | 36 | {{ if or (eq (fieldName .) "spec") }} 37 |
38 |
39 | 40 | {{ template "members" .Type }} 41 |
42 | {{ end }} 43 | 44 | 45 | {{ end }} 46 | {{ end }} 47 | 48 | {{ end }} 49 | -------------------------------------------------------------------------------- /examples/apps/h5py/scripts/concatenation/create.py: -------------------------------------------------------------------------------- 1 | import os 2 | import socket 3 | import sys 4 | 5 | import h5py 6 | import numpy as np 7 | 8 | 9 | def create_random_file(dir, index): 10 | """create one random file""" 11 | filename = 'myfile_' + str(index) + "_" + socket.gethostname() + ".h5" 12 | name = os.path.join(dir, filename) 13 | 14 | f = h5py.File(name=name, mode='w') 15 | 16 | d = f.create_dataset('data', (5, 10, 20), 'i4') 17 | data = np.random.randint(low=0, high=100, size=(5 * 10 * 20)) 18 | data = data.reshape(5, 10, 20) 19 | d[:] = data 20 | 21 | print("Flushing dataset") # That used to be missing, resulting into erroneous behaviors. 22 | d.flush() 23 | 24 | print("Closing HDF5 file") # That used to be missing, resulting into erroneous behaviors. 25 | f.flush() 26 | f.close() 27 | 28 | return name 29 | 30 | 31 | def main(argv): 32 | if len(argv) != 3: 33 | print("Inputs: [shared_dir] [num_of_files]") 34 | return 35 | 36 | shared_dir = argv[1] 37 | num_of_files = int(argv[2]) 38 | 39 | print("ShareDir:", shared_dir, " num_of_files:", num_of_files) 40 | 41 | for i_file in range(num_of_files): 42 | name = create_random_file(dir=shared_dir, index=i_file) 43 | print("Creating ", name) 44 | 45 | 46 | if __name__ == '__main__': 47 | main(sys.argv) 48 | -------------------------------------------------------------------------------- /pkg/structure/slice.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package structure 18 | 19 | // ContainsStrings searches a slice of strings for a case-sensitive match 20 | func ContainsStrings(slice []string, item string) bool { 21 | for _, a := range slice { 22 | if a == item { 23 | return true 24 | } 25 | } 26 | 27 | return false 28 | } 29 | 30 | /* 31 | // RemoveDuplicate returns a deduplicated version of the slice. 32 | // The implementation is based on Generics which require >= Go v1.18 33 | func RemoveDuplicate[T string | int](sliceList []T) []T { 34 | allKeys := make(map[T]bool) 35 | list := []T{} 36 | for _, item := range sliceList { 37 | if _, value := allKeys[item]; !value { 38 | allKeys[item] = true 39 | list = append(list, item) 40 | } 41 | } 42 | return list 43 | } 44 | */ 45 | -------------------------------------------------------------------------------- /pkg/distributions/pareto.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package distributions 18 | 19 | import ( 20 | "gonum.org/v1/gonum/stat/distuv" 21 | ) 22 | 23 | const ( 24 | DefaultParetoScale = 1 25 | DefaultParetoShape = 0.1 26 | ) 27 | 28 | // Pareto implements the Pareto (Type I) distribution 29 | type Pareto struct { 30 | Impl distuv.Pareto 31 | 32 | Number 33 | x float64 34 | } 35 | 36 | // NewPareto creates a new Pareto distribution. 37 | func NewPareto(scale float64, shape float64) *Pareto { 38 | return &Pareto{ 39 | Impl: distuv.Pareto{ 40 | Xm: scale, 41 | Alpha: shape, 42 | }, 43 | } 44 | } 45 | 46 | // Next computes the value of the probability density function at x. 47 | func (u *Pareto) Next() float64 { 48 | n := u.Impl.Prob(u.x) 49 | 50 | u.x++ 51 | 52 | return n 53 | } 54 | -------------------------------------------------------------------------------- /api/v1alpha1/type_tolerations.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | "fmt" 21 | ) 22 | 23 | // TolerateSpec specifies the system's ability to continue operating despite failures or malfunctions. 24 | // If tolerate is enable, the cluster will remain "alive" even if some services have failed. 25 | // Such failures are likely to happen as part of a Chaos experiment. 26 | type TolerateSpec struct { 27 | // FailedJobs indicate the number of services that may fail before the cluster fails itself. 28 | // +optional 29 | // +kubebuilder:validation:Minimum=1 30 | FailedJobs int `json:"failedJobs"` 31 | } 32 | 33 | func (in *TolerateSpec) String() string { 34 | if in.FailedJobs == 0 { 35 | return "None" 36 | } 37 | 38 | return fmt.Sprintf("Failed Jobs:%d", in.FailedJobs) 39 | } 40 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/templates/datasets.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: fl.quickstart.dataset.cifar 6 | spec: 7 | inputs: 8 | parameters: 9 | dataClaimName: "" 10 | service: 11 | decorators: 12 | telemetry: 13 | - frisbee.system.telemetry.resources 14 | volumes: 15 | - name: dataset 16 | persistentVolumeClaim: 17 | claimName: {{"{{.inputs.parameters.dataClaimName}}" | quote}} 18 | containers: # Container(s) 19 | - name: main 20 | image: busybox 21 | volumeMounts: 22 | - name: dataset 23 | mountPath: /dataset 24 | command: 25 | - /bin/sh # Run shell 26 | - -c # Read from string 27 | - | # Multi-line str 28 | set -eum 29 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 30 | 31 | if [ -d "/dataset/cifar-10-batches-py" ] 32 | then 33 | echo "Directory /dataset/cifar-10-batches-py exists." 34 | else 35 | echo "Download CIFAR10" 36 | wget https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz 37 | 38 | echo "Extract Cifar10 at /dataset/cifar-10-batches-py" 39 | tar -xzvf cifar-10-python.tar.gz -C /dataset/ 40 | fi -------------------------------------------------------------------------------- /pkg/home/home_windows_test.go: -------------------------------------------------------------------------------- 1 | //go:build windows 2 | 3 | /* 4 | Copyright 2022-2023 ICS-FORTH. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package home 20 | 21 | import ( 22 | "os" 23 | "testing" 24 | 25 | "github.com/carv-ics-forth/frisbee/pkg/home/xdg" 26 | ) 27 | 28 | func TestFrisbeeHome(t *testing.T) { 29 | os.Setenv(xdg.CacheHomeEnvVar, "c:\\") 30 | os.Setenv(xdg.ConfigHomeEnvVar, "d:\\") 31 | os.Setenv(xdg.DataHomeEnvVar, "e:\\") 32 | isEq := func(t *testing.T, a, b string) { 33 | if a != b { 34 | t.Errorf("Expected %q, got %q", b, a) 35 | } 36 | } 37 | 38 | isEq(t, CachePath(), "c:\\frisbee") 39 | isEq(t, ConfigPath(), "d:\\frisbee") 40 | isEq(t, DataPath(), "e:\\frisbee") 41 | 42 | // test to see if lazy-loading environment variables at runtime works 43 | os.Setenv(xdg.CacheHomeEnvVar, "f:\\") 44 | 45 | isEq(t, CachePath(), "f:\\frisbee") 46 | } 47 | -------------------------------------------------------------------------------- /examples/apps/ycsb/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: ycsb 4 | description: Yahoo! Cloud Serving Benchmark. 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | # This is the chart version. This version number should be incremented each time you make changes 28 | # to the chart and its templates, including the app version. 29 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 30 | version: 0.0.0 31 | -------------------------------------------------------------------------------- /pkg/distributions/uniform.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package distributions 18 | 19 | import ( 20 | "gonum.org/v1/gonum/stat/distuv" 21 | ) 22 | 23 | // Uniform represents a continuous uniform distribution (https://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29). 24 | type Uniform struct { 25 | Impl distuv.Uniform 26 | 27 | Number 28 | x float64 29 | } 30 | 31 | // NewUniform creates a new Uniform distribution. 32 | func NewUniform(lb int64, ub int64) *Uniform { 33 | return &Uniform{ 34 | Impl: distuv.Uniform{ 35 | Min: float64(lb), 36 | Max: float64(ub), 37 | }, 38 | Number: Number{}, 39 | x: 0, 40 | } 41 | } 42 | 43 | // Next computes the value of the probability density function at x. 44 | func (u *Uniform) Next() float64 { 45 | n := u.Impl.Prob(u.x) 46 | 47 | u.x++ 48 | 49 | return n 50 | } 51 | -------------------------------------------------------------------------------- /.github/workflows/release-docker-images.yml: -------------------------------------------------------------------------------- 1 | name: Release Docker Images 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "v[0-9]+.[0-9]+.[0-9]+" 8 | - "v[0-9]+.[0-9]+.[0-9]+-*" 9 | 10 | jobs: 11 | frisbee-controller: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v3 16 | 17 | - name: Set up QEMU 18 | uses: docker/setup-qemu-action@v1 19 | 20 | - name: Set up Docker Buildx 21 | uses: docker/setup-buildx-action@v1 22 | 23 | - name: Go Cache 24 | uses: actions/cache@v3 25 | with: 26 | path: | 27 | ~/go/pkg/mod 28 | ~/.cache/go-build 29 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 30 | restore-keys: | 31 | ${{ runner.os }}-go- 32 | 33 | - name: Docker Cache 34 | uses: actions/cache@v3 35 | with: 36 | path: /tmp/.buildx-cache 37 | key: ${{ runner.os }}-buildx-${{ github.sha }} 38 | restore-keys: | 39 | ${{ runner.os }}-buildx- 40 | 41 | - name: Login to DockerHub 42 | uses: docker/login-action@v1 43 | with: 44 | username: ${{ secrets.DOCKERHUB_USERNAME }} 45 | password: ${{ secrets.DOCKERHUB_TOKEN }} 46 | 47 | - name: Build and push image for Frisbee Controller 48 | run: | 49 | make docker-push -------------------------------------------------------------------------------- /api/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1alpha1 contains API Schema definitions for the Frisbee v1alpha1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=frisbee.dev 20 | // +k8s:deepcopy-gen=package,register 21 | package v1alpha1 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/runtime/schema" 25 | "sigs.k8s.io/controller-runtime/pkg/scheme" 26 | ) 27 | 28 | var ( 29 | // GroupVersion is group version used to register these objects. 30 | GroupVersion = schema.GroupVersion{Group: "frisbee.dev", Version: "v1alpha1"} 31 | 32 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme. 33 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 34 | 35 | // AddToScheme adds the types in this group-version to the given scheme. 36 | AddToScheme = SchemeBuilder.AddToScheme 37 | ) 38 | -------------------------------------------------------------------------------- /examples/apps/fedbed/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: FedBed 4 | description: Benchmark for Federated Learning. 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /examples/apps/datasets/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: FedBed 4 | description: Benchmark for Federated Learning. 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /charts/system/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: system 4 | description: Default templates for Frisbee 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into 9 | # versioned archives to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. 12 | # They're included as # a dependency of application charts to inject those 13 | # utilities and functions into the rendering pipeline. Library charts do not 14 | # define any templates and therefore cannot be deployed. 15 | type: application 16 | 17 | # This is the version number of the application being deployed. This version 18 | # number should be incremented each time you make changes to the application. 19 | # Versions are not expected to # follow Semantic Versioning. They should 20 | # reflect the version the application is using. It is recommended to use 21 | # it with quotes. 22 | appVersion: "1.16.0" 23 | 24 | maintainers: 25 | - name: Fotis Nikolaidis 26 | email: nikolaidis.fotis@gmail.com 27 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 28 | 29 | # This is the chart version. This version number should be incremented each 30 | # time you make changes to the chart and its templates, including the app 31 | # version. 32 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 33 | version: 0.0.0 34 | -------------------------------------------------------------------------------- /examples/apps/parallax/templates/benchmark.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: parallax.ycsb 6 | spec: 7 | inputs: # test parameters 8 | parameters: 9 | test: simple_test_delete 10 | 11 | service: 12 | decorators: # Monitoring the resources consumed by the test 13 | telemetry: [ frisbee.system.telemetry.resources ] 14 | 15 | volumes: # Create an ephemeral volume for the testdata 16 | - name: scratch-volume 17 | ephemeral: 18 | volumeClaimTemplate: 19 | spec: 20 | storageClassName: platform.storageclass.local 21 | volumeMode: Filesystem 22 | accessModes: [ReadWriteOnce] 23 | resources: 24 | requests: 25 | storage: 20Gi 26 | 27 | containers: 28 | - name: main 29 | image: gxanth/parallax:beta 30 | volumeMounts: 31 | - name: scratch-volume 32 | mountPath: /tmp/test 33 | command: 34 | - /bin/sh # Run shell 35 | - -c # Read from string 36 | - | # Multi-line str 37 | set -eum 38 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 39 | 40 | cd /parallax/build 41 | export testName={{"{{.inputs.parameters.test}}"}} 42 | 43 | ctest -R ^${testName}$ --verbose 44 | -------------------------------------------------------------------------------- /examples/apps/tebis/examples/normal-execution.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: tebis-baseline 6 | spec: 7 | actions: 8 | # Start a Zookeeper server 9 | - action: Service 10 | name: zookeeper 11 | service: 12 | templateRef: tebis.cluster.zookeeper 13 | 14 | # Initialize metadata in Zookeeper 15 | - action: Service 16 | name: boot 17 | depends: 18 | running: [ zookeeper ] 19 | service: 20 | templateRef: tebis.cluster.bootstrap 21 | inputs: 22 | - { zookeeper: zookeeper } 23 | 24 | # Initialize a data node 25 | - action: Cluster 26 | name: masters 27 | depends: { running: [ zookeeper ], success: [ boot ] } 28 | cluster: 29 | templateRef: tebis.cluster.master 30 | instances: 1 31 | inputs: 32 | - { zookeeper: zookeeper } 33 | 34 | 35 | # Initialize a client node 36 | - action: Service 37 | name: client 38 | depends: { running: [ zookeeper, masters ], success: [ boot ] } 39 | service: 40 | templateRef: tebis.cluster.client 41 | inputs: 42 | - { zookeeper: zookeeper, regions: "3" } 43 | 44 | # Teardown 45 | - action: Delete 46 | name: teardown 47 | depends: { running: [ masters, zookeeper ], success: [ client ] } 48 | delete: 49 | jobs: [ masters, zookeeper ] 50 | 51 | -------------------------------------------------------------------------------- /examples/apps/flower/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: flower 4 | description: Flower - A Friendly Federated Learning Framework 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: flower 4 | description: Flower - A Friendly Federated Learning Framework 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /examples/apps/virtual-slurm/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: vslurm 4 | description: Create a Virtual Slurm Cluster within Kubernetes 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the Frisbee operator binary 2 | FROM golang:1.19 as builder 3 | 4 | 5 | ENV GOOS=linux 6 | ENV GOARCH=amd64 7 | ENV CGO_ENABLED=0 8 | ENV GOPROXY=direct 9 | ENV GOSUMDB=off 10 | 11 | WORKDIR /workspace 12 | # Copy the Go Modules manifests 13 | COPY go.mod go.mod 14 | COPY go.sum go.sum 15 | # cache deps before building and copying source so that we don't need to re-download as much 16 | # and so that source changes don't invalidate our downloaded layer 17 | RUN go mod download 18 | 19 | # go env -w GOPROXY=direct 20 | #go env -w GOSUMDB=off 21 | 22 | # Copy the go source 23 | COPY ./cmd/manager/main.go main.go 24 | COPY api/ api/ 25 | COPY controllers/ controllers/ 26 | COPY pkg/ pkg/ 27 | 28 | # Build 29 | RUN go build -a -o /manager main.go 30 | 31 | # Use alpine as minimal base image to package the Frisbee operator binary 32 | # We use a non-root user setup. 33 | # 34 | # usage: 35 | # $ docker build --build-arg "USER=someuser" . -t test 36 | # $ docker run --rm -v ${HOME}/.kube/:/home/default/.kube test 37 | FROM alpine 38 | 39 | ARG USER=default 40 | ENV HOME /home/$USER 41 | 42 | # install sudo as root 43 | RUN apk add --update sudo 44 | 45 | # add new user 46 | RUN adduser -D $USER \ 47 | && echo "$USER ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/$USER \ 48 | && chmod 0440 /etc/sudoers.d/$USER 49 | 50 | USER $USER 51 | WORKDIR $HOME 52 | 53 | COPY --from=builder /manager ./ 54 | 55 | ENTRYPOINT ["/home/default/manager"] 56 | -------------------------------------------------------------------------------- /examples/apps/fio/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: fio 4 | description: fio is a benchmark to test I/O performance. 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into 9 | # versioned archives to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. 12 | # They're included as # a dependency of application charts to inject those 13 | # utilities and functions into the rendering pipeline. Library charts do not 14 | # define any templates and therefore cannot be deployed. 15 | type: application 16 | 17 | # This is the version number of the application being deployed. This version 18 | # number should be incremented each time you make changes to the application. 19 | # Versions are not expected to # follow Semantic Versioning. They should 20 | # reflect the version the application is using. It is recommended to use 21 | # it with quotes. 22 | appVersion: "1.16.0" 23 | 24 | maintainers: 25 | - name: Fotis Nikolaidis 26 | email: nikolaidis.fotis@gmail.com 27 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 28 | 29 | 30 | # This is the chart version. This version number should be incremented each 31 | # time you make changes to the chart and its templates, including the app 32 | # version. 33 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 34 | version: 0.0.0 35 | -------------------------------------------------------------------------------- /examples/apps/opengadget3/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: vslurm 4 | description: Create a Virtual Slurm Cluster within Kubernetes 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | 29 | # This is the chart version. This version number should be incremented each time you make changes 30 | # to the chart and its templates, including the app version. 31 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 32 | version: 0.0.0 33 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/examples/1.baseline.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: dataset 6 | spec: 7 | storageClassName: platform.storageclass.network 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadOnlyMany 11 | resources: 12 | requests: 13 | storage: 2Gi 14 | 15 | 16 | --- 17 | apiVersion: frisbee.dev/v1alpha1 18 | kind: Scenario 19 | metadata: 20 | name: baseline 21 | spec: 22 | actions: 23 | # Step 0: Create a Flower server 24 | - action: Service 25 | name: server 26 | service: 27 | templateRef: fl.quickstart.server 28 | inputs: 29 | - { clients: "3" } 30 | 31 | # Step 1: Download the dataset into a shared volume 32 | - action: Service 33 | name: downloader 34 | service: 35 | templateRef: fl.quickstart.dataset.cifar 36 | inputs: 37 | - { dataClaimName: dataset } 38 | 39 | # Step 2: Create three Flower clients 40 | - action: Cluster 41 | depends: { running: [ server ], success: [ downloader ] } 42 | name: clients 43 | cluster: 44 | templateRef: fl.quickstart.client 45 | instances: 3 46 | inputs: 47 | - { server: server, dataClaimName: dataset } 48 | 49 | 50 | # Teardown 51 | - action: Delete 52 | name: teardown 53 | depends: { running: [ server ], success: [ clients ] } 54 | delete: 55 | jobs: [ server ] 56 | -------------------------------------------------------------------------------- /examples/apps/h5py/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: h5py 4 | description: The h5py package is a Pythonic interface to the HDF5 binary data format. 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/examples/2.throttle-server.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: dataset 6 | spec: 7 | storageClassName: platform.storageclass.network 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadOnlyMany 11 | resources: 12 | requests: 13 | storage: 2Gi 14 | 15 | --- 16 | apiVersion: frisbee.dev/v1alpha1 17 | kind: Scenario 18 | metadata: 19 | name: throttle-server 20 | spec: 21 | actions: 22 | # Create a throttled Flower server 23 | - action: Service 24 | name: server 25 | service: 26 | templateRef: fl.quickstart.server 27 | inputs: 28 | - { clients: "3" } 29 | 30 | # Download the dataset into a shared volume 31 | - action: Service 32 | name: downloader 33 | service: 34 | templateRef: fl.quickstart.dataset.cifar 35 | inputs: 36 | - { dataClaimName: dataset } 37 | 38 | # Create three Flower clients with different resources 39 | - action: Cluster 40 | depends: { running: [ server ], success: [ downloader ] } 41 | name: clients 42 | cluster: 43 | templateRef: fl.quickstart.client 44 | instances: 3 45 | inputs: 46 | - { server: server, dataClaimName: dataset } 47 | 48 | # Teardown 49 | - action: Delete 50 | name: teardown 51 | depends: { running: [ server ], success: [ clients ] } 52 | delete: 53 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/mongodb/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: mongodb 4 | description: MongoDB is a source-available cross-platform document-oriented database program. 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | # This is the chart version. This version number should be incremented each time you make changes 28 | # to the chart and its templates, including the app version. 29 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 30 | version: 0.0.0 31 | -------------------------------------------------------------------------------- /examples/apps/redis/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: redis 4 | description: "Redis is an in-memory data structure store, used as a distributed, 5 | in-memory key–value database, cache and message broker, with optional durability." 6 | 7 | # A chart can be either an 'application' or a 'library' chart. 8 | # 9 | # Application charts are a collection of templates that can be packaged into versioned archives 10 | # to be deployed. 11 | # 12 | # Library charts provide useful utilities or functions for the chart developer. They're included as 13 | # a dependency of application charts to inject those utilities and functions into the rendering 14 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 15 | type: application 16 | 17 | # This is the version number of the application being deployed. This version number should be 18 | # incremented each time you make changes to the application. Versions are not expected to 19 | # follow Semantic Versioning. They should reflect the version the application is using. 20 | # It is recommended to use it with quotes. 21 | appVersion: "1.16.0" 22 | 23 | maintainers: 24 | - name: Fotis Nikolaidis 25 | email: nikolaidis.fotis@gmail.com 26 | 27 | # This is the chart version. This version number should be incremented each time you make changes 28 | # to the chart and its templates, including the app version. 29 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 30 | version: 0.0.0 31 | -------------------------------------------------------------------------------- /pkg/grafana/lister.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package grafana 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/pkg/errors" 23 | ) 24 | 25 | type PanelRef struct { 26 | Title string 27 | ID uint 28 | } 29 | 30 | // ListPanels returns a list of Panels ID with a Grafana dashboard. 31 | func (c *Client) ListPanels(ctx context.Context, dashboardUID string) ([]PanelRef, error) { 32 | if c == nil { 33 | panic("empty client was given") 34 | } 35 | 36 | board, _, err := c.Conn.GetDashboardByUID(ctx, dashboardUID) 37 | if err != nil { 38 | return nil, errors.Wrapf(err, "cannot retrieve dashboard %s", dashboardUID) 39 | } 40 | 41 | panels := make([]PanelRef, 0, len(board.Panels)) 42 | 43 | for _, panel := range board.Panels { 44 | panels = append(panels, PanelRef{ 45 | Title: panel.Title, 46 | ID: panel.ID, 47 | }) 48 | } 49 | 50 | return panels, nil 51 | } 52 | -------------------------------------------------------------------------------- /examples/apps/mongodb/examples/README.md: -------------------------------------------------------------------------------- 1 | # All six workloads have a data set which is similar. Workloads D and E insert records during the test run. 2 | 3 | # Thus, to keep the database size consistent, we apply the following sequence: 4 | 5 | # 6 | 7 | # 1) Load the database, using workload A's parameter file (workloads/workloada) and the "-load" switch to the client. 8 | 9 | # 2) Run workload A (using workloads/workloada and "-t") for a variety of throughputs. 10 | 11 | # 3) Run workload B (using workloads/workloadb and "-t") for a variety of throughputs. 12 | 13 | # 4) Run workload C (using workloads/workloadc and "-t") for a variety of throughputs. 14 | 15 | # 5) Run workload F (using workloads/workloadf and "-t") for a variety of throughputs. 16 | 17 | # 6) Run workload D (using workloads/workloadd and "-t") for a variety of throughputs. 18 | 19 | # This workload inserts records, increasing the size of the database. 20 | 21 | # 7) Delete the data in the database. Otherwise, the remaining data of the cluster might affect the results 22 | 23 | # of the following workload. 24 | 25 | # 8) Reload the database, using workload E's parameter file (workloads/workloade) and the "-load switch to the client. 26 | 27 | # 9) Run workload E (using workloads/workloadd and "-t") for a variety of throughputs. 28 | 29 | # This workload inserts records, increasing the size of the database. 30 | 31 | # 32 | 33 | # For the deletion, instead of destroying the cluster, we destroy and recreate the cluster. -------------------------------------------------------------------------------- /examples/tutorial/14b.delete-cluster-with-tolerance.yml: -------------------------------------------------------------------------------- 1 | # Demonstrates the combination of tolerance with killing. 2 | # The test should fail. Change the "failedJobs" to see that happens. 3 | --- 4 | apiVersion: frisbee.dev/v1alpha1 5 | kind: Template 6 | metadata: 7 | name: sleeper 8 | spec: 9 | service: 10 | containers: 11 | - name: main 12 | image: busybox 13 | command: [ "tail", "-f", "/dev/null" ] 14 | 15 | --- 16 | apiVersion: frisbee.dev/v1alpha1 17 | kind: Scenario 18 | metadata: 19 | name: delete-cluster-with-tolerance 20 | spec: 21 | actions: 22 | # Create 5 instances 23 | - action: Cluster 24 | name: sleepers 25 | cluster: 26 | templateRef: sleeper 27 | instances: 5 28 | tolerate: 29 | failedJobs: 1 # Cluster should fail if a second job is killed. 30 | 31 | # Delete two instances, one every 1 minute 32 | - action: Cascade 33 | name: killer 34 | depends: { running: [ sleepers ], after: "30s" } 35 | cascade: 36 | templateRef: frisbee.system.chaos.pod.kill 37 | inputs: 38 | - { target: sleepers-1 } 39 | - { target: sleepers-3 } 40 | schedule: 41 | cron: "@every 30s" 42 | 43 | # When all actions are done, delete looping servers to gracefully exit the experiment 44 | - action: Delete 45 | name: teardown 46 | depends: { running: [ sleepers ], success: [ killer ] } 47 | delete: 48 | jobs: [ sleepers ] -------------------------------------------------------------------------------- /pkg/client/api.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package client 18 | 19 | import ( 20 | frisbeev1alpha1 "github.com/carv-ics-forth/frisbee/api/v1alpha1" 21 | "k8s.io/apimachinery/pkg/runtime" 22 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 23 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 24 | "sigs.k8s.io/controller-runtime/pkg/client" 25 | ) 26 | 27 | var scheme = runtime.NewScheme() 28 | 29 | func init() { 30 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 31 | utilruntime.Must(frisbeev1alpha1.AddToScheme(scheme)) 32 | } 33 | 34 | // NewDirectAPIClient returns proxy api client. 35 | func NewDirectAPIClient(client client.Client) APIClient { 36 | return APIClient{ 37 | TestManagementClient: NewTestManagementClient(client), 38 | } 39 | } 40 | 41 | // APIClient struct managing proxy API Client dependencies. 42 | type APIClient struct { 43 | TestManagementClient 44 | } 45 | -------------------------------------------------------------------------------- /examples/apps/iperf2/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: iperf 4 | description: iPerf is a tool for active measurements of the maximum achievable bandwidth on IP networks 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /examples/apps/iperf3/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: iperf 4 | description: iPerf is a tool for active measurements of the maximum achievable bandwidth on IP networks 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | maintainers: 23 | - name: Fotis Nikolaidis 24 | email: nikolaidis.fotis@gmail.com 25 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 26 | 27 | 28 | # This is the chart version. This version number should be incremented each time you make changes 29 | # to the chart and its templates, including the app version. 30 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 31 | version: 0.0.0 32 | -------------------------------------------------------------------------------- /examples/apps/flower-custom/examples/10.scheduled-join.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: dataset 6 | spec: 7 | storageClassName: platform.storageclass.network 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadOnlyMany 11 | resources: 12 | requests: 13 | storage: 2Gi 14 | 15 | --- 16 | apiVersion: frisbee.dev/v1alpha1 17 | kind: Scenario 18 | metadata: 19 | name: scheduled-join 20 | spec: 21 | actions: 22 | # Create a Flower server 23 | - action: Service 24 | name: server 25 | service: 26 | templateRef: fl.quickstart.server 27 | inputs: 28 | - { clients: "3" } 29 | 30 | # Download the dataset into a shared volume 31 | - action: Service 32 | name: downloader 33 | service: 34 | templateRef: fl.quickstart.dataset.cifar 35 | inputs: 36 | - { dataClaimName: dataset } 37 | 38 | # Create three Flower clients 39 | - action: Cluster 40 | depends: { success: [ downloader ], running: [ server ] } 41 | name: clients 42 | cluster: 43 | instances: 3 44 | templateRef: fl.quickstart.client 45 | inputs: 46 | - { server: server, dataClaimName: dataset } 47 | schedule: 48 | cron: "@every 2m" 49 | 50 | # Teardown 51 | - action: Delete 52 | name: teardown 53 | depends: { running: [ server ], success: [ clients ] } 54 | delete: 55 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/flower-custom/examples/11.scaled-baseline.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v1 3 | kind: PersistentVolumeClaim 4 | metadata: 5 | name: dataset 6 | spec: 7 | storageClassName: platform.storageclass.network 8 | volumeMode: Filesystem 9 | accessModes: 10 | - ReadOnlyMany 11 | resources: 12 | requests: 13 | storage: 2Gi 14 | 15 | 16 | --- 17 | apiVersion: frisbee.dev/v1alpha1 18 | kind: Scenario 19 | metadata: 20 | name: scaled-baseline 21 | spec: 22 | actions: 23 | # Step 0: Create a Flower server that expects N clients 24 | - action: Service 25 | name: server 26 | service: 27 | templateRef: fl.quickstart.server 28 | inputs: 29 | - { clients: "9" } 30 | 31 | # Step 1: Download the dataset into a shared volume 32 | - action: Service 33 | name: downloader 34 | service: 35 | templateRef: fl.quickstart.dataset.cifar 36 | inputs: 37 | - { dataClaimName: dataset } 38 | 39 | # Step 2: Create twelve Flower clients 40 | - action: Cluster 41 | depends: { running: [ server ], success: [ downloader ] } 42 | name: clients 43 | cluster: 44 | templateRef: fl.quickstart.client 45 | instances: 9 46 | inputs: 47 | - { server: server, dataClaimName: dataset } 48 | 49 | 50 | # Teardown 51 | - action: Delete 52 | name: teardown 53 | depends: { running: [ server ], success: [ clients ] } 54 | delete: 55 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/fio/templates/4.shared-fs.yml: -------------------------------------------------------------------------------- 1 | # Add monitoring # https://github.com/fritchie/fio_benchmark_exporter 2 | --- 3 | apiVersion: frisbee.dev/v1alpha1 4 | kind: Template 5 | metadata: 6 | name: frisbee.apps.fio.shared-fs 7 | spec: 8 | inputs: 9 | parameters: 10 | size: "10M" 11 | direct: "0" 12 | ioengine: libaio 13 | claimName: "" 14 | 15 | service: 16 | volumes: 17 | - name: scratch-volume 18 | persistentVolumeClaim: 19 | claimName: {{"{{.inputs.parameters.claimName}}" | quote}} 20 | 21 | decorators: # decorators 22 | telemetry: [ frisbee.system.telemetry.resources, frisbee.apps.fio.telemetry ] 23 | 24 | containers: # Container 25 | - name: main 26 | image: xridge/fio 27 | volumeMounts: 28 | - name: scratch-volume 29 | mountPath: /scratch 30 | command: 31 | - /bin/sh # Run shell 32 | - -c # Read from string 33 | - | # Multi-line str 34 | set -eum 35 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 36 | 37 | DEVICE=/scratch 38 | SIZE={{"{{.inputs.parameters.size}}"}} 39 | DIRECT={{"{{.inputs.parameters.direct}}"}} 40 | IOENGINE={{"{{.inputs.parameters.ioengine}}"}} 41 | 42 | echo "USING DEVICE: $DEVICE" 43 | 44 | {{ range .Files.Lines "scripts/fio.sh" }} 45 | {{ . }} 46 | {{ end }} -------------------------------------------------------------------------------- /pkg/distributions/normal.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package distributions 18 | 19 | import ( 20 | "gonum.org/v1/gonum/stat/distuv" 21 | ) 22 | 23 | const ( 24 | NormalSigma = 4 25 | ) 26 | 27 | // Normal represents a normal (Gaussian) distribution (https://en.wikipedia.org/wiki/Normal_distribution). 28 | type Normal struct { 29 | Impl distuv.Normal 30 | 31 | Number 32 | x float64 33 | } 34 | 35 | // NewNormal creates a new Normal distribution. 36 | func NewNormal(lb int64, ub int64) *Normal { 37 | return &Normal{ 38 | Impl: distuv.Normal{ 39 | Mu: float64(lb + ub/2), // Mean of the normal distribution 40 | Sigma: NormalSigma, // Standard deviation of the normal distribution 41 | }, 42 | } 43 | } 44 | 45 | // Next computes the value of the probability density function at x. 46 | func (u *Normal) Next() float64 { 47 | n := u.Impl.Prob(u.x) 48 | 49 | u.x++ 50 | 51 | return n 52 | } 53 | -------------------------------------------------------------------------------- /controllers/chaos/jobs.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package chaos 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/carv-ics-forth/frisbee/api/v1alpha1" 23 | "github.com/carv-ics-forth/frisbee/controllers/common" 24 | "github.com/pkg/errors" 25 | "k8s.io/apimachinery/pkg/labels" 26 | ) 27 | 28 | func (r *Controller) runJob(ctx context.Context, chaos *v1alpha1.Chaos) error { 29 | var fault GenericFault 30 | 31 | if err := getRawManifest(chaos, &fault); err != nil { 32 | return errors.Wrapf(err, "cannot get manifest for chaos '%s'", chaos.GetName()) 33 | } 34 | 35 | fault.SetLabels(labels.Merge(fault.GetLabels(), chaos.GetLabels())) 36 | fault.SetAnnotations(labels.Merge(fault.GetAnnotations(), chaos.GetAnnotations())) 37 | 38 | if err := common.Create(ctx, r, chaos, &fault); err != nil { 39 | return errors.Wrapf(err, "failed to inject chaos type '%s'", chaos.Kind) 40 | } 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /pkg/home/xdg/xdg.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright The Frisbee Authors. 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | */ 15 | 16 | // Package xdg holds constants pertaining to XDG Base Directory Specification. 17 | // 18 | // The XDG Base Directory Specification https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html 19 | // specifies the environment variables that define user-specific base directories for various categories of files. 20 | package xdg 21 | 22 | const ( 23 | // CacheHomeEnvVar is the environment variable used by the 24 | // XDG base directory specification for the cache directory. 25 | CacheHomeEnvVar = "XDG_CACHE_HOME" 26 | 27 | // ConfigHomeEnvVar is the environment variable used by the 28 | // XDG base directory specification for the config directory. 29 | ConfigHomeEnvVar = "XDG_CONFIG_HOME" 30 | 31 | // DataHomeEnvVar is the environment variable used by the 32 | // XDG base directory specification for the data directory. 33 | DataHomeEnvVar = "XDG_DATA_HOME" 34 | ) 35 | -------------------------------------------------------------------------------- /pkg/home/home_unix_test.go: -------------------------------------------------------------------------------- 1 | //go:build !windows 2 | 3 | /* 4 | Copyright 2022-2023 ICS-FORTH. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | package home 19 | 20 | import ( 21 | "os" 22 | "runtime" 23 | "testing" 24 | 25 | "github.com/carv-ics-forth/frisbee/pkg/home/xdg" 26 | ) 27 | 28 | func TestFrisbeeHome(t *testing.T) { 29 | os.Setenv(xdg.CacheHomeEnvVar, "/cache") 30 | os.Setenv(xdg.ConfigHomeEnvVar, "/config") 31 | os.Setenv(xdg.DataHomeEnvVar, "/data") 32 | isEq := func(t *testing.T, got, expected string) { 33 | t.Helper() 34 | if expected != got { 35 | t.Error(runtime.GOOS) 36 | t.Errorf("Expected %q, got %q", expected, got) 37 | } 38 | } 39 | 40 | isEq(t, CachePath(), "/cache/frisbee") 41 | isEq(t, ConfigPath(), "/config/frisbee") 42 | isEq(t, DataPath(), "/data/frisbee") 43 | 44 | // test to see if lazy-loading environment variables at runtime works 45 | os.Setenv(xdg.CacheHomeEnvVar, "/cache2") 46 | 47 | isEq(t, CachePath(), "/cache2/frisbee") 48 | } 49 | -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/2.advanced-placement.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: advanced-placement 6 | spec: 7 | actions: 8 | # Create an iperf server. However, because Frisbee placement abstractions are only supported 9 | # at the level of a cluster, we must use the Cluster instead of the Service CRD. 10 | - action: Cluster 11 | name: server 12 | cluster: 13 | templateRef: frisbee.apps.iperf2.server 14 | 15 | # Create a cluster of iperf clients 16 | - action: Cluster 17 | name: clients-a 18 | depends: { running: [ server ] } 19 | cluster: 20 | templateRef: frisbee.apps.iperf2.client 21 | instances: 20 22 | inputs: 23 | - { server: .cluster.server.one, seconds: "120" } 24 | placement: 25 | collocate: true 26 | conflictsWith: [ server ] 27 | 28 | # Create another cluster of iperf clients 29 | - action: Cluster 30 | name: clients-b 31 | depends: { running: [ server ] } 32 | cluster: 33 | templateRef: frisbee.apps.iperf2.client 34 | instances: 20 35 | inputs: 36 | - { server: .cluster.server.one, seconds: "240" } 37 | placement: 38 | collocate: true 39 | conflictsWith: [ clients-a ] 40 | 41 | 42 | - action: Delete 43 | name: teardown 44 | depends: { running: [ server ], success: [ clients-a, clients-b ] } 45 | delete: 46 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/7.failure-toleration.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: failure-toleration 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create a cluster of iperf clients 15 | - action: Cluster 16 | name: clients 17 | depends: { running: [ server ] } 18 | cluster: 19 | templateRef: frisbee.apps.iperf2.client 20 | instances: 10 21 | inputs: 22 | - { server: server, seconds: "600" } 23 | tolerate: # Without this field, the cluster will fail immediately after the killing 24 | failedJobs: 3 25 | 26 | 27 | # Periodically kill some nodes. Beware that in this case we use multiple inputs. 28 | # Notice that we use fixed names, because any selecting macro may choose the same target twice, and stall the execution. 29 | - action: Cascade 30 | name: killer 31 | depends: { running: [ clients ] } 32 | cascade: 33 | templateRef: frisbee.system.chaos.pod.kill 34 | inputs: 35 | - { target: clients-4 } 36 | - { target: clients-7 } 37 | - { target: clients-3 } 38 | schedule: 39 | cron: "@every 1m" 40 | 41 | 42 | - action: Delete 43 | name: teardown 44 | depends: { running: [ server ], success: [ clients, killer ] } 45 | delete: 46 | jobs: [ server ] -------------------------------------------------------------------------------- /examples/apps/tikv/examples/plan.scaleout.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # This experiment runs a given load for various numbers of TikV instance. 3 | # This goal is to find the maximum number of TikV servers after which the overall performance does not increase further. 4 | apiVersion: frisbee.dev/v1alpha1 5 | kind: Scenario 6 | metadata: 7 | name: tikv-scaleout 8 | spec: 9 | actions: 10 | # Step 0: bootstrap. 11 | # For TiKV, we must first create a placementDriver and then add the workers. 12 | - action: Service 13 | name: coordinator 14 | service: 15 | templateRef: frisbee.apps.tikv.pd.coverage 16 | 17 | - action: Cluster 18 | depends: { running: [ coordinator ] } 19 | name: workers 20 | cluster: 21 | templateRef: frisbee.apps.tikv.worker 22 | instances: 256 23 | inputs: 24 | - { placementDriver: coordinator } 25 | 26 | 27 | # Step 1: Load a new dataset, using the parameters of workload A. 28 | # We use no throttling to maximize this step and complete it soon. 29 | - action: Cluster 30 | name: loaders 31 | depends: { running: [ coordinator, workers ] } 32 | cluster: 33 | templateRef: frisbee.apps.ycsb.tikv.loader 34 | inputs: 35 | - { server: coordinator, recordcount: "100000000000", offset: "0", threads: "32" } 36 | 37 | 38 | # Teardown 39 | - action: Delete 40 | name: teardown 41 | depends: { running: [ coordinator, workers ], success: [ loaders ] } 42 | delete: 43 | jobs: [ coordinator, workers ] -------------------------------------------------------------------------------- /controllers/cluster/utils/timeline.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package utils 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/api/v1alpha1" 21 | "github.com/carv-ics-forth/frisbee/pkg/distributions" 22 | ) 23 | 24 | func SetTimeline(cluster *v1alpha1.Cluster) { 25 | if cluster.Spec.Schedule == nil || cluster.Spec.Schedule.Timeline == nil { 26 | return 27 | } 28 | 29 | var probabilitySlice distributions.ProbabilitySlice 30 | 31 | if cluster.Spec.Schedule.Timeline.DistributionSpec.Name == v1alpha1.DistributionDefault { 32 | probabilitySlice = cluster.Status.DefaultDistribution 33 | } else { 34 | probabilitySlice = distributions.GenerateProbabilitySliceFromSpec(int64(cluster.Spec.MaxInstances), 35 | cluster.Spec.Schedule.Timeline.DistributionSpec) 36 | } 37 | 38 | cluster.Status.ExpectedTimeline = probabilitySlice.ApplyToTimeline( 39 | cluster.GetCreationTimestamp(), 40 | *cluster.Spec.Schedule.Timeline.TotalDuration, 41 | ) 42 | } 43 | -------------------------------------------------------------------------------- /examples/apps/tikv/Chart.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: v2 3 | name: tikv 4 | description: TiKV is a highly scalable, low latency, and easy to use key-value database. 5 | 6 | # A chart can be either an 'application' or a 'library' chart. 7 | # 8 | # Application charts are a collection of templates that can be packaged into versioned archives 9 | # to be deployed. 10 | # 11 | # Library charts provide useful utilities or functions for the chart developer. They're included as 12 | # a dependency of application charts to inject those utilities and functions into the rendering 13 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 14 | type: application 15 | 16 | # This is the version number of the application being deployed. This version number should be 17 | # incremented each time you make changes to the application. Versions are not expected to 18 | # follow Semantic Versioning. They should reflect the version the application is using. 19 | # It is recommended to use it with quotes. 20 | appVersion: "1.16.0" 21 | 22 | icon: https://tikv.org/img/logos/horizontal/color/tikv-horizontal-color.png 23 | 24 | maintainers: 25 | - name: Fotis Nikolaidis 26 | email: nikolaidis.fotis@gmail.com 27 | url: https://www.linkedin.com/in/fotis-nikolaidis-444a6634/ 28 | 29 | 30 | # This is the chart version. This version number should be incremented each time you make changes 31 | # to the chart and its templates, including the app version. 32 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 33 | version: 0.0.0 34 | -------------------------------------------------------------------------------- /pkg/structure/structs.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package structure 18 | 19 | import ( 20 | "reflect" 21 | "strings" 22 | ) 23 | 24 | func StructToLowercase(in interface{}) map[string]interface{} { 25 | v := reflect.ValueOf(in) 26 | if v.Kind() != reflect.Struct { 27 | return nil 28 | } 29 | 30 | vType := v.Type() 31 | 32 | result := make(map[string]interface{}, v.NumField()) 33 | 34 | for i := 0; i < v.NumField(); i++ { 35 | name := vType.Field(i).Name 36 | result[strings.ToLower(name)] = v.Field(i).Interface() 37 | } 38 | 39 | return result 40 | } 41 | 42 | func Lower(f interface{}) interface{} { 43 | switch f := f.(type) { 44 | case []interface{}: 45 | for i := range f { 46 | f[i] = Lower(f[i]) 47 | } 48 | return f 49 | case map[string]interface{}: 50 | lf := make(map[string]interface{}, len(f)) 51 | for k, v := range f { 52 | lf[strings.ToLower(k)] = Lower(v) 53 | } 54 | return lf 55 | default: 56 | return f 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /examples/tutorial/3.execution-order.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: whalesay 6 | spec: 7 | # invoke the whalesay template with 8 | # "hello world" as the default argument 9 | # to the message parameter 10 | inputs: 11 | parameters: 12 | message: "hello-world" 13 | service: 14 | containers: 15 | - name: main 16 | image: docker/whalesay 17 | command: [ cowsay ] 18 | args: [ "{{.inputs.parameters.message}}" ] 19 | 20 | --- 21 | apiVersion: frisbee.dev/v1alpha1 22 | kind: Scenario 23 | metadata: 24 | name: execution-order 25 | spec: 26 | actions: 27 | - action: Service 28 | name: a 29 | service: 30 | templateRef: whalesay 31 | inputs: 32 | - { message: "I am A" } 33 | 34 | - action: Service 35 | name: b 36 | depends: { success: [ a ] } 37 | service: 38 | templateRef: whalesay 39 | inputs: 40 | - { message: "I am B" } 41 | 42 | - action: Service 43 | name: c 44 | depends: { success: [ a ] } 45 | service: 46 | templateRef: whalesay 47 | inputs: 48 | - { message: "I am C" } 49 | 50 | - action: Service 51 | name: d 52 | depends: { success: [ b, c ] } 53 | service: 54 | templateRef: whalesay 55 | inputs: 56 | - { message: "I am D" } 57 | 58 | # Teardown 59 | - action: Delete 60 | name: teardown 61 | depends: { success: [ d ] } 62 | delete: 63 | jobs: [ ] -------------------------------------------------------------------------------- /examples/patterns/databases/normal-load/manifest.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: cockroach-normal-load 6 | spec: 7 | actions: 8 | # Step 0. Create individual cockroach servers 9 | - action: Cluster 10 | name: masters 11 | cluster: 12 | templateRef: frisbee.apps.cockroach.server 13 | instances: 3 14 | inputs: 15 | - { join: "masters-1:26257,masters-2:26257,masters-3:26257" } 16 | 17 | 18 | # Step 1. Create a cockroach cluster from the individual servers 19 | - action: Call 20 | name: boot 21 | depends: { running: [ masters ] } 22 | call: 23 | callable: boot 24 | services: [ masters-1 ] 25 | 26 | 27 | # Step 2. Preload keys. 28 | - action: Service 29 | depends: { success: [ boot ] } 30 | name: preloader 31 | service: 32 | templateRef: frisbee.apps.ycsb.cockroach.loader 33 | inputs: 34 | - { server: masters-1, workload: workloada, recordcount: "100000", threads: "16", delay: "15" } 35 | 36 | 37 | # Step 3. Run YCSB workload A 38 | - action: Service 39 | depends: { success: [ preloader ] } 40 | name: query 41 | service: 42 | templateRef: frisbee.apps.ycsb.cockroach.runner 43 | inputs: 44 | - { server: masters-1, workload: workloada, operationcount: "100000", threads: "4" } 45 | 46 | 47 | # Teardown 48 | - action: Delete 49 | name: teardown 50 | depends: { success: [ query ] } 51 | delete: 52 | jobs: [ masters ] -------------------------------------------------------------------------------- /examples/apps/flower-custom/templates/server.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: fl.quickstart.server 6 | spec: 7 | inputs: 8 | parameters: 9 | rounds: "3" 10 | clients: "2" 11 | service: 12 | decorators: 13 | telemetry: 14 | - frisbee.system.telemetry.resources 15 | 16 | containers: # Container 17 | - name: main 18 | image: icsforth/fl-demo:latest 19 | ports: 20 | - name: tcp 21 | containerPort: 8080 22 | command: 23 | - /bin/sh # Run shell 24 | - -c # Read from string 25 | - | # Multi-line str 26 | set -eum 27 | cut -d ' ' -f 4 /proc/self/stat > /dev/shm/app # Sidecar: use it for entering the cgroup 28 | 29 | export FL_NUM_OF_ROUNDS={{"{{.inputs.parameters.rounds}}"}} 30 | 31 | # Minimum number of clients that need to be connected to the server before a training round can start. 32 | # It should be at least equal ro FL_MIN_FIT_CLIENTS 33 | export FL_MIN_AVAILABLE_CLIENTS={{"{{.inputs.parameters.clients}}"}} 34 | 35 | # Minimum number of clients to be sampled for the next round. 36 | export FL_MIN_FIT_CLIENTS={{"{{.inputs.parameters.clients}}"}} 37 | 38 | export logFile=/tmp/${HOSTNAME} 39 | 40 | python3 server.py &> ${logFile} & 41 | 42 | # Exit the server if it gives the final report 43 | tail -f ${logFile} | awk -W interactive '/History (loss, distributed):/{exit 0};END{print $0}' -------------------------------------------------------------------------------- /examples/apps/h5py/templates/multiprocessing.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: h5py.pipeline.image-generator 6 | spec: 7 | service: 8 | containers: 9 | - name: main 10 | image: hdfgroup/hdf5lib:1.13.1 11 | command: 12 | - /bin/sh # Run shell 13 | - -c # Read from string 14 | - | # Multi-line str 15 | 16 | python3 - < plotter.py 52 | {{ .Files.Get "scripts/multiprocessing/image-visualizer.py" | indent 13 }} 53 | EOF 54 | 55 | # Start Xserver 56 | /startup.sh -------------------------------------------------------------------------------- /charts/platform/templates/webhook/alerts/proxy.yaml: -------------------------------------------------------------------------------- 1 | {{ if .Values.operator.enabled}} 2 | --- 3 | apiVersion: v1 4 | kind: Service 5 | metadata: 6 | name: alerting-service 7 | spec: 8 | ports: 9 | - name: http 10 | port: {{.Values.operator.webhook.grafana.port | int64}} 11 | selector: 12 | control-plane: {{.Values.operator.name}} 13 | --- 14 | 15 | {{ else }} 16 | 17 | --- 18 | #https://kubernetes: io/docs/concepts/services-networking/service/#services-without-selectors: 19 | apiVersion: v1 20 | kind: Service 21 | metadata: 22 | name: alerting-service 23 | spec: 24 | type: ClusterIP 25 | clusterIP: None 26 | ports: 27 | - name: http 28 | port: 80 29 | targetPort: {{.Values.operator.webhook.grafana.port | int64}} 30 | 31 | 32 | --- 33 | apiVersion: discovery.k8s.io/v1 34 | kind: EndpointSlice 35 | metadata: 36 | name: alerting-service-1 # by convention, use the name of the Service as a prefix for the name of the EndpointSlice 37 | labels: 38 | # You should set the "kubernetes.io/service-name" label. 39 | # Set its value to match the name of the Service 40 | kubernetes.io/service-name: alerting-service 41 | endpointslice.kubernetes.io/managed-by: "frisbee-team" 42 | addressType: IPv4 43 | ports: 44 | - name: '' # empty because Frisbee port is not assigned as a well-known # port (by IANA) 45 | appProtocol: http 46 | protocol: TCP 47 | port: {{.Values.operator.webhook.grafana.port | int64}} 48 | endpoints: 49 | - addresses: # the IP addresses in this list can appear in any order 50 | - {{.Values.operator.advertisedHost}} 51 | {{end}} -------------------------------------------------------------------------------- /examples/patterns/databases/normal-load/manifest-by-time.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: cockroach-normal-load 6 | spec: 7 | actions: 8 | # Step 0. Create individual cockroach servers 9 | - action: Cluster 10 | name: masters 11 | cluster: 12 | templateRef: frisbee.apps.cockroach.server 13 | instances: 3 14 | inputs: 15 | - { join: "masters-1:26257,masters-2:26257,masters-3:26257" } 16 | 17 | 18 | # Step 1. Create a cockroach cluster from the individual servers 19 | - action: Call 20 | name: boot 21 | depends: { running: [ masters ] } 22 | call: 23 | callable: boot 24 | services: [ masters-1 ] 25 | 26 | 27 | # Step 2. Preload keys. 28 | - action: Service 29 | depends: { success: [ boot ] } 30 | name: preloader 31 | service: 32 | templateRef: frisbee.apps.ycsb.cockroach.loader 33 | inputs: 34 | - { server: masters-1, workload: workloada, recordcount: "100000", threads: "16", delay: "15" } 35 | 36 | 37 | # Step 3. Run YCSB workload A 38 | - action: Service 39 | depends: { after: "5m" } # Time-driven Experiment 40 | name: query 41 | service: 42 | templateRef: frisbee.apps.ycsb.cockroach.runner 43 | inputs: 44 | - { server: masters-1, workload: workloada, operationcount: "100000", threads: "4" } 45 | 46 | 47 | # Teardown 48 | - action: Delete 49 | name: teardown 50 | depends: { success: [ query ] } 51 | delete: 52 | jobs: [ masters ] -------------------------------------------------------------------------------- /controllers/common/endpoints.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package common 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/carv-ics-forth/frisbee/pkg/configuration" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | ) 25 | 26 | // InternalEndpoint creates an endpoint for accessing the service within the cluster. 27 | func InternalEndpoint(name string, planName string, port int64) string { 28 | return fmt.Sprintf("%s.%s:%d", name, planName, port) 29 | } 30 | 31 | // ExternalEndpoint creates an endpoint for accessing the service outside the cluster. 32 | func ExternalEndpoint(name, planName string) string { 33 | return fmt.Sprintf("%s-%s.%s", name, planName, configuration.Global.DomainName) 34 | } 35 | 36 | // GenerateName names the children of a given resource. The instances will be named as Master-1, Master-2, ... 37 | // see https://github.com/CARV-ICS-FORTH/frisbee/issues/339 38 | func GenerateName(group metav1.Object, jobIndex int) string { 39 | return fmt.Sprintf("%s-%d", group.GetName(), jobIndex+1) 40 | } 41 | -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/commands/install.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package commands 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands/install" 21 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/env" 22 | "github.com/kubeshop/testkube/pkg/ui" 23 | "github.com/spf13/cobra" 24 | ) 25 | 26 | func NewInstallCmd() *cobra.Command { 27 | cmd := &cobra.Command{ 28 | Use: "install", 29 | Short: "Install Frisbee to current kubectl context", 30 | Aliases: []string{"i", "deploy"}, 31 | PersistentPreRun: func(cmd *cobra.Command, args []string) { 32 | env.Logo() 33 | ui.SetVerbose(env.Default.Debug) 34 | 35 | ui.Warn("If it takes long time, make sure you have used the proper values file.") 36 | }, 37 | Run: func(cmd *cobra.Command, args []string) { 38 | ui.PrintOnError("Displaying help", cmd.Help()) 39 | }, 40 | } 41 | 42 | cmd.AddCommand(install.NewInstallDevelopmentCmd()) 43 | cmd.AddCommand(install.NewInstallProductionCmd()) 44 | 45 | return cmd 46 | } 47 | -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/commands/root.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package commands 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/env" 21 | "github.com/kubeshop/testkube/pkg/ui" 22 | "github.com/spf13/cobra" 23 | ) 24 | 25 | func NewRootCmd() *cobra.Command { 26 | cmd := &cobra.Command{ 27 | Use: "kubectl-frisbee", 28 | Short: "Frisbee entrypoint for kubectl plugin", 29 | Run: func(cmd *cobra.Command, args []string) { 30 | env.Logo() 31 | ui.SetVerbose(env.Default.Debug) 32 | 33 | ui.PrintOnError("Displaying help", cmd.Help()) 34 | }, 35 | } 36 | 37 | // Add global flags 38 | env.Default.AddFlags(cmd) 39 | 40 | // Add subcommands 41 | cmd.AddCommand( 42 | // Platform Installation 43 | NewInstallCmd(), 44 | NewUninstallCmd(), 45 | 46 | // Test Management 47 | NewValidateCmd(), 48 | NewSubmitCmd(), 49 | NewGetCmd(), 50 | NewDeleteCmd(), 51 | NewInspectCmd(), 52 | 53 | // Analysis Tools 54 | NewSaveCmd(), 55 | NewReportCmd(), 56 | ) 57 | 58 | return cmd 59 | } 60 | -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/env/root_unix.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package env 18 | 19 | import ( 20 | "github.com/kubeshop/testkube/pkg/ui" 21 | "k8s.io/utils/exec" 22 | ) 23 | 24 | func (env *EnvironmentSettings) LookupBinaries() { 25 | // kubectl 26 | kubectlPath, err := exec.New().LookPath("kubectl") 27 | ui.ExitOnError("Frisbee requires 'kubectl' to be installed in your system.", err) 28 | 29 | env.kubectlPath = kubectlPath 30 | 31 | // helm 32 | helmPath, err := exec.New().LookPath("helm") 33 | ui.ExitOnError("Frisbee requires 'helm' to be installed in your system.", err) 34 | 35 | env.helmPath = helmPath 36 | 37 | // nodejs 38 | nodejsPath, err := exec.New().LookPath("node") 39 | if err != nil { 40 | ui.Warn("Disable PDF exporter due to missing dependency.", "NodeJs") 41 | } 42 | 43 | env.nodejsPath = nodejsPath 44 | 45 | // npm 46 | npmPath, err := exec.New().LookPath("npm") 47 | if err != nil { 48 | ui.Warn("Disable PDF exporter due to missing dependency.", "NPM") 49 | } 50 | 51 | env.npmPath = npmPath 52 | } 53 | -------------------------------------------------------------------------------- /examples/tutorial/4.dependency-order.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Template 4 | metadata: 5 | name: iperf.server 6 | spec: 7 | service: 8 | containers: 9 | - name: main 10 | image: czero/iperf2 11 | ports: 12 | - name: listen 13 | containerPort: 5001 14 | command: [ iperf ] 15 | args: [ "-s", "-f", "m", "-i", "5" ] 16 | 17 | 18 | --- 19 | apiVersion: frisbee.dev/v1alpha1 20 | kind: Template 21 | metadata: 22 | name: iperf.client 23 | spec: 24 | inputs: 25 | parameters: 26 | target: localhost 27 | duration: "60" 28 | service: 29 | containers: 30 | - name: main 31 | image: czero/iperf2 32 | command: [ iperf ] 33 | args: [ "-c", "{{.inputs.parameters.target}}", "-t", "{{.inputs.parameters.duration}}" ] 34 | 35 | 36 | --- 37 | apiVersion: frisbee.dev/v1alpha1 38 | kind: Scenario 39 | metadata: 40 | name: dependency-order 41 | spec: 42 | actions: 43 | # Create an iperf server 44 | - action: Service 45 | name: server 46 | service: 47 | templateRef: iperf.server 48 | 49 | # Create an iperf client 50 | - action: Service 51 | name: client 52 | depends: { running: [ server ] } 53 | service: 54 | templateRef: iperf.client 55 | inputs: 56 | - { target: server } 57 | 58 | 59 | # When all actions are done, delete looping servers to gracefully exit the experiment 60 | - action: Delete 61 | name: teardown 62 | depends: { running: [ server ], success: [ client ] } 63 | delete: 64 | jobs: [ server ] 65 | -------------------------------------------------------------------------------- /.github/workflows/release-kubectl-frisbee.yml: -------------------------------------------------------------------------------- 1 | name: Release kubectl-frisbee 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | tags: 7 | - "v[0-9]+.[0-9]+.[0-9]+" 8 | - "v[0-9]+.[0-9]+.[0-9]+-*" 9 | 10 | permissions: 11 | contents: write 12 | # packages: write 13 | # issues: write 14 | 15 | jobs: 16 | goreleaser: 17 | runs-on: ubuntu-latest 18 | strategy: 19 | matrix: 20 | include: 21 | - name: "linux" 22 | path: .builds-linux.goreleaser.yml 23 | # - name: "windows" 24 | # path: .builds-windows.goreleaser.yml 25 | # - name: "darwin" 26 | # path: .builds-darwin.goreleaser.yml 27 | 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v3 31 | with: 32 | fetch-depth: 0 33 | 34 | - name: Fetch all tags 35 | run: git fetch --force --tags 36 | 37 | - name: Set up Go 38 | uses: actions/setup-go@v3 39 | with: 40 | go-version: 1.19 41 | 42 | - name: Go Cache 43 | uses: actions/cache@v3 44 | with: 45 | path: | 46 | ~/go/pkg/mod 47 | ~/.cache/go-build 48 | key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} 49 | restore-keys: | 50 | ${{ runner.os }}-go- 51 | 52 | - name: Run GoReleaser 53 | uses: goreleaser/goreleaser-action@v3 54 | with: 55 | distribution: goreleaser 56 | version: latest 57 | args: release -f ${{ matrix.path }} --rm-dist 58 | env: 59 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /examples/apps/redis/examples/5.scaleup-scheduled.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: redis-scaleup-scheduled 6 | spec: 7 | actions: 8 | # Step 0. Create individual Redis servers 9 | - action: Cluster 10 | name: masters 11 | cluster: 12 | templateRef: redis.cluster.master 13 | instances: 3 14 | 15 | # Step 1. Create a Redis cluster from the individual servers 16 | - action: Service 17 | name: boot 18 | depends: { running: [ masters ] } 19 | service: 20 | templateRef: redis.cluster.bootstrap 21 | inputs: 22 | - { servers: .cluster.masters.all } 23 | 24 | 25 | # Step 2. Hammer the server with requests 26 | - action: Service 27 | depends: { success: [ boot ] } 28 | name: loader 29 | service: 30 | templateRef: frisbee.apps.ycsb.redis.loader 31 | inputs: 32 | - { server: .cluster.masters.one , workload: workloada, recordcount: "100000000", threads: "40", mode: "cluster" } 33 | 34 | 35 | # Step 3. Add new servers every two minutes 36 | - action: Cluster 37 | name: more-servers 38 | depends: { running: [ loader ] } 39 | cluster: 40 | templateRef: redis.cluster.master 41 | instances: 10 42 | inputs: 43 | - { join: .cluster.masters.one } 44 | schedule: 45 | cron: "@every 2m" 46 | 47 | 48 | # Teardown 49 | - action: Delete 50 | name: teardown 51 | depends: { running: [ masters, more-servers ], success: [ loader ] } 52 | delete: 53 | jobs: [ masters, more-servers ] -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/commands/delete.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2021-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package commands 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands/common" 21 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands/tests" 22 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/env" 23 | "github.com/kubeshop/testkube/pkg/ui" 24 | "github.com/spf13/cobra" 25 | ) 26 | 27 | func NewDeleteCmd() *cobra.Command { 28 | cmd := &cobra.Command{ 29 | Use: "delete ", 30 | Aliases: []string{"remove"}, 31 | Short: "Delete resources", 32 | PersistentPreRun: func(cmd *cobra.Command, args []string) { 33 | env.Logo() 34 | ui.SetVerbose(env.Default.Debug) 35 | 36 | if !common.CRDsExist(common.Scenarios) { 37 | ui.Failf("Frisbee is not installed on the kubernetes cluster.") 38 | } 39 | }, 40 | Run: func(cmd *cobra.Command, args []string) { 41 | ui.PrintOnError("Displaying help", cmd.Help()) 42 | }, 43 | } 44 | 45 | cmd.AddCommand(tests.NewDeleteTestsCmd()) 46 | 47 | return cmd 48 | } 49 | -------------------------------------------------------------------------------- /examples/apps/iperf2/examples/9.state-driven-partition.yml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: frisbee.dev/v1alpha1 3 | kind: Scenario 4 | metadata: 5 | name: state-driven-partition 6 | spec: 7 | actions: 8 | # Create an iperf server 9 | - action: Service 10 | name: server 11 | service: 12 | templateRef: frisbee.apps.iperf2.server 13 | 14 | # Create an iperf client to generate background noise 15 | - action: Service 16 | name: noise 17 | depends: { running: [ server ] } 18 | service: 19 | templateRef: frisbee.apps.iperf2.client 20 | inputs: 21 | - { server: server, seconds: "800" } 22 | 23 | 24 | # Create another iperf client, a bit later 25 | - action: Service 26 | name: client 27 | depends: { running: [ server ], after: "2m" } 28 | service: 29 | templateRef: frisbee.apps.iperf2.client 30 | inputs: 31 | - { server: server, seconds: "120" } 32 | 33 | # Inject a network failure when the client is created 34 | - action: Chaos 35 | name: partition0 36 | depends: { running: [ client ] } 37 | chaos: 38 | templateRef: system.chaos.network.partition 39 | inputs: 40 | - { targets: server } 41 | 42 | 43 | # Revoke the failure when the client is deleted 44 | - action: Delete 45 | name: delete-client 46 | depends: { success: [ client ] } 47 | delete: 48 | jobs: [ partition0 ] 49 | 50 | 51 | - action: Delete 52 | name: teardown 53 | depends: { running: [ server, noise ], success: [ delete-client ] } 54 | delete: 55 | jobs: [ server, noise ] -------------------------------------------------------------------------------- /hack/api-docs/template/pkg.tpl: -------------------------------------------------------------------------------- 1 | {{ define "packages" }} 2 | 3 | {{ with .packages}} 4 | 5 | --- 6 | title: Field Reference 7 | linktitle: Field Reference 8 | description: This document describes the fields for building a Frisbee experiment. 9 | publishdate: 2022-06-28 10 | lastmod: 2022-06-28 11 | layout: single 12 | menu: 13 | main: 14 | parent: "section name" 15 | weight: 10 16 | weight: 10 17 | draft: false 18 | aliases: [/fields] 19 | toc: true 20 | --- 21 | 22 |

Packages:

23 | 30 | {{ end}} 31 | 32 | {{ range .packages }} 33 |

34 | {{- packageDisplayName . -}} 35 |

36 | 37 | {{ with (index .GoPackages 0 )}} 38 | {{ with .DocComments }} 39 |
40 | {{ safe (renderComments .) }} 41 |
42 | {{ end }} 43 | {{ end }} 44 | 45 | Resource Types: 46 |
    47 | {{- range (visibleTypes (sortedTypes .Types)) -}} 48 | {{ if isExportedType . -}} 49 |
  • 50 | {{ typeDisplayName . }} 51 |
  • 52 | {{- end }} 53 | {{- end -}} 54 |
55 | 56 | {{ range (visibleTypes (sortedTypes .Types))}} 57 | {{ template "type" . }} 58 | {{ end }} 59 |
60 | {{ end }} 61 | 62 |

63 | Generated with gen-crd-api-reference-docs 64 | {{ with .gitCommit }} on git commit {{ . }}{{end}}. 65 |

66 | 67 | {{ end }} 68 | -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/commands/validate.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package commands 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands/common" 21 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands/tests" 22 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/env" 23 | "github.com/kubeshop/testkube/pkg/ui" 24 | "github.com/spf13/cobra" 25 | ) 26 | 27 | func NewValidateCmd() *cobra.Command { 28 | cmd := &cobra.Command{ 29 | Use: "validate ", 30 | Aliases: []string{"check"}, 31 | Short: "Validate a new test", 32 | PersistentPreRun: func(cmd *cobra.Command, args []string) { 33 | env.Logo() 34 | ui.SetVerbose(env.Default.Debug) 35 | 36 | if !common.CRDsExist(common.Scenarios) { 37 | ui.Failf("Frisbee is not installed on the kubernetes cluster.") 38 | } 39 | }, 40 | Run: func(cmd *cobra.Command, args []string) { 41 | ui.PrintOnError("Displaying help", cmd.Help()) 42 | }, 43 | } 44 | 45 | cmd.AddCommand(tests.NewValidateTestCmd()) 46 | 47 | return cmd 48 | } 49 | -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/commands/common/kubectl-wrapper_test.go: -------------------------------------------------------------------------------- 1 | package common_test 2 | 3 | /* 4 | func TestSetQuota(t *testing.T) { 5 | namespace := "my-test" 6 | 7 | if err := CreateNamespace(namespace); err != nil { 8 | t.Fatalf("cannot create namespace '%s'. err: '%s'", namespace, err) 9 | } 10 | 11 | defer func() { 12 | if err := DeleteNamespaces("", namespace); err != nil { 13 | t.Fatalf("cannot delete namespace '%s'. err: '%s'", namespace, err) 14 | } 15 | }() 16 | 17 | type args struct { 18 | testName string 19 | cpu string 20 | memory string 21 | } 22 | 23 | tests := []struct { 24 | name string 25 | args args 26 | wantErr bool 27 | }{ 28 | { 29 | name: "Default", 30 | args: args{testName: namespace, cpu: "", memory: ""}, 31 | wantErr: false, 32 | }, 33 | { 34 | name: "CPU-Only", 35 | args: args{testName: namespace, cpu: "0.1", memory: ""}, 36 | wantErr: false, 37 | }, 38 | 39 | { 40 | name: "Memory-Only", 41 | args: args{testName: namespace, cpu: "", memory: "10Mi"}, 42 | wantErr: false, 43 | }, 44 | { 45 | name: "Both", 46 | args: args{testName: namespace, cpu: "0.1", memory: "10Mi"}, 47 | wantErr: false, 48 | }, 49 | { 50 | name: "Invalid", 51 | args: args{testName: namespace, cpu: "0.1", memory: "10Mb"}, 52 | wantErr: true, 53 | }, 54 | } 55 | 56 | for _, tt := range tests { 57 | t.Run(tt.name, func(t *testing.T) { 58 | if err := SetQuota(tt.args.testName, tt.args.cpu, tt.args.memory); (err != nil) != tt.wantErr { 59 | t.Errorf("SetQuota() error = %v, wantErr %v", err, tt.wantErr) 60 | } 61 | }) 62 | } 63 | } 64 | */ 65 | -------------------------------------------------------------------------------- /cmd/kubectl-frisbee/commands/report.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022-2023 ICS-FORTH. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package commands 18 | 19 | import ( 20 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands/common" 21 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/commands/tests" 22 | "github.com/carv-ics-forth/frisbee/cmd/kubectl-frisbee/env" 23 | "github.com/kubeshop/testkube/pkg/ui" 24 | "github.com/spf13/cobra" 25 | ) 26 | 27 | func NewReportCmd() *cobra.Command { 28 | cmd := &cobra.Command{ 29 | Use: "report ", 30 | Aliases: []string{"r"}, 31 | Short: "Generate PDFs for every dashboard in Grafana.", 32 | PersistentPreRun: func(cmd *cobra.Command, args []string) { 33 | env.Logo() 34 | ui.SetVerbose(env.Default.Debug) 35 | 36 | if !common.CRDsExist(common.Scenarios) { 37 | ui.Failf("Frisbee is not installed on the kubernetes cluster.") 38 | } 39 | }, 40 | Run: func(cmd *cobra.Command, args []string) { 41 | ui.PrintOnError("Displaying help", cmd.Help()) 42 | }, 43 | } 44 | 45 | cmd.AddCommand(tests.NewReportTestCmd()) 46 | 47 | return cmd 48 | } 49 | --------------------------------------------------------------------------------