diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index af3ca77a897a2ddea9ee8d7c6e4e30fa7f369e94..a1aefe7f900ea2b03c0ce2c8ed8e9827a8fe2f57 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -48,7 +48,8 @@ default: export PUBLISHED_IMAGE_TAG=$DOCKER_TAG_NAME$CI_COMMIT_SHORT_SHA fi - "[ $DOCKERFILE ] && KANIKO_DOCKERFILE=\"--dockerfile $DOCKERFILE\"" - - /kaniko/executor --context `pwd`/$CONTEXT $KANIKO_DOCKERFILE $KANIKO_D + - "BUILD_ARGS=$(printenv | sed -n 's/BUILD_ARG_/--build-arg=/p')" + - /kaniko/executor --context `pwd`/$CONTEXT $KANIKO_DOCKERFILE $KANIKO_D $BUILD_ARGS - echo "PUBLISHED_IMAGE_TAG=$PUBLISHED_IMAGE_TAG" >> $CI_PROJECT_DIR/build.env artifacts: reports: @@ -135,6 +136,38 @@ lint-helm: - when: manual allow_failure: true +test-helm: + stage: smoketest + extends: .dind + needs: + - lint-helm + # - deploy-theodolite + image: ghcr.io/cau-se/theodolite-build-k3d-helm:20.10.12 + variables: + CLUSTERNAME: "$CI_PROJECT_NAME-$CI_PIPELINE_ID" + cache: + paths: + - helm/charts + before_script: + - k3d help + - k3d version + #- k3d cluster create testgitlabci --agents 1 --wait -p "30000:30000@agent[0]" + - k3d cluster create $CLUSTERNAME --agents 1 --wait -p "30000:30000@agent:0" # k3d 5.0 + # show cluster info + - kubectl cluster-info + - helm version + script: + # Display initial pods, etc. + - cd helm + - helm dependencies update . + - helm install theodolite . -f preconfigs/minimal.yaml --wait + - helm test theodolite + - kubectl get nodes -o wide + - kubectl get pods --all-namespaces -o wide + - kubectl get services --all-namespaces -o wide + after_script: + - k3d cluster delete $CLUSTERNAME + # Theodolite Benchmarks @@ -235,7 +268,7 @@ spotbugs-benchmarks: - changes: - theodolite-benchmarks/* - theodolite-benchmarks/$JAVA_PROJECT_NAME/**/* - - theodolite-benchmarks/{$JAVA_PROJECT_DEPS}/**/* + - theodolite-benchmarks/{commons,$JAVA_PROJECT_DEPS}/**/* if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $IMAGE_NAME && $JAVA_PROJECT_NAME && $JAVA_PROJECT_DEPS" - if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $IMAGE_NAME && $JAVA_PROJECT_NAME" when: manual @@ -851,3 +884,24 @@ deploy-buildimage-docker-compose-jq: - if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $CI_PIPELINE_SOURCE == 'web'" when: manual allow_failure: true + +deploy-buildimage-k3d-helm: + stage: deploy + extends: + - .kaniko-push + needs: [] + variables: + DOCKER_VERSION: 20.10.12 + BUILD_ARG_DOCKER_VERSION: $DOCKER_VERSION + BUILD_ARG_KUBECTL: v1.21.3 + IMAGE_NAME: theodolite-build-k3d-helm + IMAGE_TAG: $DOCKER_VERSION + before_script: + - cd buildimages/k3d-helm + rules: + - changes: + - buildimages/k3d-helm/Dockerfile + if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW" + - if: "$CR_HOST && $CR_ORG && $CR_USER && $CR_PW && $CI_PIPELINE_SOURCE == 'web'" + when: manual + allow_failure: true diff --git a/buildimages/k3d-helm/Dockerfile b/buildimages/k3d-helm/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..496cddd68a230a7ea8b0f73adb9ffa37e35e6719 --- /dev/null +++ b/buildimages/k3d-helm/Dockerfile @@ -0,0 +1,14 @@ +ARG DOCKER_VERSION=latest + +FROM docker:${DOCKER_VERSION} + +ARG KUBECTL_VERSION=v1.21.3 + +RUN apk add -U wget bash openssl +# install kubectl +RUN wget -q -O /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl && \ + chmod +x /usr/local/bin/kubectl +# install k3d +RUN wget -q -O - https://raw.githubusercontent.com/rancher/k3d/main/install.sh | bash +# install Helm +RUN wget -q -O - https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock index fc60fc6f6fddbb9b18a85ed1f472a444e0ed4cea..4acb2ba79d5cde699cf9dd4d379bf17c3c93e068 100644 --- a/docs/Gemfile.lock +++ b/docs/Gemfile.lock @@ -239,7 +239,7 @@ GEM jekyll-seo-tag (~> 2.1) minitest (5.15.0) multipart-post (2.1.1) - nokogiri (1.13.4-x86_64-linux) + nokogiri (1.13.6-x86_64-linux) racc (~> 1.4) octokit (4.22.0) faraday (>= 0.9) diff --git a/docs/api-reference/crds.md b/docs/api-reference/crds.md index fb3f02ac941870dd085d06027d972e6003c7aadb..87c4e9046396456e2177098c8085aa995534735b 100644 --- a/docs/api-reference/crds.md +++ b/docs/api-reference/crds.md @@ -114,6 +114,13 @@ Resource Types: A list of resource types that can be scaled for this `benchmark` resource. For each resource type the concrete values are defined in the `execution` object.<br/> </td> <td>true</td> + </tr><tr> + <td><b><a href="#benchmarkspecslosindex">slos</a></b></td> + <td>[]object</td> + <td> + List of resource values for the specified resource type.<br/> + </td> + <td>true</td> </tr><tr> <td><b><a href="#benchmarkspecsut">sut</a></b></td> <td>object</td> @@ -146,6 +153,15 @@ Resource Types: <i>Default</i>: <br/> </td> <td>false</td> + </tr><tr> + <td><b>waitForResourcesEnabled</b></td> + <td>boolean</td> + <td> + If true, Theodolite waits to create the resource for the SUT until the infrastructure resources are ready, and analogously, Theodolite waits to create the load-gen resource until the resources of the SUT are ready.<br/> + <br/> + <i>Default</i>: false<br/> + </td> + <td>false</td> </tr></tbody> </table> @@ -214,17 +230,87 @@ The loadGenResourceSets specifies all Kubernetes resources required to start the </tr> </thead> <tbody><tr> - <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexexec">exec</a></b></td> + <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexdelete">delete</a></b></td> <td>object</td> <td> - Specifies command to be executed.<br/> + Specifies deletion of a resource.<br/> </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexselector">selector</a></b></td> + <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexexec">exec</a></b></td> <td>object</td> <td> - The selector specifies which resource should be selected for the execution of the command.<br/> + Specifies a command that gets executed within a Container of a Pod<br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + +### benchmark.spec.loadGenerator.afterActions[index].delete +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorafteractionsindex)</sup></sup> + + + +Specifies deletion of a resource. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexdeleteselector">selector</a></b></td> + <td>object</td> + <td> + Defines how to select the resource to delete.<br/> + </td> + <td>true</td> + </tr></tbody> +</table> + + +### benchmark.spec.loadGenerator.afterActions[index].delete.selector +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorafteractionsindexdelete)</sup></sup> + + + +Defines how to select the resource to delete. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b>apiVersion</b></td> + <td>string</td> + <td> + Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>kind</b></td> + <td>string</td> + <td> + Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>nameRegex</b></td> + <td>string</td> + <td> + Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted.<br/> + <br/> + <i>Default</i>: *<br/> </td> <td>false</td> </tr></tbody> @@ -236,7 +322,7 @@ The loadGenResourceSets specifies all Kubernetes resources required to start the -Specifies command to be executed. +Specifies a command that gets executed within a Container of a Pod <table> <thead> @@ -253,20 +339,27 @@ Specifies command to be executed. <td> The command to be executed as string array.<br/> </td> - <td>false</td> + <td>true</td> + </tr><tr> + <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexexecselector">selector</a></b></td> + <td>object</td> + <td> + The selector specifies which resource should be selected for the execution of the command.<br/> + </td> + <td>true</td> </tr><tr> <td><b>timeoutSeconds</b></td> <td>integer</td> <td> Specifies the timeout (in seconds) for the specified command.<br/> </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> -### benchmark.spec.loadGenerator.afterActions[index].selector -<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorafteractionsindex)</sup></sup> +### benchmark.spec.loadGenerator.afterActions[index].exec.selector +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorafteractionsindexexec)</sup></sup> @@ -291,7 +384,7 @@ The selector specifies which resource should be selected for the execution of th </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexselectorpod">pod</a></b></td> + <td><b><a href="#benchmarkspecloadgeneratorafteractionsindexexecselectorpod">pod</a></b></td> <td>object</td> <td> Specifies the pod.<br/> @@ -301,8 +394,8 @@ The selector specifies which resource should be selected for the execution of th </table> -### benchmark.spec.loadGenerator.afterActions[index].selector.pod -<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorafteractionsindexselector)</sup></sup> +### benchmark.spec.loadGenerator.afterActions[index].exec.selector.pod +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorafteractionsindexexecselector)</sup></sup> @@ -347,17 +440,87 @@ Specifies the pod. </tr> </thead> <tbody><tr> - <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexexec">exec</a></b></td> + <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexdelete">delete</a></b></td> <td>object</td> <td> - Specifies command to be executed.<br/> + Specifies deletion of a resource.<br/> </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexselector">selector</a></b></td> + <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexexec">exec</a></b></td> <td>object</td> <td> - The selector specifies which resource should be selected for the execution of the command.<br/> + Specifies a command that gets executed within a Container of a Pod<br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + +### benchmark.spec.loadGenerator.beforeActions[index].delete +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorbeforeactionsindex)</sup></sup> + + + +Specifies deletion of a resource. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexdeleteselector">selector</a></b></td> + <td>object</td> + <td> + Defines how to select the resource to delete.<br/> + </td> + <td>true</td> + </tr></tbody> +</table> + + +### benchmark.spec.loadGenerator.beforeActions[index].delete.selector +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorbeforeactionsindexdelete)</sup></sup> + + + +Defines how to select the resource to delete. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b>apiVersion</b></td> + <td>string</td> + <td> + Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>kind</b></td> + <td>string</td> + <td> + Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>nameRegex</b></td> + <td>string</td> + <td> + Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted.<br/> + <br/> + <i>Default</i>: *<br/> </td> <td>false</td> </tr></tbody> @@ -369,7 +532,7 @@ Specifies the pod. -Specifies command to be executed. +Specifies a command that gets executed within a Container of a Pod <table> <thead> @@ -386,20 +549,27 @@ Specifies command to be executed. <td> The command to be executed as string array.<br/> </td> - <td>false</td> + <td>true</td> + </tr><tr> + <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexexecselector">selector</a></b></td> + <td>object</td> + <td> + The selector specifies which resource should be selected for the execution of the command.<br/> + </td> + <td>true</td> </tr><tr> <td><b>timeoutSeconds</b></td> <td>integer</td> <td> Specifies the timeout (in seconds) for the specified command.<br/> </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> -### benchmark.spec.loadGenerator.beforeActions[index].selector -<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorbeforeactionsindex)</sup></sup> +### benchmark.spec.loadGenerator.beforeActions[index].exec.selector +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorbeforeactionsindexexec)</sup></sup> @@ -424,7 +594,7 @@ The selector specifies which resource should be selected for the execution of th </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexselectorpod">pod</a></b></td> + <td><b><a href="#benchmarkspecloadgeneratorbeforeactionsindexexecselectorpod">pod</a></b></td> <td>object</td> <td> Specifies the pod.<br/> @@ -434,8 +604,8 @@ The selector specifies which resource should be selected for the execution of th </table> -### benchmark.spec.loadGenerator.beforeActions[index].selector.pod -<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorbeforeactionsindexselector)</sup></sup> +### benchmark.spec.loadGenerator.beforeActions[index].exec.selector.pod +<sup><sup>[↩ Parent](#benchmarkspecloadgeneratorbeforeactionsindexexecselector)</sup></sup> @@ -727,6 +897,63 @@ The fileSystem resourceSet loads the Kubernetes manifests from the filesystem. </table> +### benchmark.spec.slos[index] +<sup><sup>[↩ Parent](#benchmarkspec)</sup></sup> + + + + + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b>name</b></td> + <td>string</td> + <td> + The name of the SLO.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>offset</b></td> + <td>integer</td> + <td> + Hours by which the start and end timestamp will be shifted (for different timezones).<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>prometheusUrl</b></td> + <td>string</td> + <td> + Connection string for Promehteus.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>sloType</b></td> + <td>string</td> + <td> + The type of the SLO. It must match 'lag trend'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>properties</b></td> + <td>map[string]string</td> + <td> + (Optional) SLO specific additional arguments.<br/> + <br/> + <i>Default</i>: map[]<br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + ### benchmark.spec.sut <sup><sup>[↩ Parent](#benchmarkspec)</sup></sup> @@ -747,7 +974,7 @@ The appResourceSets specifies all Kubernetes resources required to start the sut <td><b><a href="#benchmarkspecsutafteractionsindex">afterActions</a></b></td> <td>[]object</td> <td> - <br/> + SUT after actions are executed after the teardown of the SUT.<br/> <br/> <i>Default</i>: []<br/> </td> @@ -791,17 +1018,87 @@ The appResourceSets specifies all Kubernetes resources required to start the sut </tr> </thead> <tbody><tr> - <td><b><a href="#benchmarkspecsutafteractionsindexexec">exec</a></b></td> + <td><b><a href="#benchmarkspecsutafteractionsindexdelete">delete</a></b></td> <td>object</td> <td> - Specifies command to be executed.<br/> + Specifies deletion of a resource.<br/> </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecsutafteractionsindexselector">selector</a></b></td> + <td><b><a href="#benchmarkspecsutafteractionsindexexec">exec</a></b></td> <td>object</td> <td> - The selector specifies which resource should be selected for the execution of the command.<br/> + Specifies a command that gets executed within a Container of a Pod<br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + +### benchmark.spec.sut.afterActions[index].delete +<sup><sup>[↩ Parent](#benchmarkspecsutafteractionsindex)</sup></sup> + + + +Specifies deletion of a resource. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b><a href="#benchmarkspecsutafteractionsindexdeleteselector">selector</a></b></td> + <td>object</td> + <td> + Defines how to select the resource to delete.<br/> + </td> + <td>true</td> + </tr></tbody> +</table> + + +### benchmark.spec.sut.afterActions[index].delete.selector +<sup><sup>[↩ Parent](#benchmarkspecsutafteractionsindexdelete)</sup></sup> + + + +Defines how to select the resource to delete. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b>apiVersion</b></td> + <td>string</td> + <td> + Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>kind</b></td> + <td>string</td> + <td> + Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>nameRegex</b></td> + <td>string</td> + <td> + Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted.<br/> + <br/> + <i>Default</i>: *<br/> </td> <td>false</td> </tr></tbody> @@ -813,7 +1110,7 @@ The appResourceSets specifies all Kubernetes resources required to start the sut -Specifies command to be executed. +Specifies a command that gets executed within a Container of a Pod <table> <thead> @@ -830,20 +1127,27 @@ Specifies command to be executed. <td> The command to be executed as string array.<br/> </td> - <td>false</td> + <td>true</td> + </tr><tr> + <td><b><a href="#benchmarkspecsutafteractionsindexexecselector">selector</a></b></td> + <td>object</td> + <td> + The selector specifies which resource should be selected for the execution of the command.<br/> + </td> + <td>true</td> </tr><tr> <td><b>timeoutSeconds</b></td> <td>integer</td> <td> Specifies the timeout (in seconds) for the specified command.<br/> </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> -### benchmark.spec.sut.afterActions[index].selector -<sup><sup>[↩ Parent](#benchmarkspecsutafteractionsindex)</sup></sup> +### benchmark.spec.sut.afterActions[index].exec.selector +<sup><sup>[↩ Parent](#benchmarkspecsutafteractionsindexexec)</sup></sup> @@ -868,7 +1172,7 @@ The selector specifies which resource should be selected for the execution of th </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecsutafteractionsindexselectorpod">pod</a></b></td> + <td><b><a href="#benchmarkspecsutafteractionsindexexecselectorpod">pod</a></b></td> <td>object</td> <td> Specifies the pod.<br/> @@ -878,8 +1182,8 @@ The selector specifies which resource should be selected for the execution of th </table> -### benchmark.spec.sut.afterActions[index].selector.pod -<sup><sup>[↩ Parent](#benchmarkspecsutafteractionsindexselector)</sup></sup> +### benchmark.spec.sut.afterActions[index].exec.selector.pod +<sup><sup>[↩ Parent](#benchmarkspecsutafteractionsindexexecselector)</sup></sup> @@ -902,17 +1206,78 @@ Specifies the pod. <br/> <i>Default</i>: map[]<br/> </td> - <td>false</td> + <td>false</td> + </tr></tbody> +</table> + + +### benchmark.spec.sut.beforeActions[index] +<sup><sup>[↩ Parent](#benchmarkspecsut)</sup></sup> + + + + + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b><a href="#benchmarkspecsutbeforeactionsindexdelete">delete</a></b></td> + <td>object</td> + <td> + Specifies deletion of a resource.<br/> + </td> + <td>false</td> + </tr><tr> + <td><b><a href="#benchmarkspecsutbeforeactionsindexexec">exec</a></b></td> + <td>object</td> + <td> + Specifies a command that gets executed within a Container of a Pod<br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + +### benchmark.spec.sut.beforeActions[index].delete +<sup><sup>[↩ Parent](#benchmarkspecsutbeforeactionsindex)</sup></sup> + + + +Specifies deletion of a resource. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b><a href="#benchmarkspecsutbeforeactionsindexdeleteselector">selector</a></b></td> + <td>object</td> + <td> + Defines how to select the resource to delete.<br/> + </td> + <td>true</td> </tr></tbody> </table> -### benchmark.spec.sut.beforeActions[index] -<sup><sup>[↩ Parent](#benchmarkspecsut)</sup></sup> - +### benchmark.spec.sut.beforeActions[index].delete.selector +<sup><sup>[↩ Parent](#benchmarkspecsutbeforeactionsindexdelete)</sup></sup> +Defines how to select the resource to delete. <table> <thead> @@ -924,17 +1289,26 @@ Specifies the pod. </tr> </thead> <tbody><tr> - <td><b><a href="#benchmarkspecsutbeforeactionsindexexec">exec</a></b></td> - <td>object</td> + <td><b>apiVersion</b></td> + <td>string</td> <td> - Specifies command to be executed.<br/> + Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'.<br/> </td> - <td>false</td> + <td>true</td> </tr><tr> - <td><b><a href="#benchmarkspecsutbeforeactionsindexselector">selector</a></b></td> - <td>object</td> + <td><b>kind</b></td> + <td>string</td> <td> - The selector specifies which resource should be selected for the execution of the command.<br/> + Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>nameRegex</b></td> + <td>string</td> + <td> + Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted.<br/> + <br/> + <i>Default</i>: *<br/> </td> <td>false</td> </tr></tbody> @@ -946,7 +1320,7 @@ Specifies the pod. -Specifies command to be executed. +Specifies a command that gets executed within a Container of a Pod <table> <thead> @@ -963,20 +1337,27 @@ Specifies command to be executed. <td> The command to be executed as string array.<br/> </td> - <td>false</td> + <td>true</td> + </tr><tr> + <td><b><a href="#benchmarkspecsutbeforeactionsindexexecselector">selector</a></b></td> + <td>object</td> + <td> + The selector specifies which resource should be selected for the execution of the command.<br/> + </td> + <td>true</td> </tr><tr> <td><b>timeoutSeconds</b></td> <td>integer</td> <td> Specifies the timeout (in seconds) for the specified command.<br/> </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> -### benchmark.spec.sut.beforeActions[index].selector -<sup><sup>[↩ Parent](#benchmarkspecsutbeforeactionsindex)</sup></sup> +### benchmark.spec.sut.beforeActions[index].exec.selector +<sup><sup>[↩ Parent](#benchmarkspecsutbeforeactionsindexexec)</sup></sup> @@ -1001,7 +1382,7 @@ The selector specifies which resource should be selected for the execution of th </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecsutbeforeactionsindexselectorpod">pod</a></b></td> + <td><b><a href="#benchmarkspecsutbeforeactionsindexexecselectorpod">pod</a></b></td> <td>object</td> <td> Specifies the pod.<br/> @@ -1011,8 +1392,8 @@ The selector specifies which resource should be selected for the execution of th </table> -### benchmark.spec.sut.beforeActions[index].selector.pod -<sup><sup>[↩ Parent](#benchmarkspecsutbeforeactionsindexselector)</sup></sup> +### benchmark.spec.sut.beforeActions[index].exec.selector.pod +<sup><sup>[↩ Parent](#benchmarkspecsutbeforeactionsindexexecselector)</sup></sup> @@ -1206,17 +1587,87 @@ The fileSystem resourceSet loads the Kubernetes manifests from the filesystem. </tr> </thead> <tbody><tr> - <td><b><a href="#benchmarkspecinfrastructureafteractionsindexexec">exec</a></b></td> + <td><b><a href="#benchmarkspecinfrastructureafteractionsindexdelete">delete</a></b></td> <td>object</td> <td> - Specifies command to be executed.<br/> + Specifies deletion of a resource.<br/> </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecinfrastructureafteractionsindexselector">selector</a></b></td> + <td><b><a href="#benchmarkspecinfrastructureafteractionsindexexec">exec</a></b></td> <td>object</td> <td> - The selector specifies which resource should be selected for the execution of the command.<br/> + Specifies a command that gets executed within a Container of a Pod<br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + +### benchmark.spec.infrastructure.afterActions[index].delete +<sup><sup>[↩ Parent](#benchmarkspecinfrastructureafteractionsindex)</sup></sup> + + + +Specifies deletion of a resource. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b><a href="#benchmarkspecinfrastructureafteractionsindexdeleteselector">selector</a></b></td> + <td>object</td> + <td> + Defines how to select the resource to delete.<br/> + </td> + <td>true</td> + </tr></tbody> +</table> + + +### benchmark.spec.infrastructure.afterActions[index].delete.selector +<sup><sup>[↩ Parent](#benchmarkspecinfrastructureafteractionsindexdelete)</sup></sup> + + + +Defines how to select the resource to delete. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b>apiVersion</b></td> + <td>string</td> + <td> + Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>kind</b></td> + <td>string</td> + <td> + Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>nameRegex</b></td> + <td>string</td> + <td> + Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted.<br/> + <br/> + <i>Default</i>: *<br/> </td> <td>false</td> </tr></tbody> @@ -1228,7 +1679,7 @@ The fileSystem resourceSet loads the Kubernetes manifests from the filesystem. -Specifies command to be executed. +Specifies a command that gets executed within a Container of a Pod <table> <thead> @@ -1245,20 +1696,27 @@ Specifies command to be executed. <td> The command to be executed as string array.<br/> </td> - <td>false</td> + <td>true</td> + </tr><tr> + <td><b><a href="#benchmarkspecinfrastructureafteractionsindexexecselector">selector</a></b></td> + <td>object</td> + <td> + The selector specifies which resource should be selected for the execution of the command.<br/> + </td> + <td>true</td> </tr><tr> <td><b>timeoutSeconds</b></td> <td>integer</td> <td> Specifies the timeout (in seconds) for the specified command.<br/> </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> -### benchmark.spec.infrastructure.afterActions[index].selector -<sup><sup>[↩ Parent](#benchmarkspecinfrastructureafteractionsindex)</sup></sup> +### benchmark.spec.infrastructure.afterActions[index].exec.selector +<sup><sup>[↩ Parent](#benchmarkspecinfrastructureafteractionsindexexec)</sup></sup> @@ -1283,7 +1741,7 @@ The selector specifies which resource should be selected for the execution of th </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecinfrastructureafteractionsindexselectorpod">pod</a></b></td> + <td><b><a href="#benchmarkspecinfrastructureafteractionsindexexecselectorpod">pod</a></b></td> <td>object</td> <td> Specifies the pod.<br/> @@ -1293,8 +1751,8 @@ The selector specifies which resource should be selected for the execution of th </table> -### benchmark.spec.infrastructure.afterActions[index].selector.pod -<sup><sup>[↩ Parent](#benchmarkspecinfrastructureafteractionsindexselector)</sup></sup> +### benchmark.spec.infrastructure.afterActions[index].exec.selector.pod +<sup><sup>[↩ Parent](#benchmarkspecinfrastructureafteractionsindexexecselector)</sup></sup> @@ -1339,17 +1797,87 @@ Specifies the pod. </tr> </thead> <tbody><tr> - <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexexec">exec</a></b></td> + <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexdelete">delete</a></b></td> <td>object</td> <td> - Specifies command to be executed.<br/> + Specifies deletion of a resource.<br/> </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexselector">selector</a></b></td> + <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexexec">exec</a></b></td> <td>object</td> <td> - The selector specifies which resource should be selected for the execution of the command.<br/> + Specifies a command that gets executed within a Container of a Pod<br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + +### benchmark.spec.infrastructure.beforeActions[index].delete +<sup><sup>[↩ Parent](#benchmarkspecinfrastructurebeforeactionsindex)</sup></sup> + + + +Specifies deletion of a resource. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexdeleteselector">selector</a></b></td> + <td>object</td> + <td> + Defines how to select the resource to delete.<br/> + </td> + <td>true</td> + </tr></tbody> +</table> + + +### benchmark.spec.infrastructure.beforeActions[index].delete.selector +<sup><sup>[↩ Parent](#benchmarkspecinfrastructurebeforeactionsindexdelete)</sup></sup> + + + +Defines how to select the resource to delete. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b>apiVersion</b></td> + <td>string</td> + <td> + Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>kind</b></td> + <td>string</td> + <td> + Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'.<br/> + </td> + <td>true</td> + </tr><tr> + <td><b>nameRegex</b></td> + <td>string</td> + <td> + Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted.<br/> + <br/> + <i>Default</i>: *<br/> </td> <td>false</td> </tr></tbody> @@ -1361,7 +1889,7 @@ Specifies the pod. -Specifies command to be executed. +Specifies a command that gets executed within a Container of a Pod <table> <thead> @@ -1378,20 +1906,27 @@ Specifies command to be executed. <td> The command to be executed as string array.<br/> </td> - <td>false</td> + <td>true</td> + </tr><tr> + <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexexecselector">selector</a></b></td> + <td>object</td> + <td> + The selector specifies which resource should be selected for the execution of the command.<br/> + </td> + <td>true</td> </tr><tr> <td><b>timeoutSeconds</b></td> <td>integer</td> <td> Specifies the timeout (in seconds) for the specified command.<br/> </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> -### benchmark.spec.infrastructure.beforeActions[index].selector -<sup><sup>[↩ Parent](#benchmarkspecinfrastructurebeforeactionsindex)</sup></sup> +### benchmark.spec.infrastructure.beforeActions[index].exec.selector +<sup><sup>[↩ Parent](#benchmarkspecinfrastructurebeforeactionsindexexec)</sup></sup> @@ -1416,7 +1951,7 @@ The selector specifies which resource should be selected for the execution of th </td> <td>false</td> </tr><tr> - <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexselectorpod">pod</a></b></td> + <td><b><a href="#benchmarkspecinfrastructurebeforeactionsindexexecselectorpod">pod</a></b></td> <td>object</td> <td> Specifies the pod.<br/> @@ -1426,8 +1961,8 @@ The selector specifies which resource should be selected for the execution of th </table> -### benchmark.spec.infrastructure.beforeActions[index].selector.pod -<sup><sup>[↩ Parent](#benchmarkspecinfrastructurebeforeactionsindexselector)</sup></sup> +### benchmark.spec.infrastructure.beforeActions[index].exec.selector.pod +<sup><sup>[↩ Parent](#benchmarkspecinfrastructurebeforeactionsindexexecselector)</sup></sup> @@ -1765,7 +2300,7 @@ Contains the Kafka configuration. </td> <td>true</td> </tr><tr> - <td><b><a href="#executionspecload">load</a></b></td> + <td><b><a href="#executionspecloads">loads</a></b></td> <td>object</td> <td> Specifies the load values that are benchmarked.<br/> @@ -1778,13 +2313,6 @@ Contains the Kafka configuration. Specifies the scaling resource that is benchmarked.<br/> </td> <td>true</td> - </tr><tr> - <td><b><a href="#executionspecslosindex">slos</a></b></td> - <td>[]object</td> - <td> - List of resource values for the specified resource type.<br/> - </td> - <td>true</td> </tr><tr> <td><b>name</b></td> <td>string</td> @@ -1794,6 +2322,13 @@ Contains the Kafka configuration. <i>Default</i>: <br/> </td> <td>false</td> + </tr><tr> + <td><b><a href="#executionspecslosindex">slos</a></b></td> + <td>[]object</td> + <td> + List of SLOs with their properties, which differ from the benchmark definition.<br/> + </td> + <td>false</td> </tr></tbody> </table> @@ -1906,35 +2441,83 @@ Defines the overall parameter for the execution. <td><b>repetitions</b></td> <td>integer</td> <td> - Numper of repititions for each experiments.<br/> + Number of repititions for each experiment.<br/> </td> <td>true</td> </tr><tr> - <td><b>restrictions</b></td> - <td>[]string</td> + <td><b><a href="#executionspecexecutionstrategy">strategy</a></b></td> + <td>object</td> <td> - List of restriction strategys used to delimit the search space.<br/> + Defines the used strategy for the execution, either 'LinearSearch', 'BinarySearch' or 'InitialGuessSearch'.<br/> </td> <td>true</td> </tr><tr> - <td><b>strategy</b></td> + <td><b>loadGenerationDelay</b></td> + <td>integer</td> + <td> + Seconds to wait between the start of the SUT and the load generator.<br/> + </td> + <td>false</td> + </tr><tr> + <td><b>metric</b></td> + <td>string</td> + <td> + <br/> + </td> + <td>false</td> + </tr></tbody> +</table> + + +### execution.spec.execution.strategy +<sup><sup>[↩ Parent](#executionspecexecution)</sup></sup> + + + +Defines the used strategy for the execution, either 'LinearSearch', 'BinarySearch' or 'InitialGuessSearch'. + +<table> + <thead> + <tr> + <th>Name</th> + <th>Type</th> + <th>Description</th> + <th>Required</th> + </tr> + </thead> + <tbody><tr> + <td><b>name</b></td> <td>string</td> <td> - Defines the used strategy for the execution, either 'LinearSearch' or 'BinarySearch'<br/> + <br/> </td> <td>true</td> </tr><tr> - <td><b>loadGenerationDelay</b></td> - <td>integer</td> + <td><b>guessStrategy</b></td> + <td>string</td> <td> - Seconds to wait between the start of the SUT and the load generator.<br/> + <br/> + </td> + <td>false</td> + </tr><tr> + <td><b>restrictions</b></td> + <td>[]string</td> + <td> + List of restriction strategies used to delimit the search space.<br/> + </td> + <td>false</td> + </tr><tr> + <td><b>searchStrategy</b></td> + <td>string</td> + <td> + <br/> </td> <td>false</td> </tr></tbody> </table> -### execution.spec.load +### execution.spec.loads <sup><sup>[↩ Parent](#executionspec)</sup></sup> @@ -2019,24 +2602,10 @@ Specifies the scaling resource that is benchmarked. </tr> </thead> <tbody><tr> - <td><b>offset</b></td> - <td>integer</td> - <td> - Hours by which the start and end timestamp will be shifted (for different timezones).<br/> - </td> - <td>true</td> - </tr><tr> - <td><b>prometheusUrl</b></td> - <td>string</td> - <td> - Connection string for Promehteus.<br/> - </td> - <td>true</td> - </tr><tr> - <td><b>sloType</b></td> + <td><b>name</b></td> <td>string</td> <td> - The type of the SLO. It must match 'lag trend'.<br/> + The name of the SLO. It must match a SLO specified in the Benchmark.<br/> </td> <td>true</td> </tr><tr> @@ -2047,7 +2616,7 @@ Specifies the scaling resource that is benchmarked. <br/> <i>Default</i>: map[]<br/> </td> - <td>false</td> + <td>true</td> </tr></tbody> </table> diff --git a/docs/index.yaml b/docs/index.yaml index c6cf4f6dcbeaf4b4ede37bca925025db950a2a77..956bb83b19ebbae4cddc4da6f07a0d937cf3dc2d 100644 --- a/docs/index.yaml +++ b/docs/index.yaml @@ -1,41 +1,6 @@ apiVersion: v1 entries: theodolite: - - apiVersion: v2 - appVersion: 0.7.0 - created: "2022-05-11T13:49:02.457130925+02:00" - dependencies: - - condition: grafana.enabled - name: grafana - repository: https://grafana.github.io/helm-charts - version: 6.17.5 - - condition: kube-prometheus-stack.enabled - name: kube-prometheus-stack - repository: https://prometheus-community.github.io/helm-charts - version: 20.0.1 - - condition: cp-helm-charts.enabled - name: cp-helm-charts - repository: https://soerenhenning.github.io/cp-helm-charts - version: 0.6.0 - - condition: strimzi.enabled - name: strimzi-kafka-operator - repository: https://strimzi.io/charts/ - version: 0.28.0 - description: Theodolite is a framework for benchmarking the horizontal and vertical - scalability of cloud-native applications. - digest: af10134baa30bb07423f78240fe1c609381e1c616585883cf5d3aded2d86a2b1 - home: https://www.theodolite.rocks - maintainers: - - email: soeren.henning@email.uni-kiel.de - name: Sören Henning - url: https://www.se.informatik.uni-kiel.de/en/team/soeren-henning-m-sc - name: theodolite - sources: - - https://github.com/cau-se/theodolite - type: application - urls: - - https://github.com/cau-se/theodolite/releases/download/v0.7.0/theodolite-0.7.0%20copy.tgz - version: 0.7.0 - apiVersion: v2 appVersion: 0.7.0 created: "2022-05-11T13:49:02.491041789+02:00" diff --git a/docs/installation.md b/docs/installation.md index d1c7ac3d1dd68d244c556e1ade53b50330aec6ed..2b80920bb0d9adbde11be32b710afe436b98bb0e 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -102,4 +102,16 @@ kubectl delete crd prometheuses.monitoring.coreos.com kubectl delete crd prometheusrules.monitoring.coreos.com kubectl delete crd servicemonitors.monitoring.coreos.com kubectl delete crd thanosrulers.monitoring.coreos.com +# CRDs for Strimzi +kubectl delete crd kafkabridges.kafka.strimzi.io +kubectl delete crd kafkaconnectors.kafka.strimzi.io +kubectl delete crd kafkaconnects.kafka.strimzi.io +kubectl delete crd kafkamirrormaker2s.kafka.strimzi.io +kubectl delete crd kafkamirrormakers.kafka.strimzi.io +kubectl delete crd kafkarebalances.kafka.strimzi.io +kubectl delete crd kafkas.kafka.strimzi.io +kubectl delete crd kafkatopics.kafka.strimzi.io +kubectl delete crd kafkausers.kafka.strimzi.io +kubectl delete crd strimzipodsets.core.strimzi.io + ``` diff --git a/helm/templates/strimzi/entity-role-binding.yaml b/helm/templates/strimzi/entity-role-binding.yaml new file mode 100644 index 0000000000000000000000000000000000000000..adb5394f866e0e8d61f1549e884461a529b655d1 --- /dev/null +++ b/helm/templates/strimzi/entity-role-binding.yaml @@ -0,0 +1,18 @@ +{{- if not (index .Values "strimzi-kafka-operator" "createGlobalResources") -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app: strimzi + name: strimzi-cluster-operator-entity-operator-delegation-namespaced + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: strimzi-entity-operator-namespaced +subjects: +- kind: ServiceAccount + name: strimzi-cluster-operator + namespace: {{ .Release.Namespace }} +{{- end }} + diff --git a/helm/templates/strimzi/entity-role.yaml b/helm/templates/strimzi/entity-role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9a2230a9336151a444738c3cd069bbe961c2825b --- /dev/null +++ b/helm/templates/strimzi/entity-role.yaml @@ -0,0 +1,46 @@ +{{- if not (index .Values "strimzi-kafka-operator" "createGlobalResources") -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: strimzi-entity-operator-namespaced + labels: + app: {{ template "theodolite.name" . }}-strimzi +rules: +- apiGroups: + - "kafka.strimzi.io" + resources: + # The entity operator runs the KafkaTopic assembly operator, which needs to access and manage KafkaTopic resources + - kafkatopics + - kafkatopics/status + # The entity operator runs the KafkaUser assembly operator, which needs to access and manage KafkaUser resources + - kafkausers + - kafkausers/status + verbs: + - get + - list + - watch + - create + - patch + - update + - delete +- apiGroups: + - "" + resources: + - events + verbs: + # The entity operator needs to be able to create events + - create +- apiGroups: + - "" + resources: + # The entity operator user-operator needs to access and manage secrets to store generated credentials + - secrets + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +{{- end }} diff --git a/helm/templates/strimzi/operator-role-binding.yaml b/helm/templates/strimzi/operator-role-binding.yaml new file mode 100644 index 0000000000000000000000000000000000000000..82b48bd0fa7d1535c08b0e5c005088dc65df6999 --- /dev/null +++ b/helm/templates/strimzi/operator-role-binding.yaml @@ -0,0 +1,18 @@ +{{- if not (index .Values "strimzi-kafka-operator" "createGlobalResources") -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app: strimzi + name: strimzi-cluster-operator-namespaced + namespace: {{ .Release.Namespace }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: strimzi-cluster-operator-namespaced +subjects: +- kind: ServiceAccount + name: strimzi-cluster-operator + namespace: {{ .Release.Namespace }} +{{- end }} + diff --git a/helm/templates/strimzi/operator-role.yaml b/helm/templates/strimzi/operator-role.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d5098ffc3af43d55208ddfc5e10535e73d22ac06 --- /dev/null +++ b/helm/templates/strimzi/operator-role.yaml @@ -0,0 +1,213 @@ +{{- if not (index .Values "strimzi-kafka-operator" "createGlobalResources") -}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: strimzi-cluster-operator-namespaced + labels: + app: strimzi-cluster-operator-namespaced +rules: +- apiGroups: + - "rbac.authorization.k8s.io" + resources: + # The cluster operator needs to access and manage rolebindings to grant Strimzi components cluster permissions + - rolebindings + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - "rbac.authorization.k8s.io" + resources: + # The cluster operator needs to access and manage roles to grant the entity operator permissions + - roles + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - "" + resources: + # The cluster operator needs to access and delete pods, this is to allow it to monitor pod health and coordinate rolling updates + - pods + # The cluster operator needs to access and manage service accounts to grant Strimzi components cluster permissions + - serviceaccounts + # The cluster operator needs to access and manage config maps for Strimzi components configuration + - configmaps + # The cluster operator needs to access and manage services and endpoints to expose Strimzi components to network traffic + - services + - endpoints + # The cluster operator needs to access and manage secrets to handle credentials + - secrets + # The cluster operator needs to access and manage persistent volume claims to bind them to Strimzi components for persistent data + - persistentvolumeclaims + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - "kafka.strimzi.io" + resources: + # The cluster operator runs the KafkaAssemblyOperator, which needs to access and manage Kafka resources + - kafkas + - kafkas/status + # The cluster operator runs the KafkaConnectAssemblyOperator, which needs to access and manage KafkaConnect resources + - kafkaconnects + - kafkaconnects/status + # The cluster operator runs the KafkaConnectorAssemblyOperator, which needs to access and manage KafkaConnector resources + - kafkaconnectors + - kafkaconnectors/status + # The cluster operator runs the KafkaMirrorMakerAssemblyOperator, which needs to access and manage KafkaMirrorMaker resources + - kafkamirrormakers + - kafkamirrormakers/status + # The cluster operator runs the KafkaBridgeAssemblyOperator, which needs to access and manage BridgeMaker resources + - kafkabridges + - kafkabridges/status + # The cluster operator runs the KafkaMirrorMaker2AssemblyOperator, which needs to access and manage KafkaMirrorMaker2 resources + - kafkamirrormaker2s + - kafkamirrormaker2s/status + # The cluster operator runs the KafkaRebalanceAssemblyOperator, which needs to access and manage KafkaRebalance resources + - kafkarebalances + - kafkarebalances/status + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - "core.strimzi.io" + resources: + # The cluster operator uses StrimziPodSets to manage the Kafka and ZooKeeper pods + - strimzipodsets + - strimzipodsets/status + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + # The cluster operator needs the extensions api as the operator supports Kubernetes version 1.11+ + # apps/v1 was introduced in Kubernetes 1.14 + - "extensions" + resources: + # The cluster operator needs to access and manage deployments to run deployment based Strimzi components + - deployments + - deployments/scale + # The cluster operator needs to access replica sets to manage Strimzi components and to determine error states + - replicasets + # The cluster operator needs to access and manage replication controllers to manage replicasets + - replicationcontrollers + # The cluster operator needs to access and manage network policies to lock down communication between Strimzi components + - networkpolicies + # The cluster operator needs to access and manage ingresses which allow external access to the services in a cluster + - ingresses + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - "apps" + resources: + # The cluster operator needs to access and manage deployments to run deployment based Strimzi components + - deployments + - deployments/scale + - deployments/status + # The cluster operator needs to access and manage stateful sets to run stateful sets based Strimzi components + - statefulsets + # The cluster operator needs to access replica-sets to manage Strimzi components and to determine error states + - replicasets + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - "" + resources: + # The cluster operator needs to be able to create events and delegate permissions to do so + - events + verbs: + - create +- apiGroups: + # Kafka Connect Build on OpenShift requirement + - build.openshift.io + resources: + - buildconfigs + - buildconfigs/instantiate + - builds + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - networking.k8s.io + resources: + # The cluster operator needs to access and manage network policies to lock down communication between Strimzi components + - networkpolicies + # The cluster operator needs to access and manage ingresses which allow external access to the services in a cluster + - ingresses + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - route.openshift.io + resources: + # The cluster operator needs to access and manage routes to expose Strimzi components for external access + - routes + - routes/custom-host + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +- apiGroups: + - policy + resources: + # The cluster operator needs to access and manage pod disruption budgets this limits the number of concurrent disruptions + # that a Strimzi component experiences, allowing for higher availability + - poddisruptionbudgets + verbs: + - get + - list + - watch + - create + - delete + - patch + - update +{{- end }} diff --git a/helm/templates/tests/test-connection.yaml b/helm/templates/tests/test-prometheus-connection.yaml similarity index 73% rename from helm/templates/tests/test-connection.yaml rename to helm/templates/tests/test-prometheus-connection.yaml index 7af87e98920c11bcfaccb27724e6f29fc76771a0..313a0825adf5d654642c6e1d8ff6beb4ee59df97 100644 --- a/helm/templates/tests/test-connection.yaml +++ b/helm/templates/tests/test-prometheus-connection.yaml @@ -1,3 +1,4 @@ +{{- if .Values.prometheus.enabled }} apiVersion: v1 kind: Pod metadata: @@ -5,7 +6,8 @@ metadata: labels: {{- include "theodolite.labels" . | nindent 4 }} annotations: - "helm.sh/hook": test-success + "helm.sh/hook": test + "helm.sh/hook-delete-policy": hook-succeeded spec: containers: - name: wget @@ -13,3 +15,4 @@ spec: command: ['wget'] args: ['http://prometheus-operated:9090'] restartPolicy: Never +{{- end }} diff --git a/helm/values.yaml b/helm/values.yaml index 34a32ce60927a751f645b7f8ff4af46793865797..eb4cfc4b29fee97ab2be88a3ce2ded766a122b20 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -159,7 +159,7 @@ cp-helm-charts: pollIntervalSeconds: 15 strimzi-kafka-operator: - createGlobalResources: true + createGlobalResources: false # Might disable some of Strimzi's features strimzi: enabled: true diff --git a/slo-checker/generic/app/main.py b/slo-checker/generic/app/main.py index f36c8739da00128ad94feb1f2d7871df7e2ff137..e483c26b4f421d00e093ad70ff8d12d0a9bb9e62 100644 --- a/slo-checker/generic/app/main.py +++ b/slo-checker/generic/app/main.py @@ -37,7 +37,7 @@ def aggr_query(values: dict, warmup: int, aggr_func): df = pd.DataFrame.from_dict(values) df.columns = ['timestamp', 'value'] filtered = df[df['timestamp'] >= (df['timestamp'][0] + warmup)] - filtered['value'] = filtered['value'].astype(int) + filtered['value'] = filtered['value'].astype(float).astype(int) return filtered['value'].aggregate(aggr_func) def check_result(result, operator: str, threshold): diff --git a/slo-checker/generic/resources/test-1-rep-success.json b/slo-checker/generic/resources/test-1-rep-success.json index b70f461cf620d8eee8c4d9d93feb46db7498626f..9a6db686ec632f72f0d1981657826a8443b4c348 100644 --- a/slo-checker/generic/resources/test-1-rep-success.json +++ b/slo-checker/generic/resources/test-1-rep-success.json @@ -260,7 +260,7 @@ ], [ 1.634624989695E9, - "1854284" + "3970.0000000000005" ] ] } diff --git a/theodolite-benchmarks/beam-commons/build.gradle b/theodolite-benchmarks/beam-commons/build.gradle index 64ac2bb51ae1e6d741749a81e5c6c9e296d14d68..34a98212cdca9b347027c8e1c915044d55514b9c 100644 --- a/theodolite-benchmarks/beam-commons/build.gradle +++ b/theodolite-benchmarks/beam-commons/build.gradle @@ -13,8 +13,7 @@ repositories { } dependencies { - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') implementation group: 'org.apache.beam', name: 'beam-sdks-java-core', version: '2.35.0' implementation('org.apache.beam:beam-sdks-java-io-kafka:2.35.0'){ diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/BeamService.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/BeamService.java index 0165fa644e1853353e73caeaf0b9d2df0f8e9aea..4897f4171f96dea72d1c5c002c5f817a5f3e2ba2 100644 --- a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/BeamService.java +++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/BeamService.java @@ -10,7 +10,7 @@ import org.apache.beam.sdk.options.PipelineOptionsFactory; import org.apache.commons.configuration2.Configuration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import titan.ccp.common.configuration.ServiceConfigurations; +import rocks.theodolite.benchmarks.commons.commons.configuration.ServiceConfigurations; /** * A general Apache Beam-based microservice. It is configured by Beam pipeline, a Beam runner and diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/ActivePowerRecordDeserializer.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/ActivePowerRecordDeserializer.java index 0c8d3a4a847cf9422c4e364a31024fb3d0c3f87a..8ab579d0cb2be846c715d5f16430371eb5952d2d 100644 --- a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/ActivePowerRecordDeserializer.java +++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/ActivePowerRecordDeserializer.java @@ -2,7 +2,8 @@ package rocks.theodolite.benchmarks.commons.beam.kafka; import io.confluent.kafka.streams.serdes.avro.SpecificAvroDeserializer; import org.apache.kafka.common.serialization.Deserializer; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; + /** * A Kafka {@link Deserializer} for typed Schema Registry {@link ActivePowerRecord}. diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/EventTimePolicy.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/EventTimePolicy.java index 62e56341518839b96ad059e1c496ea1babb4674d..a63b5f4939566134a0aeec765fe084ea5bcc41ff 100644 --- a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/EventTimePolicy.java +++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/EventTimePolicy.java @@ -5,7 +5,7 @@ import org.apache.beam.sdk.io.kafka.KafkaRecord; import org.apache.beam.sdk.io.kafka.TimestampPolicy; import org.apache.beam.sdk.transforms.windowing.BoundedWindow; import org.joda.time.Instant; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * TimeStampPolicy to use event time based on the timestamp of the record value. diff --git a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaActivePowerTimestampReader.java b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaActivePowerTimestampReader.java index e22d5c8eedcd545364511a1461208f30bcb0a75c..31cd3e6be851bc0f0711cc17a591df6620951dc7 100644 --- a/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaActivePowerTimestampReader.java +++ b/theodolite-benchmarks/beam-commons/src/main/java/rocks/theodolite/benchmarks/commons/beam/kafka/KafkaActivePowerTimestampReader.java @@ -8,7 +8,7 @@ import org.apache.beam.sdk.values.KV; import org.apache.beam.sdk.values.PBegin; import org.apache.beam.sdk.values.PCollection; import org.apache.kafka.common.serialization.StringDeserializer; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Simple {@link PTransform} that reads from Kafka using {@link KafkaIO} with event time. diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle index 5849bd93221794d135f1c6cb3bcb62d2174724b5..7783baaa215a12bba79f26e70d8ac8073252a780 100644 --- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle +++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.beam.gradle @@ -22,8 +22,7 @@ def apacheBeamVersion = '2.35.0' dependencies { // These dependencies are used internally, and not exposed to consumers on their own compile classpath. - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') implementation 'com.google.guava:guava:24.1-jre' implementation 'org.slf4j:slf4j-simple:1.7.25' implementation project(':beam-commons') diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle index 7671e602211b6d9e923a3b2a4c87f40fff84c6ec..5665de9d8ea42b88ef915189234ead634c66215c 100644 --- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle +++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.flink.gradle @@ -35,9 +35,7 @@ repositories { } dependencies { - // Special version required because of https://issues.apache.org/jira/browse/FLINK-13703 - implementation('org.industrial-devops:titan-ccp-common:0.1.0-flink-ready-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') implementation 'org.apache.kafka:kafka-clients:2.2.0' implementation 'com.google.guava:guava:30.1-jre' diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.hazelcastjet.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.hazelcastjet.gradle index b092c97cf0e79895d4d6aafc594979b8f48dd167..0bade8fddc045f19b13074966d29996e26a72e77 100644 --- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.hazelcastjet.gradle +++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.hazelcastjet.gradle @@ -17,13 +17,12 @@ repositories { } dependencies { - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') + implementation 'com.google.guava:guava:24.1-jre' implementation 'org.slf4j:slf4j-api:1.7.30' implementation 'org.slf4j:slf4j-simple:1.7.30' - implementation 'io.confluent:kafka-avro-serializer:5.3.0' implementation 'com.hazelcast.jet:hazelcast-jet:4.5' diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle index bf533915a8fdf4a712754857702373264a30f80a..f43b9bafe3b8135cb4606f109648fc1acb4fe024 100644 --- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle +++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.kstreams.gradle @@ -20,8 +20,7 @@ repositories { dependencies { // These dependencies are used internally, and not exposed to consumers on their own compile classpath. - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') implementation 'org.apache.kafka:kafka-streams:3.1.0' implementation 'com.google.guava:guava:24.1-jre' implementation 'org.slf4j:slf4j-simple:1.7.25' diff --git a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.load-generator.gradle b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.load-generator.gradle index fb4fd89d1fe8a6d625a3ba7b459e9b0961befdbc..b4927d53d0ed976a0f0dcecd6d096e3d6c7d9273 100644 --- a/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.load-generator.gradle +++ b/theodolite-benchmarks/buildSrc/src/main/groovy/theodolite.load-generator.gradle @@ -20,8 +20,7 @@ repositories { dependencies { // These dependencies are used internally, and not exposed to consumers on their own compile classpath. - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') implementation 'org.slf4j:slf4j-simple:1.7.25' // These dependencies are used for the workload-generator-commmon diff --git a/theodolite-benchmarks/commons/.settings/org.eclipse.jdt.ui.prefs b/theodolite-benchmarks/commons/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000000000000000000000000000000000..b2a15f439cf1844efe56f1ac0d82a2884e66cb9d --- /dev/null +++ b/theodolite-benchmarks/commons/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,286 @@ +cleanup.add_all=false +cleanup.add_default_serial_version_id=true +cleanup.add_generated_serial_version_id=false +cleanup.add_missing_annotations=true +cleanup.add_missing_deprecated_annotations=true +cleanup.add_missing_methods=false +cleanup.add_missing_nls_tags=false +cleanup.add_missing_override_annotations=true +cleanup.add_missing_override_annotations_interface_methods=true +cleanup.add_serial_version_id=false +cleanup.always_use_blocks=true +cleanup.always_use_parentheses_in_expressions=false +cleanup.always_use_this_for_non_static_field_access=true +cleanup.always_use_this_for_non_static_method_access=true +cleanup.array_with_curly=false +cleanup.arrays_fill=false +cleanup.bitwise_conditional_expression=false +cleanup.boolean_literal=false +cleanup.boolean_value_rather_than_comparison=true +cleanup.break_loop=false +cleanup.collection_cloning=false +cleanup.comparing_on_criteria=false +cleanup.comparison_statement=false +cleanup.controlflow_merge=false +cleanup.convert_functional_interfaces=false +cleanup.convert_to_enhanced_for_loop=true +cleanup.convert_to_enhanced_for_loop_if_loop_var_used=true +cleanup.convert_to_switch_expressions=false +cleanup.correct_indentation=true +cleanup.do_while_rather_than_while=true +cleanup.double_negation=false +cleanup.else_if=false +cleanup.embedded_if=false +cleanup.evaluate_nullable=false +cleanup.extract_increment=false +cleanup.format_source_code=true +cleanup.format_source_code_changes_only=false +cleanup.hash=false +cleanup.if_condition=false +cleanup.insert_inferred_type_arguments=false +cleanup.instanceof=false +cleanup.instanceof_keyword=false +cleanup.invert_equals=false +cleanup.join=false +cleanup.lazy_logical_operator=false +cleanup.make_local_variable_final=true +cleanup.make_parameters_final=true +cleanup.make_private_fields_final=true +cleanup.make_type_abstract_if_missing_method=false +cleanup.make_variable_declarations_final=true +cleanup.map_cloning=false +cleanup.merge_conditional_blocks=false +cleanup.multi_catch=false +cleanup.never_use_blocks=false +cleanup.never_use_parentheses_in_expressions=true +cleanup.no_string_creation=false +cleanup.no_super=false +cleanup.number_suffix=false +cleanup.objects_equals=false +cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=true +cleanup.operand_factorization=false +cleanup.organize_imports=true +cleanup.overridden_assignment=false +cleanup.plain_replacement=false +cleanup.precompile_regex=false +cleanup.primitive_comparison=false +cleanup.primitive_parsing=false +cleanup.primitive_rather_than_wrapper=true +cleanup.primitive_serialization=false +cleanup.pull_out_if_from_if_else=false +cleanup.pull_up_assignment=false +cleanup.push_down_negation=false +cleanup.qualify_static_field_accesses_with_declaring_class=false +cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +cleanup.qualify_static_member_accesses_with_declaring_class=true +cleanup.qualify_static_method_accesses_with_declaring_class=false +cleanup.reduce_indentation=false +cleanup.redundant_comparator=false +cleanup.redundant_falling_through_block_end=false +cleanup.remove_private_constructors=true +cleanup.remove_redundant_modifiers=false +cleanup.remove_redundant_semicolons=true +cleanup.remove_redundant_type_arguments=true +cleanup.remove_trailing_whitespaces=true +cleanup.remove_trailing_whitespaces_all=true +cleanup.remove_trailing_whitespaces_ignore_empty=false +cleanup.remove_unnecessary_array_creation=false +cleanup.remove_unnecessary_casts=true +cleanup.remove_unnecessary_nls_tags=true +cleanup.remove_unused_imports=true +cleanup.remove_unused_local_variables=false +cleanup.remove_unused_private_fields=true +cleanup.remove_unused_private_members=false +cleanup.remove_unused_private_methods=true +cleanup.remove_unused_private_types=true +cleanup.return_expression=false +cleanup.simplify_lambda_expression_and_method_ref=false +cleanup.single_used_field=false +cleanup.sort_members=false +cleanup.sort_members_all=false +cleanup.standard_comparison=false +cleanup.static_inner_class=false +cleanup.strictly_equal_or_different=false +cleanup.stringbuffer_to_stringbuilder=false +cleanup.stringbuilder=false +cleanup.stringbuilder_for_local_vars=true +cleanup.stringconcat_to_textblock=false +cleanup.substring=false +cleanup.switch=false +cleanup.system_property=false +cleanup.system_property_boolean=false +cleanup.system_property_file_encoding=false +cleanup.system_property_file_separator=false +cleanup.system_property_line_separator=false +cleanup.system_property_path_separator=false +cleanup.ternary_operator=false +cleanup.try_with_resource=false +cleanup.unlooped_while=false +cleanup.unreachable_block=false +cleanup.use_anonymous_class_creation=false +cleanup.use_autoboxing=false +cleanup.use_blocks=true +cleanup.use_blocks_only_for_return_and_throw=false +cleanup.use_directly_map_method=false +cleanup.use_lambda=true +cleanup.use_parentheses_in_expressions=true +cleanup.use_string_is_blank=false +cleanup.use_this_for_non_static_field_access=true +cleanup.use_this_for_non_static_field_access_only_if_necessary=false +cleanup.use_this_for_non_static_method_access=true +cleanup.use_this_for_non_static_method_access_only_if_necessary=false +cleanup.use_unboxing=false +cleanup.use_var=false +cleanup.useless_continue=false +cleanup.useless_return=false +cleanup.valueof_rather_than_instantiation=false +cleanup_profile=_CAU-SE-Style +cleanup_settings_version=2 +eclipse.preferences.version=1 +editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true +formatter_profile=_CAU-SE-Style +formatter_settings_version=21 +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder= +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates= +sp_cleanup.add_all=false +sp_cleanup.add_default_serial_version_id=true +sp_cleanup.add_generated_serial_version_id=false +sp_cleanup.add_missing_annotations=true +sp_cleanup.add_missing_deprecated_annotations=true +sp_cleanup.add_missing_methods=false +sp_cleanup.add_missing_nls_tags=false +sp_cleanup.add_missing_override_annotations=true +sp_cleanup.add_missing_override_annotations_interface_methods=true +sp_cleanup.add_serial_version_id=false +sp_cleanup.always_use_blocks=true +sp_cleanup.always_use_parentheses_in_expressions=false +sp_cleanup.always_use_this_for_non_static_field_access=true +sp_cleanup.always_use_this_for_non_static_method_access=true +sp_cleanup.array_with_curly=false +sp_cleanup.arrays_fill=false +sp_cleanup.bitwise_conditional_expression=false +sp_cleanup.boolean_literal=false +sp_cleanup.boolean_value_rather_than_comparison=false +sp_cleanup.break_loop=false +sp_cleanup.collection_cloning=false +sp_cleanup.comparing_on_criteria=true +sp_cleanup.comparison_statement=false +sp_cleanup.controlflow_merge=false +sp_cleanup.convert_functional_interfaces=false +sp_cleanup.convert_to_enhanced_for_loop=true +sp_cleanup.convert_to_enhanced_for_loop_if_loop_var_used=false +sp_cleanup.convert_to_switch_expressions=false +sp_cleanup.correct_indentation=true +sp_cleanup.do_while_rather_than_while=false +sp_cleanup.double_negation=false +sp_cleanup.else_if=false +sp_cleanup.embedded_if=false +sp_cleanup.evaluate_nullable=false +sp_cleanup.extract_increment=false +sp_cleanup.format_source_code=true +sp_cleanup.format_source_code_changes_only=false +sp_cleanup.hash=false +sp_cleanup.if_condition=false +sp_cleanup.insert_inferred_type_arguments=false +sp_cleanup.instanceof=false +sp_cleanup.instanceof_keyword=false +sp_cleanup.invert_equals=false +sp_cleanup.join=false +sp_cleanup.lazy_logical_operator=false +sp_cleanup.make_local_variable_final=true +sp_cleanup.make_parameters_final=true +sp_cleanup.make_private_fields_final=true +sp_cleanup.make_type_abstract_if_missing_method=false +sp_cleanup.make_variable_declarations_final=true +sp_cleanup.map_cloning=false +sp_cleanup.merge_conditional_blocks=false +sp_cleanup.multi_catch=false +sp_cleanup.never_use_blocks=false +sp_cleanup.never_use_parentheses_in_expressions=true +sp_cleanup.no_string_creation=false +sp_cleanup.no_super=false +sp_cleanup.number_suffix=false +sp_cleanup.objects_equals=false +sp_cleanup.on_save_use_additional_actions=true +sp_cleanup.one_if_rather_than_duplicate_blocks_that_fall_through=false +sp_cleanup.operand_factorization=false +sp_cleanup.organize_imports=true +sp_cleanup.overridden_assignment=false +sp_cleanup.plain_replacement=false +sp_cleanup.precompile_regex=false +sp_cleanup.primitive_comparison=false +sp_cleanup.primitive_parsing=false +sp_cleanup.primitive_rather_than_wrapper=false +sp_cleanup.primitive_serialization=false +sp_cleanup.pull_out_if_from_if_else=false +sp_cleanup.pull_up_assignment=false +sp_cleanup.push_down_negation=false +sp_cleanup.qualify_static_field_accesses_with_declaring_class=false +sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true +sp_cleanup.qualify_static_member_accesses_with_declaring_class=true +sp_cleanup.qualify_static_method_accesses_with_declaring_class=false +sp_cleanup.reduce_indentation=false +sp_cleanup.redundant_comparator=false +sp_cleanup.redundant_falling_through_block_end=false +sp_cleanup.remove_private_constructors=true +sp_cleanup.remove_redundant_modifiers=false +sp_cleanup.remove_redundant_semicolons=false +sp_cleanup.remove_redundant_type_arguments=false +sp_cleanup.remove_trailing_whitespaces=true +sp_cleanup.remove_trailing_whitespaces_all=true +sp_cleanup.remove_trailing_whitespaces_ignore_empty=false +sp_cleanup.remove_unnecessary_array_creation=false +sp_cleanup.remove_unnecessary_casts=true +sp_cleanup.remove_unnecessary_nls_tags=true +sp_cleanup.remove_unused_imports=true +sp_cleanup.remove_unused_local_variables=false +sp_cleanup.remove_unused_private_fields=true +sp_cleanup.remove_unused_private_members=false +sp_cleanup.remove_unused_private_methods=true +sp_cleanup.remove_unused_private_types=true +sp_cleanup.return_expression=false +sp_cleanup.simplify_lambda_expression_and_method_ref=false +sp_cleanup.single_used_field=false +sp_cleanup.sort_members=false +sp_cleanup.sort_members_all=false +sp_cleanup.standard_comparison=false +sp_cleanup.static_inner_class=false +sp_cleanup.strictly_equal_or_different=false +sp_cleanup.stringbuffer_to_stringbuilder=false +sp_cleanup.stringbuilder=false +sp_cleanup.stringbuilder_for_local_vars=false +sp_cleanup.stringconcat_to_textblock=false +sp_cleanup.substring=false +sp_cleanup.switch=false +sp_cleanup.system_property=false +sp_cleanup.system_property_boolean=false +sp_cleanup.system_property_file_encoding=false +sp_cleanup.system_property_file_separator=false +sp_cleanup.system_property_line_separator=false +sp_cleanup.system_property_path_separator=false +sp_cleanup.ternary_operator=false +sp_cleanup.try_with_resource=false +sp_cleanup.unlooped_while=false +sp_cleanup.unreachable_block=false +sp_cleanup.use_anonymous_class_creation=false +sp_cleanup.use_autoboxing=false +sp_cleanup.use_blocks=true +sp_cleanup.use_blocks_only_for_return_and_throw=false +sp_cleanup.use_directly_map_method=false +sp_cleanup.use_lambda=true +sp_cleanup.use_parentheses_in_expressions=true +sp_cleanup.use_string_is_blank=false +sp_cleanup.use_this_for_non_static_field_access=true +sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=false +sp_cleanup.use_this_for_non_static_method_access=true +sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=false +sp_cleanup.use_unboxing=false +sp_cleanup.use_var=false +sp_cleanup.useless_continue=true +sp_cleanup.useless_return=true +sp_cleanup.valueof_rather_than_instantiation=false diff --git a/theodolite-benchmarks/commons/.settings/qa.eclipse.plugin.checkstyle.prefs b/theodolite-benchmarks/commons/.settings/qa.eclipse.plugin.checkstyle.prefs new file mode 100644 index 0000000000000000000000000000000000000000..4fa4266c755f4ff8da465ab7341cd70ffb24ecf7 --- /dev/null +++ b/theodolite-benchmarks/commons/.settings/qa.eclipse.plugin.checkstyle.prefs @@ -0,0 +1,4 @@ +configFilePath=../config/checkstyle.xml +customModulesJarPaths= +eclipse.preferences.version=1 +enabled=false diff --git a/theodolite-benchmarks/commons/.settings/qa.eclipse.plugin.pmd.prefs b/theodolite-benchmarks/commons/.settings/qa.eclipse.plugin.pmd.prefs new file mode 100644 index 0000000000000000000000000000000000000000..40bfd0ecdbbe324bb54e4b9f9f32ba95cf5b0c2a --- /dev/null +++ b/theodolite-benchmarks/commons/.settings/qa.eclipse.plugin.pmd.prefs @@ -0,0 +1,4 @@ +customRulesJars= +eclipse.preferences.version=1 +enabled=false +ruleSetFilePath=../config/pmd.xml diff --git a/theodolite-benchmarks/commons/build.gradle b/theodolite-benchmarks/commons/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..2b00b6619f813ec83031585b86e51a0f1a0e43ed --- /dev/null +++ b/theodolite-benchmarks/commons/build.gradle @@ -0,0 +1,93 @@ +plugins { + // common java conventions + id 'theodolite.java-commons' + // avro plugin + id "com.github.davidmc24.gradle.plugin.avro-base" version "1.3.0" +} + + + +repositories { + mavenCentral() + maven { + url "https://oss.sonatype.org/content/repositories/snapshots/" + } + maven { + url 'https://packages.confluent.io/maven/' + } +} + +dependencies { + // These dependencies is exported to consumers, that is to say found on their compile classpath. + api 'org.apache.commons:commons-configuration2:2.0' + api "org.apache.avro:avro:1.11.0" + api 'org.apache.kafka:kafka-streams:2.4.0' // needed in flink uc3 + + // These dependencies are used internally, and not exposed to consumers on their own compile classpath. + implementation 'commons-beanutils:commons-beanutils:1.9.2' // necessary for commons-configuration2 + implementation 'com.google.code.gson:gson:2.8.2' + implementation 'com.google.guava:guava:24.1-jre' + implementation 'org.slf4j:slf4j-api:1.7.25' + implementation 'org.apache.kafka:kafka-clients:2.4.0' + implementation ('io.confluent:kafka-streams-avro-serde:5.3.2') { + // Kafka client is already included from Kafka Streams in version 2.4.0 + exclude group: 'org.apache.kafka', module: 'kafka-clients' + } + + // Use JUnit test framework + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.3.1' + testImplementation 'com.github.stefanbirkner:system-rules:1.17.0' +} + + +// Local sources +sourceSets { + main { + java { + srcDir 'src/main/java' + srcDir 'src-gen/main/java' + } + } +} + + +// Local avro creation +avro { + fieldVisibility = "PRIVATE" + // Setters required for flink because of https://issues.apache.org/jira/browse/FLINK-13703 + createSetters = true +} + +task("generateAvroProtocol", type: com.github.davidmc24.gradle.plugin.avro.GenerateAvroProtocolTask) { + group 'Generate Sources' + source file("src/main/avro") + include("**/*.avdl") + outputDir = file("build/generated-avro-main-avpr") +} + +task("generateAvroSchema", type: com.github.davidmc24.gradle.plugin.avro.GenerateAvroSchemaTask) { + group 'Generate Sources' + dependsOn generateAvroProtocol + source file("src/main/avro") + source file("build/generated-avro-main-avpr") + include("**/*.avpr") + outputDir = file("src-gen/main/avro") +} + +task ("generateAvroJava", type: com.github.davidmc24.gradle.plugin.avro.GenerateAvroJavaTask) { + group 'Generate Sources' + dependsOn generateAvroSchema + source file("src-gen/main/avro") + outputDir = file("src-gen/main/java") +} + +tasks.withType(Checkstyle) { + source = fileTree('src/main/java') +} + +tasks.withType(Pmd) { + exclude '**/commons/src-gen/.*' +} + + + diff --git a/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/ActivePowerRecord.avsc b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/ActivePowerRecord.avsc new file mode 100644 index 0000000000000000000000000000000000000000..91f1168632267b6d69f1b22aed658897d95958b1 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/ActivePowerRecord.avsc @@ -0,0 +1,18 @@ +{ + "type" : "record", + "name" : "ActivePowerRecord", + "namespace" : "rocks.theodolite.benchmarks.commons.model.records", + "fields" : [ { + "name" : "identifier", + "type" : "string", + "doc" : "*" + }, { + "name" : "timestamp", + "type" : "long", + "doc" : "*" + }, { + "name" : "valueInW", + "type" : "double", + "doc" : "*" + } ] +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/AggregatedActivePowerRecord.avsc b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/AggregatedActivePowerRecord.avsc new file mode 100644 index 0000000000000000000000000000000000000000..336476e8417a5b7245eea1a1c6b2b454fcc11001 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/AggregatedActivePowerRecord.avsc @@ -0,0 +1,26 @@ +{ + "type" : "record", + "name" : "AggregatedActivePowerRecord", + "namespace" : "rocks.theodolite.benchmarks.commons.model.records", + "fields" : [ { + "name" : "identifier", + "type" : "string", + "doc" : "*" + }, { + "name" : "timestamp", + "type" : "long", + "doc" : "*" + }, { + "name" : "count", + "type" : "long", + "doc" : "*" + }, { + "name" : "sumInW", + "type" : "double", + "doc" : "*" + }, { + "name" : "averageInW", + "type" : "double", + "doc" : "*" + } ] +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/DayOfWeekActivePowerRecord.avsc b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/DayOfWeekActivePowerRecord.avsc new file mode 100644 index 0000000000000000000000000000000000000000..c029937dd0d17e0a14bb613a59dff6f72635f009 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/DayOfWeekActivePowerRecord.avsc @@ -0,0 +1,33 @@ +{ + "type" : "record", + "name" : "DayOfWeekActivePowerRecord", + "namespace" : "rocks.theodolite.benchmarks.commons.model.records", + "fields" : [ { + "name" : "identifier", + "type" : "string" + }, { + "name" : "dayOfWeek", + "type" : "int" + }, { + "name" : "periodStart", + "type" : "long" + }, { + "name" : "periodEnd", + "type" : "long" + }, { + "name" : "count", + "type" : "long" + }, { + "name" : "mean", + "type" : "double" + }, { + "name" : "populationVariance", + "type" : "double" + }, { + "name" : "min", + "type" : "double" + }, { + "name" : "max", + "type" : "double" + } ] +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/HourOfDayActivePowerRecord.avsc b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/HourOfDayActivePowerRecord.avsc new file mode 100644 index 0000000000000000000000000000000000000000..3ad6d6ade5d2f29718db04e066565a11f2db412d --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/HourOfDayActivePowerRecord.avsc @@ -0,0 +1,33 @@ +{ + "type" : "record", + "name" : "HourOfDayActivePowerRecord", + "namespace" : "rocks.theodolite.benchmarks.commons.model.records", + "fields" : [ { + "name" : "identifier", + "type" : "string" + }, { + "name" : "hourOfDay", + "type" : "int" + }, { + "name" : "periodStart", + "type" : "long" + }, { + "name" : "periodEnd", + "type" : "long" + }, { + "name" : "count", + "type" : "long" + }, { + "name" : "mean", + "type" : "double" + }, { + "name" : "populationVariance", + "type" : "double" + }, { + "name" : "min", + "type" : "double" + }, { + "name" : "max", + "type" : "double" + } ] +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/HourOfWeekActivePowerRecord.avsc b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/HourOfWeekActivePowerRecord.avsc new file mode 100644 index 0000000000000000000000000000000000000000..74739f5bd074ba330cee631c433ea4ab1c1fa8d9 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/HourOfWeekActivePowerRecord.avsc @@ -0,0 +1,36 @@ +{ + "type" : "record", + "name" : "HourOfWeekActivePowerRecord", + "namespace" : "rocks.theodolite.benchmarks.commons.model.records", + "fields" : [ { + "name" : "identifier", + "type" : "string" + }, { + "name" : "dayOfWeek", + "type" : "int" + }, { + "name" : "hourOfDay", + "type" : "int" + }, { + "name" : "periodStart", + "type" : "long" + }, { + "name" : "periodEnd", + "type" : "long" + }, { + "name" : "count", + "type" : "long" + }, { + "name" : "mean", + "type" : "double" + }, { + "name" : "populationVariance", + "type" : "double" + }, { + "name" : "min", + "type" : "double" + }, { + "name" : "max", + "type" : "double" + } ] +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/MonthOfYearActivePowerRecord.avsc b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/MonthOfYearActivePowerRecord.avsc new file mode 100644 index 0000000000000000000000000000000000000000..70dd7eda5b5aaa6bb27b2ebca4ac7f4b251c630f --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/MonthOfYearActivePowerRecord.avsc @@ -0,0 +1,33 @@ +{ + "type" : "record", + "name" : "MonthOfYearActivePowerRecord", + "namespace" : "rocks.theodolite.benchmarks.commons.model.records", + "fields" : [ { + "name" : "identifier", + "type" : "string" + }, { + "name" : "monthOfYear", + "type" : "int" + }, { + "name" : "periodStart", + "type" : "long" + }, { + "name" : "periodEnd", + "type" : "long" + }, { + "name" : "count", + "type" : "long" + }, { + "name" : "mean", + "type" : "double" + }, { + "name" : "populationVariance", + "type" : "double" + }, { + "name" : "min", + "type" : "double" + }, { + "name" : "max", + "type" : "double" + } ] +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/YearActivePowerRecord.avsc b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/YearActivePowerRecord.avsc new file mode 100644 index 0000000000000000000000000000000000000000..2bfc06b6649630fbde85f068e5b3a9d0312f5424 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/avro/rocks/theodolite/benchmarks/commons/model/records/YearActivePowerRecord.avsc @@ -0,0 +1,33 @@ +{ + "type" : "record", + "name" : "YearActivePowerRecord", + "namespace" : "rocks.theodolite.benchmarks.commons.model.records", + "fields" : [ { + "name" : "identifier", + "type" : "string" + }, { + "name" : "year", + "type" : "int" + }, { + "name" : "periodStart", + "type" : "long" + }, { + "name" : "periodEnd", + "type" : "long" + }, { + "name" : "count", + "type" : "long" + }, { + "name" : "mean", + "type" : "double" + }, { + "name" : "populationVariance", + "type" : "double" + }, { + "name" : "min", + "type" : "double" + }, { + "name" : "max", + "type" : "double" + } ] +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/ActivePowerRecord.java b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/ActivePowerRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..27e0f39076e5384a89e3d8a91e4b08808244aa2a --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/ActivePowerRecord.java @@ -0,0 +1,492 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package rocks.theodolite.benchmarks.commons.model.records; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class ActivePowerRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = -5809432381123606133L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"ActivePowerRecord\",\"namespace\":\"rocks.theodolite.benchmarks.commons.model.records\",\"fields\":[{\"name\":\"identifier\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"doc\":\"*\"},{\"name\":\"timestamp\",\"type\":\"long\",\"doc\":\"*\"},{\"name\":\"valueInW\",\"type\":\"double\",\"doc\":\"*\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<ActivePowerRecord> ENCODER = + new BinaryMessageEncoder<ActivePowerRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<ActivePowerRecord> DECODER = + new BinaryMessageDecoder<ActivePowerRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder<ActivePowerRecord> getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<ActivePowerRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<ActivePowerRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<ActivePowerRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this ActivePowerRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a ActivePowerRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a ActivePowerRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static ActivePowerRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + /** * */ + private java.lang.String identifier; + /** * */ + private long timestamp; + /** * */ + private double valueInW; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use <code>newBuilder()</code>. + */ + public ActivePowerRecord() {} + + /** + * All-args constructor. + * @param identifier * + * @param timestamp * + * @param valueInW * + */ + public ActivePowerRecord(java.lang.String identifier, java.lang.Long timestamp, java.lang.Double valueInW) { + this.identifier = identifier; + this.timestamp = timestamp; + this.valueInW = valueInW; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return identifier; + case 1: return timestamp; + case 2: return valueInW; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: identifier = value$ != null ? value$.toString() : null; break; + case 1: timestamp = (java.lang.Long)value$; break; + case 2: valueInW = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'identifier' field. + * @return * + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * * + * @param value the value to set. + */ + public void setIdentifier(java.lang.String value) { + this.identifier = value; + } + + /** + * Gets the value of the 'timestamp' field. + * @return * + */ + public long getTimestamp() { + return timestamp; + } + + + /** + * Sets the value of the 'timestamp' field. + * * + * @param value the value to set. + */ + public void setTimestamp(long value) { + this.timestamp = value; + } + + /** + * Gets the value of the 'valueInW' field. + * @return * + */ + public double getValueInW() { + return valueInW; + } + + + /** + * Sets the value of the 'valueInW' field. + * * + * @param value the value to set. + */ + public void setValueInW(double value) { + this.valueInW = value; + } + + /** + * Creates a new ActivePowerRecord RecordBuilder. + * @return A new ActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder newBuilder() { + return new rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder(); + } + + /** + * Creates a new ActivePowerRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new ActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder(other); + } + } + + /** + * Creates a new ActivePowerRecord RecordBuilder by copying an existing ActivePowerRecord instance. + * @param other The existing instance to copy. + * @return A new ActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder(other); + } + } + + /** + * RecordBuilder for ActivePowerRecord instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<ActivePowerRecord> + implements org.apache.avro.data.RecordBuilder<ActivePowerRecord> { + + /** * */ + private java.lang.String identifier; + /** * */ + private long timestamp; + /** * */ + private double valueInW; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder other) { + super(other); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.timestamp)) { + this.timestamp = data().deepCopy(fields()[1].schema(), other.timestamp); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.valueInW)) { + this.valueInW = data().deepCopy(fields()[2].schema(), other.valueInW); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + } + + /** + * Creates a Builder by copying an existing ActivePowerRecord instance + * @param other The existing instance to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.timestamp)) { + this.timestamp = data().deepCopy(fields()[1].schema(), other.timestamp); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.valueInW)) { + this.valueInW = data().deepCopy(fields()[2].schema(), other.valueInW); + fieldSetFlags()[2] = true; + } + } + + /** + * Gets the value of the 'identifier' field. + * * + * @return The value. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * * + * @param value The value of 'identifier'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder setIdentifier(java.lang.String value) { + validate(fields()[0], value); + this.identifier = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'identifier' field has been set. + * * + * @return True if the 'identifier' field has been set, false otherwise. + */ + public boolean hasIdentifier() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'identifier' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder clearIdentifier() { + identifier = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'timestamp' field. + * * + * @return The value. + */ + public long getTimestamp() { + return timestamp; + } + + + /** + * Sets the value of the 'timestamp' field. + * * + * @param value The value of 'timestamp'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder setTimestamp(long value) { + validate(fields()[1], value); + this.timestamp = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'timestamp' field has been set. + * * + * @return True if the 'timestamp' field has been set, false otherwise. + */ + public boolean hasTimestamp() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'timestamp' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder clearTimestamp() { + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'valueInW' field. + * * + * @return The value. + */ + public double getValueInW() { + return valueInW; + } + + + /** + * Sets the value of the 'valueInW' field. + * * + * @param value The value of 'valueInW'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder setValueInW(double value) { + validate(fields()[2], value); + this.valueInW = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'valueInW' field has been set. + * * + * @return True if the 'valueInW' field has been set, false otherwise. + */ + public boolean hasValueInW() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'valueInW' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord.Builder clearValueInW() { + fieldSetFlags()[2] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public ActivePowerRecord build() { + try { + ActivePowerRecord record = new ActivePowerRecord(); + record.identifier = fieldSetFlags()[0] ? this.identifier : (java.lang.String) defaultValue(fields()[0]); + record.timestamp = fieldSetFlags()[1] ? this.timestamp : (java.lang.Long) defaultValue(fields()[1]); + record.valueInW = fieldSetFlags()[2] ? this.valueInW : (java.lang.Double) defaultValue(fields()[2]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<ActivePowerRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<ActivePowerRecord>)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<ActivePowerRecord> + READER$ = (org.apache.avro.io.DatumReader<ActivePowerRecord>)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.identifier); + + out.writeLong(this.timestamp); + + out.writeDouble(this.valueInW); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.identifier = in.readString(); + + this.timestamp = in.readLong(); + + this.valueInW = in.readDouble(); + + } else { + for (int i = 0; i < 3; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.identifier = in.readString(); + break; + + case 1: + this.timestamp = in.readLong(); + break; + + case 2: + this.valueInW = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/AggregatedActivePowerRecord.java b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/AggregatedActivePowerRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..7aa6e0b5f988bae1f63d8a2817a1fed2b4880b6a --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/AggregatedActivePowerRecord.java @@ -0,0 +1,664 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package rocks.theodolite.benchmarks.commons.model.records; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class AggregatedActivePowerRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = 334342381382209426L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"AggregatedActivePowerRecord\",\"namespace\":\"rocks.theodolite.benchmarks.commons.model.records\",\"fields\":[{\"name\":\"identifier\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"},\"doc\":\"*\"},{\"name\":\"timestamp\",\"type\":\"long\",\"doc\":\"*\"},{\"name\":\"count\",\"type\":\"long\",\"doc\":\"*\"},{\"name\":\"sumInW\",\"type\":\"double\",\"doc\":\"*\"},{\"name\":\"averageInW\",\"type\":\"double\",\"doc\":\"*\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<AggregatedActivePowerRecord> ENCODER = + new BinaryMessageEncoder<AggregatedActivePowerRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<AggregatedActivePowerRecord> DECODER = + new BinaryMessageDecoder<AggregatedActivePowerRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder<AggregatedActivePowerRecord> getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<AggregatedActivePowerRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<AggregatedActivePowerRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<AggregatedActivePowerRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this AggregatedActivePowerRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a AggregatedActivePowerRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a AggregatedActivePowerRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static AggregatedActivePowerRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + /** * */ + private java.lang.String identifier; + /** * */ + private long timestamp; + /** * */ + private long count; + /** * */ + private double sumInW; + /** * */ + private double averageInW; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use <code>newBuilder()</code>. + */ + public AggregatedActivePowerRecord() {} + + /** + * All-args constructor. + * @param identifier * + * @param timestamp * + * @param count * + * @param sumInW * + * @param averageInW * + */ + public AggregatedActivePowerRecord(java.lang.String identifier, java.lang.Long timestamp, java.lang.Long count, java.lang.Double sumInW, java.lang.Double averageInW) { + this.identifier = identifier; + this.timestamp = timestamp; + this.count = count; + this.sumInW = sumInW; + this.averageInW = averageInW; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return identifier; + case 1: return timestamp; + case 2: return count; + case 3: return sumInW; + case 4: return averageInW; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: identifier = value$ != null ? value$.toString() : null; break; + case 1: timestamp = (java.lang.Long)value$; break; + case 2: count = (java.lang.Long)value$; break; + case 3: sumInW = (java.lang.Double)value$; break; + case 4: averageInW = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'identifier' field. + * @return * + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * * + * @param value the value to set. + */ + public void setIdentifier(java.lang.String value) { + this.identifier = value; + } + + /** + * Gets the value of the 'timestamp' field. + * @return * + */ + public long getTimestamp() { + return timestamp; + } + + + /** + * Sets the value of the 'timestamp' field. + * * + * @param value the value to set. + */ + public void setTimestamp(long value) { + this.timestamp = value; + } + + /** + * Gets the value of the 'count' field. + * @return * + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * * + * @param value the value to set. + */ + public void setCount(long value) { + this.count = value; + } + + /** + * Gets the value of the 'sumInW' field. + * @return * + */ + public double getSumInW() { + return sumInW; + } + + + /** + * Sets the value of the 'sumInW' field. + * * + * @param value the value to set. + */ + public void setSumInW(double value) { + this.sumInW = value; + } + + /** + * Gets the value of the 'averageInW' field. + * @return * + */ + public double getAverageInW() { + return averageInW; + } + + + /** + * Sets the value of the 'averageInW' field. + * * + * @param value the value to set. + */ + public void setAverageInW(double value) { + this.averageInW = value; + } + + /** + * Creates a new AggregatedActivePowerRecord RecordBuilder. + * @return A new AggregatedActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder newBuilder() { + return new rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder(); + } + + /** + * Creates a new AggregatedActivePowerRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new AggregatedActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder(other); + } + } + + /** + * Creates a new AggregatedActivePowerRecord RecordBuilder by copying an existing AggregatedActivePowerRecord instance. + * @param other The existing instance to copy. + * @return A new AggregatedActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder(other); + } + } + + /** + * RecordBuilder for AggregatedActivePowerRecord instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<AggregatedActivePowerRecord> + implements org.apache.avro.data.RecordBuilder<AggregatedActivePowerRecord> { + + /** * */ + private java.lang.String identifier; + /** * */ + private long timestamp; + /** * */ + private long count; + /** * */ + private double sumInW; + /** * */ + private double averageInW; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder other) { + super(other); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.timestamp)) { + this.timestamp = data().deepCopy(fields()[1].schema(), other.timestamp); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.count)) { + this.count = data().deepCopy(fields()[2].schema(), other.count); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.sumInW)) { + this.sumInW = data().deepCopy(fields()[3].schema(), other.sumInW); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.averageInW)) { + this.averageInW = data().deepCopy(fields()[4].schema(), other.averageInW); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + } + + /** + * Creates a Builder by copying an existing AggregatedActivePowerRecord instance + * @param other The existing instance to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.timestamp)) { + this.timestamp = data().deepCopy(fields()[1].schema(), other.timestamp); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.count)) { + this.count = data().deepCopy(fields()[2].schema(), other.count); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.sumInW)) { + this.sumInW = data().deepCopy(fields()[3].schema(), other.sumInW); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.averageInW)) { + this.averageInW = data().deepCopy(fields()[4].schema(), other.averageInW); + fieldSetFlags()[4] = true; + } + } + + /** + * Gets the value of the 'identifier' field. + * * + * @return The value. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * * + * @param value The value of 'identifier'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder setIdentifier(java.lang.String value) { + validate(fields()[0], value); + this.identifier = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'identifier' field has been set. + * * + * @return True if the 'identifier' field has been set, false otherwise. + */ + public boolean hasIdentifier() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'identifier' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder clearIdentifier() { + identifier = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'timestamp' field. + * * + * @return The value. + */ + public long getTimestamp() { + return timestamp; + } + + + /** + * Sets the value of the 'timestamp' field. + * * + * @param value The value of 'timestamp'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder setTimestamp(long value) { + validate(fields()[1], value); + this.timestamp = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'timestamp' field has been set. + * * + * @return True if the 'timestamp' field has been set, false otherwise. + */ + public boolean hasTimestamp() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'timestamp' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder clearTimestamp() { + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'count' field. + * * + * @return The value. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * * + * @param value The value of 'count'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder setCount(long value) { + validate(fields()[2], value); + this.count = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'count' field has been set. + * * + * @return True if the 'count' field has been set, false otherwise. + */ + public boolean hasCount() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'count' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder clearCount() { + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'sumInW' field. + * * + * @return The value. + */ + public double getSumInW() { + return sumInW; + } + + + /** + * Sets the value of the 'sumInW' field. + * * + * @param value The value of 'sumInW'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder setSumInW(double value) { + validate(fields()[3], value); + this.sumInW = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'sumInW' field has been set. + * * + * @return True if the 'sumInW' field has been set, false otherwise. + */ + public boolean hasSumInW() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'sumInW' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder clearSumInW() { + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'averageInW' field. + * * + * @return The value. + */ + public double getAverageInW() { + return averageInW; + } + + + /** + * Sets the value of the 'averageInW' field. + * * + * @param value The value of 'averageInW'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder setAverageInW(double value) { + validate(fields()[4], value); + this.averageInW = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'averageInW' field has been set. + * * + * @return True if the 'averageInW' field has been set, false otherwise. + */ + public boolean hasAverageInW() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'averageInW' field. + * * + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord.Builder clearAverageInW() { + fieldSetFlags()[4] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public AggregatedActivePowerRecord build() { + try { + AggregatedActivePowerRecord record = new AggregatedActivePowerRecord(); + record.identifier = fieldSetFlags()[0] ? this.identifier : (java.lang.String) defaultValue(fields()[0]); + record.timestamp = fieldSetFlags()[1] ? this.timestamp : (java.lang.Long) defaultValue(fields()[1]); + record.count = fieldSetFlags()[2] ? this.count : (java.lang.Long) defaultValue(fields()[2]); + record.sumInW = fieldSetFlags()[3] ? this.sumInW : (java.lang.Double) defaultValue(fields()[3]); + record.averageInW = fieldSetFlags()[4] ? this.averageInW : (java.lang.Double) defaultValue(fields()[4]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<AggregatedActivePowerRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<AggregatedActivePowerRecord>)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<AggregatedActivePowerRecord> + READER$ = (org.apache.avro.io.DatumReader<AggregatedActivePowerRecord>)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.identifier); + + out.writeLong(this.timestamp); + + out.writeLong(this.count); + + out.writeDouble(this.sumInW); + + out.writeDouble(this.averageInW); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.identifier = in.readString(); + + this.timestamp = in.readLong(); + + this.count = in.readLong(); + + this.sumInW = in.readDouble(); + + this.averageInW = in.readDouble(); + + } else { + for (int i = 0; i < 5; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.identifier = in.readString(); + break; + + case 1: + this.timestamp = in.readLong(); + break; + + case 2: + this.count = in.readLong(); + break; + + case 3: + this.sumInW = in.readDouble(); + break; + + case 4: + this.averageInW = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/DayOfWeekActivePowerRecord.java b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/DayOfWeekActivePowerRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..6e6917a6393f6b7deea3237384f08094a9cfc200 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/DayOfWeekActivePowerRecord.java @@ -0,0 +1,945 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package rocks.theodolite.benchmarks.commons.model.records; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class DayOfWeekActivePowerRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = 874988617222069934L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"DayOfWeekActivePowerRecord\",\"namespace\":\"rocks.theodolite.benchmarks.commons.model.records\",\"fields\":[{\"name\":\"identifier\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"dayOfWeek\",\"type\":\"int\"},{\"name\":\"periodStart\",\"type\":\"long\"},{\"name\":\"periodEnd\",\"type\":\"long\"},{\"name\":\"count\",\"type\":\"long\"},{\"name\":\"mean\",\"type\":\"double\"},{\"name\":\"populationVariance\",\"type\":\"double\"},{\"name\":\"min\",\"type\":\"double\"},{\"name\":\"max\",\"type\":\"double\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<DayOfWeekActivePowerRecord> ENCODER = + new BinaryMessageEncoder<DayOfWeekActivePowerRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<DayOfWeekActivePowerRecord> DECODER = + new BinaryMessageDecoder<DayOfWeekActivePowerRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder<DayOfWeekActivePowerRecord> getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<DayOfWeekActivePowerRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<DayOfWeekActivePowerRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<DayOfWeekActivePowerRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this DayOfWeekActivePowerRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a DayOfWeekActivePowerRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a DayOfWeekActivePowerRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static DayOfWeekActivePowerRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private java.lang.String identifier; + private int dayOfWeek; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use <code>newBuilder()</code>. + */ + public DayOfWeekActivePowerRecord() {} + + /** + * All-args constructor. + * @param identifier The new value for identifier + * @param dayOfWeek The new value for dayOfWeek + * @param periodStart The new value for periodStart + * @param periodEnd The new value for periodEnd + * @param count The new value for count + * @param mean The new value for mean + * @param populationVariance The new value for populationVariance + * @param min The new value for min + * @param max The new value for max + */ + public DayOfWeekActivePowerRecord(java.lang.String identifier, java.lang.Integer dayOfWeek, java.lang.Long periodStart, java.lang.Long periodEnd, java.lang.Long count, java.lang.Double mean, java.lang.Double populationVariance, java.lang.Double min, java.lang.Double max) { + this.identifier = identifier; + this.dayOfWeek = dayOfWeek; + this.periodStart = periodStart; + this.periodEnd = periodEnd; + this.count = count; + this.mean = mean; + this.populationVariance = populationVariance; + this.min = min; + this.max = max; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return identifier; + case 1: return dayOfWeek; + case 2: return periodStart; + case 3: return periodEnd; + case 4: return count; + case 5: return mean; + case 6: return populationVariance; + case 7: return min; + case 8: return max; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: identifier = value$ != null ? value$.toString() : null; break; + case 1: dayOfWeek = (java.lang.Integer)value$; break; + case 2: periodStart = (java.lang.Long)value$; break; + case 3: periodEnd = (java.lang.Long)value$; break; + case 4: count = (java.lang.Long)value$; break; + case 5: mean = (java.lang.Double)value$; break; + case 6: populationVariance = (java.lang.Double)value$; break; + case 7: min = (java.lang.Double)value$; break; + case 8: max = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value of the 'identifier' field. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value the value to set. + */ + public void setIdentifier(java.lang.String value) { + this.identifier = value; + } + + /** + * Gets the value of the 'dayOfWeek' field. + * @return The value of the 'dayOfWeek' field. + */ + public int getDayOfWeek() { + return dayOfWeek; + } + + + /** + * Sets the value of the 'dayOfWeek' field. + * @param value the value to set. + */ + public void setDayOfWeek(int value) { + this.dayOfWeek = value; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value of the 'periodStart' field. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value the value to set. + */ + public void setPeriodStart(long value) { + this.periodStart = value; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value of the 'periodEnd' field. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value the value to set. + */ + public void setPeriodEnd(long value) { + this.periodEnd = value; + } + + /** + * Gets the value of the 'count' field. + * @return The value of the 'count' field. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value the value to set. + */ + public void setCount(long value) { + this.count = value; + } + + /** + * Gets the value of the 'mean' field. + * @return The value of the 'mean' field. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value the value to set. + */ + public void setMean(double value) { + this.mean = value; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value of the 'populationVariance' field. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value the value to set. + */ + public void setPopulationVariance(double value) { + this.populationVariance = value; + } + + /** + * Gets the value of the 'min' field. + * @return The value of the 'min' field. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value the value to set. + */ + public void setMin(double value) { + this.min = value; + } + + /** + * Gets the value of the 'max' field. + * @return The value of the 'max' field. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value the value to set. + */ + public void setMax(double value) { + this.max = value; + } + + /** + * Creates a new DayOfWeekActivePowerRecord RecordBuilder. + * @return A new DayOfWeekActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder newBuilder() { + return new rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder(); + } + + /** + * Creates a new DayOfWeekActivePowerRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new DayOfWeekActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder(other); + } + } + + /** + * Creates a new DayOfWeekActivePowerRecord RecordBuilder by copying an existing DayOfWeekActivePowerRecord instance. + * @param other The existing instance to copy. + * @return A new DayOfWeekActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder(other); + } + } + + /** + * RecordBuilder for DayOfWeekActivePowerRecord instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<DayOfWeekActivePowerRecord> + implements org.apache.avro.data.RecordBuilder<DayOfWeekActivePowerRecord> { + + private java.lang.String identifier; + private int dayOfWeek; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder other) { + super(other); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.dayOfWeek)) { + this.dayOfWeek = data().deepCopy(fields()[1].schema(), other.dayOfWeek); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = other.fieldSetFlags()[5]; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = other.fieldSetFlags()[6]; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = other.fieldSetFlags()[7]; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = other.fieldSetFlags()[8]; + } + } + + /** + * Creates a Builder by copying an existing DayOfWeekActivePowerRecord instance + * @param other The existing instance to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.dayOfWeek)) { + this.dayOfWeek = data().deepCopy(fields()[1].schema(), other.dayOfWeek); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = true; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = true; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = true; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = true; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = true; + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value The value of 'identifier'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setIdentifier(java.lang.String value) { + validate(fields()[0], value); + this.identifier = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'identifier' field has been set. + * @return True if the 'identifier' field has been set, false otherwise. + */ + public boolean hasIdentifier() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'identifier' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearIdentifier() { + identifier = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'dayOfWeek' field. + * @return The value. + */ + public int getDayOfWeek() { + return dayOfWeek; + } + + + /** + * Sets the value of the 'dayOfWeek' field. + * @param value The value of 'dayOfWeek'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setDayOfWeek(int value) { + validate(fields()[1], value); + this.dayOfWeek = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'dayOfWeek' field has been set. + * @return True if the 'dayOfWeek' field has been set, false otherwise. + */ + public boolean hasDayOfWeek() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'dayOfWeek' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearDayOfWeek() { + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value The value of 'periodStart'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setPeriodStart(long value) { + validate(fields()[2], value); + this.periodStart = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'periodStart' field has been set. + * @return True if the 'periodStart' field has been set, false otherwise. + */ + public boolean hasPeriodStart() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'periodStart' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearPeriodStart() { + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value The value of 'periodEnd'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setPeriodEnd(long value) { + validate(fields()[3], value); + this.periodEnd = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'periodEnd' field has been set. + * @return True if the 'periodEnd' field has been set, false otherwise. + */ + public boolean hasPeriodEnd() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'periodEnd' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearPeriodEnd() { + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'count' field. + * @return The value. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value The value of 'count'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setCount(long value) { + validate(fields()[4], value); + this.count = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'count' field has been set. + * @return True if the 'count' field has been set, false otherwise. + */ + public boolean hasCount() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'count' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearCount() { + fieldSetFlags()[4] = false; + return this; + } + + /** + * Gets the value of the 'mean' field. + * @return The value. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value The value of 'mean'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setMean(double value) { + validate(fields()[5], value); + this.mean = value; + fieldSetFlags()[5] = true; + return this; + } + + /** + * Checks whether the 'mean' field has been set. + * @return True if the 'mean' field has been set, false otherwise. + */ + public boolean hasMean() { + return fieldSetFlags()[5]; + } + + + /** + * Clears the value of the 'mean' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearMean() { + fieldSetFlags()[5] = false; + return this; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value The value of 'populationVariance'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setPopulationVariance(double value) { + validate(fields()[6], value); + this.populationVariance = value; + fieldSetFlags()[6] = true; + return this; + } + + /** + * Checks whether the 'populationVariance' field has been set. + * @return True if the 'populationVariance' field has been set, false otherwise. + */ + public boolean hasPopulationVariance() { + return fieldSetFlags()[6]; + } + + + /** + * Clears the value of the 'populationVariance' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearPopulationVariance() { + fieldSetFlags()[6] = false; + return this; + } + + /** + * Gets the value of the 'min' field. + * @return The value. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value The value of 'min'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setMin(double value) { + validate(fields()[7], value); + this.min = value; + fieldSetFlags()[7] = true; + return this; + } + + /** + * Checks whether the 'min' field has been set. + * @return True if the 'min' field has been set, false otherwise. + */ + public boolean hasMin() { + return fieldSetFlags()[7]; + } + + + /** + * Clears the value of the 'min' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearMin() { + fieldSetFlags()[7] = false; + return this; + } + + /** + * Gets the value of the 'max' field. + * @return The value. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value The value of 'max'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder setMax(double value) { + validate(fields()[8], value); + this.max = value; + fieldSetFlags()[8] = true; + return this; + } + + /** + * Checks whether the 'max' field has been set. + * @return True if the 'max' field has been set, false otherwise. + */ + public boolean hasMax() { + return fieldSetFlags()[8]; + } + + + /** + * Clears the value of the 'max' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.DayOfWeekActivePowerRecord.Builder clearMax() { + fieldSetFlags()[8] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public DayOfWeekActivePowerRecord build() { + try { + DayOfWeekActivePowerRecord record = new DayOfWeekActivePowerRecord(); + record.identifier = fieldSetFlags()[0] ? this.identifier : (java.lang.String) defaultValue(fields()[0]); + record.dayOfWeek = fieldSetFlags()[1] ? this.dayOfWeek : (java.lang.Integer) defaultValue(fields()[1]); + record.periodStart = fieldSetFlags()[2] ? this.periodStart : (java.lang.Long) defaultValue(fields()[2]); + record.periodEnd = fieldSetFlags()[3] ? this.periodEnd : (java.lang.Long) defaultValue(fields()[3]); + record.count = fieldSetFlags()[4] ? this.count : (java.lang.Long) defaultValue(fields()[4]); + record.mean = fieldSetFlags()[5] ? this.mean : (java.lang.Double) defaultValue(fields()[5]); + record.populationVariance = fieldSetFlags()[6] ? this.populationVariance : (java.lang.Double) defaultValue(fields()[6]); + record.min = fieldSetFlags()[7] ? this.min : (java.lang.Double) defaultValue(fields()[7]); + record.max = fieldSetFlags()[8] ? this.max : (java.lang.Double) defaultValue(fields()[8]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<DayOfWeekActivePowerRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<DayOfWeekActivePowerRecord>)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<DayOfWeekActivePowerRecord> + READER$ = (org.apache.avro.io.DatumReader<DayOfWeekActivePowerRecord>)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.identifier); + + out.writeInt(this.dayOfWeek); + + out.writeLong(this.periodStart); + + out.writeLong(this.periodEnd); + + out.writeLong(this.count); + + out.writeDouble(this.mean); + + out.writeDouble(this.populationVariance); + + out.writeDouble(this.min); + + out.writeDouble(this.max); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.identifier = in.readString(); + + this.dayOfWeek = in.readInt(); + + this.periodStart = in.readLong(); + + this.periodEnd = in.readLong(); + + this.count = in.readLong(); + + this.mean = in.readDouble(); + + this.populationVariance = in.readDouble(); + + this.min = in.readDouble(); + + this.max = in.readDouble(); + + } else { + for (int i = 0; i < 9; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.identifier = in.readString(); + break; + + case 1: + this.dayOfWeek = in.readInt(); + break; + + case 2: + this.periodStart = in.readLong(); + break; + + case 3: + this.periodEnd = in.readLong(); + break; + + case 4: + this.count = in.readLong(); + break; + + case 5: + this.mean = in.readDouble(); + break; + + case 6: + this.populationVariance = in.readDouble(); + break; + + case 7: + this.min = in.readDouble(); + break; + + case 8: + this.max = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/HourOfDayActivePowerRecord.java b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/HourOfDayActivePowerRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..491a91f4dfe5d439d094d66290d82d77001e72c9 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/HourOfDayActivePowerRecord.java @@ -0,0 +1,945 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package rocks.theodolite.benchmarks.commons.model.records; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class HourOfDayActivePowerRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = 6460936513507715126L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"HourOfDayActivePowerRecord\",\"namespace\":\"rocks.theodolite.benchmarks.commons.model.records\",\"fields\":[{\"name\":\"identifier\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"hourOfDay\",\"type\":\"int\"},{\"name\":\"periodStart\",\"type\":\"long\"},{\"name\":\"periodEnd\",\"type\":\"long\"},{\"name\":\"count\",\"type\":\"long\"},{\"name\":\"mean\",\"type\":\"double\"},{\"name\":\"populationVariance\",\"type\":\"double\"},{\"name\":\"min\",\"type\":\"double\"},{\"name\":\"max\",\"type\":\"double\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<HourOfDayActivePowerRecord> ENCODER = + new BinaryMessageEncoder<HourOfDayActivePowerRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<HourOfDayActivePowerRecord> DECODER = + new BinaryMessageDecoder<HourOfDayActivePowerRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder<HourOfDayActivePowerRecord> getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<HourOfDayActivePowerRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<HourOfDayActivePowerRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<HourOfDayActivePowerRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this HourOfDayActivePowerRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a HourOfDayActivePowerRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a HourOfDayActivePowerRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static HourOfDayActivePowerRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private java.lang.String identifier; + private int hourOfDay; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use <code>newBuilder()</code>. + */ + public HourOfDayActivePowerRecord() {} + + /** + * All-args constructor. + * @param identifier The new value for identifier + * @param hourOfDay The new value for hourOfDay + * @param periodStart The new value for periodStart + * @param periodEnd The new value for periodEnd + * @param count The new value for count + * @param mean The new value for mean + * @param populationVariance The new value for populationVariance + * @param min The new value for min + * @param max The new value for max + */ + public HourOfDayActivePowerRecord(java.lang.String identifier, java.lang.Integer hourOfDay, java.lang.Long periodStart, java.lang.Long periodEnd, java.lang.Long count, java.lang.Double mean, java.lang.Double populationVariance, java.lang.Double min, java.lang.Double max) { + this.identifier = identifier; + this.hourOfDay = hourOfDay; + this.periodStart = periodStart; + this.periodEnd = periodEnd; + this.count = count; + this.mean = mean; + this.populationVariance = populationVariance; + this.min = min; + this.max = max; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return identifier; + case 1: return hourOfDay; + case 2: return periodStart; + case 3: return periodEnd; + case 4: return count; + case 5: return mean; + case 6: return populationVariance; + case 7: return min; + case 8: return max; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: identifier = value$ != null ? value$.toString() : null; break; + case 1: hourOfDay = (java.lang.Integer)value$; break; + case 2: periodStart = (java.lang.Long)value$; break; + case 3: periodEnd = (java.lang.Long)value$; break; + case 4: count = (java.lang.Long)value$; break; + case 5: mean = (java.lang.Double)value$; break; + case 6: populationVariance = (java.lang.Double)value$; break; + case 7: min = (java.lang.Double)value$; break; + case 8: max = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value of the 'identifier' field. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value the value to set. + */ + public void setIdentifier(java.lang.String value) { + this.identifier = value; + } + + /** + * Gets the value of the 'hourOfDay' field. + * @return The value of the 'hourOfDay' field. + */ + public int getHourOfDay() { + return hourOfDay; + } + + + /** + * Sets the value of the 'hourOfDay' field. + * @param value the value to set. + */ + public void setHourOfDay(int value) { + this.hourOfDay = value; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value of the 'periodStart' field. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value the value to set. + */ + public void setPeriodStart(long value) { + this.periodStart = value; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value of the 'periodEnd' field. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value the value to set. + */ + public void setPeriodEnd(long value) { + this.periodEnd = value; + } + + /** + * Gets the value of the 'count' field. + * @return The value of the 'count' field. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value the value to set. + */ + public void setCount(long value) { + this.count = value; + } + + /** + * Gets the value of the 'mean' field. + * @return The value of the 'mean' field. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value the value to set. + */ + public void setMean(double value) { + this.mean = value; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value of the 'populationVariance' field. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value the value to set. + */ + public void setPopulationVariance(double value) { + this.populationVariance = value; + } + + /** + * Gets the value of the 'min' field. + * @return The value of the 'min' field. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value the value to set. + */ + public void setMin(double value) { + this.min = value; + } + + /** + * Gets the value of the 'max' field. + * @return The value of the 'max' field. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value the value to set. + */ + public void setMax(double value) { + this.max = value; + } + + /** + * Creates a new HourOfDayActivePowerRecord RecordBuilder. + * @return A new HourOfDayActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder newBuilder() { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder(); + } + + /** + * Creates a new HourOfDayActivePowerRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new HourOfDayActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder(other); + } + } + + /** + * Creates a new HourOfDayActivePowerRecord RecordBuilder by copying an existing HourOfDayActivePowerRecord instance. + * @param other The existing instance to copy. + * @return A new HourOfDayActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder(other); + } + } + + /** + * RecordBuilder for HourOfDayActivePowerRecord instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<HourOfDayActivePowerRecord> + implements org.apache.avro.data.RecordBuilder<HourOfDayActivePowerRecord> { + + private java.lang.String identifier; + private int hourOfDay; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder other) { + super(other); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.hourOfDay)) { + this.hourOfDay = data().deepCopy(fields()[1].schema(), other.hourOfDay); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = other.fieldSetFlags()[5]; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = other.fieldSetFlags()[6]; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = other.fieldSetFlags()[7]; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = other.fieldSetFlags()[8]; + } + } + + /** + * Creates a Builder by copying an existing HourOfDayActivePowerRecord instance + * @param other The existing instance to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.hourOfDay)) { + this.hourOfDay = data().deepCopy(fields()[1].schema(), other.hourOfDay); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = true; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = true; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = true; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = true; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = true; + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value The value of 'identifier'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setIdentifier(java.lang.String value) { + validate(fields()[0], value); + this.identifier = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'identifier' field has been set. + * @return True if the 'identifier' field has been set, false otherwise. + */ + public boolean hasIdentifier() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'identifier' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearIdentifier() { + identifier = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'hourOfDay' field. + * @return The value. + */ + public int getHourOfDay() { + return hourOfDay; + } + + + /** + * Sets the value of the 'hourOfDay' field. + * @param value The value of 'hourOfDay'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setHourOfDay(int value) { + validate(fields()[1], value); + this.hourOfDay = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'hourOfDay' field has been set. + * @return True if the 'hourOfDay' field has been set, false otherwise. + */ + public boolean hasHourOfDay() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'hourOfDay' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearHourOfDay() { + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value The value of 'periodStart'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setPeriodStart(long value) { + validate(fields()[2], value); + this.periodStart = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'periodStart' field has been set. + * @return True if the 'periodStart' field has been set, false otherwise. + */ + public boolean hasPeriodStart() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'periodStart' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearPeriodStart() { + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value The value of 'periodEnd'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setPeriodEnd(long value) { + validate(fields()[3], value); + this.periodEnd = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'periodEnd' field has been set. + * @return True if the 'periodEnd' field has been set, false otherwise. + */ + public boolean hasPeriodEnd() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'periodEnd' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearPeriodEnd() { + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'count' field. + * @return The value. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value The value of 'count'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setCount(long value) { + validate(fields()[4], value); + this.count = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'count' field has been set. + * @return True if the 'count' field has been set, false otherwise. + */ + public boolean hasCount() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'count' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearCount() { + fieldSetFlags()[4] = false; + return this; + } + + /** + * Gets the value of the 'mean' field. + * @return The value. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value The value of 'mean'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setMean(double value) { + validate(fields()[5], value); + this.mean = value; + fieldSetFlags()[5] = true; + return this; + } + + /** + * Checks whether the 'mean' field has been set. + * @return True if the 'mean' field has been set, false otherwise. + */ + public boolean hasMean() { + return fieldSetFlags()[5]; + } + + + /** + * Clears the value of the 'mean' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearMean() { + fieldSetFlags()[5] = false; + return this; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value The value of 'populationVariance'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setPopulationVariance(double value) { + validate(fields()[6], value); + this.populationVariance = value; + fieldSetFlags()[6] = true; + return this; + } + + /** + * Checks whether the 'populationVariance' field has been set. + * @return True if the 'populationVariance' field has been set, false otherwise. + */ + public boolean hasPopulationVariance() { + return fieldSetFlags()[6]; + } + + + /** + * Clears the value of the 'populationVariance' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearPopulationVariance() { + fieldSetFlags()[6] = false; + return this; + } + + /** + * Gets the value of the 'min' field. + * @return The value. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value The value of 'min'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setMin(double value) { + validate(fields()[7], value); + this.min = value; + fieldSetFlags()[7] = true; + return this; + } + + /** + * Checks whether the 'min' field has been set. + * @return True if the 'min' field has been set, false otherwise. + */ + public boolean hasMin() { + return fieldSetFlags()[7]; + } + + + /** + * Clears the value of the 'min' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearMin() { + fieldSetFlags()[7] = false; + return this; + } + + /** + * Gets the value of the 'max' field. + * @return The value. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value The value of 'max'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder setMax(double value) { + validate(fields()[8], value); + this.max = value; + fieldSetFlags()[8] = true; + return this; + } + + /** + * Checks whether the 'max' field has been set. + * @return True if the 'max' field has been set, false otherwise. + */ + public boolean hasMax() { + return fieldSetFlags()[8]; + } + + + /** + * Clears the value of the 'max' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord.Builder clearMax() { + fieldSetFlags()[8] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public HourOfDayActivePowerRecord build() { + try { + HourOfDayActivePowerRecord record = new HourOfDayActivePowerRecord(); + record.identifier = fieldSetFlags()[0] ? this.identifier : (java.lang.String) defaultValue(fields()[0]); + record.hourOfDay = fieldSetFlags()[1] ? this.hourOfDay : (java.lang.Integer) defaultValue(fields()[1]); + record.periodStart = fieldSetFlags()[2] ? this.periodStart : (java.lang.Long) defaultValue(fields()[2]); + record.periodEnd = fieldSetFlags()[3] ? this.periodEnd : (java.lang.Long) defaultValue(fields()[3]); + record.count = fieldSetFlags()[4] ? this.count : (java.lang.Long) defaultValue(fields()[4]); + record.mean = fieldSetFlags()[5] ? this.mean : (java.lang.Double) defaultValue(fields()[5]); + record.populationVariance = fieldSetFlags()[6] ? this.populationVariance : (java.lang.Double) defaultValue(fields()[6]); + record.min = fieldSetFlags()[7] ? this.min : (java.lang.Double) defaultValue(fields()[7]); + record.max = fieldSetFlags()[8] ? this.max : (java.lang.Double) defaultValue(fields()[8]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<HourOfDayActivePowerRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<HourOfDayActivePowerRecord>)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<HourOfDayActivePowerRecord> + READER$ = (org.apache.avro.io.DatumReader<HourOfDayActivePowerRecord>)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.identifier); + + out.writeInt(this.hourOfDay); + + out.writeLong(this.periodStart); + + out.writeLong(this.periodEnd); + + out.writeLong(this.count); + + out.writeDouble(this.mean); + + out.writeDouble(this.populationVariance); + + out.writeDouble(this.min); + + out.writeDouble(this.max); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.identifier = in.readString(); + + this.hourOfDay = in.readInt(); + + this.periodStart = in.readLong(); + + this.periodEnd = in.readLong(); + + this.count = in.readLong(); + + this.mean = in.readDouble(); + + this.populationVariance = in.readDouble(); + + this.min = in.readDouble(); + + this.max = in.readDouble(); + + } else { + for (int i = 0; i < 9; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.identifier = in.readString(); + break; + + case 1: + this.hourOfDay = in.readInt(); + break; + + case 2: + this.periodStart = in.readLong(); + break; + + case 3: + this.periodEnd = in.readLong(); + break; + + case 4: + this.count = in.readLong(); + break; + + case 5: + this.mean = in.readDouble(); + break; + + case 6: + this.populationVariance = in.readDouble(); + break; + + case 7: + this.min = in.readDouble(); + break; + + case 8: + this.max = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/HourOfWeekActivePowerRecord.java b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/HourOfWeekActivePowerRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..112e1f7bc1c180e658367fb42b997405eb31a62c --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/HourOfWeekActivePowerRecord.java @@ -0,0 +1,1024 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package rocks.theodolite.benchmarks.commons.model.records; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class HourOfWeekActivePowerRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = -2060891996492175489L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"HourOfWeekActivePowerRecord\",\"namespace\":\"rocks.theodolite.benchmarks.commons.model.records\",\"fields\":[{\"name\":\"identifier\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"dayOfWeek\",\"type\":\"int\"},{\"name\":\"hourOfDay\",\"type\":\"int\"},{\"name\":\"periodStart\",\"type\":\"long\"},{\"name\":\"periodEnd\",\"type\":\"long\"},{\"name\":\"count\",\"type\":\"long\"},{\"name\":\"mean\",\"type\":\"double\"},{\"name\":\"populationVariance\",\"type\":\"double\"},{\"name\":\"min\",\"type\":\"double\"},{\"name\":\"max\",\"type\":\"double\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<HourOfWeekActivePowerRecord> ENCODER = + new BinaryMessageEncoder<HourOfWeekActivePowerRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<HourOfWeekActivePowerRecord> DECODER = + new BinaryMessageDecoder<HourOfWeekActivePowerRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder<HourOfWeekActivePowerRecord> getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<HourOfWeekActivePowerRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<HourOfWeekActivePowerRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<HourOfWeekActivePowerRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this HourOfWeekActivePowerRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a HourOfWeekActivePowerRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a HourOfWeekActivePowerRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static HourOfWeekActivePowerRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private java.lang.String identifier; + private int dayOfWeek; + private int hourOfDay; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use <code>newBuilder()</code>. + */ + public HourOfWeekActivePowerRecord() {} + + /** + * All-args constructor. + * @param identifier The new value for identifier + * @param dayOfWeek The new value for dayOfWeek + * @param hourOfDay The new value for hourOfDay + * @param periodStart The new value for periodStart + * @param periodEnd The new value for periodEnd + * @param count The new value for count + * @param mean The new value for mean + * @param populationVariance The new value for populationVariance + * @param min The new value for min + * @param max The new value for max + */ + public HourOfWeekActivePowerRecord(java.lang.String identifier, java.lang.Integer dayOfWeek, java.lang.Integer hourOfDay, java.lang.Long periodStart, java.lang.Long periodEnd, java.lang.Long count, java.lang.Double mean, java.lang.Double populationVariance, java.lang.Double min, java.lang.Double max) { + this.identifier = identifier; + this.dayOfWeek = dayOfWeek; + this.hourOfDay = hourOfDay; + this.periodStart = periodStart; + this.periodEnd = periodEnd; + this.count = count; + this.mean = mean; + this.populationVariance = populationVariance; + this.min = min; + this.max = max; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return identifier; + case 1: return dayOfWeek; + case 2: return hourOfDay; + case 3: return periodStart; + case 4: return periodEnd; + case 5: return count; + case 6: return mean; + case 7: return populationVariance; + case 8: return min; + case 9: return max; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: identifier = value$ != null ? value$.toString() : null; break; + case 1: dayOfWeek = (java.lang.Integer)value$; break; + case 2: hourOfDay = (java.lang.Integer)value$; break; + case 3: periodStart = (java.lang.Long)value$; break; + case 4: periodEnd = (java.lang.Long)value$; break; + case 5: count = (java.lang.Long)value$; break; + case 6: mean = (java.lang.Double)value$; break; + case 7: populationVariance = (java.lang.Double)value$; break; + case 8: min = (java.lang.Double)value$; break; + case 9: max = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value of the 'identifier' field. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value the value to set. + */ + public void setIdentifier(java.lang.String value) { + this.identifier = value; + } + + /** + * Gets the value of the 'dayOfWeek' field. + * @return The value of the 'dayOfWeek' field. + */ + public int getDayOfWeek() { + return dayOfWeek; + } + + + /** + * Sets the value of the 'dayOfWeek' field. + * @param value the value to set. + */ + public void setDayOfWeek(int value) { + this.dayOfWeek = value; + } + + /** + * Gets the value of the 'hourOfDay' field. + * @return The value of the 'hourOfDay' field. + */ + public int getHourOfDay() { + return hourOfDay; + } + + + /** + * Sets the value of the 'hourOfDay' field. + * @param value the value to set. + */ + public void setHourOfDay(int value) { + this.hourOfDay = value; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value of the 'periodStart' field. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value the value to set. + */ + public void setPeriodStart(long value) { + this.periodStart = value; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value of the 'periodEnd' field. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value the value to set. + */ + public void setPeriodEnd(long value) { + this.periodEnd = value; + } + + /** + * Gets the value of the 'count' field. + * @return The value of the 'count' field. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value the value to set. + */ + public void setCount(long value) { + this.count = value; + } + + /** + * Gets the value of the 'mean' field. + * @return The value of the 'mean' field. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value the value to set. + */ + public void setMean(double value) { + this.mean = value; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value of the 'populationVariance' field. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value the value to set. + */ + public void setPopulationVariance(double value) { + this.populationVariance = value; + } + + /** + * Gets the value of the 'min' field. + * @return The value of the 'min' field. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value the value to set. + */ + public void setMin(double value) { + this.min = value; + } + + /** + * Gets the value of the 'max' field. + * @return The value of the 'max' field. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value the value to set. + */ + public void setMax(double value) { + this.max = value; + } + + /** + * Creates a new HourOfWeekActivePowerRecord RecordBuilder. + * @return A new HourOfWeekActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder newBuilder() { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder(); + } + + /** + * Creates a new HourOfWeekActivePowerRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new HourOfWeekActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder(other); + } + } + + /** + * Creates a new HourOfWeekActivePowerRecord RecordBuilder by copying an existing HourOfWeekActivePowerRecord instance. + * @param other The existing instance to copy. + * @return A new HourOfWeekActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder(other); + } + } + + /** + * RecordBuilder for HourOfWeekActivePowerRecord instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<HourOfWeekActivePowerRecord> + implements org.apache.avro.data.RecordBuilder<HourOfWeekActivePowerRecord> { + + private java.lang.String identifier; + private int dayOfWeek; + private int hourOfDay; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder other) { + super(other); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.dayOfWeek)) { + this.dayOfWeek = data().deepCopy(fields()[1].schema(), other.dayOfWeek); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.hourOfDay)) { + this.hourOfDay = data().deepCopy(fields()[2].schema(), other.hourOfDay); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[3].schema(), other.periodStart); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[4].schema(), other.periodEnd); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + if (isValidValue(fields()[5], other.count)) { + this.count = data().deepCopy(fields()[5].schema(), other.count); + fieldSetFlags()[5] = other.fieldSetFlags()[5]; + } + if (isValidValue(fields()[6], other.mean)) { + this.mean = data().deepCopy(fields()[6].schema(), other.mean); + fieldSetFlags()[6] = other.fieldSetFlags()[6]; + } + if (isValidValue(fields()[7], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[7].schema(), other.populationVariance); + fieldSetFlags()[7] = other.fieldSetFlags()[7]; + } + if (isValidValue(fields()[8], other.min)) { + this.min = data().deepCopy(fields()[8].schema(), other.min); + fieldSetFlags()[8] = other.fieldSetFlags()[8]; + } + if (isValidValue(fields()[9], other.max)) { + this.max = data().deepCopy(fields()[9].schema(), other.max); + fieldSetFlags()[9] = other.fieldSetFlags()[9]; + } + } + + /** + * Creates a Builder by copying an existing HourOfWeekActivePowerRecord instance + * @param other The existing instance to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.dayOfWeek)) { + this.dayOfWeek = data().deepCopy(fields()[1].schema(), other.dayOfWeek); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.hourOfDay)) { + this.hourOfDay = data().deepCopy(fields()[2].schema(), other.hourOfDay); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[3].schema(), other.periodStart); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[4].schema(), other.periodEnd); + fieldSetFlags()[4] = true; + } + if (isValidValue(fields()[5], other.count)) { + this.count = data().deepCopy(fields()[5].schema(), other.count); + fieldSetFlags()[5] = true; + } + if (isValidValue(fields()[6], other.mean)) { + this.mean = data().deepCopy(fields()[6].schema(), other.mean); + fieldSetFlags()[6] = true; + } + if (isValidValue(fields()[7], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[7].schema(), other.populationVariance); + fieldSetFlags()[7] = true; + } + if (isValidValue(fields()[8], other.min)) { + this.min = data().deepCopy(fields()[8].schema(), other.min); + fieldSetFlags()[8] = true; + } + if (isValidValue(fields()[9], other.max)) { + this.max = data().deepCopy(fields()[9].schema(), other.max); + fieldSetFlags()[9] = true; + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value The value of 'identifier'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setIdentifier(java.lang.String value) { + validate(fields()[0], value); + this.identifier = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'identifier' field has been set. + * @return True if the 'identifier' field has been set, false otherwise. + */ + public boolean hasIdentifier() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'identifier' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearIdentifier() { + identifier = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'dayOfWeek' field. + * @return The value. + */ + public int getDayOfWeek() { + return dayOfWeek; + } + + + /** + * Sets the value of the 'dayOfWeek' field. + * @param value The value of 'dayOfWeek'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setDayOfWeek(int value) { + validate(fields()[1], value); + this.dayOfWeek = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'dayOfWeek' field has been set. + * @return True if the 'dayOfWeek' field has been set, false otherwise. + */ + public boolean hasDayOfWeek() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'dayOfWeek' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearDayOfWeek() { + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'hourOfDay' field. + * @return The value. + */ + public int getHourOfDay() { + return hourOfDay; + } + + + /** + * Sets the value of the 'hourOfDay' field. + * @param value The value of 'hourOfDay'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setHourOfDay(int value) { + validate(fields()[2], value); + this.hourOfDay = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'hourOfDay' field has been set. + * @return True if the 'hourOfDay' field has been set, false otherwise. + */ + public boolean hasHourOfDay() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'hourOfDay' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearHourOfDay() { + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value The value of 'periodStart'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setPeriodStart(long value) { + validate(fields()[3], value); + this.periodStart = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'periodStart' field has been set. + * @return True if the 'periodStart' field has been set, false otherwise. + */ + public boolean hasPeriodStart() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'periodStart' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearPeriodStart() { + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value The value of 'periodEnd'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setPeriodEnd(long value) { + validate(fields()[4], value); + this.periodEnd = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'periodEnd' field has been set. + * @return True if the 'periodEnd' field has been set, false otherwise. + */ + public boolean hasPeriodEnd() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'periodEnd' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearPeriodEnd() { + fieldSetFlags()[4] = false; + return this; + } + + /** + * Gets the value of the 'count' field. + * @return The value. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value The value of 'count'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setCount(long value) { + validate(fields()[5], value); + this.count = value; + fieldSetFlags()[5] = true; + return this; + } + + /** + * Checks whether the 'count' field has been set. + * @return True if the 'count' field has been set, false otherwise. + */ + public boolean hasCount() { + return fieldSetFlags()[5]; + } + + + /** + * Clears the value of the 'count' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearCount() { + fieldSetFlags()[5] = false; + return this; + } + + /** + * Gets the value of the 'mean' field. + * @return The value. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value The value of 'mean'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setMean(double value) { + validate(fields()[6], value); + this.mean = value; + fieldSetFlags()[6] = true; + return this; + } + + /** + * Checks whether the 'mean' field has been set. + * @return True if the 'mean' field has been set, false otherwise. + */ + public boolean hasMean() { + return fieldSetFlags()[6]; + } + + + /** + * Clears the value of the 'mean' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearMean() { + fieldSetFlags()[6] = false; + return this; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value The value of 'populationVariance'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setPopulationVariance(double value) { + validate(fields()[7], value); + this.populationVariance = value; + fieldSetFlags()[7] = true; + return this; + } + + /** + * Checks whether the 'populationVariance' field has been set. + * @return True if the 'populationVariance' field has been set, false otherwise. + */ + public boolean hasPopulationVariance() { + return fieldSetFlags()[7]; + } + + + /** + * Clears the value of the 'populationVariance' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearPopulationVariance() { + fieldSetFlags()[7] = false; + return this; + } + + /** + * Gets the value of the 'min' field. + * @return The value. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value The value of 'min'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setMin(double value) { + validate(fields()[8], value); + this.min = value; + fieldSetFlags()[8] = true; + return this; + } + + /** + * Checks whether the 'min' field has been set. + * @return True if the 'min' field has been set, false otherwise. + */ + public boolean hasMin() { + return fieldSetFlags()[8]; + } + + + /** + * Clears the value of the 'min' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearMin() { + fieldSetFlags()[8] = false; + return this; + } + + /** + * Gets the value of the 'max' field. + * @return The value. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value The value of 'max'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder setMax(double value) { + validate(fields()[9], value); + this.max = value; + fieldSetFlags()[9] = true; + return this; + } + + /** + * Checks whether the 'max' field has been set. + * @return True if the 'max' field has been set, false otherwise. + */ + public boolean hasMax() { + return fieldSetFlags()[9]; + } + + + /** + * Clears the value of the 'max' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.HourOfWeekActivePowerRecord.Builder clearMax() { + fieldSetFlags()[9] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public HourOfWeekActivePowerRecord build() { + try { + HourOfWeekActivePowerRecord record = new HourOfWeekActivePowerRecord(); + record.identifier = fieldSetFlags()[0] ? this.identifier : (java.lang.String) defaultValue(fields()[0]); + record.dayOfWeek = fieldSetFlags()[1] ? this.dayOfWeek : (java.lang.Integer) defaultValue(fields()[1]); + record.hourOfDay = fieldSetFlags()[2] ? this.hourOfDay : (java.lang.Integer) defaultValue(fields()[2]); + record.periodStart = fieldSetFlags()[3] ? this.periodStart : (java.lang.Long) defaultValue(fields()[3]); + record.periodEnd = fieldSetFlags()[4] ? this.periodEnd : (java.lang.Long) defaultValue(fields()[4]); + record.count = fieldSetFlags()[5] ? this.count : (java.lang.Long) defaultValue(fields()[5]); + record.mean = fieldSetFlags()[6] ? this.mean : (java.lang.Double) defaultValue(fields()[6]); + record.populationVariance = fieldSetFlags()[7] ? this.populationVariance : (java.lang.Double) defaultValue(fields()[7]); + record.min = fieldSetFlags()[8] ? this.min : (java.lang.Double) defaultValue(fields()[8]); + record.max = fieldSetFlags()[9] ? this.max : (java.lang.Double) defaultValue(fields()[9]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<HourOfWeekActivePowerRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<HourOfWeekActivePowerRecord>)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<HourOfWeekActivePowerRecord> + READER$ = (org.apache.avro.io.DatumReader<HourOfWeekActivePowerRecord>)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.identifier); + + out.writeInt(this.dayOfWeek); + + out.writeInt(this.hourOfDay); + + out.writeLong(this.periodStart); + + out.writeLong(this.periodEnd); + + out.writeLong(this.count); + + out.writeDouble(this.mean); + + out.writeDouble(this.populationVariance); + + out.writeDouble(this.min); + + out.writeDouble(this.max); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.identifier = in.readString(); + + this.dayOfWeek = in.readInt(); + + this.hourOfDay = in.readInt(); + + this.periodStart = in.readLong(); + + this.periodEnd = in.readLong(); + + this.count = in.readLong(); + + this.mean = in.readDouble(); + + this.populationVariance = in.readDouble(); + + this.min = in.readDouble(); + + this.max = in.readDouble(); + + } else { + for (int i = 0; i < 10; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.identifier = in.readString(); + break; + + case 1: + this.dayOfWeek = in.readInt(); + break; + + case 2: + this.hourOfDay = in.readInt(); + break; + + case 3: + this.periodStart = in.readLong(); + break; + + case 4: + this.periodEnd = in.readLong(); + break; + + case 5: + this.count = in.readLong(); + break; + + case 6: + this.mean = in.readDouble(); + break; + + case 7: + this.populationVariance = in.readDouble(); + break; + + case 8: + this.min = in.readDouble(); + break; + + case 9: + this.max = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/MonthOfYearActivePowerRecord.java b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/MonthOfYearActivePowerRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..4c1cd52fee2fd703e0f98bfdc0bf08b069321952 --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/MonthOfYearActivePowerRecord.java @@ -0,0 +1,945 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package rocks.theodolite.benchmarks.commons.model.records; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class MonthOfYearActivePowerRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = -6007754522109150657L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"MonthOfYearActivePowerRecord\",\"namespace\":\"rocks.theodolite.benchmarks.commons.model.records\",\"fields\":[{\"name\":\"identifier\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"monthOfYear\",\"type\":\"int\"},{\"name\":\"periodStart\",\"type\":\"long\"},{\"name\":\"periodEnd\",\"type\":\"long\"},{\"name\":\"count\",\"type\":\"long\"},{\"name\":\"mean\",\"type\":\"double\"},{\"name\":\"populationVariance\",\"type\":\"double\"},{\"name\":\"min\",\"type\":\"double\"},{\"name\":\"max\",\"type\":\"double\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<MonthOfYearActivePowerRecord> ENCODER = + new BinaryMessageEncoder<MonthOfYearActivePowerRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<MonthOfYearActivePowerRecord> DECODER = + new BinaryMessageDecoder<MonthOfYearActivePowerRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder<MonthOfYearActivePowerRecord> getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<MonthOfYearActivePowerRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<MonthOfYearActivePowerRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<MonthOfYearActivePowerRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this MonthOfYearActivePowerRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a MonthOfYearActivePowerRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a MonthOfYearActivePowerRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static MonthOfYearActivePowerRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private java.lang.String identifier; + private int monthOfYear; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use <code>newBuilder()</code>. + */ + public MonthOfYearActivePowerRecord() {} + + /** + * All-args constructor. + * @param identifier The new value for identifier + * @param monthOfYear The new value for monthOfYear + * @param periodStart The new value for periodStart + * @param periodEnd The new value for periodEnd + * @param count The new value for count + * @param mean The new value for mean + * @param populationVariance The new value for populationVariance + * @param min The new value for min + * @param max The new value for max + */ + public MonthOfYearActivePowerRecord(java.lang.String identifier, java.lang.Integer monthOfYear, java.lang.Long periodStart, java.lang.Long periodEnd, java.lang.Long count, java.lang.Double mean, java.lang.Double populationVariance, java.lang.Double min, java.lang.Double max) { + this.identifier = identifier; + this.monthOfYear = monthOfYear; + this.periodStart = periodStart; + this.periodEnd = periodEnd; + this.count = count; + this.mean = mean; + this.populationVariance = populationVariance; + this.min = min; + this.max = max; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return identifier; + case 1: return monthOfYear; + case 2: return periodStart; + case 3: return periodEnd; + case 4: return count; + case 5: return mean; + case 6: return populationVariance; + case 7: return min; + case 8: return max; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: identifier = value$ != null ? value$.toString() : null; break; + case 1: monthOfYear = (java.lang.Integer)value$; break; + case 2: periodStart = (java.lang.Long)value$; break; + case 3: periodEnd = (java.lang.Long)value$; break; + case 4: count = (java.lang.Long)value$; break; + case 5: mean = (java.lang.Double)value$; break; + case 6: populationVariance = (java.lang.Double)value$; break; + case 7: min = (java.lang.Double)value$; break; + case 8: max = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value of the 'identifier' field. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value the value to set. + */ + public void setIdentifier(java.lang.String value) { + this.identifier = value; + } + + /** + * Gets the value of the 'monthOfYear' field. + * @return The value of the 'monthOfYear' field. + */ + public int getMonthOfYear() { + return monthOfYear; + } + + + /** + * Sets the value of the 'monthOfYear' field. + * @param value the value to set. + */ + public void setMonthOfYear(int value) { + this.monthOfYear = value; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value of the 'periodStart' field. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value the value to set. + */ + public void setPeriodStart(long value) { + this.periodStart = value; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value of the 'periodEnd' field. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value the value to set. + */ + public void setPeriodEnd(long value) { + this.periodEnd = value; + } + + /** + * Gets the value of the 'count' field. + * @return The value of the 'count' field. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value the value to set. + */ + public void setCount(long value) { + this.count = value; + } + + /** + * Gets the value of the 'mean' field. + * @return The value of the 'mean' field. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value the value to set. + */ + public void setMean(double value) { + this.mean = value; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value of the 'populationVariance' field. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value the value to set. + */ + public void setPopulationVariance(double value) { + this.populationVariance = value; + } + + /** + * Gets the value of the 'min' field. + * @return The value of the 'min' field. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value the value to set. + */ + public void setMin(double value) { + this.min = value; + } + + /** + * Gets the value of the 'max' field. + * @return The value of the 'max' field. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value the value to set. + */ + public void setMax(double value) { + this.max = value; + } + + /** + * Creates a new MonthOfYearActivePowerRecord RecordBuilder. + * @return A new MonthOfYearActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder newBuilder() { + return new rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder(); + } + + /** + * Creates a new MonthOfYearActivePowerRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new MonthOfYearActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder(other); + } + } + + /** + * Creates a new MonthOfYearActivePowerRecord RecordBuilder by copying an existing MonthOfYearActivePowerRecord instance. + * @param other The existing instance to copy. + * @return A new MonthOfYearActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder(other); + } + } + + /** + * RecordBuilder for MonthOfYearActivePowerRecord instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<MonthOfYearActivePowerRecord> + implements org.apache.avro.data.RecordBuilder<MonthOfYearActivePowerRecord> { + + private java.lang.String identifier; + private int monthOfYear; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder other) { + super(other); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.monthOfYear)) { + this.monthOfYear = data().deepCopy(fields()[1].schema(), other.monthOfYear); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = other.fieldSetFlags()[5]; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = other.fieldSetFlags()[6]; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = other.fieldSetFlags()[7]; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = other.fieldSetFlags()[8]; + } + } + + /** + * Creates a Builder by copying an existing MonthOfYearActivePowerRecord instance + * @param other The existing instance to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.monthOfYear)) { + this.monthOfYear = data().deepCopy(fields()[1].schema(), other.monthOfYear); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = true; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = true; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = true; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = true; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = true; + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value The value of 'identifier'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setIdentifier(java.lang.String value) { + validate(fields()[0], value); + this.identifier = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'identifier' field has been set. + * @return True if the 'identifier' field has been set, false otherwise. + */ + public boolean hasIdentifier() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'identifier' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearIdentifier() { + identifier = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'monthOfYear' field. + * @return The value. + */ + public int getMonthOfYear() { + return monthOfYear; + } + + + /** + * Sets the value of the 'monthOfYear' field. + * @param value The value of 'monthOfYear'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setMonthOfYear(int value) { + validate(fields()[1], value); + this.monthOfYear = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'monthOfYear' field has been set. + * @return True if the 'monthOfYear' field has been set, false otherwise. + */ + public boolean hasMonthOfYear() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'monthOfYear' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearMonthOfYear() { + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value The value of 'periodStart'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setPeriodStart(long value) { + validate(fields()[2], value); + this.periodStart = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'periodStart' field has been set. + * @return True if the 'periodStart' field has been set, false otherwise. + */ + public boolean hasPeriodStart() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'periodStart' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearPeriodStart() { + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value The value of 'periodEnd'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setPeriodEnd(long value) { + validate(fields()[3], value); + this.periodEnd = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'periodEnd' field has been set. + * @return True if the 'periodEnd' field has been set, false otherwise. + */ + public boolean hasPeriodEnd() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'periodEnd' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearPeriodEnd() { + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'count' field. + * @return The value. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value The value of 'count'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setCount(long value) { + validate(fields()[4], value); + this.count = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'count' field has been set. + * @return True if the 'count' field has been set, false otherwise. + */ + public boolean hasCount() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'count' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearCount() { + fieldSetFlags()[4] = false; + return this; + } + + /** + * Gets the value of the 'mean' field. + * @return The value. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value The value of 'mean'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setMean(double value) { + validate(fields()[5], value); + this.mean = value; + fieldSetFlags()[5] = true; + return this; + } + + /** + * Checks whether the 'mean' field has been set. + * @return True if the 'mean' field has been set, false otherwise. + */ + public boolean hasMean() { + return fieldSetFlags()[5]; + } + + + /** + * Clears the value of the 'mean' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearMean() { + fieldSetFlags()[5] = false; + return this; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value The value of 'populationVariance'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setPopulationVariance(double value) { + validate(fields()[6], value); + this.populationVariance = value; + fieldSetFlags()[6] = true; + return this; + } + + /** + * Checks whether the 'populationVariance' field has been set. + * @return True if the 'populationVariance' field has been set, false otherwise. + */ + public boolean hasPopulationVariance() { + return fieldSetFlags()[6]; + } + + + /** + * Clears the value of the 'populationVariance' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearPopulationVariance() { + fieldSetFlags()[6] = false; + return this; + } + + /** + * Gets the value of the 'min' field. + * @return The value. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value The value of 'min'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setMin(double value) { + validate(fields()[7], value); + this.min = value; + fieldSetFlags()[7] = true; + return this; + } + + /** + * Checks whether the 'min' field has been set. + * @return True if the 'min' field has been set, false otherwise. + */ + public boolean hasMin() { + return fieldSetFlags()[7]; + } + + + /** + * Clears the value of the 'min' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearMin() { + fieldSetFlags()[7] = false; + return this; + } + + /** + * Gets the value of the 'max' field. + * @return The value. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value The value of 'max'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder setMax(double value) { + validate(fields()[8], value); + this.max = value; + fieldSetFlags()[8] = true; + return this; + } + + /** + * Checks whether the 'max' field has been set. + * @return True if the 'max' field has been set, false otherwise. + */ + public boolean hasMax() { + return fieldSetFlags()[8]; + } + + + /** + * Clears the value of the 'max' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.MonthOfYearActivePowerRecord.Builder clearMax() { + fieldSetFlags()[8] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public MonthOfYearActivePowerRecord build() { + try { + MonthOfYearActivePowerRecord record = new MonthOfYearActivePowerRecord(); + record.identifier = fieldSetFlags()[0] ? this.identifier : (java.lang.String) defaultValue(fields()[0]); + record.monthOfYear = fieldSetFlags()[1] ? this.monthOfYear : (java.lang.Integer) defaultValue(fields()[1]); + record.periodStart = fieldSetFlags()[2] ? this.periodStart : (java.lang.Long) defaultValue(fields()[2]); + record.periodEnd = fieldSetFlags()[3] ? this.periodEnd : (java.lang.Long) defaultValue(fields()[3]); + record.count = fieldSetFlags()[4] ? this.count : (java.lang.Long) defaultValue(fields()[4]); + record.mean = fieldSetFlags()[5] ? this.mean : (java.lang.Double) defaultValue(fields()[5]); + record.populationVariance = fieldSetFlags()[6] ? this.populationVariance : (java.lang.Double) defaultValue(fields()[6]); + record.min = fieldSetFlags()[7] ? this.min : (java.lang.Double) defaultValue(fields()[7]); + record.max = fieldSetFlags()[8] ? this.max : (java.lang.Double) defaultValue(fields()[8]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<MonthOfYearActivePowerRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<MonthOfYearActivePowerRecord>)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<MonthOfYearActivePowerRecord> + READER$ = (org.apache.avro.io.DatumReader<MonthOfYearActivePowerRecord>)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.identifier); + + out.writeInt(this.monthOfYear); + + out.writeLong(this.periodStart); + + out.writeLong(this.periodEnd); + + out.writeLong(this.count); + + out.writeDouble(this.mean); + + out.writeDouble(this.populationVariance); + + out.writeDouble(this.min); + + out.writeDouble(this.max); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.identifier = in.readString(); + + this.monthOfYear = in.readInt(); + + this.periodStart = in.readLong(); + + this.periodEnd = in.readLong(); + + this.count = in.readLong(); + + this.mean = in.readDouble(); + + this.populationVariance = in.readDouble(); + + this.min = in.readDouble(); + + this.max = in.readDouble(); + + } else { + for (int i = 0; i < 9; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.identifier = in.readString(); + break; + + case 1: + this.monthOfYear = in.readInt(); + break; + + case 2: + this.periodStart = in.readLong(); + break; + + case 3: + this.periodEnd = in.readLong(); + break; + + case 4: + this.count = in.readLong(); + break; + + case 5: + this.mean = in.readDouble(); + break; + + case 6: + this.populationVariance = in.readDouble(); + break; + + case 7: + this.min = in.readDouble(); + break; + + case 8: + this.max = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/YearActivePowerRecord.java b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/YearActivePowerRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..0471c825551cc048e5e553309ddf2751b6e7ba3d --- /dev/null +++ b/theodolite-benchmarks/commons/src-gen/main/java/rocks/theodolite/benchmarks/commons/model/records/YearActivePowerRecord.java @@ -0,0 +1,945 @@ +/** + * Autogenerated by Avro + * + * DO NOT EDIT DIRECTLY + */ +package rocks.theodolite.benchmarks.commons.model.records; + +import org.apache.avro.generic.GenericArray; +import org.apache.avro.specific.SpecificData; +import org.apache.avro.util.Utf8; +import org.apache.avro.message.BinaryMessageEncoder; +import org.apache.avro.message.BinaryMessageDecoder; +import org.apache.avro.message.SchemaStore; + +@org.apache.avro.specific.AvroGenerated +public class YearActivePowerRecord extends org.apache.avro.specific.SpecificRecordBase implements org.apache.avro.specific.SpecificRecord { + private static final long serialVersionUID = 1269303032337461873L; + + + public static final org.apache.avro.Schema SCHEMA$ = new org.apache.avro.Schema.Parser().parse("{\"type\":\"record\",\"name\":\"YearActivePowerRecord\",\"namespace\":\"rocks.theodolite.benchmarks.commons.model.records\",\"fields\":[{\"name\":\"identifier\",\"type\":{\"type\":\"string\",\"avro.java.string\":\"String\"}},{\"name\":\"year\",\"type\":\"int\"},{\"name\":\"periodStart\",\"type\":\"long\"},{\"name\":\"periodEnd\",\"type\":\"long\"},{\"name\":\"count\",\"type\":\"long\"},{\"name\":\"mean\",\"type\":\"double\"},{\"name\":\"populationVariance\",\"type\":\"double\"},{\"name\":\"min\",\"type\":\"double\"},{\"name\":\"max\",\"type\":\"double\"}]}"); + public static org.apache.avro.Schema getClassSchema() { return SCHEMA$; } + + private static final SpecificData MODEL$ = new SpecificData(); + + private static final BinaryMessageEncoder<YearActivePowerRecord> ENCODER = + new BinaryMessageEncoder<YearActivePowerRecord>(MODEL$, SCHEMA$); + + private static final BinaryMessageDecoder<YearActivePowerRecord> DECODER = + new BinaryMessageDecoder<YearActivePowerRecord>(MODEL$, SCHEMA$); + + /** + * Return the BinaryMessageEncoder instance used by this class. + * @return the message encoder used by this class + */ + public static BinaryMessageEncoder<YearActivePowerRecord> getEncoder() { + return ENCODER; + } + + /** + * Return the BinaryMessageDecoder instance used by this class. + * @return the message decoder used by this class + */ + public static BinaryMessageDecoder<YearActivePowerRecord> getDecoder() { + return DECODER; + } + + /** + * Create a new BinaryMessageDecoder instance for this class that uses the specified {@link SchemaStore}. + * @param resolver a {@link SchemaStore} used to find schemas by fingerprint + * @return a BinaryMessageDecoder instance for this class backed by the given SchemaStore + */ + public static BinaryMessageDecoder<YearActivePowerRecord> createDecoder(SchemaStore resolver) { + return new BinaryMessageDecoder<YearActivePowerRecord>(MODEL$, SCHEMA$, resolver); + } + + /** + * Serializes this YearActivePowerRecord to a ByteBuffer. + * @return a buffer holding the serialized data for this instance + * @throws java.io.IOException if this instance could not be serialized + */ + public java.nio.ByteBuffer toByteBuffer() throws java.io.IOException { + return ENCODER.encode(this); + } + + /** + * Deserializes a YearActivePowerRecord from a ByteBuffer. + * @param b a byte buffer holding serialized data for an instance of this class + * @return a YearActivePowerRecord instance decoded from the given buffer + * @throws java.io.IOException if the given bytes could not be deserialized into an instance of this class + */ + public static YearActivePowerRecord fromByteBuffer( + java.nio.ByteBuffer b) throws java.io.IOException { + return DECODER.decode(b); + } + + private java.lang.String identifier; + private int year; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** + * Default constructor. Note that this does not initialize fields + * to their default values from the schema. If that is desired then + * one should use <code>newBuilder()</code>. + */ + public YearActivePowerRecord() {} + + /** + * All-args constructor. + * @param identifier The new value for identifier + * @param year The new value for year + * @param periodStart The new value for periodStart + * @param periodEnd The new value for periodEnd + * @param count The new value for count + * @param mean The new value for mean + * @param populationVariance The new value for populationVariance + * @param min The new value for min + * @param max The new value for max + */ + public YearActivePowerRecord(java.lang.String identifier, java.lang.Integer year, java.lang.Long periodStart, java.lang.Long periodEnd, java.lang.Long count, java.lang.Double mean, java.lang.Double populationVariance, java.lang.Double min, java.lang.Double max) { + this.identifier = identifier; + this.year = year; + this.periodStart = periodStart; + this.periodEnd = periodEnd; + this.count = count; + this.mean = mean; + this.populationVariance = populationVariance; + this.min = min; + this.max = max; + } + + public org.apache.avro.specific.SpecificData getSpecificData() { return MODEL$; } + public org.apache.avro.Schema getSchema() { return SCHEMA$; } + // Used by DatumWriter. Applications should not call. + public java.lang.Object get(int field$) { + switch (field$) { + case 0: return identifier; + case 1: return year; + case 2: return periodStart; + case 3: return periodEnd; + case 4: return count; + case 5: return mean; + case 6: return populationVariance; + case 7: return min; + case 8: return max; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + // Used by DatumReader. Applications should not call. + @SuppressWarnings(value="unchecked") + public void put(int field$, java.lang.Object value$) { + switch (field$) { + case 0: identifier = value$ != null ? value$.toString() : null; break; + case 1: year = (java.lang.Integer)value$; break; + case 2: periodStart = (java.lang.Long)value$; break; + case 3: periodEnd = (java.lang.Long)value$; break; + case 4: count = (java.lang.Long)value$; break; + case 5: mean = (java.lang.Double)value$; break; + case 6: populationVariance = (java.lang.Double)value$; break; + case 7: min = (java.lang.Double)value$; break; + case 8: max = (java.lang.Double)value$; break; + default: throw new IndexOutOfBoundsException("Invalid index: " + field$); + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value of the 'identifier' field. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value the value to set. + */ + public void setIdentifier(java.lang.String value) { + this.identifier = value; + } + + /** + * Gets the value of the 'year' field. + * @return The value of the 'year' field. + */ + public int getYear() { + return year; + } + + + /** + * Sets the value of the 'year' field. + * @param value the value to set. + */ + public void setYear(int value) { + this.year = value; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value of the 'periodStart' field. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value the value to set. + */ + public void setPeriodStart(long value) { + this.periodStart = value; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value of the 'periodEnd' field. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value the value to set. + */ + public void setPeriodEnd(long value) { + this.periodEnd = value; + } + + /** + * Gets the value of the 'count' field. + * @return The value of the 'count' field. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value the value to set. + */ + public void setCount(long value) { + this.count = value; + } + + /** + * Gets the value of the 'mean' field. + * @return The value of the 'mean' field. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value the value to set. + */ + public void setMean(double value) { + this.mean = value; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value of the 'populationVariance' field. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value the value to set. + */ + public void setPopulationVariance(double value) { + this.populationVariance = value; + } + + /** + * Gets the value of the 'min' field. + * @return The value of the 'min' field. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value the value to set. + */ + public void setMin(double value) { + this.min = value; + } + + /** + * Gets the value of the 'max' field. + * @return The value of the 'max' field. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value the value to set. + */ + public void setMax(double value) { + this.max = value; + } + + /** + * Creates a new YearActivePowerRecord RecordBuilder. + * @return A new YearActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder newBuilder() { + return new rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder(); + } + + /** + * Creates a new YearActivePowerRecord RecordBuilder by copying an existing Builder. + * @param other The existing builder to copy. + * @return A new YearActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder(other); + } + } + + /** + * Creates a new YearActivePowerRecord RecordBuilder by copying an existing YearActivePowerRecord instance. + * @param other The existing instance to copy. + * @return A new YearActivePowerRecord RecordBuilder + */ + public static rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder newBuilder(rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord other) { + if (other == null) { + return new rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder(); + } else { + return new rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder(other); + } + } + + /** + * RecordBuilder for YearActivePowerRecord instances. + */ + @org.apache.avro.specific.AvroGenerated + public static class Builder extends org.apache.avro.specific.SpecificRecordBuilderBase<YearActivePowerRecord> + implements org.apache.avro.data.RecordBuilder<YearActivePowerRecord> { + + private java.lang.String identifier; + private int year; + private long periodStart; + private long periodEnd; + private long count; + private double mean; + private double populationVariance; + private double min; + private double max; + + /** Creates a new Builder */ + private Builder() { + super(SCHEMA$, MODEL$); + } + + /** + * Creates a Builder by copying an existing Builder. + * @param other The existing Builder to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder other) { + super(other); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = other.fieldSetFlags()[0]; + } + if (isValidValue(fields()[1], other.year)) { + this.year = data().deepCopy(fields()[1].schema(), other.year); + fieldSetFlags()[1] = other.fieldSetFlags()[1]; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = other.fieldSetFlags()[2]; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = other.fieldSetFlags()[3]; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = other.fieldSetFlags()[4]; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = other.fieldSetFlags()[5]; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = other.fieldSetFlags()[6]; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = other.fieldSetFlags()[7]; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = other.fieldSetFlags()[8]; + } + } + + /** + * Creates a Builder by copying an existing YearActivePowerRecord instance + * @param other The existing instance to copy. + */ + private Builder(rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord other) { + super(SCHEMA$, MODEL$); + if (isValidValue(fields()[0], other.identifier)) { + this.identifier = data().deepCopy(fields()[0].schema(), other.identifier); + fieldSetFlags()[0] = true; + } + if (isValidValue(fields()[1], other.year)) { + this.year = data().deepCopy(fields()[1].schema(), other.year); + fieldSetFlags()[1] = true; + } + if (isValidValue(fields()[2], other.periodStart)) { + this.periodStart = data().deepCopy(fields()[2].schema(), other.periodStart); + fieldSetFlags()[2] = true; + } + if (isValidValue(fields()[3], other.periodEnd)) { + this.periodEnd = data().deepCopy(fields()[3].schema(), other.periodEnd); + fieldSetFlags()[3] = true; + } + if (isValidValue(fields()[4], other.count)) { + this.count = data().deepCopy(fields()[4].schema(), other.count); + fieldSetFlags()[4] = true; + } + if (isValidValue(fields()[5], other.mean)) { + this.mean = data().deepCopy(fields()[5].schema(), other.mean); + fieldSetFlags()[5] = true; + } + if (isValidValue(fields()[6], other.populationVariance)) { + this.populationVariance = data().deepCopy(fields()[6].schema(), other.populationVariance); + fieldSetFlags()[6] = true; + } + if (isValidValue(fields()[7], other.min)) { + this.min = data().deepCopy(fields()[7].schema(), other.min); + fieldSetFlags()[7] = true; + } + if (isValidValue(fields()[8], other.max)) { + this.max = data().deepCopy(fields()[8].schema(), other.max); + fieldSetFlags()[8] = true; + } + } + + /** + * Gets the value of the 'identifier' field. + * @return The value. + */ + public java.lang.String getIdentifier() { + return identifier; + } + + + /** + * Sets the value of the 'identifier' field. + * @param value The value of 'identifier'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setIdentifier(java.lang.String value) { + validate(fields()[0], value); + this.identifier = value; + fieldSetFlags()[0] = true; + return this; + } + + /** + * Checks whether the 'identifier' field has been set. + * @return True if the 'identifier' field has been set, false otherwise. + */ + public boolean hasIdentifier() { + return fieldSetFlags()[0]; + } + + + /** + * Clears the value of the 'identifier' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearIdentifier() { + identifier = null; + fieldSetFlags()[0] = false; + return this; + } + + /** + * Gets the value of the 'year' field. + * @return The value. + */ + public int getYear() { + return year; + } + + + /** + * Sets the value of the 'year' field. + * @param value The value of 'year'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setYear(int value) { + validate(fields()[1], value); + this.year = value; + fieldSetFlags()[1] = true; + return this; + } + + /** + * Checks whether the 'year' field has been set. + * @return True if the 'year' field has been set, false otherwise. + */ + public boolean hasYear() { + return fieldSetFlags()[1]; + } + + + /** + * Clears the value of the 'year' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearYear() { + fieldSetFlags()[1] = false; + return this; + } + + /** + * Gets the value of the 'periodStart' field. + * @return The value. + */ + public long getPeriodStart() { + return periodStart; + } + + + /** + * Sets the value of the 'periodStart' field. + * @param value The value of 'periodStart'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setPeriodStart(long value) { + validate(fields()[2], value); + this.periodStart = value; + fieldSetFlags()[2] = true; + return this; + } + + /** + * Checks whether the 'periodStart' field has been set. + * @return True if the 'periodStart' field has been set, false otherwise. + */ + public boolean hasPeriodStart() { + return fieldSetFlags()[2]; + } + + + /** + * Clears the value of the 'periodStart' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearPeriodStart() { + fieldSetFlags()[2] = false; + return this; + } + + /** + * Gets the value of the 'periodEnd' field. + * @return The value. + */ + public long getPeriodEnd() { + return periodEnd; + } + + + /** + * Sets the value of the 'periodEnd' field. + * @param value The value of 'periodEnd'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setPeriodEnd(long value) { + validate(fields()[3], value); + this.periodEnd = value; + fieldSetFlags()[3] = true; + return this; + } + + /** + * Checks whether the 'periodEnd' field has been set. + * @return True if the 'periodEnd' field has been set, false otherwise. + */ + public boolean hasPeriodEnd() { + return fieldSetFlags()[3]; + } + + + /** + * Clears the value of the 'periodEnd' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearPeriodEnd() { + fieldSetFlags()[3] = false; + return this; + } + + /** + * Gets the value of the 'count' field. + * @return The value. + */ + public long getCount() { + return count; + } + + + /** + * Sets the value of the 'count' field. + * @param value The value of 'count'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setCount(long value) { + validate(fields()[4], value); + this.count = value; + fieldSetFlags()[4] = true; + return this; + } + + /** + * Checks whether the 'count' field has been set. + * @return True if the 'count' field has been set, false otherwise. + */ + public boolean hasCount() { + return fieldSetFlags()[4]; + } + + + /** + * Clears the value of the 'count' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearCount() { + fieldSetFlags()[4] = false; + return this; + } + + /** + * Gets the value of the 'mean' field. + * @return The value. + */ + public double getMean() { + return mean; + } + + + /** + * Sets the value of the 'mean' field. + * @param value The value of 'mean'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setMean(double value) { + validate(fields()[5], value); + this.mean = value; + fieldSetFlags()[5] = true; + return this; + } + + /** + * Checks whether the 'mean' field has been set. + * @return True if the 'mean' field has been set, false otherwise. + */ + public boolean hasMean() { + return fieldSetFlags()[5]; + } + + + /** + * Clears the value of the 'mean' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearMean() { + fieldSetFlags()[5] = false; + return this; + } + + /** + * Gets the value of the 'populationVariance' field. + * @return The value. + */ + public double getPopulationVariance() { + return populationVariance; + } + + + /** + * Sets the value of the 'populationVariance' field. + * @param value The value of 'populationVariance'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setPopulationVariance(double value) { + validate(fields()[6], value); + this.populationVariance = value; + fieldSetFlags()[6] = true; + return this; + } + + /** + * Checks whether the 'populationVariance' field has been set. + * @return True if the 'populationVariance' field has been set, false otherwise. + */ + public boolean hasPopulationVariance() { + return fieldSetFlags()[6]; + } + + + /** + * Clears the value of the 'populationVariance' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearPopulationVariance() { + fieldSetFlags()[6] = false; + return this; + } + + /** + * Gets the value of the 'min' field. + * @return The value. + */ + public double getMin() { + return min; + } + + + /** + * Sets the value of the 'min' field. + * @param value The value of 'min'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setMin(double value) { + validate(fields()[7], value); + this.min = value; + fieldSetFlags()[7] = true; + return this; + } + + /** + * Checks whether the 'min' field has been set. + * @return True if the 'min' field has been set, false otherwise. + */ + public boolean hasMin() { + return fieldSetFlags()[7]; + } + + + /** + * Clears the value of the 'min' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearMin() { + fieldSetFlags()[7] = false; + return this; + } + + /** + * Gets the value of the 'max' field. + * @return The value. + */ + public double getMax() { + return max; + } + + + /** + * Sets the value of the 'max' field. + * @param value The value of 'max'. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder setMax(double value) { + validate(fields()[8], value); + this.max = value; + fieldSetFlags()[8] = true; + return this; + } + + /** + * Checks whether the 'max' field has been set. + * @return True if the 'max' field has been set, false otherwise. + */ + public boolean hasMax() { + return fieldSetFlags()[8]; + } + + + /** + * Clears the value of the 'max' field. + * @return This builder. + */ + public rocks.theodolite.benchmarks.commons.model.records.YearActivePowerRecord.Builder clearMax() { + fieldSetFlags()[8] = false; + return this; + } + + @Override + @SuppressWarnings("unchecked") + public YearActivePowerRecord build() { + try { + YearActivePowerRecord record = new YearActivePowerRecord(); + record.identifier = fieldSetFlags()[0] ? this.identifier : (java.lang.String) defaultValue(fields()[0]); + record.year = fieldSetFlags()[1] ? this.year : (java.lang.Integer) defaultValue(fields()[1]); + record.periodStart = fieldSetFlags()[2] ? this.periodStart : (java.lang.Long) defaultValue(fields()[2]); + record.periodEnd = fieldSetFlags()[3] ? this.periodEnd : (java.lang.Long) defaultValue(fields()[3]); + record.count = fieldSetFlags()[4] ? this.count : (java.lang.Long) defaultValue(fields()[4]); + record.mean = fieldSetFlags()[5] ? this.mean : (java.lang.Double) defaultValue(fields()[5]); + record.populationVariance = fieldSetFlags()[6] ? this.populationVariance : (java.lang.Double) defaultValue(fields()[6]); + record.min = fieldSetFlags()[7] ? this.min : (java.lang.Double) defaultValue(fields()[7]); + record.max = fieldSetFlags()[8] ? this.max : (java.lang.Double) defaultValue(fields()[8]); + return record; + } catch (org.apache.avro.AvroMissingFieldException e) { + throw e; + } catch (java.lang.Exception e) { + throw new org.apache.avro.AvroRuntimeException(e); + } + } + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumWriter<YearActivePowerRecord> + WRITER$ = (org.apache.avro.io.DatumWriter<YearActivePowerRecord>)MODEL$.createDatumWriter(SCHEMA$); + + @Override public void writeExternal(java.io.ObjectOutput out) + throws java.io.IOException { + WRITER$.write(this, SpecificData.getEncoder(out)); + } + + @SuppressWarnings("unchecked") + private static final org.apache.avro.io.DatumReader<YearActivePowerRecord> + READER$ = (org.apache.avro.io.DatumReader<YearActivePowerRecord>)MODEL$.createDatumReader(SCHEMA$); + + @Override public void readExternal(java.io.ObjectInput in) + throws java.io.IOException { + READER$.read(this, SpecificData.getDecoder(in)); + } + + @Override protected boolean hasCustomCoders() { return true; } + + @Override public void customEncode(org.apache.avro.io.Encoder out) + throws java.io.IOException + { + out.writeString(this.identifier); + + out.writeInt(this.year); + + out.writeLong(this.periodStart); + + out.writeLong(this.periodEnd); + + out.writeLong(this.count); + + out.writeDouble(this.mean); + + out.writeDouble(this.populationVariance); + + out.writeDouble(this.min); + + out.writeDouble(this.max); + + } + + @Override public void customDecode(org.apache.avro.io.ResolvingDecoder in) + throws java.io.IOException + { + org.apache.avro.Schema.Field[] fieldOrder = in.readFieldOrderIfDiff(); + if (fieldOrder == null) { + this.identifier = in.readString(); + + this.year = in.readInt(); + + this.periodStart = in.readLong(); + + this.periodEnd = in.readLong(); + + this.count = in.readLong(); + + this.mean = in.readDouble(); + + this.populationVariance = in.readDouble(); + + this.min = in.readDouble(); + + this.max = in.readDouble(); + + } else { + for (int i = 0; i < 9; i++) { + switch (fieldOrder[i].pos()) { + case 0: + this.identifier = in.readString(); + break; + + case 1: + this.year = in.readInt(); + break; + + case 2: + this.periodStart = in.readLong(); + break; + + case 3: + this.periodEnd = in.readLong(); + break; + + case 4: + this.count = in.readLong(); + break; + + case 5: + this.mean = in.readDouble(); + break; + + case 6: + this.populationVariance = in.readDouble(); + break; + + case 7: + this.min = in.readDouble(); + break; + + case 8: + this.max = in.readDouble(); + break; + + default: + throw new java.io.IOException("Corrupt ResolvingDecoder."); + } + } + } + } +} + + + + + + + + + + diff --git a/theodolite-benchmarks/commons/src/main/avro/ActivePower.avdl b/theodolite-benchmarks/commons/src/main/avro/ActivePower.avdl new file mode 100644 index 0000000000000000000000000000000000000000..6ee82d6becc6393617d569de27d0b162f892e192 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/avro/ActivePower.avdl @@ -0,0 +1,19 @@ +@namespace("rocks.theodolite.benchmarks.commons.model.records") +protocol ActivePower { + + record ActivePowerRecord { + /** + * + */ + string identifier; + /** + * + */ + long timestamp; + /** + * + */ + double valueInW; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/avro/AggregatedActivePower.avdl b/theodolite-benchmarks/commons/src/main/avro/AggregatedActivePower.avdl new file mode 100644 index 0000000000000000000000000000000000000000..571f30f3247cae7c829aaa7742a37f8f3c89cfed --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/avro/AggregatedActivePower.avdl @@ -0,0 +1,27 @@ +@namespace("rocks.theodolite.benchmarks.commons.model.records") +protocol AggregatedActivePower { + + record AggregatedActivePowerRecord { + /** + * + */ + string identifier; + /** + * + */ + long timestamp; + /** + * + */ + long count; + /** + * + */ + double sumInW; + /** + * + */ + double averageInW; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/avro/StatsActivePower.avdl b/theodolite-benchmarks/commons/src/main/avro/StatsActivePower.avdl new file mode 100644 index 0000000000000000000000000000000000000000..9f4c6360661a6b40f267a17ae8205b8178044895 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/avro/StatsActivePower.avdl @@ -0,0 +1,65 @@ +@namespace("rocks.theodolite.benchmarks.commons.model.records") +protocol StatsActivePower { + + record HourOfDayActivePowerRecord { + string identifier; + int hourOfDay; + long periodStart; + long periodEnd; + long count; + double mean; + double populationVariance; + double min; + double max; + } + + record DayOfWeekActivePowerRecord { + string identifier; + int dayOfWeek; + long periodStart; + long periodEnd; + long count; + double mean; + double populationVariance; + double min; + double max; + } + + record HourOfWeekActivePowerRecord { + string identifier; + int dayOfWeek; + int hourOfDay; + long periodStart; + long periodEnd; + long count; + double mean; + double populationVariance; + double min; + double max; + } + + record MonthOfYearActivePowerRecord { + string identifier; + int monthOfYear; + long periodStart; + long periodEnd; + long count; + double mean; + double populationVariance; + double min; + double max; + } + + record YearActivePowerRecord { + string identifier; + int year; + long periodStart; + long periodEnd; + long count; + double mean; + double populationVariance; + double min; + double max; + } + +} \ No newline at end of file diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/commons/configuration/NameResolvingEnvironmentConfiguration.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/commons/configuration/NameResolvingEnvironmentConfiguration.java new file mode 100644 index 0000000000000000000000000000000000000000..fb29d078d2fb5125103188247f1673a1da766536 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/commons/configuration/NameResolvingEnvironmentConfiguration.java @@ -0,0 +1,34 @@ +package rocks.theodolite.benchmarks.commons.commons.configuration; + +import java.util.Locale; +import org.apache.commons.configuration2.EnvironmentConfiguration; + +/** + * {@link EnvironmentConfiguration} that automatically translates Java property file style variables + * ({@code my.variable.name}) to environment style variables ({@code MY__VARIABLE_NAME}). + */ +public class NameResolvingEnvironmentConfiguration extends EnvironmentConfiguration { + + @Override + protected Object getPropertyInternal(final String key) { + final Object value = super.getPropertyInternal(key); + if (value == null) { + return super.getPropertyInternal(formatKeyAsEnvVariable(key)); + } + return value; + } + + @Override + protected boolean containsKeyInternal(final String key) { + final boolean value = super.containsKeyInternal(key); + if (!value) { + return super.containsKeyInternal(formatKeyAsEnvVariable(key)); + } + return value; + } + + public static String formatKeyAsEnvVariable(final String key) { + return key.toUpperCase(Locale.ROOT).replace('.', '_'); + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/commons/configuration/ServiceConfigurations.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/commons/configuration/ServiceConfigurations.java new file mode 100644 index 0000000000000000000000000000000000000000..6ad0703697aa02f641c9b86f7384bfd9b9e1956c --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/commons/configuration/ServiceConfigurations.java @@ -0,0 +1,120 @@ +package rocks.theodolite.benchmarks.commons.commons.configuration; + +import com.google.common.io.Resources; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.apache.commons.configuration2.CompositeConfiguration; +import org.apache.commons.configuration2.Configuration; +import org.apache.commons.configuration2.ex.ConfigurationException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Helper class for creating {@link Configuration}s. + */ +public final class ServiceConfigurations { + + private static final Logger LOGGER = LoggerFactory.getLogger(ServiceConfigurations.class); + + private static final String DEFAULT_PROPERTIES_LOCATION = "META-INF/application.properties"; + private static final String USER_PROPERTIES_LOCATION = "config/application.properties"; + + private ServiceConfigurations() {} + + /** + * Create a {@link Configuration} as it typically used by microservices. More precisely, this + * means when trying to access value with a particular key, this configuration first looks for + * this key in the current environment variables, then in a properties file located in + * {@code config/application.properties}, and finally for a properties file in the classpath at + * {@code META-INF/application.properties}. + * + * @see NameResolvingEnvironmentConfiguration for details regarding the environemnt variable + * lookup. + */ + public static Configuration createWithDefaults() { + return builder() + .withEnvironmentVariables() + .withUserConfigurationFile(USER_PROPERTIES_LOCATION) + .withDefaultConfigurationFile(DEFAULT_PROPERTIES_LOCATION) + .build(); + } + + public static Builder builder() { + return new Builder(); + } + + /** + * Builder class for a {@link Configuration} for a microservice. + */ + public static class Builder { + + private final CompositeConfiguration configuration = new CompositeConfiguration(); + + private Builder() {} + + public Builder withEnvironmentVariables() { + this.configuration.addConfiguration(new NameResolvingEnvironmentConfiguration()); + return this; + } + + /** + * Add a properties file from the user's file system to the {@link Configuration}. + */ + public Builder withUserConfigurationFile(final String userPropertiesLocation) { + final Path path = Paths.get(userPropertiesLocation); + LOGGER.info("Looking for user configuration at {}", userPropertiesLocation); + if (Files.exists(path)) { + LOGGER.info("Found user configuration at {}", userPropertiesLocation); + try { + this.configuration.addConfiguration(configurations().properties(path.toFile())); + } catch (final ConfigurationException e) { + throw new IllegalArgumentException( + "Cannot load configuration from file '" + userPropertiesLocation + "'", e); + } + } else { + LOGGER.info("No user configuration found at {}", userPropertiesLocation); + } + return this; + } + + /** + * Add a properties file from the class path to the {@link Configuration}. + */ + public Builder withDefaultConfigurationFile(final String defaultPropertiesLocation) { + if (resourceExists(defaultPropertiesLocation)) { + try { + this.configuration + .addConfiguration(configurations().properties(defaultPropertiesLocation)); + } catch (final ConfigurationException e) { + throw new IllegalArgumentException( + "Cannot load configuration from ressource '" + defaultPropertiesLocation + "'", e); + } + } + return this; + } + + public Configuration build() { + return this.configuration; + } + + } + + /** + * Shortcut for long class name. + */ + private static org.apache.commons.configuration2.builder.fluent.Configurations configurations() { + // TODO Refactor when Configurations class is removed + return new org.apache.commons.configuration2.builder.fluent.Configurations(); + } + + private static boolean resourceExists(final String resourceName) { + try { + Resources.getResource(resourceName); + } catch (final IllegalArgumentException e) { + return false; + } + return true; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/configuration/events/Event.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/configuration/events/Event.java new file mode 100644 index 0000000000000000000000000000000000000000..895b3401c5d59abb6863caa246414e9ead69d773 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/configuration/events/Event.java @@ -0,0 +1,13 @@ +package rocks.theodolite.benchmarks.commons.configuration.events; + +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; + +/** + * Events that could occur when modifying a {@link SensorRegistry}. Currently only a general change + * event and a status posting event are supported. + */ +public enum Event { + + SENSOR_REGISTRY_CHANGED, SENSOR_REGISTRY_STATUS; + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/configuration/events/EventSerde.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/configuration/events/EventSerde.java new file mode 100644 index 0000000000000000000000000000000000000000..50a3faad61d6c6179efe983b0c172e66e0d28367 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/configuration/events/EventSerde.java @@ -0,0 +1,81 @@ +package rocks.theodolite.benchmarks.commons.configuration.events; + +import java.nio.ByteBuffer; +import java.util.Map; +import org.apache.kafka.common.serialization.ByteBufferDeserializer; +import org.apache.kafka.common.serialization.ByteBufferSerializer; +import org.apache.kafka.common.serialization.Deserializer; +import org.apache.kafka.common.serialization.Serde; +import org.apache.kafka.common.serialization.Serdes; +import org.apache.kafka.common.serialization.Serializer; + +/** + * Provides factory methods for creating Kafka serializers and deserializers for {@link Event}s. + */ +public final class EventSerde { + + private EventSerde() {} + + public static Serde<Event> serde() { + return Serdes.serdeFrom(new EventSerializer(), new EventDeserializer()); + } + + public static Serializer<Event> serializer() { + return new EventSerializer(); + } + + public static Deserializer<Event> deserializer() { + return new EventDeserializer(); + } + + private static class EventSerializer implements Serializer<Event> { + + private static final int INT_SIZE = 4; + + private final ByteBufferSerializer byteBufferSerializer = new ByteBufferSerializer(); + + @Override + public void configure(final Map<String, ?> configs, final boolean isKey) { + this.byteBufferSerializer.configure(configs, isKey); + } + + @Override + public byte[] serialize(final String topic, final Event event) { + return this.byteBufferSerializer.serialize(topic, + ByteBuffer.allocate(INT_SIZE).putInt(event.ordinal())); + } + + @Override + public void close() { + this.byteBufferSerializer.close(); + } + + } + + private static class EventDeserializer implements Deserializer<Event> { + + private final ByteBufferDeserializer byteBufferDeserializer = new ByteBufferDeserializer(); + + @Override + public void configure(final Map<String, ?> configs, final boolean isKey) { + this.byteBufferDeserializer.configure(configs, isKey); + } + + @Override + public Event deserialize(final String topic, final byte[] data) { + final int ordinal = this.byteBufferDeserializer.deserialize(topic, data).getInt(); + for (final Event event : Event.values()) { + if (ordinal == event.ordinal()) { + return event; + } + } + throw new IllegalArgumentException("Deserialized data is not a valid event."); + } + + @Override + public void close() { + this.byteBufferDeserializer.close(); + } + + } +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/avro/SchemaRegistryAvroSerdeFactory.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/avro/SchemaRegistryAvroSerdeFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..9f3d5721efd90000b9265b593be5656b989c4f44 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/avro/SchemaRegistryAvroSerdeFactory.java @@ -0,0 +1,39 @@ +package rocks.theodolite.benchmarks.commons.kafka.avro; + +import io.confluent.kafka.serializers.AbstractKafkaAvroSerDeConfig; +import io.confluent.kafka.streams.serdes.avro.SpecificAvroSerde; +import java.util.Collections; +import java.util.Map; +import org.apache.avro.specific.SpecificRecord; +import org.apache.kafka.common.serialization.Serde; + +/** + * Factory methods to create {@link Serde}s for Avro records using the Confluent Schema Registry. + */ +public final class SchemaRegistryAvroSerdeFactory { + + private static final String SCHEMA_REGISTRY_URL_KEY = + AbstractKafkaAvroSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG; + + private final Map<String, String> serdeConfig; + + public SchemaRegistryAvroSerdeFactory(final String schemaRegistryUrl) { + this.serdeConfig = Collections.singletonMap(SCHEMA_REGISTRY_URL_KEY, schemaRegistryUrl); + + } + + public <T extends SpecificRecord> Serde<T> forKeys() { + return this.build(true); + } + + public <T extends SpecificRecord> Serde<T> forValues() { + return this.build(false); + } + + private <T extends SpecificRecord> Serde<T> build(final boolean isKey) { + final Serde<T> avroSerde = new SpecificAvroSerde<>(); + avroSerde.configure(this.serdeConfig, isKey); + return avroSerde; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferConstants.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferConstants.java new file mode 100644 index 0000000000000000000000000000000000000000..b29c05359d04ebf2552da7a3c3a6b915ede1cd35 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferConstants.java @@ -0,0 +1,18 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +import java.nio.charset.Charset; + +/** + * Shared constants between {@link WriteBuffer} and {@link ReadBuffer}. + */ +public final class BufferConstants { + + public static final Charset CHARSET = Charset.forName("UTF-8"); + + public static final byte BOOLEAN_FALSE = 0; + + public static final byte BOOLEAN_TRUE = 1; + + private BufferConstants() {} + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferDeserializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferDeserializer.java new file mode 100644 index 0000000000000000000000000000000000000000..88fba611be5600d3a5557b34d5244e523dcbb017 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferDeserializer.java @@ -0,0 +1,13 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +/** + * Deserializer to deserialize a {@link ReadBuffer} to an object. + * + * @param <T> the type of the deserialized object + */ +@FunctionalInterface +public interface BufferDeserializer<T> { + + T deserialize(ReadBuffer buffer); + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferSerde.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferSerde.java new file mode 100644 index 0000000000000000000000000000000000000000..e14f03e2b36e5551911536f2dff20f70e8efe08a --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferSerde.java @@ -0,0 +1,11 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +/** + * Combine {@link BufferSerializer} and {@link BufferDeserializer} into one type. This allows + * implementing a serde in one class. + * + * @param <T> Type of the serializer and deserializer. + */ +public interface BufferSerde<T> extends BufferSerializer<T>, BufferDeserializer<T> { + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferSerializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..9c7353a64a39839f183ad4153f369e3d33bcfe5b --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/BufferSerializer.java @@ -0,0 +1,13 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +/** + * Serializer to serialize an object to a {@link WriteBuffer}. + * + * @param <T> the type of the serialized object + */ +@FunctionalInterface +public interface BufferSerializer<T> { + + void serialize(WriteBuffer buffer, T data); + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/ReadBuffer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/ReadBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..cf0e7af93c31b20e7136d4f6b1c870691cd4801d --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/ReadBuffer.java @@ -0,0 +1,67 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +import java.nio.ByteBuffer; + +/** + * A buffer that is constructed from a byte array and data can be sequentially read to different + * kinds of data types. It is the counterpart to {@link WriteBuffer}. + */ +public class ReadBuffer { + + private final ByteBuffer buffer; + + /** + * Create this buffer by a byte array. + */ + public ReadBuffer(final byte[] bytes) { + this.buffer = ByteBuffer.wrap(bytes); + } + + public byte getByte() { + return this.buffer.get(); + } + + /** + * Get a byte array. + */ + public byte[] getBytes() { + final int bytesLength = this.buffer.getInt(); + final byte[] bytes = new byte[bytesLength]; + this.buffer.get(bytes); + return bytes; + } + + public boolean getBoolean() { // NOPMD + return this.getByte() == BufferConstants.BOOLEAN_TRUE; + } + + public short getShort() { // NOPMD + return this.buffer.getShort(); + } + + public int getInt() { + return this.buffer.getInt(); + } + + public long getLong() { + return this.buffer.getLong(); + } + + public float getFloat() { + return this.buffer.getFloat(); + } + + public double getDouble() { + return this.buffer.getDouble(); + } + + public int getChar() { + return this.buffer.getChar(); + } + + public String getString() { + final byte[] bytes = this.getBytes(); + return new String(bytes, BufferConstants.CHARSET); + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleDeserializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleDeserializer.java new file mode 100644 index 0000000000000000000000000000000000000000..d3d2b6756c417f62c85bfd5a269d0d47d36daa7c --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleDeserializer.java @@ -0,0 +1,38 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +import java.util.Map; +import org.apache.kafka.common.serialization.Deserializer; + +/** + * Kafka {@link Deserializer} to be configured with a {@link BufferDeserializer} for simpler usage. + * + * @param <T> the type of the deserialized object + */ +public class SimpleDeserializer<T> implements Deserializer<T> { + + private final BufferDeserializer<T> deserializer; + + public SimpleDeserializer(final BufferDeserializer<T> deserializer) { + this.deserializer = deserializer; + } + + @Override + public void configure(final Map<String, ?> configs, final boolean isKey) { + // Do nothing + } + + @Override + public T deserialize(final String topic, final byte[] bytes) { + if (bytes == null) { + return null; + } + final ReadBuffer buffer = new ReadBuffer(bytes); + return this.deserializer.deserialize(buffer); + } + + @Override + public void close() { + // Do nothing + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleSerdes.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleSerdes.java new file mode 100644 index 0000000000000000000000000000000000000000..ae1c0530f8283122451b7e20d32f56300cdf6ef7 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleSerdes.java @@ -0,0 +1,24 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +import org.apache.kafka.common.serialization.Serde; +import org.apache.kafka.common.serialization.Serdes; + +/** + * Factory class to create <i>Simple Serdes</i>. These are serdes created from a + * {@link BufferSerializer} and a {@link BufferDeserializer}. + */ +public final class SimpleSerdes { + + private SimpleSerdes() {} + + public static <T> Serde<T> create(final BufferSerde<T> serde) { + return Serdes.serdeFrom(new SimpleSerializer<>(serde), new SimpleDeserializer<>(serde)); + } + + public static <T> Serde<T> create(final BufferSerializer<T> serializer, + final BufferDeserializer<T> deserializer) { + return Serdes.serdeFrom(new SimpleSerializer<>(serializer), + new SimpleDeserializer<>(deserializer)); + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleSerializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..4ed3d91f74a3ad6bc3a0ff8f52d91e53a741e65d --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/SimpleSerializer.java @@ -0,0 +1,39 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +import java.util.Map; +import org.apache.kafka.common.serialization.Serializer; + +/** + * Kafka {@link Serializer} to be configured with a {@link BufferSerializer} for simpler usage. + * + * @param <T> the type of the serialized objects + */ +public class SimpleSerializer<T> implements Serializer<T> { + + private final BufferSerializer<T> serializer; + + public SimpleSerializer(final BufferSerializer<T> serializer) { + this.serializer = serializer; + } + + @Override + public void configure(final Map<String, ?> configs, final boolean isKey) { + // Do nothing + } + + @Override + public byte[] serialize(final String topic, final T data) { + if (data == null) { + return null; + } + final WriteBuffer buffer = new WriteBuffer(); + this.serializer.serialize(buffer, data); + return buffer.getBytes(); + } + + @Override + public void close() { + // Do nothing + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/WriteBuffer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/WriteBuffer.java new file mode 100644 index 0000000000000000000000000000000000000000..144b125f031250c09900360898f98f871643f036 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/kafka/simpleserdes/WriteBuffer.java @@ -0,0 +1,69 @@ +package rocks.theodolite.benchmarks.commons.kafka.simpleserdes; + +import java.nio.ByteBuffer; + +/** + * A buffer to which different kinds of data types can be written and its content can be returned as + * bytes. Its counterpart is a {@link ReadBuffer} which allows to read the data in the order it is + * written. + */ +public class WriteBuffer { + + private static final int BYTE_BUFFER_CAPACITY = 65_536; // Is only virtual memory + + private final ByteBuffer buffer = ByteBuffer.allocateDirect(BYTE_BUFFER_CAPACITY); + + public void putByte(final byte value) { + this.buffer.put(value); + } + + public void putBytes(final byte[] value) { + this.buffer.putInt(value.length); + this.buffer.put(value); + } + + public void putBoolean(final boolean value) { + this.putByte( + value ? BufferConstants.BOOLEAN_TRUE : BufferConstants.BOOLEAN_FALSE); + } + + public void putShort(final short value) { // NOPMD + this.buffer.putShort(value); + } + + public void putInt(final int value) { + this.buffer.putInt(value); + } + + public void putLong(final long value) { + this.buffer.putLong(value); + } + + public void putFloat(final float value) { + this.buffer.putFloat(value); + } + + public void putDouble(final double value) { + this.buffer.putDouble(value); + } + + public void putChar(final char value) { + this.buffer.putChar(value); + } + + public void putString(final String value) { + final byte[] bytes = value.getBytes(BufferConstants.CHARSET); + this.putBytes(bytes); + } + + /** + * Get the content of this buffer as bytes. + */ + public byte[] getBytes() { + this.buffer.flip(); + final byte[] bytes = new byte[this.buffer.remaining()]; + this.buffer.get(bytes, 0, bytes.length); + return bytes; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/AbstractSensor.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/AbstractSensor.java new file mode 100644 index 0000000000000000000000000000000000000000..3dad538bb9ddb41959511ee41591d069450b7f69 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/AbstractSensor.java @@ -0,0 +1,35 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.Optional; + +abstract class AbstractSensor implements Sensor { + + private final AggregatedSensor parent; + + private final String identifier; + + private final String name; + + protected AbstractSensor(final AggregatedSensor parent, final String identifier, + final String name) { + this.parent = parent; + this.identifier = identifier; + this.name = name; + } + + @Override + public Optional<AggregatedSensor> getParent() { + return Optional.ofNullable(this.parent); + } + + @Override + public String getIdentifier() { + return this.identifier; + } + + @Override + public String getName() { + return this.name; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/AggregatedSensor.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/AggregatedSensor.java new file mode 100644 index 0000000000000000000000000000000000000000..fa8717ded4643f2350174e4c26dd10ffe608d2ac --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/AggregatedSensor.java @@ -0,0 +1,56 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; + +/** + * Representing an aggregated sensor in the {@link SensorRegistry}, i.e. one that may have child + * sensors. + */ +public interface AggregatedSensor extends Sensor { + + Collection<Sensor> getChildren(); + + /** + * Returns all {@link MachineSensor}s that are children (including grandchildren etc.) of this + * aggregated sensor. In other words, it returns all leaves located below this aggregated sensor + * in the corresponding {@link SensorRegistry}. + */ + default Collection<MachineSensor> getAllChildren() { + final List<MachineSensor> allChildren = new ArrayList<>(); + final Queue<Sensor> untraversedSensors = new LinkedList<>(this.getChildren()); + while (!untraversedSensors.isEmpty()) { + final Sensor sensor = untraversedSensors.poll(); + if (sensor instanceof MachineSensor) { + allChildren.add((MachineSensor) sensor); + } else if (sensor instanceof AggregatedSensor) { + untraversedSensors.addAll(((AggregatedSensor) sensor).getChildren()); + } + } + return allChildren; + } + + /** + * Flattens this {@link AggregatedSensor} and all of its children to a collection of + * {@link Sensor}s. + * + * @return A collection containing this {@link AggregatedSensor} and all of its children. + */ + default Collection<Sensor> flatten() { + final List<Sensor> accumulator = new ArrayList<>(); + final Queue<Sensor> untraversedSensors = new LinkedList<>(); + untraversedSensors.add(this); + while (!untraversedSensors.isEmpty()) { + final Sensor sensor = untraversedSensors.poll(); + accumulator.add(sensor); + if (sensor instanceof AggregatedSensor) { + untraversedSensors.addAll(((AggregatedSensor) sensor).getChildren()); + } + } + return accumulator; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ImmutableSensorRegistry.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ImmutableSensorRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..bac00a0c0c4086c1e3847619e5603f020ca78e8a --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ImmutableSensorRegistry.java @@ -0,0 +1,145 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList.Builder; +import com.google.common.collect.ImmutableMap; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.util.Collection; +import java.util.Objects; +import java.util.Optional; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.AggregatedSensorSerializer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.MachineSensorSerializer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.SensorRegistryDeserializer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.SensorRegistrySerializer; + +/** + * Implementation of a {@link SensorRegistry} that is immutable. + */ +public final class ImmutableSensorRegistry implements SensorRegistry { + + private static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(ImmutableSensorRegistry.class, new SensorRegistrySerializer()) + .registerTypeAdapter(ImmutableSensorRegistry.ImmutableAggregatatedSensor.class, + new AggregatedSensorSerializer()) + .registerTypeAdapter(MachineSensorImpl.class, new MachineSensorSerializer()) + .registerTypeAdapter(SensorRegistry.class, new SensorRegistryDeserializer()).create(); + + private final ImmutableMap<String, MachineSensor> machineSensors; + private final AggregatedSensor topLevelSensor; + + private ImmutableSensorRegistry(final SensorRegistry sensorRegistry) { + final ImmutableMap.Builder<String, MachineSensor> mapBuilder = ImmutableMap.builder(); + this.topLevelSensor = + new ImmutableAggregatatedSensor(null, sensorRegistry.getTopLevelSensor(), mapBuilder); + this.machineSensors = mapBuilder.build(); + } + + @Override + public Optional<MachineSensor> getSensorForIdentifier(final String identifier) { + return Optional.ofNullable(this.machineSensors.get(identifier)); + } + + @Override + public AggregatedSensor getTopLevelSensor() { + return this.topLevelSensor; + } + + @Override + public Collection<MachineSensor> getMachineSensors() { + return this.machineSensors.values(); + } + + @Override + public String toJson() { + // Necessary method. Deletion would cause SensorRegistry.toJson() to fail. + return GSON.toJson(this); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.topLevelSensor); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof SensorRegistry) { + final SensorRegistry other = (SensorRegistry) obj; + return Objects.equals(this.getTopLevelSensor(), other.getTopLevelSensor()); + } + return false; + } + + public static ImmutableSensorRegistry copyOf(final SensorRegistry sensorRegistry) { + return new ImmutableSensorRegistry(sensorRegistry); + } + + public static SensorRegistry fromJson(final String json) { + return GSON.fromJson(json, SensorRegistry.class); + } + + private static final class ImmutableAggregatatedSensor extends AbstractSensor + implements AggregatedSensor { + + private final ImmutableList<Sensor> children; + + private ImmutableAggregatatedSensor(final AggregatedSensor newParent, + final AggregatedSensor sensorToCopy, + final ImmutableMap.Builder<String, MachineSensor> sensorRegistryMapBuilder) { + super(newParent, sensorToCopy.getIdentifier(), sensorToCopy.getName()); + final Builder<Sensor> childrenBuilder = ImmutableList.builder(); + for (final Sensor child : sensorToCopy.getChildren()) { + if (child instanceof MachineSensor) { + final MachineSensor newChild = + new MachineSensorImpl(this, child.getIdentifier(), child.getName()); + childrenBuilder.add(newChild); + sensorRegistryMapBuilder.put(newChild.getIdentifier(), newChild); + } else if (child instanceof AggregatedSensor) { + final AggregatedSensor newChild = new ImmutableAggregatatedSensor(this, + (AggregatedSensor) child, sensorRegistryMapBuilder); + childrenBuilder.add(newChild); + } else { + throw new IllegalStateException( + "Sensor " + child + " is neither of type '" + + MachineSensor.class.getSimpleName() + "' nor " + + AggregatedSensor.class.getSimpleName() + "' and thus not supported."); + } + } + this.children = childrenBuilder.build(); + } + + @Override + public Collection<Sensor> getChildren() { + return this.children; + } + + @Override + public int hashCode() { + return Objects.hash(this.getIdentifier(), this.children); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof AggregatedSensor) { + final AggregatedSensor other = (AggregatedSensor) obj; + return Objects.equals(this.getIdentifier(), other.getIdentifier()) + && Objects.equals(this.children, other.getChildren()); + } + return false; + } + + @Override + public String toString() { + return this.getName() + '[' + this.getIdentifier() + "] (" + this.children.size() + + " children)"; + } + + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MachineSensor.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MachineSensor.java new file mode 100644 index 0000000000000000000000000000000000000000..cdb4b535bffd807acb92fbfd057f5986b4840ba8 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MachineSensor.java @@ -0,0 +1,25 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; + +/** + * Representing a real sensor in the {@link SensorRegistry}, i.e. one that is not aggregated. + */ +public interface MachineSensor extends Sensor { + + /** + * Get a list of parent, grandparent etc. sensors. + */ + default List<AggregatedSensor> getParents() { + Optional<AggregatedSensor> parent = this.getParent(); + final List<AggregatedSensor> parents = new ArrayList<>(); + while (parent.isPresent()) { + parents.add(parent.get()); + parent = parent.get().getParent(); + } + return parents; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MachineSensorImpl.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MachineSensorImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..191664bfdee31874003d7420ef7f81560c4fe29b --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MachineSensorImpl.java @@ -0,0 +1,34 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.Objects; + +class MachineSensorImpl extends AbstractSensor implements MachineSensor { + + protected MachineSensorImpl(final AggregatedSensor parent, final String identifier, + final String name) { + super(parent, identifier, name); + } + + @Override + public int hashCode() { + return Objects.hashCode(this.getIdentifier()); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof MachineSensor) { + final MachineSensor other = (MachineSensor) obj; + return Objects.equals(this.getIdentifier(), other.getIdentifier()); + } + return false; + } + + @Override + public String toString() { + return this.getName() + '[' + this.getIdentifier() + ']'; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableAggregatedSensor.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableAggregatedSensor.java new file mode 100644 index 0000000000000000000000000000000000000000..c0b5e42c83998622294adcb38dab50fd591d286d --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableAggregatedSensor.java @@ -0,0 +1,96 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; + +/** + * A {@link MutableAggregatedSensor} which can child sensors be added to. + */ +public class MutableAggregatedSensor extends AbstractSensor implements AggregatedSensor { + + private final List<Sensor> children = new ArrayList<>(); + private final MutableSensorRegistry sensorRegistry; + + protected MutableAggregatedSensor(final MutableSensorRegistry registry, final String identifier, + final String name) { + super(null, identifier, name); + this.sensorRegistry = registry; + } + + protected MutableAggregatedSensor(final MutableAggregatedSensor parent, final String identifier, + final String name) { + super(parent, identifier, name); + this.sensorRegistry = parent.sensorRegistry; + } + + @Override + public Collection<Sensor> getChildren() { + return this.children; + } + + /** + * Create a new {@link MutableAggregatedSensor} as child of this sensor. + */ + public MutableAggregatedSensor addChildAggregatedSensor(final String identifier) { + return this.addChildAggregatedSensor(identifier, ""); + } + + /** + * Create a new {@link MutableAggregatedSensor} as child of this sensor. + */ + public MutableAggregatedSensor addChildAggregatedSensor(final String identifier, + final String name) { + final MutableAggregatedSensor aggregatedSensor = + new MutableAggregatedSensor(this, identifier, name); + this.children.add(aggregatedSensor); + return aggregatedSensor; + } + + /** + * Create a new {@link MachineSensor} as child of this sensor. + */ + public MachineSensor addChildMachineSensor(final String identifier) { + return this.addChildMachineSensor(identifier, ""); + } + + /** + * Create a new {@link MachineSensor} as child of this sensor. + */ + public MachineSensor addChildMachineSensor(final String identifier, final String name) { + final MachineSensorImpl machineSensor = new MachineSensorImpl(this, identifier, name); + final boolean registerResult = this.sensorRegistry.register(machineSensor); + if (!registerResult) { + throw new IllegalArgumentException( + "Sensor width identifier " + identifier + " is already registered."); + } + this.children.add(machineSensor); + return machineSensor; + } + + @Override + public int hashCode() { + return Objects.hash(this.getIdentifier(), this.children); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof AggregatedSensor) { + final AggregatedSensor other = (AggregatedSensor) obj; + return Objects.equals(this.getIdentifier(), other.getIdentifier()) + && Objects.equals(this.children, other.getChildren()); + } + return false; + } + + @Override + public String toString() { + return this.getName() + '[' + this.getIdentifier() + "] (" + this.children.size() + + " children)"; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableSensorRegistry.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableSensorRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..53a0418e6c2a8efe6139fd2150de218b4f8c6966 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableSensorRegistry.java @@ -0,0 +1,84 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.AggregatedSensorSerializer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.MachineSensorSerializer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.SensorRegistrySerializer; + +/** + * A {@link SensorRegistry} to which sensors can be added. + */ +public class MutableSensorRegistry implements SensorRegistry { + + private static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(MutableSensorRegistry.class, new SensorRegistrySerializer()) + .registerTypeAdapter(MutableAggregatedSensor.class, new AggregatedSensorSerializer()) + .registerTypeAdapter(MachineSensorImpl.class, new MachineSensorSerializer()).create(); + + // TODO HashMap for efficient access to machine sensors + private final Map<String, MachineSensorImpl> machineSensors = new HashMap<>(); + + // TODO maybe access to root + private final MutableAggregatedSensor topLevelSensor; + + public MutableSensorRegistry(final String topLevelSensorIdentifier) { + this(topLevelSensorIdentifier, ""); + } + + public MutableSensorRegistry(final String topLevelSensorIdentifier, + final String topLevelSensorName) { + this.topLevelSensor = + new MutableAggregatedSensor(this, topLevelSensorIdentifier, topLevelSensorName); + } + + @Override + public Optional<MachineSensor> getSensorForIdentifier(final String identifier) { + return Optional.ofNullable(this.machineSensors.get(identifier)); + } + + @Override + public MutableAggregatedSensor getTopLevelSensor() { + return this.topLevelSensor; + } + + @Override + public Collection<MachineSensor> getMachineSensors() { + return Collections.unmodifiableCollection(this.machineSensors.values()); + } + + protected boolean register(final MachineSensorImpl machineSensor) { + final Object oldValue = + this.machineSensors.putIfAbsent(machineSensor.getIdentifier(), machineSensor); + return oldValue == null; + } + + @Override + public int hashCode() { + return Objects.hashCode(this.topLevelSensor); + } + + @Override + public boolean equals(final Object obj) { + if (obj == this) { + return true; + } + if (obj instanceof SensorRegistry) { + final SensorRegistry other = (SensorRegistry) obj; + return Objects.equals(this.getTopLevelSensor(), other.getTopLevelSensor()); + } + return false; + } + + @Override + public String toJson() { + return GSON.toJson(this); + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/Sensor.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/Sensor.java new file mode 100644 index 0000000000000000000000000000000000000000..b22cc81d3912d8094ae67475ce261ce958d3d236 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/Sensor.java @@ -0,0 +1,16 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.Optional; + +/** + * Class representing a sensor in the {@link SensorRegistry}. + */ +public interface Sensor { + + Optional<AggregatedSensor> getParent(); + + String getIdentifier(); + + String getName(); + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/SensorRegistry.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/SensorRegistry.java new file mode 100644 index 0000000000000000000000000000000000000000..e079f5c12e4a3ddfe9f680860444c239ae51aa6b --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/SensorRegistry.java @@ -0,0 +1,45 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.Collection; +import java.util.Optional; + +/** + * Hierarchical data structure (i.e. a tree) for organizing sensors. A {@link SensorRegistry} has + * one top-level sensor which can have multiple child sensors. These sensors can either be real + * {@link MachineSensor}s or {@link AggregatedSensor}s, having child sensors. + */ +public interface SensorRegistry { + + Optional<MachineSensor> getSensorForIdentifier(final String identifier); + + AggregatedSensor getTopLevelSensor(); + + Collection<MachineSensor> getMachineSensors(); + + /** + * Flattens the hierarchy to a collection of all contained {@link Sensor}s. + * + * @return A collection of all {@link Sensor}s contained in the hierarchy. + */ + default Collection<Sensor> flatten() { + return this.getTopLevelSensor().flatten(); + } + + /** + * Converts this sensor registry into a json string. + * + * <p> + * Per default a copy of this sensor registry is created to ensure that proper (de)serializers + * exist. If subclasses have appropriate serdes, they should override this method. + * </p> + */ + default String toJson() { + final ImmutableSensorRegistry immutableSensorRegistry = ImmutableSensorRegistry.copyOf(this); + return immutableSensorRegistry.toJson(); + } + + static SensorRegistry fromJson(final String json) { + return ImmutableSensorRegistry.fromJson(json); + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/AggregatedSensorSerializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/AggregatedSensorSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..64156fbc10af5a64a02107840d3586cafc30f6e8 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/AggregatedSensorSerializer.java @@ -0,0 +1,25 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; + +/** + * {@link JsonSerializer} for {@link AggregatedSensor}s. + */ +public final class AggregatedSensorSerializer implements JsonSerializer<AggregatedSensor> { + + @Override + public JsonElement serialize(final AggregatedSensor sensor, final Type type, + final JsonSerializationContext context) { + final JsonObject jsonSensorObject = new JsonObject(); + jsonSensorObject.addProperty("identifier", sensor.getIdentifier()); + jsonSensorObject.addProperty("name", sensor.getName()); + jsonSensorObject.add("children", context.serialize(sensor.getChildren())); + return jsonSensorObject; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/MachineSensorSerializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/MachineSensorSerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..4301552e922801d402f456b51a5607d9e1351294 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/MachineSensorSerializer.java @@ -0,0 +1,24 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MachineSensor; + +/** + * {@link JsonSerializer} for {@link MachineSensor}s. + */ +public final class MachineSensorSerializer implements JsonSerializer<MachineSensor> { + + @Override + public JsonElement serialize(final MachineSensor sensor, final Type type, + final JsonSerializationContext context) { + final JsonObject jsonSensorObject = new JsonObject(); + jsonSensorObject.addProperty("identifier", sensor.getIdentifier()); + jsonSensorObject.addProperty("name", sensor.getName()); + return jsonSensorObject; + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistryDeserializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistryDeserializer.java new file mode 100644 index 0000000000000000000000000000000000000000..b0a3a30524ae4d6c3b78d584c5eb574644fcbb08 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistryDeserializer.java @@ -0,0 +1,120 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization; + +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import java.lang.reflect.Type; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.ImmutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableAggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; + +/** + * {@link JsonDeserializer} for {@link AggregatedSensor}s. + */ +public final class SensorRegistryDeserializer implements JsonDeserializer<SensorRegistry> { + + private static final String IDENTIFIER_KEY = "identifier"; + + private static final String NAME_KEY = "name"; + + private static final String CHILDREN_KEY = "children"; + + @Override + public SensorRegistry deserialize(final JsonElement jsonElement, final Type type, + final JsonDeserializationContext context) { + final MutableSensorRegistry sensorRegistry = this.transformTopLevelSensor(jsonElement); + + return ImmutableSensorRegistry.copyOf(sensorRegistry); + } + + private MutableSensorRegistry transformTopLevelSensor(final JsonElement jsonElement) { + final SensorParseResult parseResult = this.parseSensor(jsonElement); // + if (parseResult == null) { + // create empty registry + return new MutableSensorRegistry("", ""); + } else { + // create registry from result + final MutableSensorRegistry sensorRegistry = + new MutableSensorRegistry(parseResult.identifier, parseResult.name); + if (parseResult.children != null) { + for (final JsonElement childJsonElement : parseResult.children) { + this.addSensor(childJsonElement, sensorRegistry.getTopLevelSensor()); + } + } + return sensorRegistry; + } + } + + private void addSensor(final JsonElement jsonElement, + final MutableAggregatedSensor parentSensor) { + final SensorParseResult parseResult = this.parseSensor(jsonElement); + if (parseResult != null) { + // create child sensor from result + if (parseResult.children == null) { + // create MachineSensor + parentSensor.addChildMachineSensor(parseResult.identifier, parseResult.name); + } else { + // create Aggregated Sensor + final MutableAggregatedSensor sensor = + parentSensor.addChildAggregatedSensor(parseResult.identifier, parseResult.name); + for (final JsonElement childJsonElement : parseResult.children) { + this.addSensor(childJsonElement, sensor); + } + } + } + } + + // returns null if invalid JsonElement + private SensorParseResult parseSensor(final JsonElement jsonElement) { + if (jsonElement.isJsonObject()) { + final JsonObject jsonObject = jsonElement.getAsJsonObject(); + if (jsonObject.has(IDENTIFIER_KEY)) { + final JsonElement identifierJsonElement = jsonObject.get(IDENTIFIER_KEY); + final JsonElement nameJsonElement = jsonObject.get(NAME_KEY); + if (identifierJsonElement.isJsonPrimitive() && nameJsonElement.isJsonPrimitive()) { + final JsonPrimitive identifierJsonPrimitive = identifierJsonElement.getAsJsonPrimitive(); + final JsonPrimitive nameJsonPrimitive = nameJsonElement.getAsJsonPrimitive(); + if (identifierJsonPrimitive.isString()) { + final String identifierString = identifierJsonPrimitive.getAsString(); + final String nameString = nameJsonPrimitive.getAsString(); + final JsonArray childrenJsonArray = this.parseChildren(jsonObject); + return new SensorParseResult(identifierString, nameString, childrenJsonArray); + } + } + } + } + return null; + // TODO throw exception + } + + // returns null if JsonObject does not have children or children is not an array + private JsonArray parseChildren(final JsonObject parentJsonObject) { + if (parentJsonObject.has(CHILDREN_KEY)) { + final JsonElement childrenJsonElement = parentJsonObject.get(CHILDREN_KEY); + if (childrenJsonElement.isJsonArray()) { + return childrenJsonElement.getAsJsonArray(); + } + } + return null; + // TODO throw exception + } + + private static class SensorParseResult { + private final String identifier; + private final String name; + private final JsonArray children; + + private SensorParseResult(final String identifier, final String name, + final JsonArray children) { + this.identifier = identifier; + this.children = children; + this.name = name; + } + } + +} diff --git a/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistrySerializer.java b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistrySerializer.java new file mode 100644 index 0000000000000000000000000000000000000000..0a3581164a3e17c7e681b4c78f3d71a5a398ee92 --- /dev/null +++ b/theodolite-benchmarks/commons/src/main/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistrySerializer.java @@ -0,0 +1,20 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization; + +import com.google.gson.JsonElement; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; +import java.lang.reflect.Type; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; + +/** + * {@link JsonSerializer} for {@link SensorRegistry}s. + */ +public final class SensorRegistrySerializer implements JsonSerializer<SensorRegistry> { + + @Override + public JsonElement serialize(final SensorRegistry sensorRegistry, final Type type, + final JsonSerializationContext context) { + return context.serialize(sensorRegistry.getTopLevelSensor()); + } + +} diff --git a/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/common/configuration/NameResolvingEnvironmentConfigurationTest.java b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/common/configuration/NameResolvingEnvironmentConfigurationTest.java new file mode 100644 index 0000000000000000000000000000000000000000..e7bc8d0f66b1aea0b367756bd383af6d6ea6c0f9 --- /dev/null +++ b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/common/configuration/NameResolvingEnvironmentConfigurationTest.java @@ -0,0 +1,88 @@ +package rocks.theodolite.benchmarks.commons.common.configuration; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import org.apache.commons.configuration2.Configuration; +import org.junit.Rule; +import org.junit.Test; +import org.junit.contrib.java.lang.system.EnvironmentVariables; +import rocks.theodolite.benchmarks.commons.commons.configuration.NameResolvingEnvironmentConfiguration; + +public class NameResolvingEnvironmentConfigurationTest { + + private static final String PROPERTY_FILES_KEY = "my.env.var"; + private static final String ENV_VAR_KEY = "MY_ENV_VAR"; + private static final String STRING_VALUE = "value"; + private static final String STRING_VALUE_2 = "value2"; + private static final int INT_VALUE = 7; + + @Rule + public final EnvironmentVariables environmentVariables = new EnvironmentVariables(); + + @Test + public void testHelperLibrary() { + this.environmentVariables.clear("name"); + this.environmentVariables.set("name", STRING_VALUE); + assertEquals("value", System.getenv("name")); + } + + @Test + public void testGetUsingEnvVarFormat() { + this.environmentVariables.clear(ENV_VAR_KEY); + this.environmentVariables.set(ENV_VAR_KEY, STRING_VALUE); + final Configuration config = new NameResolvingEnvironmentConfiguration(); + final String result = config.getString(ENV_VAR_KEY); + assertEquals(STRING_VALUE, result); + } + + @Test + public void testGetUsingPropertiesFormat() { + this.environmentVariables.clear(ENV_VAR_KEY); + this.environmentVariables.set(ENV_VAR_KEY, STRING_VALUE); + final Configuration config = new NameResolvingEnvironmentConfiguration(); + final String result = config.getString(PROPERTY_FILES_KEY); + assertEquals(STRING_VALUE, result); + } + + @Test + public void testGetOfNumber() { + this.environmentVariables.clear(ENV_VAR_KEY); + this.environmentVariables.set(ENV_VAR_KEY, String.valueOf(INT_VALUE)); + final Configuration config = new NameResolvingEnvironmentConfiguration(); + final int result = config.getInt(PROPERTY_FILES_KEY); + assertEquals(INT_VALUE, result); + } + + @Test + public void testGetOfBothExisting() { + this.environmentVariables.clear(ENV_VAR_KEY, PROPERTY_FILES_KEY); + this.environmentVariables.set(ENV_VAR_KEY, STRING_VALUE); + this.environmentVariables.set(PROPERTY_FILES_KEY, STRING_VALUE_2); + final Configuration config = new NameResolvingEnvironmentConfiguration(); + final String result = config.getString(PROPERTY_FILES_KEY); + assertEquals(STRING_VALUE_2, result); + } + + @Test + public void testGetNonExistingUsingEnvVarFormat() { + this.environmentVariables.clear(ENV_VAR_KEY); + final Configuration config = new NameResolvingEnvironmentConfiguration(); + final String result = config.getString(ENV_VAR_KEY); + assertNull(result); + } + + @Test + public void testGetNonExistingUsingPropertiesFormat() { + this.environmentVariables.clear(ENV_VAR_KEY); + final Configuration config = new NameResolvingEnvironmentConfiguration(); + final String result = config.getString(PROPERTY_FILES_KEY); + assertNull(result); + } + + @Test + public void testFormatKeyAsEnvVariable() { + assertEquals(ENV_VAR_KEY, + NameResolvingEnvironmentConfiguration.formatKeyAsEnvVariable(PROPERTY_FILES_KEY)); + } + +} diff --git a/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ExampleSensors.java b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ExampleSensors.java new file mode 100644 index 0000000000000000000000000000000000000000..9d1b4d65a46202561de0aee701895d57cba4ee12 --- /dev/null +++ b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ExampleSensors.java @@ -0,0 +1,36 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import java.util.List; +import java.util.stream.Collectors; + +public final class ExampleSensors { + + private static final SensorRegistry REGISTRY; + + static { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + final MutableAggregatedSensor comcent = topLevel.addChildAggregatedSensor("comcent"); + final MutableAggregatedSensor server1 = comcent.addChildAggregatedSensor("comcent.server1"); + final MachineSensor server1pw1 = server1.addChildMachineSensor("comcent.server1.pw1"); + final MachineSensor server1pw2 = server1.addChildMachineSensor("comcent.server1.pw2"); + final MachineSensor server1pw3 = server1.addChildMachineSensor("comcent.server1.pw3"); + final MutableAggregatedSensor server2 = comcent.addChildAggregatedSensor("comcent.server2"); + final MachineSensor server2pw1 = server2.addChildMachineSensor("comcent.server2.pw1"); + final MachineSensor server2pw2 = server2.addChildMachineSensor("comcent.server2.pw2"); + + REGISTRY = ImmutableSensorRegistry.copyOf(sensorRegistry); + } + + private ExampleSensors() {} + + public static List<String> machineSensorNames() { + return REGISTRY.getMachineSensors().stream().map(s -> s.getIdentifier()) + .collect(Collectors.toList()); + } + + public static SensorRegistry registry() { + return REGISTRY; + } + +} diff --git a/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ImmutableSensorRegistryTest.java b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ImmutableSensorRegistryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..2be6ce4d5920f6c2640e0701a4f6afbc0cfa544f --- /dev/null +++ b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/ImmutableSensorRegistryTest.java @@ -0,0 +1,106 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Test; + +public class ImmutableSensorRegistryTest { + + @Test + public void testEquals() { + final ImmutableSensorRegistry sensorRegistry1 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + final ImmutableSensorRegistry sensorRegistry2 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.equals(sensorRegistry2)); + assertTrue(sensorRegistry2.equals(sensorRegistry1)); + } + + @Test + public void testEqualsWithDifferentNames() { + final ImmutableSensorRegistry sensorRegistry1 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + final ImmutableSensorRegistry sensorRegistry2 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistryWithDifferentNames()); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.equals(sensorRegistry2)); + assertTrue(sensorRegistry2.equals(sensorRegistry1)); + } + + @Test + public void testNotEquals() { + final ImmutableSensorRegistry sensorRegistry1 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + final ImmutableSensorRegistry sensorRegistry2 = + ImmutableSensorRegistry.copyOf(this.getOtherSensorRegistry()); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertFalse(sensorRegistry1.equals(sensorRegistry2)); + assertFalse(sensorRegistry2.equals(sensorRegistry1)); + } + + @Test + public void testEqualHashCodes() { + final ImmutableSensorRegistry sensorRegistry1 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + final ImmutableSensorRegistry sensorRegistry2 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.hashCode() == sensorRegistry2.hashCode()); + } + + @Test + public void testEqualHashCodesWithDifferentNames() { + final ImmutableSensorRegistry sensorRegistry1 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + final ImmutableSensorRegistry sensorRegistry2 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistryWithDifferentNames()); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.hashCode() == sensorRegistry2.hashCode()); + } + + @Test + public void testNotEqualHashCodes() { + final ImmutableSensorRegistry sensorRegistry1 = + ImmutableSensorRegistry.copyOf(this.getSensorRegistry()); + final ImmutableSensorRegistry sensorRegistry2 = + ImmutableSensorRegistry.copyOf(this.getOtherSensorRegistry()); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertFalse(sensorRegistry1.hashCode() == sensorRegistry2.hashCode()); + } + + private MutableSensorRegistry getSensorRegistry() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + topLevel.addChildMachineSensor("child-1", "Child 1"); + final MutableAggregatedSensor aggregatedSensor = + topLevel.addChildAggregatedSensor("child-2", "Child 2"); + aggregatedSensor.addChildMachineSensor("grandchild-1", "Grandchild 1"); + aggregatedSensor.addChildMachineSensor("grandchild-2", "Grandchild 2"); + return sensorRegistry; + } + + private MutableSensorRegistry getSensorRegistryWithDifferentNames() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + topLevel.addChildMachineSensor("child-1", "Child 1 Alternative"); + final MutableAggregatedSensor aggregatedSensor = + topLevel.addChildAggregatedSensor("child-2", "Child 2"); + aggregatedSensor.addChildMachineSensor("grandchild-1", "Grandchild 1"); + aggregatedSensor.addChildMachineSensor("grandchild-2", "Grandchild 2 Alternative"); + return sensorRegistry; + } + + private MutableSensorRegistry getOtherSensorRegistry() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + topLevel.addChildMachineSensor("child-1", "Child 1"); + final MutableAggregatedSensor aggregatedSensor = + topLevel.addChildAggregatedSensor("child-2", "Child 2"); + aggregatedSensor.addChildMachineSensor("grandchild-1", "Grandchild 1"); + aggregatedSensor.addChildMachineSensor("grandchild-2", "Grandchild 2"); + aggregatedSensor.addChildMachineSensor("grandchild-3", "Grandchild 3"); + return sensorRegistry; + } + +} diff --git a/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MaschineSensorImplExposer.java b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MaschineSensorImplExposer.java new file mode 100644 index 0000000000000000000000000000000000000000..f397d8ad7c2676e7f98be8d0fdb1743347509960 --- /dev/null +++ b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MaschineSensorImplExposer.java @@ -0,0 +1,13 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +/** + * Helper class to allow tests in other packages access {@link MachineSensorImpl} class objects. + */ +public final class MaschineSensorImplExposer { + + public static final Class<? extends MachineSensor> MACHINE_SENSOR_IMPL_CLASS = + MachineSensorImpl.class; + + private MaschineSensorImplExposer() {} + +} diff --git a/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableSensorRegistryTest.java b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableSensorRegistryTest.java new file mode 100644 index 0000000000000000000000000000000000000000..5d49c65c69209c574de35ac4509cf32c04c89459 --- /dev/null +++ b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/MutableSensorRegistryTest.java @@ -0,0 +1,102 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import java.util.Optional; +import org.junit.Test; + +public class MutableSensorRegistryTest { + + @Test + public void parentOfTopLevelShouldBeNotPresent() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root"); + final Optional<AggregatedSensor> parent = sensorRegistry.getTopLevelSensor().getParent(); + assertFalse(parent.isPresent()); + } + + @Test + public void testEquals() { + final MutableSensorRegistry sensorRegistry1 = this.getSensorRegistry(); + final MutableSensorRegistry sensorRegistry2 = this.getSensorRegistry(); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.equals(sensorRegistry2)); + assertTrue(sensorRegistry2.equals(sensorRegistry1)); + } + + @Test + public void testEqualsWithDifferentNames() { + final MutableSensorRegistry sensorRegistry1 = this.getSensorRegistry(); + final MutableSensorRegistry sensorRegistry2 = this.getSensorRegistryWithDifferentNames(); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.equals(sensorRegistry2)); + assertTrue(sensorRegistry2.equals(sensorRegistry1)); + } + + @Test + public void testNotEquals() { + final MutableSensorRegistry sensorRegistry1 = this.getSensorRegistry(); + final MutableSensorRegistry sensorRegistry2 = this.getOtherSensorRegistry(); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertFalse(sensorRegistry1.equals(sensorRegistry2)); + assertFalse(sensorRegistry2.equals(sensorRegistry1)); + } + + @Test + public void testEqualHashCodes() { + final MutableSensorRegistry sensorRegistry1 = this.getSensorRegistry(); + final MutableSensorRegistry sensorRegistry2 = this.getSensorRegistry(); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.hashCode() == sensorRegistry2.hashCode()); + } + + @Test + public void testEqualHashCodesWithDifferentNames() { + final MutableSensorRegistry sensorRegistry1 = this.getSensorRegistry(); + final MutableSensorRegistry sensorRegistry2 = this.getSensorRegistryWithDifferentNames(); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertTrue(sensorRegistry1.hashCode() == sensorRegistry2.hashCode()); + } + + @Test + public void testNotEqualHashCodes() { + final MutableSensorRegistry sensorRegistry1 = this.getSensorRegistry(); + final MutableSensorRegistry sensorRegistry2 = this.getOtherSensorRegistry(); + assertFalse(sensorRegistry1 == sensorRegistry2); + assertFalse(sensorRegistry1.hashCode() == sensorRegistry2.hashCode()); + } + + private MutableSensorRegistry getSensorRegistry() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + topLevel.addChildMachineSensor("child-1", "Child 1"); + final MutableAggregatedSensor aggregatedSensor = + topLevel.addChildAggregatedSensor("child-2", "Child 2"); + aggregatedSensor.addChildMachineSensor("grandchild-1", "Grandchild 1"); + aggregatedSensor.addChildMachineSensor("grandchild-2", "Grandchild 2"); + return sensorRegistry; + } + + private MutableSensorRegistry getSensorRegistryWithDifferentNames() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + topLevel.addChildMachineSensor("child-1", "Child 1 Alternative"); + final MutableAggregatedSensor aggregatedSensor = + topLevel.addChildAggregatedSensor("child-2", "Child 2"); + aggregatedSensor.addChildMachineSensor("grandchild-1", "Grandchild 1"); + aggregatedSensor.addChildMachineSensor("grandchild-2", "Grandchild 2 Alternative"); + return sensorRegistry; + } + + private MutableSensorRegistry getOtherSensorRegistry() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + topLevel.addChildMachineSensor("child-1", "Child 1"); + final MutableAggregatedSensor aggregatedSensor = + topLevel.addChildAggregatedSensor("child-2", "Child 2"); + aggregatedSensor.addChildMachineSensor("grandchild-1", "Grandchild 1"); + aggregatedSensor.addChildMachineSensor("grandchild-2", "Grandchild 2"); + aggregatedSensor.addChildMachineSensor("grandchild-3", "Grandchild 3"); + return sensorRegistry; + } + +} diff --git a/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistryDeserializerTest.java b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistryDeserializerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..a9821eb90a916e42fdff8750d5c0d7c3cfd265a8 --- /dev/null +++ b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistryDeserializerTest.java @@ -0,0 +1,174 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MachineSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.Sensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.SensorRegistryDeserializer; + +public class SensorRegistryDeserializerTest { + + private Gson gson; + + @Before + public void setUp() throws Exception { + this.gson = new GsonBuilder().registerTypeAdapter(SensorRegistry.class, new SensorRegistryDeserializer()).create(); + } + + @After + public void tearDown() throws Exception { + this.gson = null; + } + + @Test + public void testEmptyRegistry() { + final String json = ""; + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + assertNull(registry); + } + + @Test + public void testRegistryOfWrongType() { + final String json = "[{\"identifier\": \"my-id\", \"name\": \"My Name\"}]"; + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + assertEquals(registry.getTopLevelSensor().getIdentifier(), ""); + assertTrue(registry.getTopLevelSensor().getChildren().isEmpty()); + } + + @Test + public void testRegistryWithMissingIdentifier() { + final String json = "{\"children\": []}"; + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + assertEquals(registry.getTopLevelSensor().getIdentifier(), ""); + assertTrue(registry.getTopLevelSensor().getChildren().isEmpty()); + } + + @Test + public void testRegistryWithMissingChildren() { + final String json = "{\"identifier\": \"my-root-id\", \"name\": \"My Name\"}"; + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + assertEquals(registry.getTopLevelSensor().getIdentifier(), "my-root-id"); + assertTrue(registry.getTopLevelSensor().getChildren().isEmpty()); + } + + @Test + public void testRegistryWithZeroChildren() { + final String json = "{\"identifier\": \"my-root-id\", \"name\": \"My Name\", \"children\": []}"; + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + assertEquals(registry.getTopLevelSensor().getIdentifier(), "my-root-id"); + assertTrue(registry.getTopLevelSensor().getChildren().isEmpty()); + } + + @Test + public void testRegistryWithOneGenerationChildren() { + final String json = "{\"identifier\": \"my-root-id\", \"name\": \"My Name\", \"children\": [{\"identifier\": \"child-id-1\", \"name\": \"Child 1\"}, {\"identifier\": \"child-id-2\", \"name\": \"Child 2\"}, {\"identifier\": \"child-id-3\", \"name\": \"Child 3\"}]}"; + final List<String> childIdentifiers = ImmutableList.of("child-id-1", "child-id-2", "child-id-3"); // List.of() in Java <= 9 + + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + final AggregatedSensor topLevelSensor = registry.getTopLevelSensor(); + assertEquals(topLevelSensor.getIdentifier(), "my-root-id"); + final List<Sensor> childSensors = Lists.newArrayList(topLevelSensor.getChildren()); + assertEquals(childSensors.size(), 3); + for (final Sensor sensor : childSensors) { + assertTrue(childIdentifiers.contains(sensor.getIdentifier())); + assertTrue(sensor instanceof MachineSensor); + } + for (final String childIdentifier : childIdentifiers) { + assertTrue(registry.getSensorForIdentifier(childIdentifier).isPresent()); + } + } + + @Test + public void testRegistryWithCorruptedChild() { + final String json = "{\"identifier\": \"my-root-id\", \"name\": \"My Name\", \"children\": [{\"identifier\": \"child-id-1\", \"name\": \"Child 1\"}, {\"no-identifier\": \"child-id-2\", \"name\": \"Child 2\"}]}"; + final List<String> childIdentifiers = ImmutableList.of("child-id-1"); // List.of() in Java <= 9 + + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + final AggregatedSensor topLevelSensor = registry.getTopLevelSensor(); + assertEquals(topLevelSensor.getIdentifier(), "my-root-id"); + final List<Sensor> childSensors = Lists.newArrayList(topLevelSensor.getChildren()); + assertEquals(childSensors.size(), 1); + for (final Sensor sensor : childSensors) { + assertTrue(childIdentifiers.contains(sensor.getIdentifier())); + assertTrue(sensor instanceof MachineSensor); + } + for (final String childIdentifier : childIdentifiers) { + assertTrue(registry.getSensorForIdentifier(childIdentifier).isPresent()); + } + } + + @Test + public void testRegistryWithArrayAsChild() { + final String json = "{\"identifier\": \"my-root-id\", \"name\": \"My Name\", \"children\": [{\"identifier\": \"child-id-1\", \"name\": \"Child 1\"}, [{\"identifier\": \"child-id-2\", \"name\": \"Child 2\"}]]}"; + final List<String> childIdentifiers = ImmutableList.of("child-id-1"); // List.of() in Java <= 9 + + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + final AggregatedSensor topLevelSensor = registry.getTopLevelSensor(); + assertEquals(topLevelSensor.getIdentifier(), "my-root-id"); + final List<Sensor> childSensors = Lists.newArrayList(topLevelSensor.getChildren()); + assertEquals(childSensors.size(), 1); + for (final Sensor sensor : childSensors) { + assertTrue(childIdentifiers.contains(sensor.getIdentifier())); + assertTrue(sensor instanceof MachineSensor); + } + for (final String childIdentifier : childIdentifiers) { + assertTrue(registry.getSensorForIdentifier(childIdentifier).isPresent()); + } + } + + @Test + public void testRegistryWithTwoGenerationChildren() { + final String json = "{\"identifier\": \"my-root-id\", \"name\": \"My Name\", \"children\": [{\"identifier\": \"child-id-1\", \"name\": \"Child 1\", \"children\": [{\"identifier\": \"child-id-1-1\", \"name\": \"Child 1a\"}, {\"identifier\": \"child-id-1-2\", \"name\": \"Child 1b\"}, {\"identifier\": \"child-id-1-3\", \"name\": \"Child 1c\"}]}, {\"identifier\": \"child-id-2\", \"name\": \"Child 2\"}]}"; + final List<String> childIdentifiers = ImmutableList.of("child-id-1", "child-id-2"); // List.of() in Java <= 9 + final List<String> grandChildIdentifiers = ImmutableList.of("child-id-1-1", "child-id-1-2", "child-id-1-3"); // List.of() in Java <= 9 + final List<String> machineSensorIdentifiers = ImmutableList.of("child-id-2", "child-id-1-1", "child-id-1-2", // List.of() in Java <= 9 + "child-id-1-3"); + + final SensorRegistry registry = this.gson.fromJson(json, SensorRegistry.class); + final AggregatedSensor topLevelSensor = registry.getTopLevelSensor(); + assertEquals(topLevelSensor.getIdentifier(), "my-root-id"); + final List<Sensor> childSensors = Lists.newArrayList(topLevelSensor.getChildren()); + assertEquals(childSensors.size(), 2); + for (final Sensor sensor : childSensors) { + assertTrue(childIdentifiers.contains(sensor.getIdentifier())); + if (sensor.getIdentifier().equals("child-id-2")) { + assertTrue(sensor instanceof MachineSensor); + } else if (sensor.getIdentifier().equals("child-id-1")) { + assertTrue(sensor instanceof AggregatedSensor); + if (sensor instanceof AggregatedSensor) { + final AggregatedSensor aggregatedSensor = (AggregatedSensor) sensor; + final List<Sensor> grandChildSensors = Lists.newArrayList(aggregatedSensor.getChildren()); + assertEquals(grandChildSensors.size(), 3); + for (final Sensor grandChildSensor : grandChildSensors) { + assertTrue(grandChildIdentifiers.contains(grandChildSensor.getIdentifier())); + assertTrue(grandChildSensor instanceof MachineSensor); + } + } else { + fail(); // Should never happen because of asserTrue check before + } + } else { + fail("Sensor is neither of type MachineSensor nor AggregatedSensor"); + } + } + for (final String identifier : machineSensorIdentifiers) { + assertTrue(registry.getSensorForIdentifier(identifier).isPresent()); + } + } + +} diff --git a/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistrySerializerTest.java b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistrySerializerTest.java new file mode 100644 index 0000000000000000000000000000000000000000..c2413b571c3445df71480f76cb2b0cf251ad6009 --- /dev/null +++ b/theodolite-benchmarks/commons/src/test/java/rocks/theodolite/benchmarks/commons/model/sensorregistry/serialization/SensorRegistrySerializerTest.java @@ -0,0 +1,74 @@ +package rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization; + +import static org.junit.Assert.assertEquals; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MaschineSensorImplExposer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableAggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.AggregatedSensorSerializer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.MachineSensorSerializer; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.serialization.SensorRegistrySerializer; + +public class SensorRegistrySerializerTest { + + private Gson gson; + + @Before + public void setUp() throws Exception { + this.gson = new GsonBuilder() + .registerTypeAdapter(MutableSensorRegistry.class, new SensorRegistrySerializer()) + .registerTypeAdapter(MutableAggregatedSensor.class, new AggregatedSensorSerializer()) + .registerTypeAdapter(MaschineSensorImplExposer.MACHINE_SENSOR_IMPL_CLASS, + new MachineSensorSerializer()) + .create(); + } + + @After + public void tearDown() throws Exception { + this.gson = null; + } + + @Test + public void testEmptySensorRegistry() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + + final String json = this.gson.toJson(sensorRegistry); + System.out.println(json); + assertEquals(json, "{\"identifier\":\"root\",\"name\":\"Root\",\"children\":[]}"); + } + + @Test + public void testEmptySensorRegistryWithChildren() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + topLevel.addChildMachineSensor("child-1", "Child 1"); + topLevel.addChildMachineSensor("child-2"); + + final String json = this.gson.toJson(sensorRegistry); + System.out.println(json); + assertEquals(json, + "{\"identifier\":\"root\",\"name\":\"Root\",\"children\":[{\"identifier\":\"child-1\",\"name\":\"Child 1\"},{\"identifier\":\"child-2\",\"name\":\"\"}]}"); + } + + @Test + public void testEmptySensorRegistryWithGrandChildren() { + final MutableSensorRegistry sensorRegistry = new MutableSensorRegistry("root", "Root"); + final MutableAggregatedSensor topLevel = sensorRegistry.getTopLevelSensor(); + final MutableAggregatedSensor aggregatedSensor = + topLevel.addChildAggregatedSensor("child-1", "Child 1"); + aggregatedSensor.addChildMachineSensor("child-1-1", "Child 1a"); + aggregatedSensor.addChildMachineSensor("child-1-2", "Child 1b"); + topLevel.addChildMachineSensor("child-2", "Child 2"); + + final String json = this.gson.toJson(sensorRegistry); + System.out.println(json); + assertEquals(json, + "{\"identifier\":\"root\",\"name\":\"Root\",\"children\":[{\"identifier\":\"child-1\",\"name\":\"Child 1\",\"children\":[{\"identifier\":\"child-1-1\",\"name\":\"Child 1a\"},{\"identifier\":\"child-1-2\",\"name\":\"Child 1b\"}]},{\"identifier\":\"child-2\",\"name\":\"Child 2\"}]}"); + } + +} diff --git a/theodolite-benchmarks/definitions/uc1-beam-flink/uc1-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-beam-flink/uc1-beam-flink-benchmark-operator.yaml index 2e110abfc13e1537792da381de2260fb3adbd606..17266b969b3abfc7a14b4578ba1855f06b830086 100644 --- a/theodolite-benchmarks/definitions/uc1-beam-flink/uc1-beam-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc1-beam-flink/uc1-beam-flink-benchmark-operator.yaml @@ -49,6 +49,15 @@ spec: resource: "uc1-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc1-beam-samza/uc1-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-beam-samza/uc1-beam-samza-benchmark-operator.yaml index 46030c67b135c97fcefe99482bd511f0c8138a0e..d3ee8f5242c4740aedf9862dc7be091a920582d1 100644 --- a/theodolite-benchmarks/definitions/uc1-beam-samza/uc1-beam-samza-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc1-beam-samza/uc1-beam-samza-benchmark-operator.yaml @@ -12,12 +12,12 @@ spec: - "beam-samza-service.yaml" - "service-monitor.yaml" afterActions: - - selector: # delete zookeeper nodes to reset zookeeper - pod: - matchLabels: - app: "zookeeper-client" - container: "zookeeper-client" - exec: + - exec: + selector: # delete zookeeper nodes to reset zookeeper + pod: + matchLabels: + app: "zookeeper-client" + container: "zookeeper-client" command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc1-application-1"] timeoutSeconds: 60 loadGenerator: @@ -44,6 +44,15 @@ spec: resource: "uc1-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml index 20953c2d1e64895417f4f5339a0f3820d78735ac..ac89e714018a6d9d68d3459a3b7245475176fd6a 100644 --- a/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc1-flink/uc1-flink-benchmark-operator.yaml @@ -49,6 +49,15 @@ spec: resource: "uc1-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-benchmark-operator.yaml index ca8994c40350ed55e2a6b927c370b3d11a6d4bfa..ad42faedd39e07d52ebb7655d644ea92a7b9e04a 100644 --- a/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc1-hazelcastjet/uc1-benchmark-operator.yaml @@ -34,6 +34,15 @@ spec: resource: "uc1-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml index c340547c703c03a2e91738d4f53537938da97e0e..80352e27dee3c80ae38c558825736bbc17c97283 100644 --- a/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc1-kstreams/uc1-kstreams-benchmark-operator.yaml @@ -36,6 +36,15 @@ spec: resource: "uc1-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc2-beam-flink/uc2-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-beam-flink/uc2-beam-flink-benchmark-operator.yaml index ffe613b401301e00cb1d368ec44609210d299df1..f172b33cec4327b7bc5193ee6fea43f5313dee8d 100644 --- a/theodolite-benchmarks/definitions/uc2-beam-flink/uc2-beam-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc2-beam-flink/uc2-beam-flink-benchmark-operator.yaml @@ -49,6 +49,15 @@ spec: resource: "uc2-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc2-beam-samza/uc2-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-beam-samza/uc2-beam-samza-benchmark-operator.yaml index 46b61aaeaead664d6ed723278384c1bdf8b99ed1..619e87b608f2342324b49ecaf17aad4071570b03 100644 --- a/theodolite-benchmarks/definitions/uc2-beam-samza/uc2-beam-samza-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc2-beam-samza/uc2-beam-samza-benchmark-operator.yaml @@ -12,12 +12,12 @@ spec: - "beam-samza-service.yaml" - "service-monitor.yaml" afterActions: - - selector: # delete zookeeper nodes to reset zookeeper - pod: - matchLabels: - app: "zookeeper-client" - container: "zookeeper-client" - exec: + - exec: + selector: # delete zookeeper nodes to reset zookeeper + pod: + matchLabels: + app: "zookeeper-client" + container: "zookeeper-client" command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc2-application-1"] timeoutSeconds: 60 loadGenerator: @@ -44,6 +44,15 @@ spec: resource: "uc2-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml index 3020bb317c8b500562f1edcf2dc770f1288a8788..b45f9d4baa37ab9495adbc82f7f2cd9196d8413d 100644 --- a/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc2-flink/uc2-flink-benchmark-operator.yaml @@ -49,6 +49,15 @@ spec: resource: "uc2-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-benchmark-operator.yaml index 436bcc790c50c86e96b3b1853b198a0f6da1aec9..0c1408df5d1bd2f5efee8d28567bfe58db32fca8 100644 --- a/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc2-hazelcastjet/uc2-benchmark-operator.yaml @@ -34,6 +34,15 @@ spec: resource: "uc2-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml index b9f2b14e369b3c8e241be62c04bd480f38d847dc..3e9ffd9a20932b99a0d1903c412b417c19a710d3 100644 --- a/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc2-kstreams/uc2-kstreams-benchmark-operator.yaml @@ -36,6 +36,15 @@ spec: resource: "uc2-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc3-beam-flink/uc3-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-beam-flink/uc3-beam-flink-benchmark-operator.yaml index 4449252c0de5aa81c3069b65c19325256bab57e9..af899991712bcb51abc204b84a3a48de9d687b25 100644 --- a/theodolite-benchmarks/definitions/uc3-beam-flink/uc3-beam-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc3-beam-flink/uc3-beam-flink-benchmark-operator.yaml @@ -49,6 +49,15 @@ spec: resource: "uc3-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc3-beam-samza/uc3-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-beam-samza/uc3-beam-samza-benchmark-operator.yaml index 36d812d4ca1fd226c7edcd96472b5aefff26bfda..2dd5fcdf32bfc9de143a8a39c7550db912108200 100644 --- a/theodolite-benchmarks/definitions/uc3-beam-samza/uc3-beam-samza-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc3-beam-samza/uc3-beam-samza-benchmark-operator.yaml @@ -12,12 +12,12 @@ spec: - "beam-samza-service.yaml" - "service-monitor.yaml" afterActions: - - selector: # delete zookeeper nodes to reset zookeeper - pod: - matchLabels: - app: "zookeeper-client" - container: "zookeeper-client" - exec: + - exec: + selector: # delete zookeeper nodes to reset zookeeper + pod: + matchLabels: + app: "zookeeper-client" + container: "zookeeper-client" command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc3-application-1"] timeoutSeconds: 60 loadGenerator: @@ -44,6 +44,15 @@ spec: resource: "uc3-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml index 0b6e2490f3b58e5c843f2719b24378b46406c6a9..8cdc00a559cc94fe9e9bcf95dd722662880be07e 100644 --- a/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc3-flink/uc3-flink-benchmark-operator.yaml @@ -49,6 +49,15 @@ spec: resource: "uc3-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-benchmark-operator.yaml index 3d9f755dc741458b0c8a27fe5ef450b09478b8cb..5c50ce87cee65e90dbf393ae0f7dcdf8fdf72a26 100644 --- a/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc3-hazelcastjet/uc3-benchmark-operator.yaml @@ -34,6 +34,15 @@ spec: resource: "uc3-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml index 1db619303fe1bb108205654c2245b8032b723c15..e34f8707e9a461c7df4fc9361fd95763fcadf784 100644 --- a/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc3-kstreams/uc3-kstreams-benchmark-operator.yaml @@ -36,6 +36,15 @@ spec: resource: "uc3-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc4-beam-flink/uc4-beam-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-beam-flink/uc4-beam-flink-benchmark-operator.yaml index 738b1c837469a9272bf27d4df08d6e5242b1a4c2..3d6e07f4e3049a19f2fbb44ccff5f077d87d2322 100644 --- a/theodolite-benchmarks/definitions/uc4-beam-flink/uc4-beam-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc4-beam-flink/uc4-beam-flink-benchmark-operator.yaml @@ -50,6 +50,15 @@ spec: properties: loadGenMaxRecords: "150000" numSensors: "4.0" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc4-beam-samza/uc4-beam-samza-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-beam-samza/uc4-beam-samza-benchmark-operator.yaml index 12690cec23761a38c948b0cb8757550ded54acef..8835db1d3ff6287d4c9cfb04021881deb65acb39 100644 --- a/theodolite-benchmarks/definitions/uc4-beam-samza/uc4-beam-samza-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc4-beam-samza/uc4-beam-samza-benchmark-operator.yaml @@ -12,12 +12,12 @@ spec: - "beam-samza-service.yaml" - "service-monitor.yaml" afterActions: - - selector: # delete zookeeper nodes to reset zookeeper - pod: - matchLabels: - app: "zookeeper-client" - container: "zookeeper-client" - exec: + - exec: + selector: # delete zookeeper nodes to reset zookeeper + pod: + matchLabels: + app: "zookeeper-client" + container: "zookeeper-client" command: ["bash", "-c", "bin/zkCli.sh -server $ZOOKEEPER_SERVER deleteall /app-theodolite-uc4-application-1"] timeoutSeconds: 60 loadGenerator: @@ -45,6 +45,15 @@ spec: properties: loadGenMaxRecords: "150000" numSensors: "4.0" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml index 28ae937e964127ded0e34d637ab307fa08db8ec3..2e4011d44d63ce6767e30f5519a41b36fd8b9bc5 100644 --- a/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc4-flink/uc4-flink-benchmark-operator.yaml @@ -50,6 +50,15 @@ spec: properties: loadGenMaxRecords: "150000" numSensors: "4.0" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-benchmark-operator.yaml index f0151969ccb2ff34558c4a56c78f17db9fd3678e..06c22a1cf69ec4fb747fc10f27e4c08718d6a8c1 100644 --- a/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc4-hazelcastjet/uc4-benchmark-operator.yaml @@ -35,6 +35,15 @@ spec: properties: loadGenMaxRecords: "150000" numSensors: "4.0" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml index 9ce6daa2dc14e8beecba1c43381defea6bba0d37..257c6814dd4ebbec727c0223161ce6649c4d4b42 100644 --- a/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml +++ b/theodolite-benchmarks/definitions/uc4-kstreams/uc4-kstreams-benchmark-operator.yaml @@ -37,6 +37,15 @@ spec: properties: loadGenMaxRecords: "150000" numSensors: "4.0" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 2000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite-benchmarks/docker-test/uc4-hazelcastjet/docker-compose.yml b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/docker-compose.yml index 9a254f5228677322ed98afcd73349cf7a50d80bc..ca6f3c85fe670e53bafd6a56e568cad9166ae501 100644 --- a/theodolite-benchmarks/docker-test/uc4-hazelcastjet/docker-compose.yml +++ b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/docker-compose.yml @@ -38,7 +38,7 @@ services: SCHEMA_REGISTRY_HOST_NAME: schema-registry SCHEMA_REGISTRY_KAFKASTORE_BOOTSTRAP_SERVERS: kafka:9092 benchmark: - image: ghcr.io/cau-se/theodolite-uc1-hazelcastjet:${THEODOLITE_TAG:-latest} + image: ghcr.io/cau-se/theodolite-uc4-hazelcastjet:${THEODOLITE_TAG:-latest} depends_on: - schema-registry - kafka diff --git a/theodolite-benchmarks/docker-test/uc4-hazelcastjet/test.sh b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/test.sh index d9bb6ccf241935c39df63ea5e2f0fce02476e976..a141feee36c7a58e75baf5462ee06e3bc1f4c882 100755 --- a/theodolite-benchmarks/docker-test/uc4-hazelcastjet/test.sh +++ b/theodolite-benchmarks/docker-test/uc4-hazelcastjet/test.sh @@ -2,7 +2,7 @@ until docker-compose exec -T kcat kcat -L -b kafka:9092 -t output -J | jq -r '.topics[0].partitions | length' | grep "\b3\b"; do sleep 5s; done -docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=avro -r http://schema-registry:8081 -f '%k:%s\n' -c 600 | +docker-compose exec -T kcat kcat -C -b kafka:9092 -t output -s key=s -s value=avro -r http://schema-registry:8081 -f '%k:%s\n' -c 1200 | tee /dev/stderr | awk -F ':' '!/^%/ {print $1}' | sort | diff --git a/theodolite-benchmarks/http-bridge/build.gradle b/theodolite-benchmarks/http-bridge/build.gradle index fa98d9fdd602174a945df95321f5e32b8c64052f..7714f9947b1361badb8a17d3eb6f063b1dc39aab 100644 --- a/theodolite-benchmarks/http-bridge/build.gradle +++ b/theodolite-benchmarks/http-bridge/build.gradle @@ -17,8 +17,7 @@ repositories { } dependencies { - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') implementation project(':load-generator-commons') implementation 'io.javalin:javalin:4.3.0' diff --git a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/EnvVarHttpBridgeFactory.java b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/EnvVarHttpBridgeFactory.java index d3c172ac87221ab03f0171883df26802bf5a3aa9..2d49f05eea8aee1a3ed72d63868fbd6a50a92f48 100644 --- a/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/EnvVarHttpBridgeFactory.java +++ b/theodolite-benchmarks/http-bridge/src/main/java/rocks/theodolite/benchmarks/httpbridge/EnvVarHttpBridgeFactory.java @@ -3,9 +3,9 @@ package rocks.theodolite.benchmarks.httpbridge; import java.util.List; import java.util.Objects; import java.util.Optional; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.loadgenerator.ConfigurationKeys; import rocks.theodolite.benchmarks.loadgenerator.TitanKafkaSenderFactory; -import titan.ccp.model.records.ActivePowerRecord; class EnvVarHttpBridgeFactory { diff --git a/theodolite-benchmarks/kstreams-commons/build.gradle b/theodolite-benchmarks/kstreams-commons/build.gradle index 167a75327b251af20b1142fe42c82b3bbedfe62b..e443e3af19d8b51e230d6f57a865aef9a4d90e30 100644 --- a/theodolite-benchmarks/kstreams-commons/build.gradle +++ b/theodolite-benchmarks/kstreams-commons/build.gradle @@ -14,9 +14,8 @@ repositories { dependencies { // These dependencies are used internally, and not exposed to consumers on their own compile classpath. + implementation project(':commons') // implementation 'org.slf4j:slf4j-simple:1.7.25' - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } implementation 'org.apache.kafka:kafka-streams:3.1.0' // Use JUnit test framework diff --git a/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/GenericSerde.java b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/GenericSerde.java new file mode 100644 index 0000000000000000000000000000000000000000..4fa269385e522d42f9c3af3a6f4102468380bc35 --- /dev/null +++ b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/GenericSerde.java @@ -0,0 +1,64 @@ +package rocks.theodolite.benchmarks.commons.kstreams; + +import java.util.Map; +import java.util.function.Function; +import org.apache.kafka.common.serialization.Deserializer; +import org.apache.kafka.common.serialization.Serde; +import org.apache.kafka.common.serialization.Serializer; + +/** + * Factory methods to create generic {@link Serde}s. + */ +public final class GenericSerde { + + private GenericSerde() {} + + /** + * Create a {@link Serde} using a serialize and a deserialize function. + * + * @param serializer function to convert a record into a byte array + * @param deserializer function to create a record from a byte array + */ + public static <T> Serde<T> from(final Function<T, byte[]> serializer, + final Function<byte[], T> deserializer) { + return org.apache.kafka.common.serialization.Serdes.serdeFrom(new Serializer<T>() { + + @Override + public void configure(final Map<String, ?> configs, final boolean isKey) { + // Do nothing + } + + @Override + public byte[] serialize(final String topic, final T data) { + return serializer.apply(data); + } + + @Override + public void close() { + // Do nothing + } + }, new Deserializer<T>() { + + @Override + public void configure(final Map<String, ?> configs, final boolean isKey) { + // Do nothing + } + + @Override + public T deserialize(final String topic, final byte[] data) { + if (data == null) { + return null; + } + return deserializer.apply(data); + } + + @Override + public void close() { + // Do nothing + } + + }); + + } + +} diff --git a/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/KafkaStreamsBuilder.java b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/KafkaStreamsBuilder.java index 06e8591eebc538fcfaed2db394625d8a6dd8b033..5a2716c6ebcb2a857946908b500554d3de883174 100644 --- a/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/KafkaStreamsBuilder.java +++ b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/KafkaStreamsBuilder.java @@ -7,7 +7,6 @@ import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.KafkaStreams; import org.apache.kafka.streams.StreamsConfig; import org.apache.kafka.streams.Topology; -import titan.ccp.common.kafka.streams.PropertiesBuilder; /** * Builder for the Kafka Streams configuration. diff --git a/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/PropertiesBuilder.java b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/PropertiesBuilder.java new file mode 100644 index 0000000000000000000000000000000000000000..78dda383a25b155c7ab1de91df9ddd6f320fbecc --- /dev/null +++ b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/PropertiesBuilder.java @@ -0,0 +1,50 @@ +package rocks.theodolite.benchmarks.commons.kstreams; + +import java.util.Properties; +import java.util.function.Predicate; + + +/** + * Interface for a helper class for constructing and logging Kafka Stream {@link Properties}. + */ +public interface PropertiesBuilder { + + /** + * Set the provided configuration key to the provided value. + */ + <T> PropertiesBuilder set(String configKey, T value); + + /** + * Set the provided configuration key to the provided value if a given condition is evaluated to + * true. + */ + <T> PropertiesBuilder set(String configKey, T value, Predicate<T> condition); + + /** + * Build a {@link Properties} object with the option being set before. + */ + Properties build(); + + /** + * Interface representing an Kafka Stream {@link Properties} builder without the application id + * yet being set. + */ + interface WithoutApplicationId { + + /** + * Continue building Kafka Stream properties by specifying an application id. From now on, all + * configuration properties can be set directly. + */ + PropertiesBuilder applicationId(String applicationId); + + } + + /** + * Start building Kafka Stream properties by specifying a bootstrap server. Next, an application + * id has to be specified. + */ + static PropertiesBuilder.WithoutApplicationId bootstrapServers(final String bootstrapServers) { + return PropertiesBuilderImpl.bootstrapServers(bootstrapServers); + } + +} diff --git a/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/PropertiesBuilderImpl.java b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/PropertiesBuilderImpl.java new file mode 100644 index 0000000000000000000000000000000000000000..34459b8ea3d4c7d842e38c06cf12d7f0ffb9f14c --- /dev/null +++ b/theodolite-benchmarks/kstreams-commons/src/main/java/rocks/theodolite/benchmarks/commons/kstreams/PropertiesBuilderImpl.java @@ -0,0 +1,52 @@ +package rocks.theodolite.benchmarks.commons.kstreams; + +import java.util.Objects; +import java.util.Properties; +import java.util.function.Predicate; +import org.apache.kafka.streams.StreamsConfig; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Default implementation for {@link PropertiesBuilder} and + * {@link PropertiesBuilder.WithoutApplicationId}. + */ +class PropertiesBuilderImpl implements PropertiesBuilder, PropertiesBuilder.WithoutApplicationId { + + private static final Logger LOGGER = LoggerFactory.getLogger(PropertiesBuilderImpl.class); + + private final Properties properties = new Properties(); + + @Override + public <T> PropertiesBuilderImpl set(final String configKey, final T value) { + this.properties.put(configKey, value); + LOGGER.info("Set Kafka Streams configuration parameter '{}' to '{}'.", configKey, value); + return this; + } + + @Override + public <T> PropertiesBuilderImpl set(final String configKey, final T value, + final Predicate<T> condition) { + if (condition.test(value)) { + this.set(configKey, value); + } + return this; + } + + @Override + public Properties build() { + return this.properties; + } + + @Override + public PropertiesBuilderImpl applicationId(final String applicationId) { + Objects.requireNonNull(applicationId, "Kafka Streams application ID cannot be null."); + return this.set(StreamsConfig.APPLICATION_ID_CONFIG, applicationId); + } + + protected static PropertiesBuilderImpl bootstrapServers(final String bootsrapservers) { + Objects.requireNonNull(bootsrapservers, "Kafka bootstrap servers cannot be null."); + return new PropertiesBuilderImpl().set(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, bootsrapservers); + } + +} diff --git a/theodolite-benchmarks/load-generator-commons/build.gradle b/theodolite-benchmarks/load-generator-commons/build.gradle index 62542eeabc1cccb35fa9f71d1929b72956a56999..082fb8eb9f1df15fb7b054588bb9728940eb442f 100644 --- a/theodolite-benchmarks/load-generator-commons/build.gradle +++ b/theodolite-benchmarks/load-generator-commons/build.gradle @@ -18,8 +18,7 @@ dependencies { implementation 'org.slf4j:slf4j-simple:1.7.25' implementation 'com.google.guava:guava:30.1-jre' implementation 'com.google.code.gson:gson:2.8.2' - implementation('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - implementation('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } + implementation project(':commons') implementation 'org.apache.kafka:kafka-streams:2.6.0' // TODO required? implementation platform('com.google.cloud:libraries-bom:24.2.0') implementation 'com.google.protobuf:protobuf-java-util' diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/EnvVarLoadGeneratorFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/EnvVarLoadGeneratorFactory.java index ae9a6d4220ceaec091a0a2fb49fb82f16fdbb42e..5d5f3c0c64b4d8a0efc4f4c7c332986ea4b9560d 100644 --- a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/EnvVarLoadGeneratorFactory.java +++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/EnvVarLoadGeneratorFactory.java @@ -7,7 +7,7 @@ import java.util.Properties; import org.apache.kafka.clients.producer.ProducerConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; class EnvVarLoadGeneratorFactory { diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSender.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSender.java index 56b1946ad78d888fe6e5140fdc373bb2cd3a4ed4..0593e850112bf20d0e02f0a6f2aa884b9ce4406e 100644 --- a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSender.java +++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/KafkaRecordSender.java @@ -8,7 +8,7 @@ import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.serialization.Serializer; import org.apache.kafka.common.serialization.StringSerializer; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; /** * Sends records to Kafka. diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanKafkaSenderFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanKafkaSenderFactory.java index ee7d416513439a5d0ba7bad7bcdb09e1baf5e4c7..02a46952d9f21bfda5dc7ebea24fc1c7779e77bb 100644 --- a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanKafkaSenderFactory.java +++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanKafkaSenderFactory.java @@ -1,7 +1,7 @@ package rocks.theodolite.benchmarks.loadgenerator; import java.util.Properties; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * A factory for creating {@link KafkaRecordSender}s that sends Titan {@link ActivePowerRecord}s. diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanPubSubSenderFactory.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanPubSubSenderFactory.java index 569d98fb9dcd235d12a0c415fdae495eeb6abdd4..c355033343854004e0aa4dff066da6abdebd7f8b 100644 --- a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanPubSubSenderFactory.java +++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanPubSubSenderFactory.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.loadgenerator; import java.io.IOException; import java.nio.ByteBuffer; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * A factory for creating {@link PubSubRecordSender}s that sends Titan {@link ActivePowerRecord}s. diff --git a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGenerator.java b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGenerator.java index 34b17db4220e60e1fd273b1acf0a0c1543a0742b..41ee632fccb836f0264251142e01386019746674 100644 --- a/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGenerator.java +++ b/theodolite-benchmarks/load-generator-commons/src/main/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGenerator.java @@ -1,7 +1,7 @@ package rocks.theodolite.benchmarks.loadgenerator; import java.time.Clock; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * A factory for creating {@link RecordGenerator}s that creates Titan {@link ActivePowerRecord}s. diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSenderTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSenderTest.java index 731dda6c74fd3cd6d74771f95896c2260ce6df29..74e10711643398c7d0eb79a80a8ba3ff033cb4a7 100644 --- a/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSenderTest.java +++ b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/HttpRecordSenderTest.java @@ -14,7 +14,7 @@ import java.net.URI; import org.junit.Before; import org.junit.Rule; import org.junit.Test; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; public class HttpRecordSenderTest { diff --git a/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGeneratorTest.java b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGeneratorTest.java index eb7c7f2a403dfb7138bdfd8e0855930001a4488b..7ef2ae41935120a0619f76379ee321bc83c9ba4c 100644 --- a/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGeneratorTest.java +++ b/theodolite-benchmarks/load-generator-commons/src/test/java/rocks/theodolite/benchmarks/loadgenerator/TitanRecordGeneratorTest.java @@ -7,7 +7,7 @@ import java.time.ZoneId; import java.time.ZoneOffset; import org.junit.Assert; import org.junit.Test; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; public class TitanRecordGeneratorTest { diff --git a/theodolite-benchmarks/settings.gradle b/theodolite-benchmarks/settings.gradle index 0040989a8b3b02487c2d7328726b7caadb90f32f..1979f5f335444084b5421dcdba3228594a7b907e 100644 --- a/theodolite-benchmarks/settings.gradle +++ b/theodolite-benchmarks/settings.gradle @@ -1,5 +1,14 @@ +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + } +} rootProject.name = 'theodolite-benchmarks' + + +include 'commons' include 'load-generator-commons' include 'kstreams-commons' include 'flink-commons' diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/ConverterAdapter.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/ConverterAdapter.java index 08834a47223e8b4209da79c4cdcbb6a60e027418..b32d0cb8213b57cbad7f97f97409992e90d03abd 100644 --- a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/ConverterAdapter.java +++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/ConverterAdapter.java @@ -2,8 +2,8 @@ package rocks.theodolite.benchmarks.uc1.beam; import org.apache.beam.sdk.transforms.SimpleFunction; import org.apache.beam.sdk.values.TypeDescriptor; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.RecordConverter; -import titan.ccp.model.records.ActivePowerRecord; /** * {@link SimpleFunction} which wraps a {@link RecordConverter} to be used with Beam. diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/GenericSink.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/GenericSink.java index 04eae799837b2e5278842d248d135e479f84086b..e42b7dea8ce346af11e5379e258970949a9def45 100644 --- a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/GenericSink.java +++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/GenericSink.java @@ -4,8 +4,8 @@ import org.apache.beam.sdk.transforms.MapElements; import org.apache.beam.sdk.transforms.PTransform; import org.apache.beam.sdk.transforms.ParDo; import org.apache.beam.sdk.values.PCollection; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter; -import titan.ccp.model.records.ActivePowerRecord; /** * A {@link PTransform} for a generic {@link DatabaseAdapter}. diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/PipelineFactory.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/PipelineFactory.java index d95d9b3343835f8348af15c3d00c34ef807d4501..74271aca04e28ab213ef396d61e12adc30517035 100644 --- a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/PipelineFactory.java +++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/PipelineFactory.java @@ -9,8 +9,8 @@ import org.apache.beam.sdk.transforms.Values; import org.apache.commons.configuration2.Configuration; import rocks.theodolite.benchmarks.commons.beam.AbstractPipelineFactory; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.beam.firestore.FirestoreOptionsExpander; -import titan.ccp.model.records.ActivePowerRecord; /** * {@link AbstractPipelineFactory} for UC1. diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkFactory.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkFactory.java index d4854293b0c26804f0204e58c09a45f13dbf171f..73b95bb2257c80a1523b76c1e6b136319e6537cf 100644 --- a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkFactory.java +++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkFactory.java @@ -3,7 +3,7 @@ package rocks.theodolite.benchmarks.uc1.beam; import org.apache.beam.sdk.transforms.PTransform; import org.apache.beam.sdk.values.PCollection; import org.apache.commons.configuration2.Configuration; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Interface for a class that creates sinks (i.e., {@link PTransform}s that map and store diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkType.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkType.java index da836815e09631e2ebc071badc02618171e0792a..60eaabfddbbc7738c33f1c2b563703710e3f0a0e 100644 --- a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkType.java +++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/SinkType.java @@ -4,9 +4,9 @@ import java.util.stream.Stream; import org.apache.beam.sdk.transforms.PTransform; import org.apache.beam.sdk.values.PCollection; import org.apache.commons.configuration2.Configuration; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.beam.firestore.FirestoreSink; import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * Supported Sink types, i.e., {@link PTransform} for converting and storing diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/DocumentMapper.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/DocumentMapper.java index 1abf847250779150bb48b45c162afaeac1130044..6d23c929688bbbcda1586fb41a454605f48e2ef7 100644 --- a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/DocumentMapper.java +++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/DocumentMapper.java @@ -4,7 +4,7 @@ import com.google.firestore.v1.Document; import com.google.firestore.v1.Value; import java.io.IOException; import org.apache.beam.sdk.transforms.SimpleFunction; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; final class DocumentMapper extends SimpleFunction<ActivePowerRecord, Document> { diff --git a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreSink.java b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreSink.java index dfe3f240b9727d0fa5027ea5f29cd67def3323ba..100bb6205bd91d2562f9141332943610ba3b5e3e 100644 --- a/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreSink.java +++ b/theodolite-benchmarks/uc1-beam/src/main/java/rocks/theodolite/benchmarks/uc1/beam/firestore/FirestoreSink.java @@ -7,7 +7,7 @@ import org.apache.beam.sdk.transforms.MapElements; import org.apache.beam.sdk.transforms.PTransform; import org.apache.beam.sdk.values.PCollection; import org.apache.commons.configuration2.Configuration; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * A {@link PTransform} mapping {@link ActivePowerRecord}s to {@link Document}s, followed by storing diff --git a/theodolite-benchmarks/uc1-commons/build.gradle b/theodolite-benchmarks/uc1-commons/build.gradle index 0f7d31d1f557ecd214b3a57227851d0f70b61084..7f742b99d8555f8be8f0ac4861ba257b1913afef 100644 --- a/theodolite-benchmarks/uc1-commons/build.gradle +++ b/theodolite-benchmarks/uc1-commons/build.gradle @@ -13,11 +13,7 @@ repositories { } dependencies { - // Make this implementation once this is a local subproject. - // Currently, Flink needs its own version of these dependencies. - compileOnly('org.industrial-devops:titan-ccp-common:0.1.0-SNAPSHOT') { changing = true } - compileOnly('org.industrial-devops:titan-ccp-common-kafka:0.1.0-SNAPSHOT') { changing = true } - + implementation project(':commons') implementation 'com.google.code.gson:gson:2.8.9' testImplementation 'junit:junit:4.12' diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseAdapter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseAdapter.java index a1cb1ade0dc76b168cf9ee54f64d5ac88d6b3a98..99e59a6e6fcbef8e49fe04d7ecaf9ed929e9b13e 100644 --- a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseAdapter.java +++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/DatabaseAdapter.java @@ -1,7 +1,7 @@ package rocks.theodolite.benchmarks.uc1.commons; import java.util.Objects; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * A database adapter consisting of a {@link RecordConverter} and a {@link DatabaseWriter}. diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/RecordConverter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/RecordConverter.java index 105f19e0e920e3516f7277cd7804dae210a7d0b1..a728e9d6b676a273c3847b89b2091e8928aba114 100644 --- a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/RecordConverter.java +++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/RecordConverter.java @@ -1,6 +1,6 @@ package rocks.theodolite.benchmarks.uc1.commons; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Converts an {@link ActivePowerRecord} to the type required by a database. diff --git a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/JsonConverter.java b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/JsonConverter.java index f9974affb7bf57fc63e9bfe8ba92fd056da9a97b..a59f02687c1c6a0455f43e5a34c421c85e6972cd 100644 --- a/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/JsonConverter.java +++ b/theodolite-benchmarks/uc1-commons/src/main/java/rocks/theodolite/benchmarks/uc1/commons/logger/JsonConverter.java @@ -2,8 +2,8 @@ package rocks.theodolite.benchmarks.uc1.commons.logger; import com.google.gson.Gson; import java.io.Serializable; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.RecordConverter; -import titan.ccp.model.records.ActivePowerRecord; /** * {@link RecordConverter} that converts {@link ActivePowerRecord}s to JSON strings. diff --git a/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConverterAdapter.java b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConverterAdapter.java index 064b8afbb03dc16262ca7fcf90a0fdd8af4419a9..8380cdc09caa35814f3203bdf6dc1746875fdf9b 100644 --- a/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConverterAdapter.java +++ b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/ConverterAdapter.java @@ -1,8 +1,8 @@ package rocks.theodolite.benchmarks.uc1.flink; import org.apache.flink.api.common.functions.MapFunction; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.RecordConverter; -import titan.ccp.model.records.ActivePowerRecord; /** * {@link MapFunction} which wraps a {@link RecordConverter} to be used with Flink. diff --git a/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/HistoryServiceFlinkJob.java b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/HistoryServiceFlinkJob.java index a5e833b0bbb7cd8a153e5fa7c51c1a548ef63083..9d3412c7f7a318b471902f9f2f38e714bf1034ec 100644 --- a/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/HistoryServiceFlinkJob.java +++ b/theodolite-benchmarks/uc1-flink/src/main/java/rocks/theodolite/benchmarks/uc1/flink/HistoryServiceFlinkJob.java @@ -5,9 +5,9 @@ import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import rocks.theodolite.benchmarks.commons.flink.AbstractFlinkService; import rocks.theodolite.benchmarks.commons.flink.KafkaConnectorFactory; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter; import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * The History microservice implemented as a Flink job. @@ -24,7 +24,7 @@ public final class HistoryServiceFlinkJob extends AbstractFlinkService { @Override protected void configureSerializers() { - // No serializers needed here + // No serializers needed here } diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1HazelcastJetFactory.java b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1HazelcastJetFactory.java index 4a5c5dead14e606847dc5e2ac3c95414d9f611b3..93aaa1a7e844634bb4fdf283d5b9f41a0d6c0b7f 100644 --- a/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1HazelcastJetFactory.java +++ b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1HazelcastJetFactory.java @@ -134,8 +134,8 @@ public class Uc1HazelcastJetFactory { * @return The Uc1HazelcastJetBuilder factory with set kafkaPropertiesForPipeline. */ public Uc1HazelcastJetFactory setPropertiesFromEnv(final String bootstrapServersDefault, // NOPMD - final String schemaRegistryUrlDefault, - final String jobName) { + final String schemaRegistryUrlDefault, + final String jobName) { // Use KafkaPropertiesBuilder to build a properties object used for kafka final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder(); final Properties kafkaProps = diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1PipelineBuilder.java b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1PipelineBuilder.java index c02ea1e7ea7fb3f27bdbf818248678011a93f6a2..e6107682ef3aff91d45bcd7a65675b5a6323975e 100644 --- a/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1PipelineBuilder.java +++ b/theodolite-benchmarks/uc1-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc1/hazelcastjet/Uc1PipelineBuilder.java @@ -1,18 +1,18 @@ package rocks.theodolite.benchmarks.uc1.hazelcastjet; -import static com.hazelcast.jet.pipeline.SinkBuilder.sinkBuilder; - import com.hazelcast.jet.kafka.KafkaSources; import com.hazelcast.jet.pipeline.Pipeline; import com.hazelcast.jet.pipeline.Sink; +import com.hazelcast.jet.pipeline.SinkBuilder; import com.hazelcast.jet.pipeline.StreamSource; import com.hazelcast.jet.pipeline.StreamStage; import java.util.Map.Entry; import java.util.Properties; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter; import rocks.theodolite.benchmarks.uc1.commons.DatabaseWriter; import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory; -import titan.ccp.model.records.ActivePowerRecord; + /** * Builder to build a HazelcastJet Pipeline for UC1 which can be used for stream processing using @@ -45,7 +45,7 @@ public class Uc1PipelineBuilder { // Do not refactor this to just use the call // (There is a problem with static calls in functions in hazelcastjet) final DatabaseWriter<String> writer = this.databaseAdapter.getDatabaseWriter(); - final Sink<String> sink = sinkBuilder( + final Sink<String> sink = SinkBuilder.sinkBuilder( "Sink into database", x -> writer) .<String>receiveFn(DatabaseWriter::write) .build(); diff --git a/theodolite-benchmarks/uc1-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc1/hazelcast/Uc1PipelineTest.java b/theodolite-benchmarks/uc1-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc1/hazelcast/Uc1PipelineTest.java index 525327ddbcdcddb6cf1bfe4e2d6be62d3384fc0c..8ffde0487ab88c260655f51eac3d2701f31a7ab0 100644 --- a/theodolite-benchmarks/uc1-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc1/hazelcast/Uc1PipelineTest.java +++ b/theodolite-benchmarks/uc1-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc1/hazelcast/Uc1PipelineTest.java @@ -1,5 +1,7 @@ package rocks.theodolite.benchmarks.uc1.hazelcast; +import static com.hazelcast.jet.pipeline.SinkBuilder.sinkBuilder; +import static com.hazelcast.logging.Logger.getLogger; import com.hazelcast.jet.Jet; import com.hazelcast.jet.JetInstance; import com.hazelcast.jet.config.JetConfig; @@ -12,24 +14,21 @@ import com.hazelcast.jet.pipeline.test.AssertionCompletedException; import com.hazelcast.jet.pipeline.test.Assertions; import com.hazelcast.jet.pipeline.test.TestSources; import com.hazelcast.jet.test.SerialTest; +import com.hazelcast.logging.ILogger; import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.CompletionException; -import com.hazelcast.logging.ILogger; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; import org.slf4j.Logger; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter; import rocks.theodolite.benchmarks.uc1.commons.DatabaseWriter; import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory; import rocks.theodolite.benchmarks.uc1.hazelcastjet.Uc1PipelineBuilder; -import titan.ccp.model.records.ActivePowerRecord; - -import static com.hazelcast.jet.pipeline.SinkBuilder.sinkBuilder; -import static com.hazelcast.logging.Logger.getLogger; /** * Test methods for the Hazelcast Jet Implementation of UC1. @@ -44,7 +43,7 @@ public class Uc1PipelineTest extends JetTestSupport { // Standart Logger private static final Logger LOGGER = org.slf4j.LoggerFactory.getLogger(Uc1PipelineTest.class); // HazelcastJet Logger - private static final ILogger logger = getLogger(Uc1PipelineTest.class); + private static final ILogger logger = getLogger(Uc1PipelineTest.class); private final DatabaseAdapter<String> databaseAdapter = LogWriterFactory.forJson(); @@ -55,7 +54,7 @@ public class Uc1PipelineTest extends JetTestSupport { @Before public void buildUc1Pipeline() { - this.logger.info("Hazelcast Logger"); + Uc1PipelineTest.logger.info("Hazelcast Logger"); LOGGER.info("Standard Logger"); @@ -67,9 +66,9 @@ public class Uc1PipelineTest extends JetTestSupport { // Create mock jet instance with configuration final String testClusterName = randomName(); final JetConfig testJetConfig = new JetConfig(); -// testJetConfig.setProperty( "hazelcast.logging.type", "slf4j" ); + // testJetConfig.setProperty( "hazelcast.logging.type", "slf4j" ); testJetConfig.getHazelcastConfig().setClusterName(testClusterName); - this.testInstance = createJetMember(testJetConfig); + this.testInstance = this.createJetMember(testJetConfig); // Create a test source @@ -92,17 +91,17 @@ public class Uc1PipelineTest extends JetTestSupport { final DatabaseWriter<String> adapter = this.databaseAdapter.getDatabaseWriter(); final Sink<String> sink = sinkBuilder( "database-sink", x -> adapter) - .<String>receiveFn(DatabaseWriter::write) - .build(); + .<String>receiveFn(DatabaseWriter::write) + .build(); -// Map Stage, can be used instead of sink -// StreamStage<String> log = uc1Topology.map(s -> { -// LOGGER.info(s); -// return s; -// }); -// log.writeTo(sink); + // Map Stage, can be used instead of sink + // StreamStage<String> log = uc1Topology.map(s -> { + // LOGGER.info(s); + // return s; + // }); + // log.writeTo(sink); - //apply sink + // apply sink this.uc1Topology.writeTo(sink); } @@ -121,8 +120,8 @@ public class Uc1PipelineTest extends JetTestSupport { // Assertion this.uc1Topology.apply(Assertions.assertCollectedEventually(assertTimeoutSeconds, collection -> { - //print the newest Record -// LOGGER.info(collection.get(collection.size()-1)); + // print the newest Record + // LOGGER.info(collection.get(collection.size()-1)); // Run pipeline until 5th item Assert.assertTrue("Not enough data arrived in the end", diff --git a/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/HistoryService.java b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/HistoryService.java index 0a2a1bec7c3515f903905efeb07e717a46e329ea..dd792ac8a814514338d6fb27b4f67f4b6f033105 100644 --- a/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/HistoryService.java +++ b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/HistoryService.java @@ -3,7 +3,7 @@ package rocks.theodolite.benchmarks.uc1.kstreams; import java.util.concurrent.CompletableFuture; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.KafkaStreams; -import titan.ccp.common.configuration.ServiceConfigurations; +import rocks.theodolite.benchmarks.commons.commons.configuration.ServiceConfigurations; /** * A microservice that manages the history and, therefore, stores and aggregates incoming diff --git a/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/TopologyBuilder.java b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/TopologyBuilder.java index 944e449c4693dc7c234844c97567d7f9f048cf3b..efbf774066773cd6a17d830cf07b629231fe06ef 100644 --- a/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/TopologyBuilder.java +++ b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/TopologyBuilder.java @@ -5,10 +5,10 @@ import org.apache.kafka.common.serialization.Serdes; import org.apache.kafka.streams.StreamsBuilder; import org.apache.kafka.streams.Topology; import org.apache.kafka.streams.kstream.Consumed; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc1.commons.DatabaseAdapter; import rocks.theodolite.benchmarks.uc1.commons.logger.LogWriterFactory; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * Builds Kafka Stream Topology for the History microservice. diff --git a/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/Uc1KafkaStreamsBuilder.java b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/Uc1KafkaStreamsBuilder.java index a1e9c4d78d0f340273fb3db944ba96913c8d0b13..05d6a5845a9eb79998d7c4fc1940357559d0936d 100644 --- a/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/Uc1KafkaStreamsBuilder.java +++ b/theodolite-benchmarks/uc1-kstreams/src/main/java/rocks/theodolite/benchmarks/uc1/kstreams/Uc1KafkaStreamsBuilder.java @@ -4,8 +4,8 @@ import java.util.Objects; import java.util.Properties; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.Topology; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; /** * Builder for the Kafka Streams configuration. diff --git a/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/PipelineFactory.java b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/PipelineFactory.java index 375b2a6cba5256e0644b6beaf26d41e010089250..decbcae1c4b524f9f39295ecd49275a3c1b09951 100644 --- a/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/PipelineFactory.java +++ b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/PipelineFactory.java @@ -22,7 +22,7 @@ import rocks.theodolite.benchmarks.commons.beam.AbstractPipelineFactory; import rocks.theodolite.benchmarks.commons.beam.ConfigurationKeys; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaWriterTransformation; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * {@link AbstractPipelineFactory} for UC2. diff --git a/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsAggregation.java b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsAggregation.java index a8956ee4b55c1e545e2c25ce38e2911b7c961337..cf320bf18b37f25b787c1baea1109892f2aa83fa 100644 --- a/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsAggregation.java +++ b/theodolite-benchmarks/uc2-beam/src/main/java/rocks/theodolite/benchmarks/uc2/beam/StatsAggregation.java @@ -6,7 +6,7 @@ import java.io.Serializable; import org.apache.beam.sdk.coders.AvroCoder; import org.apache.beam.sdk.coders.DefaultCoder; import org.apache.beam.sdk.transforms.Combine.CombineFn; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Aggregation Class for ActivePowerRecords. Creates a StatsAccumulator based on the ValueInW. diff --git a/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/HistoryServiceFlinkJob.java b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/HistoryServiceFlinkJob.java index 1109fb7bb431811dde4c448b445990599bc6d626..ea7716dbc10f61f03a6c5705c9d17e2d3a12745d 100644 --- a/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/HistoryServiceFlinkJob.java +++ b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/HistoryServiceFlinkJob.java @@ -1,10 +1,13 @@ package rocks.theodolite.benchmarks.uc2.flink; import com.google.common.math.Stats; +import org.apache.flink.api.common.functions.AggregateFunction; import org.apache.flink.api.common.typeinfo.Types; import org.apache.flink.api.java.tuple.Tuple2; +import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction; import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; import org.apache.flink.streaming.api.windowing.time.Time; +import org.apache.flink.streaming.api.windowing.windows.TimeWindow; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaConsumer; import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; import org.apache.kafka.common.serialization.Serdes; @@ -61,7 +64,9 @@ public final class HistoryServiceFlinkJob extends AbstractFlinkService { // .rebalance() .keyBy(ActivePowerRecord::getIdentifier) .window(TumblingEventTimeWindows.of(windowDuration)) - .aggregate(new StatsAggregateFunction(), new StatsProcessWindowFunction()) + .aggregate( + (AggregateFunction<ActivePowerRecord, Stats, Stats>) new StatsAggregateFunction(), + (ProcessWindowFunction<Stats, Tuple2<String, Stats>, String, TimeWindow>) new StatsProcessWindowFunction()) .map(t -> { final String key = t.f0; final String value = t.f1.toString(); diff --git a/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsAggregateFunction.java b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsAggregateFunction.java index b2a9e5f538c9e92ba777dbcd61caaa3199ebb383..ca5c9b2aee2285f5e8415d853fd9fe09f2d51b49 100644 --- a/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsAggregateFunction.java +++ b/theodolite-benchmarks/uc2-flink/src/main/java/rocks/theodolite/benchmarks/uc2/flink/StatsAggregateFunction.java @@ -3,8 +3,8 @@ package rocks.theodolite.benchmarks.uc2.flink; import com.google.common.math.Stats; import com.google.common.math.StatsAccumulator; import org.apache.flink.api.common.functions.AggregateFunction; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc2.flink.util.StatsFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * Statistical aggregation of {@link ActivePowerRecord}s using {@link Stats}. diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/HistoryService.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/HistoryService.java index f382978b714fdfdff6c190339c2ed23a2e037069..7737959bde97ce8332c87fc88b0aa9fd90bf8250 100644 --- a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/HistoryService.java +++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/HistoryService.java @@ -57,8 +57,8 @@ public class HistoryService { */ private void createHazelcastJetApplication() throws Exception { // NOPMD new Uc2HazelcastJetFactory() - .setReadPropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT,JOB_NAME) - .setWritePropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT,SCHEMA_REGISTRY_URL_DEFAULT) + .setReadPropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT, JOB_NAME) + .setWritePropertiesFromEnv(KAFKA_BOOTSTRAP_DEFAULT, SCHEMA_REGISTRY_URL_DEFAULT) .setKafkaInputTopicFromEnv(KAFKA_INPUT_TOPIC_DEFAULT) .setKafkaOutputTopicFromEnv(KAFKA_OUTPUT_TOPIC_DEFAULT) .setDownsampleIntervalFromEnv(DOWNSAMPLE_INTERVAL_DEFAULT_MS) diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2HazelcastJetFactory.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2HazelcastJetFactory.java index 143b154f3726e75d2842766b49bd2e26f57ce39b..92029a78405deacae5e7ad352b184eb852cd842e 100644 --- a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2HazelcastJetFactory.java +++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2HazelcastJetFactory.java @@ -180,9 +180,9 @@ public class Uc2HazelcastJetFactory { * @return The Uc2HazelcastJetBuilder factory with set kafkaReadPropertiesForPipeline. */ public Uc2HazelcastJetFactory setReadPropertiesFromEnv(// NOPMD - final String bootstrapServersDefault, - final String schemaRegistryUrlDefault, - final String jobName) { + final String bootstrapServersDefault, + final String schemaRegistryUrlDefault, + final String jobName) { // Use KafkaPropertiesBuilder to build a properties object used for kafka final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder(); final Properties kafkaReadProps = diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineBuilder.java b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineBuilder.java index 73377de6122d4a723c5dbbcb8198fa814c4bed1e..92e59d256c5f2d5b43644b2e498ca1f2dbca4202 100644 --- a/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineBuilder.java +++ b/theodolite-benchmarks/uc2-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineBuilder.java @@ -14,8 +14,10 @@ import com.hazelcast.jet.pipeline.WindowDefinition; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc2.hazelcastjet.uc2specifics.StatsAccumulatorSupplier; -import titan.ccp.model.records.ActivePowerRecord; + + /** * Builder to build a HazelcastJet Pipeline for UC2 which can be used for stream processing using @@ -108,8 +110,7 @@ public class Uc2PipelineBuilder { * @return An AggregateOperation used by Hazelcast Jet in a streaming stage which aggregates * ActivePowerRecord Objects into Stats Objects. */ - public AggregateOperation1<Entry<String, ActivePowerRecord>, - StatsAccumulator, Stats> uc2AggregateOperation() { + public AggregateOperation1<Entry<String, ActivePowerRecord>, StatsAccumulator, Stats> uc2AggregateOperation() { // NOCS // Aggregate Operation to Create a Stats Object from Entry<String,ActivePowerRecord> items using // the Statsaccumulator. return AggregateOperation @@ -129,7 +130,7 @@ public class Uc2PipelineBuilder { .andExportFinish( (accumulator) -> { return accumulator.snapshot(); - }); + }); } } diff --git a/theodolite-benchmarks/uc2-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineTest.java b/theodolite-benchmarks/uc2-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineTest.java index ff72b9558f43334feb8846d50bef2c6714d9404a..0a579c8d4ad2c872f7c90b1d6456de78b3a20f91 100644 --- a/theodolite-benchmarks/uc2-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineTest.java +++ b/theodolite-benchmarks/uc2-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc2/hazelcastjet/Uc2PipelineTest.java @@ -19,7 +19,7 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Test methods for the Hazelcast Jet Implementation of UC2. @@ -39,10 +39,10 @@ public class Uc2PipelineTest extends JetTestSupport { public void buildUc2Pipeline() { // Setup Configuration - int testItemsPerSecond = 1; - String testSensorName = "TEST-SENSOR"; - Double testValueInW = 10.0; - int testWindowInMs = 5000; + final int testItemsPerSecond = 1; + final String testSensorName = "TEST-SENSOR"; + final Double testValueInW = 10.0; + final int testWindowInMs = 5000; // Create mock jet instance with configuration final String testClusterName = randomName(); @@ -61,7 +61,7 @@ public class Uc2PipelineTest extends JetTestSupport { }); // Create pipeline to test - Uc2PipelineBuilder pipelineBuilder = new Uc2PipelineBuilder(); + final Uc2PipelineBuilder pipelineBuilder = new Uc2PipelineBuilder(); this.testPipeline = Pipeline.create(); this.uc2Topology = pipelineBuilder.extendUc2Topology(this.testPipeline, testSource, testWindowInMs); @@ -75,14 +75,15 @@ public class Uc2PipelineTest extends JetTestSupport { public void testOutput() { // Assertion Configuration - int timeout = 14; - String expectedOutput = "Stats{count=5, mean=10.0, populationStandardDeviation=0.0, min=10.0, max=10.0}"; + final int timeout = 14; + final String expectedOutput = + "Stats{count=5, mean=10.0, populationStandardDeviation=0.0, min=10.0, max=10.0}"; // Assertion this.uc2Topology.apply(Assertions.assertCollectedEventually(timeout, collection -> Assert.assertTrue( "Not the right amount items in Stats Object!", - collection.get(collection.size()-1).getValue().equals(expectedOutput)))); + collection.get(collection.size() - 1).getValue().equals(expectedOutput)))); // Run the test! try { diff --git a/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/HistoryService.java b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/HistoryService.java index 3b87053507a7739381482719acf317903fe2d361..4afc2d91eaaf98226f262f072cfd7e5aed6f847e 100644 --- a/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/HistoryService.java +++ b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/HistoryService.java @@ -5,8 +5,8 @@ import java.util.Objects; import java.util.concurrent.CompletableFuture; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.KafkaStreams; +import rocks.theodolite.benchmarks.commons.commons.configuration.ServiceConfigurations; import rocks.theodolite.benchmarks.commons.kstreams.ConfigurationKeys; -import titan.ccp.common.configuration.ServiceConfigurations; /** * A microservice that manages the history and, therefore, stores and aggregates incoming diff --git a/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/TopologyBuilder.java b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/TopologyBuilder.java index ae17c83bc141ef6056d7f9f89738d1442ba4afed..cd1d8cd92149d368a27452fa7689f5549a9c2bc7 100644 --- a/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/TopologyBuilder.java +++ b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/TopologyBuilder.java @@ -13,10 +13,10 @@ import org.apache.kafka.streams.kstream.Produced; import org.apache.kafka.streams.kstream.TimeWindows; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; +import rocks.theodolite.benchmarks.commons.kstreams.GenericSerde; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc2.kstreams.util.StatsFactory; -import titan.ccp.common.kafka.GenericSerde; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * Builds Kafka Stream Topology for the History microservice. diff --git a/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/Uc2KafkaStreamsBuilder.java b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/Uc2KafkaStreamsBuilder.java index 9db55ef921e44ac6ebb8b31ca58c13862c33ddcb..d9d4a23ec512ce4f7799648a4ea4f629e7b369ad 100644 --- a/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/Uc2KafkaStreamsBuilder.java +++ b/theodolite-benchmarks/uc2-kstreams/src/main/java/rocks/theodolite/benchmarks/uc2/kstreams/Uc2KafkaStreamsBuilder.java @@ -5,8 +5,8 @@ import java.util.Objects; import java.util.Properties; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.Topology; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; /** * Builder for the Kafka Streams configuration. diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeySerde.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeySerde.java index 1c09d7d508888b48c2a509d83f55ff49ca967f17..8bc32ccc2146f6467f6fcf374f95e8b87c2c351c 100644 --- a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeySerde.java +++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/HourOfDayKeySerde.java @@ -1,10 +1,10 @@ package rocks.theodolite.benchmarks.uc3.beam; import org.apache.kafka.common.serialization.Serde; -import titan.ccp.common.kafka.simpleserdes.BufferSerde; -import titan.ccp.common.kafka.simpleserdes.ReadBuffer; -import titan.ccp.common.kafka.simpleserdes.SimpleSerdes; -import titan.ccp.common.kafka.simpleserdes.WriteBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.BufferSerde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.ReadBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.SimpleSerdes; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.WriteBuffer; /** * {@link BufferSerde} for a {@link HourOfDayKey}. Use the {@link #create()} method to create a new diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/MapTimeFormat.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/MapTimeFormat.java index 3c0d7acdbeccfaf03aac70df478e3db6dd1378e4..0cad038141bd7b30d765520403529e9184bbcb86 100644 --- a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/MapTimeFormat.java +++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/MapTimeFormat.java @@ -5,7 +5,7 @@ import java.time.LocalDateTime; import java.time.ZoneId; import org.apache.beam.sdk.transforms.SimpleFunction; import org.apache.beam.sdk.values.KV; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Changes the time format to us Europe/Paris time. diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/PipelineFactory.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/PipelineFactory.java index 9c766e41254555647dd7ef1eed0417613b7c1629..f6587be4c4660a2e34f34efdaa417a7080073d0e 100644 --- a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/PipelineFactory.java +++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/PipelineFactory.java @@ -23,7 +23,7 @@ import rocks.theodolite.benchmarks.commons.beam.AbstractPipelineFactory; import rocks.theodolite.benchmarks.commons.beam.ConfigurationKeys; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaWriterTransformation; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * {@link AbstractPipelineFactory} for UC3. diff --git a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsAggregation.java b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsAggregation.java index e479c0ab5e192f7e5239c100a05df454bd2973ad..4fca536baf6db33e57700263cefb837ca8eb5b8b 100644 --- a/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsAggregation.java +++ b/theodolite-benchmarks/uc3-beam/src/main/java/rocks/theodolite/benchmarks/uc3/beam/StatsAggregation.java @@ -6,7 +6,7 @@ import java.io.Serializable; import org.apache.beam.sdk.coders.AvroCoder; import org.apache.beam.sdk.coders.DefaultCoder; import org.apache.beam.sdk.transforms.Combine.CombineFn; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HistoryServiceFlinkJob.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HistoryServiceFlinkJob.java index ad38303b4f8957bcb6de23608451be2da4ae41ac..d80f64fafb69d3e0287347a8f90080584d4fcd82 100644 --- a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HistoryServiceFlinkJob.java +++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/HistoryServiceFlinkJob.java @@ -17,11 +17,11 @@ import org.slf4j.LoggerFactory; import rocks.theodolite.benchmarks.commons.flink.AbstractFlinkService; import rocks.theodolite.benchmarks.commons.flink.KafkaConnectorFactory; import rocks.theodolite.benchmarks.commons.flink.serialization.StatsSerializer; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc3.flink.util.HourOfDayKey; import rocks.theodolite.benchmarks.uc3.flink.util.HourOfDayKeyFactory; import rocks.theodolite.benchmarks.uc3.flink.util.HourOfDayKeySerde; import rocks.theodolite.benchmarks.uc3.flink.util.StatsKeyFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * The History microservice implemented as a Flink job. diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/StatsAggregateFunction.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/StatsAggregateFunction.java index 38d277dac28e88c82a38a1b56ef15cab2c00db14..83951a4228fe0b73a4330bfae5177f508b9c1b0e 100644 --- a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/StatsAggregateFunction.java +++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/StatsAggregateFunction.java @@ -3,8 +3,8 @@ package rocks.theodolite.benchmarks.uc3.flink; import com.google.common.math.Stats; import com.google.common.math.StatsAccumulator; import org.apache.flink.api.common.functions.AggregateFunction; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc3.flink.util.StatsFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * Statistical aggregation of {@link ActivePowerRecord}s using {@link Stats}. diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeySerde.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeySerde.java index 2c5bd40fe29f683693fb57bc679dd288e7d3bfb9..5b08fcad2ff744e3d0e14e51d35fad88d2900470 100644 --- a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeySerde.java +++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayKeySerde.java @@ -6,10 +6,10 @@ import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import java.io.Serializable; import org.apache.kafka.common.serialization.Serde; -import titan.ccp.common.kafka.simpleserdes.BufferSerde; -import titan.ccp.common.kafka.simpleserdes.ReadBuffer; -import titan.ccp.common.kafka.simpleserdes.SimpleSerdes; -import titan.ccp.common.kafka.simpleserdes.WriteBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.BufferSerde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.ReadBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.SimpleSerdes; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.WriteBuffer; /** * {@link BufferSerde} for a {@link HourOfDayKey}. Use the {@link #create()} method to create a new diff --git a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayRecordFactory.java b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayRecordFactory.java index 5c52a446eac7f7ba39dfe12c247744054fd735d5..420179a0825d5b897f6927040eb57c43d27837ef 100644 --- a/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayRecordFactory.java +++ b/theodolite-benchmarks/uc3-flink/src/main/java/rocks/theodolite/benchmarks/uc3/flink/util/HourOfDayRecordFactory.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc3.flink.util; import com.google.common.math.Stats; import org.apache.kafka.streams.kstream.Windowed; -import titan.ccp.model.records.HourOfDayActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord; /** * {@link StatsRecordFactory} to create an {@link HourOfDayActivePowerRecord}. diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3HazelcastJetFactory.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3HazelcastJetFactory.java index be6d70d27b9a868914ec5d28e84b4a90454ab56c..d87aa19d316b278160dbc92b19b9be3d40a41d61 100644 --- a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3HazelcastJetFactory.java +++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3HazelcastJetFactory.java @@ -192,9 +192,9 @@ public class Uc3HazelcastJetFactory { // NOPMD * @return The Uc3HazelcastJetBuilder factory with set kafkaReadPropertiesForPipeline. */ public Uc3HazelcastJetFactory setReadPropertiesFromEnv(// NOPMD - final String bootstrapServersDefault, - final String schemaRegistryUrlDefault, - final String jobName) { + final String bootstrapServersDefault, + final String schemaRegistryUrlDefault, + final String jobName) { // Use KafkaPropertiesBuilder to build a properties object used for kafka final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder(); final Properties kafkaReadProps = diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineBuilder.java b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineBuilder.java index c8427de60742c2923d4ec17703592f5b8310de0c..e651d44fd2d099ae41296cc08487c787501d9b46 100644 --- a/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineBuilder.java +++ b/theodolite-benchmarks/uc3-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineBuilder.java @@ -15,10 +15,10 @@ import java.util.Map.Entry; import java.util.Properties; import java.util.TimeZone; import java.util.concurrent.TimeUnit; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKey; import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HoursOfDayKeyFactory; import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.StatsKeyFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * Builder to build a HazelcastJet Pipeline for UC3 which can be used for stream processing using diff --git a/theodolite-benchmarks/uc3-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineTest.java b/theodolite-benchmarks/uc3-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineTest.java index 3df4f4642f1bc6c8637f90bcae3f352f5c298e51..969ff27d1154a0bd52cb3a048eca2f12ca901138 100644 --- a/theodolite-benchmarks/uc3-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineTest.java +++ b/theodolite-benchmarks/uc3-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc3/hazelcastjet/Uc3PipelineTest.java @@ -14,20 +14,18 @@ import com.hazelcast.jet.pipeline.test.TestSources; import com.hazelcast.jet.test.SerialTest; import java.time.Instant; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.Map; -import java.util.TimeZone; import java.util.Map.Entry; +import java.util.TimeZone; import java.util.concurrent.CompletionException; import org.junit.After; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; -import rocks.theodolite.benchmarks.uc3.hazelcastjet.Uc3PipelineBuilder; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKey; import rocks.theodolite.benchmarks.uc3.hazelcastjet.uc3specifics.HourOfDayKeySerializer; -import titan.ccp.model.records.ActivePowerRecord; /** * Test methods for the Hazelcast Jet Implementation of UC3. @@ -49,13 +47,13 @@ public class Uc3PipelineTest extends JetTestSupport { public void buildUc3Pipeline() { // Setup Configuration - int testItemsPerSecond = 1; - String testSensorName = "TEST-SENSOR"; - Double testValueInW = 10.0; - int testHopSizeInSec = 1; - int testWindowSizeInSec = 50; + final int testItemsPerSecond = 1; + final String testSensorName = "TEST-SENSOR"; + final Double testValueInW = 10.0; + final int testHopSizeInSec = 1; + final int testWindowSizeInSec = 50; // Used to check hourOfDay - long mockTimestamp = 1632741651; + final long mockTimestamp = 1632741651; // Create mock jet instance with configuration @@ -75,9 +73,9 @@ public class Uc3PipelineTest extends JetTestSupport { }); // Create pipeline to test - Uc3PipelineBuilder pipelineBuilder = new Uc3PipelineBuilder(); + final Uc3PipelineBuilder pipelineBuilder = new Uc3PipelineBuilder(); this.testPipeline = Pipeline.create(); - this.uc3Topology = pipelineBuilder.extendUc3Topology(testPipeline, testSource, + this.uc3Topology = pipelineBuilder.extendUc3Topology(this.testPipeline, testSource, testHopSizeInSec, testWindowSizeInSec); } @@ -88,11 +86,11 @@ public class Uc3PipelineTest extends JetTestSupport { public void testOutput() { // Assertion Configuration - int timeout = 10; - String testSensorName = "TEST-SENSOR"; - Double testValueInW = 10.0; + final int timeout = 10; + final String testSensorName = "TEST-SENSOR"; + final Double testValueInW = 10.0; // Used to check hourOfDay - long mockTimestamp = 1632741651; + final long mockTimestamp = 1632741651; // Assertion this.uc3Topology.apply(Assertions.assertCollectedEventually(timeout, @@ -105,17 +103,15 @@ public class Uc3PipelineTest extends JetTestSupport { boolean allOkay = true; if (collection != null) { System.out.println("DEBUG: CHECK 2 || Collection Size: " + collection.size()); - for (int i = 0; i < collection.size(); i++) { + for (final Entry<String, String> currentEntry : collection) { // Build hour of day - long timestamp = mockTimestamp; - int expectedHour = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), + final long timestamp = mockTimestamp; + final int expectedHour = LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), TimeZone.getDefault().toZoneId()).getHour(); - // Compare expected output with generated output - Entry<String, String> currentEntry = collection.get(i); - String expectedKey = testSensorName + ";" + expectedHour; - String expectedValue = testValueInW.toString(); + final String expectedKey = testSensorName + ";" + expectedHour; + final String expectedValue = testValueInW.toString(); // DEBUG System.out.println( diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HistoryService.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HistoryService.java index a327d2ecfa4c0727e7a29a69e7ab8910afdfd3d2..8776fcda3092d8282f6ab85f69c734bf834a2bcc 100644 --- a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HistoryService.java +++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HistoryService.java @@ -4,8 +4,8 @@ import java.time.Duration; import java.util.concurrent.CompletableFuture; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.KafkaStreams; +import rocks.theodolite.benchmarks.commons.commons.configuration.ServiceConfigurations; import rocks.theodolite.benchmarks.commons.kstreams.ConfigurationKeys; -import titan.ccp.common.configuration.ServiceConfigurations; /** * A microservice that manages the history and, therefore, stores and aggregates incoming diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeySerde.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeySerde.java index 4014e5e30dee36a737ab582e527fc8fb4b8a32a9..e2a3b03e1e51df2756299b66d24e89d9cf0403b9 100644 --- a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeySerde.java +++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayKeySerde.java @@ -1,10 +1,10 @@ package rocks.theodolite.benchmarks.uc3.kstreams; import org.apache.kafka.common.serialization.Serde; -import titan.ccp.common.kafka.simpleserdes.BufferSerde; -import titan.ccp.common.kafka.simpleserdes.ReadBuffer; -import titan.ccp.common.kafka.simpleserdes.SimpleSerdes; -import titan.ccp.common.kafka.simpleserdes.WriteBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.BufferSerde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.ReadBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.SimpleSerdes; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.WriteBuffer; /** * {@link BufferSerde} for a {@link HourOfDayKey}. Use the {@link #create()} method to create a new diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayRecordFactory.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayRecordFactory.java index 3d67a6ebe86eb33378fe0711b6b8ca1ab1f5c6a9..4d2e2d5b5014dda3604085972fdcf56e8f8aa011 100644 --- a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayRecordFactory.java +++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/HourOfDayRecordFactory.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc3.kstreams; import com.google.common.math.Stats; import org.apache.kafka.streams.kstream.Windowed; -import titan.ccp.model.records.HourOfDayActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.HourOfDayActivePowerRecord; /** * {@link StatsRecordFactory} to create an {@link HourOfDayActivePowerRecord}. diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/TopologyBuilder.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/TopologyBuilder.java index b956959c5680c3c23eb35c0548004bb55de09a20..f2825ca81f69b5a70e883dcf034c51093745221d 100644 --- a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/TopologyBuilder.java +++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/TopologyBuilder.java @@ -16,10 +16,10 @@ import org.apache.kafka.streams.kstream.Grouped; import org.apache.kafka.streams.kstream.Materialized; import org.apache.kafka.streams.kstream.Produced; import org.apache.kafka.streams.kstream.TimeWindows; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; +import rocks.theodolite.benchmarks.commons.kstreams.GenericSerde; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc3.kstreams.util.StatsFactory; -import titan.ccp.common.kafka.GenericSerde; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; -import titan.ccp.model.records.ActivePowerRecord; /** * Builds Kafka Stream Topology for the History microservice. diff --git a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/Uc3KafkaStreamsBuilder.java b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/Uc3KafkaStreamsBuilder.java index 3c80e5eedef0c9dda8ac3c729f158d0872b5769b..e05b30f75a3a1e01f132e56595e50297160c5c66 100644 --- a/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/Uc3KafkaStreamsBuilder.java +++ b/theodolite-benchmarks/uc3-kstreams/src/main/java/rocks/theodolite/benchmarks/uc3/kstreams/Uc3KafkaStreamsBuilder.java @@ -5,8 +5,8 @@ import java.util.Objects; import java.util.Properties; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.Topology; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; /** * Builder for the Kafka Streams configuration. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedActivePowerRecordEventTimePolicy.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedActivePowerRecordEventTimePolicy.java index 3af4957aa210a5f6a184bf4b513202dd4087567f..1a2f99cd82a9f8b4af7b3b5a13ad8610036cbc72 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedActivePowerRecordEventTimePolicy.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedActivePowerRecordEventTimePolicy.java @@ -5,7 +5,7 @@ import org.apache.beam.sdk.io.kafka.KafkaRecord; import org.apache.beam.sdk.io.kafka.TimestampPolicy; import org.apache.beam.sdk.transforms.windowing.BoundedWindow; import org.joda.time.Instant; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; /** * TimeStampPolicy to use event time based on the timestamp of the record value. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedToActive.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedToActive.java index 63f914dca0e6536d52ce225e791d2e3b89107394..4d1c2241eefa8706c29d08256304ecec8313e478 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedToActive.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/AggregatedToActive.java @@ -2,8 +2,8 @@ package rocks.theodolite.benchmarks.uc4.beam; import org.apache.beam.sdk.transforms.SimpleFunction; import org.apache.beam.sdk.values.KV; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; /** * Converts AggregatedActivePowerRecord to ActivePowerRecord. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/DuplicateAsFlatMap.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/DuplicateAsFlatMap.java index 1b430c99bb127f0746772571443f625ae69be54d..1c4071f4a3bbe78683c9e4854f62d428fc8a07ad 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/DuplicateAsFlatMap.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/DuplicateAsFlatMap.java @@ -10,7 +10,7 @@ import org.apache.beam.sdk.state.ValueState; import org.apache.beam.sdk.transforms.DoFn; import org.apache.beam.sdk.values.KV; import org.apache.beam.sdk.values.PCollectionView; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterEvents.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterEvents.java index 6a96d7270640c1cfa3a162e0d506792d577103c5..59818e18b7e86c53b80b2a6230087957870d2f47 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterEvents.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterEvents.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc4.beam; import org.apache.beam.sdk.transforms.SerializableFunction; import org.apache.beam.sdk.values.KV; -import titan.ccp.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; /** * Filters for {@code Event.SENSOR_REGISTRY_CHANGED} and {@code Event.SENSOR_REGISTRY_STATUS} diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterNullValues.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterNullValues.java index 9aa48d7b8f6fdc64aad205821ec4db25f606156b..903204363ace1f19439c3686dfd278fc89da2be9 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterNullValues.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/FilterNullValues.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc4.beam; import org.apache.beam.sdk.transforms.SerializableFunction; import org.apache.beam.sdk.values.KV; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Filters {@code null} Values. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/GenerateParentsFn.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/GenerateParentsFn.java index e6f01c3d59c5c92f5d0c51ac807a76f0a37612b1..a020d32735893c4dd0851d902dcf62304223199d 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/GenerateParentsFn.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/GenerateParentsFn.java @@ -8,10 +8,10 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.apache.beam.sdk.transforms.DoFn; import org.apache.beam.sdk.values.KV; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.sensorregistry.AggregatedSensor; -import titan.ccp.model.sensorregistry.Sensor; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.Sensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; /** * DoFn class to generate a child-parent pair for every sensor in the hierarchy. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/PipelineFactory.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/PipelineFactory.java index 42d12d82026df0682f771b0cec5c1705ead83b2e..955f7101515c9467edc2e4900aa5464437f0e904 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/PipelineFactory.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/PipelineFactory.java @@ -40,15 +40,15 @@ import rocks.theodolite.benchmarks.commons.beam.ConfigurationKeys; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaActivePowerTimestampReader; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaGenericReader; import rocks.theodolite.benchmarks.commons.beam.kafka.KafkaWriterTransformation; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; import rocks.theodolite.benchmarks.uc4.beam.serialization.AggregatedActivePowerRecordCoder; import rocks.theodolite.benchmarks.uc4.beam.serialization.AggregatedActivePowerRecordDeserializer; import rocks.theodolite.benchmarks.uc4.beam.serialization.AggregatedActivePowerRecordSerializer; import rocks.theodolite.benchmarks.uc4.beam.serialization.EventCoder; import rocks.theodolite.benchmarks.uc4.beam.serialization.EventDeserializer; import rocks.theodolite.benchmarks.uc4.beam.serialization.SensorParentKeyCoder; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; /** * {@link AbstractPipelineFactory} for UC4. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/RecordAggregation.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/RecordAggregation.java index 6fbf6ff3f3abcdfd4f5ca0de93d68c2532655b4d..e853e0b6e5a22d68f9b315799f86f1b6dfa1947a 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/RecordAggregation.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/RecordAggregation.java @@ -4,8 +4,8 @@ import java.io.Serializable; import org.apache.beam.sdk.coders.AvroCoder; import org.apache.beam.sdk.coders.DefaultCoder; import org.apache.beam.sdk.transforms.Combine.CombineFn; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetIdForAggregated.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetIdForAggregated.java index 23ebb6d0104ef3992b4e2a4763dd23e722fe30f9..a616a966733e2dd3ead7d2c126efaa7c37577ff6 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetIdForAggregated.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetIdForAggregated.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc4.beam; import org.apache.beam.sdk.transforms.SimpleFunction; import org.apache.beam.sdk.values.KV; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; /** * Sets the identifier for new {@link AggregatedActivePowerRecord}. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetKeyToGroup.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetKeyToGroup.java index 3ffba12823aca2da88250eb601615de1ac5177e2..8477e987cad81625d373ee7d1155eaf701a53087 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetKeyToGroup.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/SetKeyToGroup.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc4.beam; import org.apache.beam.sdk.transforms.SimpleFunction; import org.apache.beam.sdk.values.KV; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Set the Key for a group of {@code ActivePowerRecords} to their Parent. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordCoder.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordCoder.java index f460d42de2042064952434f6bf044920f217138a..759b8baab70b73ad2a32c50768b7911059c68aab 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordCoder.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordCoder.java @@ -8,7 +8,7 @@ import java.util.List; import org.apache.beam.sdk.coders.AvroCoder; import org.apache.beam.sdk.coders.Coder; import org.apache.beam.sdk.coders.CoderException; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; /** * {@link Coder} for an {@link AggregatedActivePowerRecord}. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordDeserializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordDeserializer.java index 2c481f8e6f68a3a0decbcb73c3751f464646b7cf..1083103f7394e88c5d59ccd97aaa0885ff6b634b 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordDeserializer.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordDeserializer.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc4.beam.serialization; import io.confluent.kafka.streams.serdes.avro.SpecificAvroDeserializer; import org.apache.kafka.common.serialization.Deserializer; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; /** * {@link Deserializer} for an {@link AggregatedActivePowerRecord}. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordSerializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordSerializer.java index 073c3d0f94c24872460ae58c6236a0c4e19e0d5d..2c742ca65d288e2ee04bfb860fb89cf7ecbb8bbf 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordSerializer.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/AggregatedActivePowerRecordSerializer.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc4.beam.serialization; import io.confluent.kafka.streams.serdes.avro.SpecificAvroSerializer; import org.apache.kafka.common.serialization.Serializer; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; /** * {@link Serializer} for an {@link AggregatedActivePowerRecord}. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventCoder.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventCoder.java index b96398398e61f3db0f0632f8384d11f30ccc7aca..2d555ef12db49b76fa3d8c4a9398ce562eaa6453 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventCoder.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventCoder.java @@ -10,8 +10,8 @@ import java.util.List; import org.apache.beam.sdk.coders.Coder; import org.apache.beam.sdk.coders.CoderException; import org.apache.kafka.common.serialization.Serde; -import titan.ccp.configuration.events.Event; -import titan.ccp.configuration.events.EventSerde; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.configuration.events.EventSerde; /** * Wrapper Class that encapsulates a Event Serde in a org.apache.beam.sdk.coders.Coder. diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventDeserializer.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventDeserializer.java index ae9c480e1c76949f8cfa5d27c73282e270232d0a..9399a42606d6e8e7f3f58bf4a515e5f83041a88d 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventDeserializer.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/EventDeserializer.java @@ -3,7 +3,7 @@ package rocks.theodolite.benchmarks.uc4.beam.serialization; import java.util.Map; import org.apache.kafka.common.serialization.ByteBufferDeserializer; import org.apache.kafka.common.serialization.Deserializer; -import titan.ccp.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; /** * Deserializer for Events(SensorRegistry changes). diff --git a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeySerde.java b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeySerde.java index 64242b3fd2618b154e47cc46ce2fe6f9375be209..9c8d1eff664c72fcb31e6dcfddff5f53b97ff055 100644 --- a/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeySerde.java +++ b/theodolite-benchmarks/uc4-beam/src/main/java/rocks/theodolite/benchmarks/uc4/beam/serialization/SensorParentKeySerde.java @@ -1,11 +1,11 @@ package rocks.theodolite.benchmarks.uc4.beam.serialization; import org.apache.kafka.common.serialization.Serde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.BufferSerde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.ReadBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.SimpleSerdes; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.WriteBuffer; import rocks.theodolite.benchmarks.uc4.beam.SensorParentKey; -import titan.ccp.common.kafka.simpleserdes.BufferSerde; -import titan.ccp.common.kafka.simpleserdes.ReadBuffer; -import titan.ccp.common.kafka.simpleserdes.SimpleSerdes; -import titan.ccp.common.kafka.simpleserdes.WriteBuffer; /** * {@link Serde} factory for {@link SensorParentKey}. diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/AggregationServiceFlinkJob.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/AggregationServiceFlinkJob.java index 35ef7dd1426f287c7529ca12f00c7c1d23606ab1..5f4515cb851439841d1de3193f21275545033481 100644 --- a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/AggregationServiceFlinkJob.java +++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/AggregationServiceFlinkJob.java @@ -16,20 +16,20 @@ import org.apache.flink.streaming.connectors.kafka.FlinkKafkaProducer; import org.apache.kafka.common.serialization.Serdes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.configuration.events.EventSerde; import rocks.theodolite.benchmarks.commons.flink.AbstractFlinkService; import rocks.theodolite.benchmarks.commons.flink.KafkaConnectorFactory; import rocks.theodolite.benchmarks.commons.flink.TupleType; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.ImmutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; import rocks.theodolite.benchmarks.uc4.flink.util.ImmutableSensorRegistrySerializer; import rocks.theodolite.benchmarks.uc4.flink.util.ImmutableSetSerializer; import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKey; import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKeySerializer; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; -import titan.ccp.configuration.events.Event; -import titan.ccp.configuration.events.EventSerde; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; -import titan.ccp.model.sensorregistry.ImmutableSensorRegistry; -import titan.ccp.model.sensorregistry.SensorRegistry; /** * The Aggregation microservice implemented as a Flink job. diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ChildParentsFlatMapFunction.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ChildParentsFlatMapFunction.java index c439df1e49381f8779a64814ae056635bd408c64..77391393d2977218ff15972f0329393388d24453 100644 --- a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ChildParentsFlatMapFunction.java +++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/ChildParentsFlatMapFunction.java @@ -13,9 +13,9 @@ import org.apache.flink.api.common.typeinfo.TypeInformation; import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.configuration.Configuration; import org.apache.flink.util.Collector; -import titan.ccp.model.sensorregistry.AggregatedSensor; -import titan.ccp.model.sensorregistry.Sensor; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.Sensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; /** * Transforms a {@link SensorRegistry} into key value pairs of Sensor identifiers and their parents' diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/JoinAndDuplicateCoFlatMapFunction.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/JoinAndDuplicateCoFlatMapFunction.java index 624327a69feb8bce2f1b85af3e57cf5db9511e74..0171e4b0b0c876242834edc76e8117615dc6b3b2 100644 --- a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/JoinAndDuplicateCoFlatMapFunction.java +++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/JoinAndDuplicateCoFlatMapFunction.java @@ -9,8 +9,8 @@ import org.apache.flink.api.java.tuple.Tuple2; import org.apache.flink.configuration.Configuration; import org.apache.flink.streaming.api.functions.co.RichCoFlatMapFunction; import org.apache.flink.util.Collector; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKey; -import titan.ccp.model.records.ActivePowerRecord; /** * A {@link RichCoFlatMapFunction} which joins each incoming {@link ActivePowerRecord} with its diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/RecordAggregationProcessWindowFunction.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/RecordAggregationProcessWindowFunction.java index 29e1ea32235ae0789e72f4931932b2697c60759b..6dff6edaf5fb6343f0c6c4b12cbff4a9175751eb 100644 --- a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/RecordAggregationProcessWindowFunction.java +++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/RecordAggregationProcessWindowFunction.java @@ -11,9 +11,9 @@ import org.apache.flink.configuration.Configuration; import org.apache.flink.streaming.api.functions.windowing.ProcessWindowFunction; import org.apache.flink.streaming.api.windowing.windows.TimeWindow; import org.apache.flink.util.Collector; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; import rocks.theodolite.benchmarks.uc4.flink.util.SensorParentKey; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; /** * A {@link ProcessWindowFunction} which performs the windowed aggregation of all diff --git a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSensorRegistrySerializer.java b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSensorRegistrySerializer.java index 54d8826900cc70a5eb86d71df7fcf9c4a4da4a7f..c491adc47d31211e809a00ad283266511e96c534 100644 --- a/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSensorRegistrySerializer.java +++ b/theodolite-benchmarks/uc4-flink/src/main/java/rocks/theodolite/benchmarks/uc4/flink/util/ImmutableSensorRegistrySerializer.java @@ -5,7 +5,7 @@ import com.esotericsoftware.kryo.Serializer; import com.esotericsoftware.kryo.io.Input; import com.esotericsoftware.kryo.io.Output; import java.io.Serializable; -import titan.ccp.model.sensorregistry.ImmutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.ImmutableSensorRegistry; /** * A {@link Serializer} for {@link ImmutableSensorRegistry}s. diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4HazelcastJetFactory.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4HazelcastJetFactory.java index 9b6aa71267150296d8b65268b1922925b7ada796..69ccee100f2946237390c8b19ff0f20036237d37 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4HazelcastJetFactory.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4HazelcastJetFactory.java @@ -13,13 +13,13 @@ import org.slf4j.Logger; import rocks.theodolite.benchmarks.commons.hazelcastjet.ConfigurationKeys; import rocks.theodolite.benchmarks.commons.hazelcastjet.JetInstanceBuilder; import rocks.theodolite.benchmarks.commons.hazelcastjet.KafkaPropertiesBuilder; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.ImmutableSensorRegistry; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.EventDeserializer; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ImmutableSensorRegistryUc4Serializer; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKey; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKeySerializer; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroup; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroupSerializer; -import titan.ccp.model.sensorregistry.ImmutableSensorRegistry; /** * A Hazelcast Jet factory which can build a Hazelcast Jet Instance and Pipeline for the UC4 @@ -57,18 +57,8 @@ public class Uc4HazelcastJetFactory { * @throws Exception If either no JetInstance or Pipeline is set, a job cannot be startet. */ public void runUc4Job(final String jobName) throws IllegalStateException { // NOPMD - - // Check if a Jet Instance for UC4 is set. - if (this.uc4JetInstance == null) { - throw new IllegalStateException("Jet Instance is not set! " - + "Cannot start a hazelcast jet job for UC4."); - } - - // Check if a Pipeline for UC3 is set. - if (this.uc4JetPipeline == null) { - throw new IllegalStateException( - "Hazelcast Pipeline is not set! Cannot start a hazelcast jet job for UC4."); - } + Objects.requireNonNull(this.uc4JetInstance, "Jet instance is not set."); + Objects.requireNonNull(this.uc4JetPipeline, "Jet pipeline is not set."); // Adds the job name and joins a job to the JetInstance defined in this factory final JobConfig jobConfig = new JobConfig() @@ -197,9 +187,9 @@ public class Uc4HazelcastJetFactory { * @return The Uc4HazelcastJetBuilder factory with set kafkaReadPropertiesForPipeline. */ public Uc4HazelcastJetFactory setReadPropertiesFromEnv(// NOPMD - final String bootstrapServersDefault, - final String schemaRegistryUrlDefault, - final String jobName) { + final String bootstrapServersDefault, + final String schemaRegistryUrlDefault, + final String jobName) { // Use KafkaPropertiesBuilder to build a properties object used for kafka final KafkaPropertiesBuilder propsBuilder = new KafkaPropertiesBuilder(); diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineBuilder.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineBuilder.java index 2efb8250c0e1136b34412e4553b2d216c5e24b43..87d10bc5c0fd417082c12c5a1a26bbf9116c8a50 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineBuilder.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineBuilder.java @@ -1,4 +1,4 @@ -package rocks.theodolite.benchmarks.uc4.hazelcastjet; +package rocks.theodolite.benchmarks.uc4.hazelcastjet; // NOPMD Excessive imports import com.hazelcast.function.BiFunctionEx; import com.hazelcast.jet.Traverser; @@ -17,7 +17,6 @@ import com.hazelcast.jet.pipeline.StreamStageWithKey; import com.hazelcast.jet.pipeline.WindowDefinition; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -25,20 +24,19 @@ import java.util.Properties; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.AggregatedActivePowerRecordAccumulator; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ChildParentsTransformer; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKey; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroup; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; -import titan.ccp.model.sensorregistry.SensorRegistry; /** * Builder to build a HazelcastJet Pipeline for UC4 which can be used for stream processing using * Hazelcast Jet. */ -@SuppressWarnings("PMD.ExcessiveImports") public class Uc4PipelineBuilder { private static final Logger LOGGER = LoggerFactory.getLogger(Uc4PipelineBuilder.class); @@ -117,9 +115,9 @@ public class Uc4PipelineBuilder { * * <p> * UC4 takes {@code ActivePowerRecord} events from sensors and a {@code SensorRegistry} with maps - * from keys to groups to map values to their according groups. A feedback stream allows for - * group keys to be mapped to values and eventually to be mapped to other top level groups defines - * by the {@code SensorRegistry}. + * from keys to groups to map values to their according groups. A feedback stream allows for group + * keys to be mapped to values and eventually to be mapped to other top level groups defines by + * the {@code SensorRegistry}. * </p> * * <p> @@ -180,10 +178,10 @@ public class Uc4PipelineBuilder { ////////////////////////////////// // (2) UC4 Merge Input with aggregation stream - final StreamStageWithKey<Entry<String, ActivePowerRecord>, String> - mergedInputAndAggregations = inputStream - .merge(aggregations) - .groupingKey(Entry::getKey); + final StreamStageWithKey<Entry<String, ActivePowerRecord>, String> mergedInputAndAggregations = + inputStream + .merge(aggregations) + .groupingKey(Entry::getKey); ////////////////////////////////// // (3) UC4 Join Configuration and Merges Input/Aggregation Stream @@ -192,20 +190,10 @@ public class Uc4PipelineBuilder { .<Set<String>, Entry<String, ValueGroup>>mapUsingIMap( SENSOR_PARENT_MAP_NAME, (sensorEvent, sensorParentsSet) -> { - // Check whether a groupset exists for a key or not - if (sensorParentsSet == null) { - // No group set exists for this key: return valuegroup with default null group set. - final Set<String> nullSet = new HashSet<>(); - nullSet.add("NULL-GROUPSET"); - return Util.entry(sensorEvent.getKey(), - new ValueGroup(sensorEvent.getValue(), nullSet)); - } else { - // Group set exists for this key: return valuegroup with the groupset. - final ValueGroup valueParentsPair = - new ValueGroup(sensorEvent.getValue(), sensorParentsSet); - // Return solution - return Util.entry(sensorEvent.getKey(), valueParentsPair); - } + final ValueGroup valueParentsPair = new ValueGroup( + sensorEvent.getValue(), + sensorParentsSet == null ? Set.of() : sensorParentsSet); + return Util.entry(sensorEvent.getKey(), valueParentsPair); }); ////////////////////////////////// @@ -235,28 +223,25 @@ public class Uc4PipelineBuilder { ////////////////////////////////// // (5) UC4 Last Value Map // Table with tumbling window differentiation [ (sensorKey,Group) , value ],Time - final StageWithWindow<Entry<SensorGroupKey, ActivePowerRecord>> - windowedLastValues = dupliAsFlatmappedStage - .window(WindowDefinition.tumbling(windowSize)); + final StageWithWindow<Entry<SensorGroupKey, ActivePowerRecord>> windowedLastValues = + dupliAsFlatmappedStage + .window(WindowDefinition.tumbling(windowSize)); - final AggregateOperation1<Entry<SensorGroupKey, ActivePowerRecord>, - AggregatedActivePowerRecordAccumulator, AggregatedActivePowerRecord> aggrOp = + final AggregateOperation1<Entry<SensorGroupKey, ActivePowerRecord>, AggregatedActivePowerRecordAccumulator, AggregatedActivePowerRecord> aggrOp = // NOCS AggregateOperation - .withCreate(AggregatedActivePowerRecordAccumulator::new) - .<Entry<SensorGroupKey, ActivePowerRecord>>andAccumulate((acc, rec) -> { - acc.setId(rec.getKey().getGroup()); - acc.addInputs(rec.getValue()); - }) - .andCombine((acc, acc2) -> - acc.addInputs(acc2.getId(), acc2.getSumInW(), acc2.getCount(), acc.getTimestamp())) - .andDeduct((acc, acc2) -> acc.removeInputs(acc2.getSumInW(), acc2.getCount())) - .andExportFinish(acc -> - new AggregatedActivePowerRecord(acc.getId(), + .withCreate(AggregatedActivePowerRecordAccumulator::new) + .<Entry<SensorGroupKey, ActivePowerRecord>>andAccumulate((acc, rec) -> { + acc.setId(rec.getKey().getGroup()); + acc.addInputs(rec.getValue()); + }) + .andCombine((acc, acc2) -> acc.addInputs(acc2.getId(), acc2.getSumInW(), + acc2.getCount(), acc.getTimestamp())) + .andDeduct((acc, acc2) -> acc.removeInputs(acc2.getSumInW(), acc2.getCount())) + .andExportFinish(acc -> new AggregatedActivePowerRecord(acc.getId(), acc.getTimestamp(), acc.getCount(), acc.getSumInW(), - acc.getAverageInW()) - ); + acc.getAverageInW())); // write aggregation back to kafka diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/AggregatedActivePowerRecordAccumulator.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/AggregatedActivePowerRecordAccumulator.java index 3166f16cd31bf0e6d4dff6548468791e7a5e5c5c..14934fbe3ceec6e01836958c1f7686e225ea40fd 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/AggregatedActivePowerRecordAccumulator.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/AggregatedActivePowerRecordAccumulator.java @@ -1,6 +1,6 @@ package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Accumulator class for AggregatedActivePowerRecords. @@ -25,10 +25,10 @@ public class AggregatedActivePowerRecordAccumulator { * Creates an AggregationObject. */ public AggregatedActivePowerRecordAccumulator(final String id, - final long timestamp, - final long count, - final double sumInW, - final double averageInW) { + final long timestamp, + final long count, + final double sumInW, + final double averageInW) { this.id = id; this.timestamp = timestamp; this.count = count; @@ -50,16 +50,16 @@ public class AggregatedActivePowerRecordAccumulator { this.count += 1; this.sumInW += record.getValueInW(); this.timestamp = record.getTimestamp(); - this.averageInW = sumInW / count; + this.averageInW = this.sumInW / this.count; } /** * Adds the records from another aggregator. */ public void addInputs(final String id, - final double sumInW, - final long count, - final long timestamp) { + final double sumInW, + final long count, + final long timestamp) { this.id = this.id == null ? id : this.id; this.sumInW += sumInW; this.count += count; @@ -68,8 +68,8 @@ public class AggregatedActivePowerRecordAccumulator { } /** - * Removes the values of another aggreagator. - * Not a complete reset since the old timestamp is lost. + * Removes the values of another aggreagator. Not a complete reset since the old timestamp is + * lost. */ public void removeInputs(final double sumInW, final long count) { this.sumInW -= sumInW; @@ -79,22 +79,22 @@ public class AggregatedActivePowerRecordAccumulator { } public long getCount() { - return count; + return this.count; } public double getSumInW() { - return sumInW; + return this.sumInW; } public double getAverageInW() { - return averageInW; + return this.averageInW; } public String getId() { - return id; + return this.id; } public long getTimestamp() { - return timestamp; + return this.timestamp; } } diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ChildParentsTransformer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ChildParentsTransformer.java index ad3b2294cb934ba04b07df2e2b2d3dbdd6e1a905..3ba604270e37d746c2e98bc4eef5c80d2526b446 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ChildParentsTransformer.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ChildParentsTransformer.java @@ -10,10 +10,11 @@ import org.apache.kafka.streams.kstream.Transformer; import org.apache.kafka.streams.processor.ProcessorContext; import org.apache.kafka.streams.state.KeyValueIterator; import org.apache.kafka.streams.state.KeyValueStore; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.sensorregistry.AggregatedSensor; -import titan.ccp.model.sensorregistry.Sensor; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.Sensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; + /** * Transforms a {@link SensorRegistry} into key value pairs of Sensor identifiers and their parents' diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/EventDeserializer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/EventDeserializer.java index c8d06b497009944b9a9a0fda4ab224e5fe992e3d..ebdc9de86e82a9c8c16a71830190d26e6f0e34fa 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/EventDeserializer.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/EventDeserializer.java @@ -2,8 +2,8 @@ package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics; import java.util.Map; import org.apache.kafka.common.serialization.Deserializer; -import titan.ccp.configuration.events.Event; -import titan.ccp.configuration.events.EventSerde; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.configuration.events.EventSerde; /** * Deserializer for Event Objects. diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ImmutableSensorRegistryUc4Serializer.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ImmutableSensorRegistryUc4Serializer.java index 53d22f7f156891cf11e5b8915eed17b74c3d57fb..84e007dde7fb3a075a605bacfbbda05f206c2ee4 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ImmutableSensorRegistryUc4Serializer.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ImmutableSensorRegistryUc4Serializer.java @@ -4,7 +4,7 @@ import com.hazelcast.nio.ObjectDataInput; import com.hazelcast.nio.ObjectDataOutput; import com.hazelcast.nio.serialization.StreamSerializer; import java.io.IOException; -import titan.ccp.model.sensorregistry.ImmutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.ImmutableSensorRegistry; /** * {@link StreamSerializer} for Hazelcast Jet to serialize and deserialize an diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroup.java b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroup.java index 893efcf74fe8a16202d795fca5cc43b63190dc50..b5f5fc7cb2822667dcaa26560fa83b2da3a513d9 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroup.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/main/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/uc4specifics/ValueGroup.java @@ -2,7 +2,8 @@ package rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics; import java.util.Objects; import java.util.Set; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; + /** * Structure: (valueInW, Set(Groups)). diff --git a/theodolite-benchmarks/uc4-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineTest.java b/theodolite-benchmarks/uc4-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineTest.java index b74c2874b92a51b138ffe8b44b1cf750dfce5880..e59f4cabc5acb09943f1f53dcb881dae001ffc26 100644 --- a/theodolite-benchmarks/uc4-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineTest.java +++ b/theodolite-benchmarks/uc4-hazelcastjet/src/test/java/rocks/theodolite/benchmarks/uc4/hazelcastjet/Uc4PipelineTest.java @@ -22,24 +22,23 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.experimental.categories.Category; -import rocks.theodolite.benchmarks.uc4.hazelcastjet.Uc4PipelineBuilder; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.ImmutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MachineSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableAggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableSensorRegistry; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ImmutableSensorRegistryUc4Serializer; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKey; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.SensorGroupKeySerializer; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroup; import rocks.theodolite.benchmarks.uc4.hazelcastjet.uc4specifics.ValueGroupSerializer; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; -import titan.ccp.model.sensorregistry.ImmutableSensorRegistry; -import titan.ccp.model.sensorregistry.MachineSensor; -import titan.ccp.model.sensorregistry.MutableAggregatedSensor; -import titan.ccp.model.sensorregistry.MutableSensorRegistry; + @Category(SerialTest.class) public class Uc4PipelineTest extends JetTestSupport { - // TEst Machinery JetInstance testInstance = null; Pipeline testPipeline = null; StreamStage<Entry<String, AggregatedActivePowerRecord>> uc4Topology = null; @@ -55,7 +54,7 @@ public class Uc4PipelineTest extends JetTestSupport { final Double testValueInW = 10.0; final int testWindowSize = 5000; // As window size is bugged, not necessary. - // Create mock jet instance with configuration + // Create mocked Hazelcast Jet instance with configuration final String testClusterName = randomName(); final JetConfig testJetConfig = new JetConfig(); testJetConfig.getHazelcastConfig().setClusterName(testClusterName); @@ -75,7 +74,7 @@ public class Uc4PipelineTest extends JetTestSupport { final StreamSource<Entry<String, AggregatedActivePowerRecord>> testAggregationSource = TestSources.itemStream(testItemsPerSecond, (timestamp, item) -> { - AggregatedActivePowerRecord test = + final AggregatedActivePowerRecord test = new AggregatedActivePowerRecord(testSensorName, System.currentTimeMillis(), 1L, @@ -100,7 +99,7 @@ public class Uc4PipelineTest extends JetTestSupport { // Topology: // level2Group -> level1Group -> testSensor - + // Create Registry final MutableSensorRegistry testRegistry = new MutableSensorRegistry(testLevel2GroupName); // Add Sensors @@ -118,7 +117,7 @@ public class Uc4PipelineTest extends JetTestSupport { // Create pipeline to test final Uc4PipelineBuilder pipelineBuilder = new Uc4PipelineBuilder(); this.testPipeline = Pipeline.create(); - this.uc4Topology = pipelineBuilder.extendUc4Topology(testPipeline, + this.uc4Topology = pipelineBuilder.extendUc4Topology(this.testPipeline, testInputSource, testAggregationSource, testConfigSource, testWindowSize); this.uc4Topology.writeTo(Sinks.logger()); @@ -130,8 +129,8 @@ public class Uc4PipelineTest extends JetTestSupport { @Test public void testOutput() { -// System.out.println("DEBUG DEBUG DEBUG || ENTERED TEST 1"); - + // System.out.println("DEBUG DEBUG DEBUG || ENTERED TEST 1"); + // Assertion Configuration final int timeout = 20; final String testSensorName = "TEST-SENSOR"; @@ -141,7 +140,7 @@ public class Uc4PipelineTest extends JetTestSupport { // Assertion - this.uc4Topology.apply(Assertions.assertCollectedEventually(timeout, + this.uc4Topology.apply(Assertions.assertCollectedEventually(timeout, collection -> { System.out.println("DEBUG || ENTERED ASSERTION COLLECTED EVENTUALLY"); @@ -168,11 +167,11 @@ public class Uc4PipelineTest extends JetTestSupport { testLevel1contained = true; } - if(Objects.equals(key, testLevel2GroupName)){ + if (Objects.equals(key, testLevel2GroupName)) { testLevel2contained = true; } - if (testValueInW != agg.getAverageInW()){ + if (testValueInW != agg.getAverageInW()) { averageEqTest = false; } @@ -191,10 +190,10 @@ public class Uc4PipelineTest extends JetTestSupport { System.out.println("avOk: " + avOk); Assert.assertTrue("Assertion did not complete!", allOkay); - + })); - try{ + try { final JobConfig jobConfig = new JobConfig() .registerSerializer(ValueGroup.class, ValueGroupSerializer.class) @@ -209,7 +208,7 @@ public class Uc4PipelineTest extends JetTestSupport { "Job was expected to complete with AssertionCompletedException, but completed with: " + e.getCause(), errorMsg.contains(AssertionCompletedException.class.getName())); - } catch (Exception e){ + } catch (final Exception e) { System.out.println("ERRORORORO TEST BROKEN !!!!"); System.out.println(e); } @@ -218,7 +217,6 @@ public class Uc4PipelineTest extends JetTestSupport { @After public void after() { - System.out.println("Shutting down"); // Shuts down all running Jet Instances Jet.shutdownAll(); } diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/AggregationService.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/AggregationService.java index 341c37bc086dabb3a93dcd3b0f221dd91007b8b3..26ea02957fb013c61c4ee0c3e2f280b0b9b8c993 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/AggregationService.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/AggregationService.java @@ -4,8 +4,8 @@ import java.time.Duration; import java.util.concurrent.CompletableFuture; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.KafkaStreams; +import rocks.theodolite.benchmarks.commons.commons.configuration.ServiceConfigurations; import rocks.theodolite.benchmarks.commons.kstreams.ConfigurationKeys; -import titan.ccp.common.configuration.ServiceConfigurations; /** * A microservice that manages the history and, therefore, stores and aggregates incoming diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformer.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformer.java index bdc8fc7d4267fbdb427d8dc217ef296c0553da1b..d311ff009c138c6afe29cf9e95c323ea46a6bc0f 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformer.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformer.java @@ -10,10 +10,10 @@ import org.apache.kafka.streams.kstream.Transformer; import org.apache.kafka.streams.processor.ProcessorContext; import org.apache.kafka.streams.state.KeyValueIterator; import org.apache.kafka.streams.state.KeyValueStore; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.sensorregistry.AggregatedSensor; -import titan.ccp.model.sensorregistry.Sensor; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.Sensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; /** * Transforms a {@link SensorRegistry} into key value pairs of Sensor identifiers and their parents' diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformerSupplier.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformerSupplier.java index 538643f0cdb119988e446f3eae793e2efcccadd6..734989af63b6b2a7fc97b368bb2651112c98fda5 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformerSupplier.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ChildParentsTransformerSupplier.java @@ -10,8 +10,8 @@ import org.apache.kafka.streams.kstream.TransformerSupplier; import org.apache.kafka.streams.state.KeyValueStore; import org.apache.kafka.streams.state.StoreBuilder; import org.apache.kafka.streams.state.Stores; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; /** * Supplier class for a {@link ChildParentsTransformer}. diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformer.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformer.java index 38cbca81d664ca72494525263d8a7ab3a7523bfc..06cbe1f40719fcbb6b9b8a22767ec415def3dc80 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformer.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformer.java @@ -9,7 +9,7 @@ import org.apache.kafka.streams.KeyValue; import org.apache.kafka.streams.kstream.Transformer; import org.apache.kafka.streams.processor.ProcessorContext; import org.apache.kafka.streams.state.KeyValueStore; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Transforms the join result of an {@link ActivePowerRecord} and the corresponding sensor parents diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformerSupplier.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformerSupplier.java index 2e635ec368bca87bdb882580b51f763abba8f32a..67efca0671ad347add9d5dcc1f255a9c8d9de09b 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformerSupplier.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointFlatTransformerSupplier.java @@ -9,7 +9,7 @@ import org.apache.kafka.streams.kstream.TransformerSupplier; import org.apache.kafka.streams.state.KeyValueStore; import org.apache.kafka.streams.state.StoreBuilder; import org.apache.kafka.streams.state.Stores; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * Supplier class for {@link JointFlatTransformerSupplier}. diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointRecordParents.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointRecordParents.java index 5892c6d3ac84c6d1ff56cfb440186e07fd9d9eb0..85b3a817564367098996196694994497b9db8793 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointRecordParents.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/JointRecordParents.java @@ -2,7 +2,7 @@ package rocks.theodolite.benchmarks.uc4.kstreams; import java.util.Objects; import java.util.Set; -import titan.ccp.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; /** * A joined pair of an {@link ActivePowerRecord} and its associated parents. Both the record and the diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerde.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerde.java index 3738fadd52b22abb8e13f20ae6066017112f0455..e5ff9c676b4ea539fb9605fc51c93920c3757fc8 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerde.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/OptionalParentsSerde.java @@ -4,10 +4,10 @@ import java.util.HashSet; import java.util.Optional; import java.util.Set; import org.apache.kafka.common.serialization.Serde; -import titan.ccp.common.kafka.simpleserdes.BufferSerde; -import titan.ccp.common.kafka.simpleserdes.ReadBuffer; -import titan.ccp.common.kafka.simpleserdes.SimpleSerdes; -import titan.ccp.common.kafka.simpleserdes.WriteBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.BufferSerde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.ReadBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.SimpleSerdes; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.WriteBuffer; /** * {@link Serde} factory for an optional {@link Set} of parent identifiers. diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerde.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerde.java index dac58c84bc1914b4e54fe5eb6da0930204e34eb5..b70df46325f60c82a3759219827e9ab54b17b57a 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerde.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/ParentsSerde.java @@ -3,10 +3,10 @@ package rocks.theodolite.benchmarks.uc4.kstreams; import java.util.HashSet; import java.util.Set; import org.apache.kafka.common.serialization.Serde; -import titan.ccp.common.kafka.simpleserdes.BufferSerde; -import titan.ccp.common.kafka.simpleserdes.ReadBuffer; -import titan.ccp.common.kafka.simpleserdes.SimpleSerdes; -import titan.ccp.common.kafka.simpleserdes.WriteBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.BufferSerde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.ReadBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.SimpleSerdes; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.WriteBuffer; /** * {@link Serde} factory for {@link Set} of parent identifiers. diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/RecordAggregator.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/RecordAggregator.java index d107dedbfdb58489a6f00e2baf248f15bb823db9..bbc6079521d38b75ae35ea49fda26e7504746b23 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/RecordAggregator.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/RecordAggregator.java @@ -1,8 +1,8 @@ package rocks.theodolite.benchmarks.uc4.kstreams; import org.apache.kafka.streams.kstream.Windowed; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; /** * Updates an {@link AggregatedActivePowerRecord} by a new {@link ActivePowerRecord}. diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerde.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerde.java index 80fd16f64c6f08e32a89bb3558b61d3f560be890..1beab6094bcc87bed0bbbedbc449edadf3523c19 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerde.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/SensorParentKeySerde.java @@ -1,10 +1,10 @@ package rocks.theodolite.benchmarks.uc4.kstreams; import org.apache.kafka.common.serialization.Serde; -import titan.ccp.common.kafka.simpleserdes.BufferSerde; -import titan.ccp.common.kafka.simpleserdes.ReadBuffer; -import titan.ccp.common.kafka.simpleserdes.SimpleSerdes; -import titan.ccp.common.kafka.simpleserdes.WriteBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.BufferSerde; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.ReadBuffer; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.SimpleSerdes; +import rocks.theodolite.benchmarks.commons.kafka.simpleserdes.WriteBuffer; /** * {@link Serde} factory for {@link SensorParentKey}. diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/TopologyBuilder.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/TopologyBuilder.java index fbd3ed109965b103e4f1cdeb4324581bc6c82e8b..876e53422183306963cf07853939247bbb012464 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/TopologyBuilder.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/TopologyBuilder.java @@ -18,12 +18,12 @@ import org.apache.kafka.streams.kstream.Suppressed.BufferConfig; import org.apache.kafka.streams.kstream.TimeWindows; import org.apache.kafka.streams.kstream.Windowed; import org.apache.kafka.streams.kstream.WindowedSerdes; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; -import titan.ccp.configuration.events.Event; -import titan.ccp.configuration.events.EventSerde; -import titan.ccp.model.records.ActivePowerRecord; -import titan.ccp.model.records.AggregatedActivePowerRecord; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.configuration.events.EventSerde; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; +import rocks.theodolite.benchmarks.commons.model.records.ActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.records.AggregatedActivePowerRecord; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; /** * Builds Kafka Stream Topology for the History microservice. diff --git a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/Uc4KafkaStreamsBuilder.java b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/Uc4KafkaStreamsBuilder.java index 4d2b96ccb751dbb804eab0806303312a88702dc0..209eb519f9e61b2aaa684686e391ccc11aa808e7 100644 --- a/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/Uc4KafkaStreamsBuilder.java +++ b/theodolite-benchmarks/uc4-kstreams/src/main/java/rocks/theodolite/benchmarks/uc4/kstreams/Uc4KafkaStreamsBuilder.java @@ -5,8 +5,8 @@ import java.util.Objects; import java.util.Properties; import org.apache.commons.configuration2.Configuration; import org.apache.kafka.streams.Topology; +import rocks.theodolite.benchmarks.commons.kafka.avro.SchemaRegistryAvroSerdeFactory; import rocks.theodolite.benchmarks.commons.kstreams.KafkaStreamsBuilder; -import titan.ccp.common.kafka.avro.SchemaRegistryAvroSerdeFactory; /** * Builder for the Kafka Streams configuration. diff --git a/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/ConfigPublisher.java b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/ConfigPublisher.java index 98f470b0df1873766c3bf56fb7e6a8eae0019ce4..60c95321f05edff35681d8984baa03ca711f48da 100644 --- a/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/ConfigPublisher.java +++ b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/ConfigPublisher.java @@ -7,8 +7,8 @@ import org.apache.kafka.clients.producer.Producer; import org.apache.kafka.clients.producer.ProducerConfig; import org.apache.kafka.clients.producer.ProducerRecord; import org.apache.kafka.common.serialization.StringSerializer; -import titan.ccp.configuration.events.Event; -import titan.ccp.configuration.events.EventSerde; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.configuration.events.EventSerde; /** * Class to publish a configuration to Kafka. diff --git a/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java index 2077de2d9918d46a7a3e671ae9820a7c7abadbfc..3f02a4b5ebf232e4dcb3ff236f656cf6fb485989 100644 --- a/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java +++ b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/LoadGenerator.java @@ -3,9 +3,9 @@ package rocks.theodolite.benchmarks.uc4.loadgenerator; import java.util.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import rocks.theodolite.benchmarks.commons.configuration.events.Event; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; import rocks.theodolite.benchmarks.loadgenerator.KeySpace; -import titan.ccp.configuration.events.Event; -import titan.ccp.model.sensorregistry.SensorRegistry; /** * Load generator for Theodolite use case UC4. diff --git a/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilder.java b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilder.java index c69dffb6093f914111b8c74bc25f3ca3a0a34ae6..c9dcfa0af8676460c5cc59ed2f4f6b4641911525 100644 --- a/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilder.java +++ b/theodolite-benchmarks/uc4-load-generator/src/main/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilder.java @@ -1,8 +1,8 @@ package rocks.theodolite.benchmarks.uc4.loadgenerator; -import titan.ccp.model.sensorregistry.MutableAggregatedSensor; -import titan.ccp.model.sensorregistry.MutableSensorRegistry; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableAggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MutableSensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; /** * Builder for creating a nested {@link SensorRegistry} with {@code numNestedGroups} levels and diff --git a/theodolite-benchmarks/uc4-load-generator/src/test/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilderTest.java b/theodolite-benchmarks/uc4-load-generator/src/test/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilderTest.java index a169eddb10ac34b91b814a657bf327a79ae00ac4..037bd8119ef1ea93ed3dae346282538ff5399f25 100644 --- a/theodolite-benchmarks/uc4-load-generator/src/test/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilderTest.java +++ b/theodolite-benchmarks/uc4-load-generator/src/test/java/rocks/theodolite/benchmarks/uc4/loadgenerator/SensorRegistryBuilderTest.java @@ -5,10 +5,10 @@ import java.util.Set; import java.util.stream.Collectors; import org.junit.Assert; import org.junit.Test; -import titan.ccp.model.sensorregistry.AggregatedSensor; -import titan.ccp.model.sensorregistry.MachineSensor; -import titan.ccp.model.sensorregistry.Sensor; -import titan.ccp.model.sensorregistry.SensorRegistry; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.AggregatedSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.MachineSensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.Sensor; +import rocks.theodolite.benchmarks.commons.model.sensorregistry.SensorRegistry; public class SensorRegistryBuilderTest { diff --git a/theodolite/crd/crd-benchmark.yaml b/theodolite/crd/crd-benchmark.yaml index c901e61360c05b2f1cf2b1767a20f624eb262231..cfc9d3bd6a196cd5740463d41beb64276f4ffa57 100644 --- a/theodolite/crd/crd-benchmark.yaml +++ b/theodolite/crd/crd-benchmark.yaml @@ -20,12 +20,16 @@ spec: properties: spec: type: object - required: ["sut", "loadGenerator", "resourceTypes", "loadTypes"] + required: ["sut", "loadGenerator", "resourceTypes", "loadTypes", "slos"] properties: name: description: This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten. type: string default: "" + waitForResourcesEnabled: + description: If true, Theodolite waits to create the resource for the SUT until the infrastructure resources are ready, and analogously, Theodolite waits to create the load-gen resource until the resources of the SUT are ready. + type: boolean + default: false infrastructure: description: (Optional) A list of file names that reference Kubernetes resources that are deployed on the cluster to create the required infrastructure. type: object @@ -70,29 +74,33 @@ spec: description: Infrastructure before actions are executed before the infrastructure is set up. items: type: object + anyOf: + - required: [ exec ] + - required: [ delete ] properties: - selector: + exec: type: object - description: The selector specifies which resource should be selected for the execution of the command. + description: Specifies a command that gets executed within a Container of a Pod + required: [ selector, command, timeoutSeconds ] properties: - pod: + selector: type: object - description: Specifies the pod. + description: The selector specifies which resource should be selected for the execution of the command. properties: - matchLabels: + pod: type: object - description: The matchLabels of the desired pod. - additionalProperties: true - x-kubernetes-map-type: "granular" - default: { } - container: - description: Specifies the container. - default: "" - type: string - exec: - type: object - description: Specifies command to be executed. - properties: + description: Specifies the pod. + properties: + matchLabels: + type: object + description: The matchLabels of the desired pod. + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + description: Specifies the container. + default: "" + type: string command: type: array description: The command to be executed as string array. @@ -101,35 +109,59 @@ spec: timeoutSeconds: description: Specifies the timeout (in seconds) for the specified command. type: integer + delete: + type: object + description: Specifies deletion of a resource. + required: [ selector ] + properties: + selector: + type: object + description: Defines how to select the resource to delete. + required: [ apiVersion, kind ] + properties: + apiVersion: + type: string + description: Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'. + kind: + type: string + description: Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'. + nameRegex: + type: string + description: Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted. + default: "*" afterActions: type: array - default: [] + default: [ ] description: Infrastructure after actions are executed after the teardown of the infrastructure. items: type: object + anyOf: + - required: [ exec ] + - required: [ delete ] properties: - selector: + exec: type: object - description: The selector specifies which resource should be selected for the execution of the command. + description: Specifies a command that gets executed within a Container of a Pod + required: [ selector, command, timeoutSeconds ] properties: - pod: + selector: type: object - description: Specifies the pod. + description: The selector specifies which resource should be selected for the execution of the command. properties: - matchLabels: + pod: type: object - description: The matchLabels of the desired pod. - additionalProperties: true - x-kubernetes-map-type: "granular" - default: { } - container: - description: Specifies the container. - default: "" - type: string - exec: - type: object - description: Specifies command to be executed. - properties: + description: Specifies the pod. + properties: + matchLabels: + type: object + description: The matchLabels of the desired pod. + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + description: Specifies the container. + default: "" + type: string command: type: array description: The command to be executed as string array. @@ -138,6 +170,26 @@ spec: timeoutSeconds: description: Specifies the timeout (in seconds) for the specified command. type: integer + delete: + type: object + description: Specifies deletion of a resource. + required: [ selector ] + properties: + selector: + type: object + description: Defines how to select the resource to delete. + required: [ apiVersion, kind ] + properties: + apiVersion: + type: string + description: Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'. + kind: + type: string + description: Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'. + nameRegex: + type: string + description: Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted. + default: "*" sut: description: The appResourceSets specifies all Kubernetes resources required to start the sut. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet. type: object @@ -177,33 +229,37 @@ spec: type: string beforeActions: type: array - default: [] + default: [ ] description: SUT before actions are executed before the SUT is started. items: type: object + anyOf: + - required: [ exec ] + - required: [ delete ] properties: - selector: + exec: type: object - description: The selector specifies which resource should be selected for the execution of the command. + description: Specifies a command that gets executed within a Container of a Pod + required: [ selector, command, timeoutSeconds ] properties: - pod: + selector: type: object - description: Specifies the pod. + description: The selector specifies which resource should be selected for the execution of the command. properties: - matchLabels: + pod: type: object - description: The matchLabels of the desired pod. - additionalProperties: true - x-kubernetes-map-type: "granular" - default: { } - container: - description: Specifies the container. - default: "" - type: string - exec: - type: object - description: Specifies command to be executed. - properties: + description: Specifies the pod. + properties: + matchLabels: + type: object + description: The matchLabels of the desired pod. + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + description: Specifies the container. + default: "" + type: string command: type: array description: The command to be executed as string array. @@ -212,34 +268,59 @@ spec: timeoutSeconds: description: Specifies the timeout (in seconds) for the specified command. type: integer + delete: + type: object + description: Specifies deletion of a resource. + required: [ selector ] + properties: + selector: + type: object + description: Defines how to select the resource to delete. + required: [ apiVersion, kind ] + properties: + apiVersion: + type: string + description: Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'. + kind: + type: string + description: Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'. + nameRegex: + type: string + description: Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted. + default: "*" afterActions: type: array - default: [] + default: [ ] + description: SUT after actions are executed after the teardown of the SUT. items: type: object + anyOf: + - required: [ exec ] + - required: [ delete ] properties: - selector: + exec: type: object - description: The selector specifies which resource should be selected for the execution of the command. + description: Specifies a command that gets executed within a Container of a Pod + required: [ selector, command, timeoutSeconds ] properties: - pod: + selector: type: object - description: Specifies the pod. + description: The selector specifies which resource should be selected for the execution of the command. properties: - matchLabels: + pod: type: object - description: The matchLabels of the desired pod. - additionalProperties: true - x-kubernetes-map-type: "granular" - default: { } - container: - description: Specifies the container. - default: "" - type: string - exec: - type: object - description: Specifies command to be executed. - properties: + description: Specifies the pod. + properties: + matchLabels: + type: object + description: The matchLabels of the desired pod. + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + description: Specifies the container. + default: "" + type: string command: type: array description: The command to be executed as string array. @@ -248,6 +329,26 @@ spec: timeoutSeconds: description: Specifies the timeout (in seconds) for the specified command. type: integer + delete: + type: object + description: Specifies deletion of a resource. + required: [ selector ] + properties: + selector: + type: object + description: Defines how to select the resource to delete. + required: [ apiVersion, kind ] + properties: + apiVersion: + type: string + description: Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'. + kind: + type: string + description: Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'. + nameRegex: + type: string + description: Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted. + default: "*" loadGenerator: description: The loadGenResourceSets specifies all Kubernetes resources required to start the load generator. A resourceSet can be either a configMap resourceSet or a fileSystem resourceSet. type: object @@ -291,29 +392,33 @@ spec: description: Load generator before actions are executed before the load generator is started. items: type: object + anyOf: + - required: [ exec ] + - required: [ delete ] properties: - selector: + exec: type: object - description: The selector specifies which resource should be selected for the execution of the command. + description: Specifies a command that gets executed within a Container of a Pod + required: [ selector, command, timeoutSeconds ] properties: - pod: + selector: type: object - description: Specifies the pod. + description: The selector specifies which resource should be selected for the execution of the command. properties: - matchLabels: + pod: type: object - description: The matchLabels of the desired pod. - additionalProperties: true - x-kubernetes-map-type: "granular" - default: { } - container: - description: Specifies the container. - default: "" - type: string - exec: - type: object - description: Specifies command to be executed. - properties: + description: Specifies the pod. + properties: + matchLabels: + type: object + description: The matchLabels of the desired pod. + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + description: Specifies the container. + default: "" + type: string command: type: array description: The command to be executed as string array. @@ -322,35 +427,59 @@ spec: timeoutSeconds: description: Specifies the timeout (in seconds) for the specified command. type: integer + delete: + type: object + description: Specifies deletion of a resource. + required: [ selector ] + properties: + selector: + type: object + description: Defines how to select the resource to delete. + required: [ apiVersion, kind ] + properties: + apiVersion: + type: string + description: Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'. + kind: + type: string + description: Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'. + nameRegex: + type: string + description: Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted. + default: "*" afterActions: type: array - default: [] + default: [ ] description: Load generator after actions are executed after the teardown of the load generator. items: type: object + anyOf: + - required: [ exec ] + - required: [ delete ] properties: - selector: + exec: type: object - description: The selector specifies which resource should be selected for the execution of the command. + description: Specifies a command that gets executed within a Container of a Pod + required: [ selector, command, timeoutSeconds ] properties: - pod: + selector: type: object - description: Specifies the pod. + description: The selector specifies which resource should be selected for the execution of the command. properties: - matchLabels: + pod: type: object - description: The matchLabels of the desired pod. - additionalProperties: true - x-kubernetes-map-type: "granular" - default: { } - container: - description: Specifies the container. - default: "" - type: string - exec: - type: object - description: Specifies command to be executed. - properties: + description: Specifies the pod. + properties: + matchLabels: + type: object + description: The matchLabels of the desired pod. + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } + container: + description: Specifies the container. + default: "" + type: string command: type: array description: The command to be executed as string array. @@ -359,6 +488,26 @@ spec: timeoutSeconds: description: Specifies the timeout (in seconds) for the specified command. type: integer + delete: + type: object + description: Specifies deletion of a resource. + required: [ selector ] + properties: + selector: + type: object + description: Defines how to select the resource to delete. + required: [ apiVersion, kind ] + properties: + apiVersion: + type: string + description: Specifies the api/version of the resource that should be deleted, e.g. 'kafka.strimzi.io/v1beta2'. + kind: + type: string + description: Specifies the Kind of the resource that should be deleted, e.g. 'KafkaTopic'. + nameRegex: + type: string + description: Specifies a regular expression that is matched with the metadata.name property of all resources with given api/version and Kind that should be deleted. + default: "*" resourceTypes: description: A list of resource types that can be scaled for this `benchmark` resource. For each resource type the concrete values are defined in the `execution` object. type: array @@ -425,6 +574,31 @@ spec: additionalProperties: true x-kubernetes-map-type: "granular" default: {} + slos: # def of service level objectives + description: List of resource values for the specified resource type. + type: array + items: + type: object + required: ["name", "sloType", "prometheusUrl", "offset"] + properties: + name: + description: The name of the SLO. + type: string + sloType: + description: The type of the SLO. It must match 'lag trend'. + type: string + prometheusUrl: + description: Connection string for Promehteus. + type: string + offset: + description: Hours by which the start and end timestamp will be shifted (for different timezones). + type: integer + properties: + description: (Optional) SLO specific additional arguments. + type: object + additionalProperties: true + x-kubernetes-map-type: "granular" + default: { } kafkaConfig: description: Contains the Kafka configuration. type: object diff --git a/theodolite/crd/crd-execution.yaml b/theodolite/crd/crd-execution.yaml index 92a8ca18d87009143620097caf2abfe8da202c82..0db251864bac3e6f2541534eec8895297b21cf39 100644 --- a/theodolite/crd/crd-execution.yaml +++ b/theodolite/crd/crd-execution.yaml @@ -20,7 +20,7 @@ spec: properties: spec: type: object - required: ["benchmark", "load", "resources", "slos", "execution", "configOverrides"] + required: ["benchmark", "loads", "resources", "execution", "configOverrides"] properties: name: description: This field exists only for technical reasons and should not be set by the user. The value of the field will be overwritten. @@ -29,7 +29,7 @@ spec: benchmark: description: The name of the benchmark this execution is referring to. type: string - load: # definition of the load dimension + loads: # definition of the load dimension description: Specifies the load values that are benchmarked. type: object required: ["loadType", "loadValues"] @@ -56,21 +56,15 @@ spec: items: type: integer slos: # def of service level objectives - description: List of resource values for the specified resource type. + description: List of SLOs with their properties, which differ from the benchmark definition. type: array items: type: object - required: ["sloType", "prometheusUrl", "offset"] + required: ["name", "properties"] properties: - sloType: - description: The type of the SLO. It must match 'lag trend'. + name: + description: The name of the SLO. It must match a SLO specified in the Benchmark. type: string - prometheusUrl: - description: Connection string for Promehteus. - type: string - offset: - description: Hours by which the start and end timestamp will be shifted (for different timezones). - type: integer properties: description: (Optional) SLO specific additional arguments. type: object @@ -80,25 +74,35 @@ spec: execution: # def execution config description: Defines the overall parameter for the execution. type: object - required: ["strategy", "duration", "repetitions", "restrictions"] + required: ["strategy", "duration", "repetitions"] properties: - strategy: - description: Defines the used strategy for the execution, either 'LinearSearch' or 'BinarySearch' + metric: type: string + strategy: + description: Defines the used strategy for the execution, either 'LinearSearch', 'BinarySearch' or 'InitialGuessSearch'. + type: object + required: ["name"] + properties: + name: + type: string + restrictions: + description: List of restriction strategies used to delimit the search space. + type: array + items: + type: string + guessStrategy: + type: string + searchStrategy: + type: string duration: description: Defines the duration of each experiment in seconds. type: integer repetitions: - description: Numper of repititions for each experiments. + description: Number of repititions for each experiment. type: integer loadGenerationDelay: description: Seconds to wait between the start of the SUT and the load generator. type: integer - restrictions: - description: List of restriction strategys used to delimit the search space. - type: array - items: - type: string configOverrides: description: List of patchers that are used to override existing configurations. type: array diff --git a/theodolite/examples/operator/example-benchmark.yaml b/theodolite/examples/operator/example-benchmark.yaml index 62920091e831ff914fb67e85a67cd3f1d98995ab..be7116c46f8222eeba0f3bffd086f7cc2b6ee227 100644 --- a/theodolite/examples/operator/example-benchmark.yaml +++ b/theodolite/examples/operator/example-benchmark.yaml @@ -33,6 +33,15 @@ spec: resource: "uc1-load-generator-deployment.yaml" properties: loadGenMaxRecords: "150000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 3000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite/examples/operator/example-execution.yaml b/theodolite/examples/operator/example-execution.yaml index 576a74b90dfc38483de79502ac14d42f6bedfb49..87e6275a8409177394dd313f2f1f0436e2162577 100644 --- a/theodolite/examples/operator/example-execution.yaml +++ b/theodolite/examples/operator/example-execution.yaml @@ -4,27 +4,25 @@ metadata: name: theodolite-example-execution spec: benchmark: "example-benchmark" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: resourceType: "Instances" resourceValues: [1, 2, 3, 4, 5] slos: - - sloType: "lag trend" - prometheusUrl: "http://prometheus-operated:9090" - offset: 0 + - name: "lag trend" properties: threshold: 2000 - externalSloUrl: "http://localhost:80/evaluate-slope" - warmup: 60 # in seconds execution: - strategy: "LinearSearch" + strategy: + name: "RestrictionSearch" + restrictions: + - "LowerBound" + searchStrategy: "LinearSearch" duration: 300 # in seconds repetitions: 1 loadGenerationDelay: 30 # in seconds - restrictions: - - "LowerBound" configOverrides: [] # - patcher: # type: "NodeSelectorPatcher" diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/Config.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/Config.kt new file mode 100644 index 0000000000000000000000000000000000000000..c429d6b3f456c345c7ab2adb1ccd95635603ef4f --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/Config.kt @@ -0,0 +1,21 @@ +package rocks.theodolite.core + +import io.quarkus.runtime.annotations.RegisterForReflection +import rocks.theodolite.core.strategies.Metric +import rocks.theodolite.core.strategies.searchstrategy.SearchStrategy + +/** + * Config class that represents a configuration of a theodolite run. + * + * @param loads the possible loads of the execution + * @param resources the possible resources of the execution + * @param searchStrategy the [SearchStrategy] of the execution + * @param metric the Metric of the execution + */ +@RegisterForReflection +data class Config( + val loads: List<Int>, + val resources: List<Int>, + val searchStrategy: SearchStrategy, + val metric: Metric +) diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/ExecutionRunner.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/ExecutionRunner.kt new file mode 100644 index 0000000000000000000000000000000000000000..a63269bb8ebb009ecd858be145523c4029814888 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/ExecutionRunner.kt @@ -0,0 +1,50 @@ +package rocks.theodolite.core + +import rocks.theodolite.core.strategies.Metric +import rocks.theodolite.core.strategies.searchstrategy.SearchStrategy + + +class ExecutionRunner (private val searchStrategy: SearchStrategy, + private val resources: List<Int>, private val loads: List<Int>, + private val metric: Metric, private val executionId: Int) { + + /** + * Run all experiments for given loads and resources. + * Called by [rocks.theodolite.kubernetes.execution.TheodoliteExecutor] to run an Execution. + */ + fun run() { + + val ioHandler = IOHandler() + val resultsFolder = ioHandler.getResultFolderURL() + + //execute benchmarks for each load for the demand metric, or for each resource amount for capacity metric + try { + searchStrategy.applySearchStrategyByMetric(loads, resources, metric) + + } finally { + ioHandler.writeToJSONFile( + searchStrategy.experimentRunner.results, + "${resultsFolder}exp${executionId}-result" + ) + // Create expXYZ_demand.csv file or expXYZ_capacity.csv depending on metric + when(metric) { + Metric.DEMAND -> + ioHandler.writeToCSVFile( + "${resultsFolder}exp${executionId}_demand", + calculateMetric(loads, searchStrategy.experimentRunner.results), + listOf("load","resources") + ) + Metric.CAPACITY -> + ioHandler.writeToCSVFile( + "${resultsFolder}exp${executionId}_capacity", + calculateMetric(resources, searchStrategy.experimentRunner.results), + listOf("resource", "loads") + ) + } + } + } + + private fun calculateMetric(xValues: List<Int>, results: Results): List<List<String>> { + return xValues.map { listOf(it.toString(), results.getOptYDimensionValue(it).toString()) } + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/ExperimentRunner.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/ExperimentRunner.kt new file mode 100644 index 0000000000000000000000000000000000000000..830469320d98cf66cd9395e3cdf74b2443758c3c --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/ExperimentRunner.kt @@ -0,0 +1,29 @@ +package rocks.theodolite.core + +import java.util.concurrent.atomic.AtomicBoolean + + +/** + * Abstract class acts as an interface for the theodolite core to run experiments. + * The results of the experiments are stored in [results]. + * + * @property results + */ +abstract class ExperimentRunner(val results: Results) { + + var run: AtomicBoolean = AtomicBoolean(true) + + /** + * Run an experiment for the given parametrization, evaluate the + * experiment and save the result. + * + * @param load to be tested. + * @param resource to be tested. + * @return True, if the number of resources are suitable for the + * given load, false otherwise (demand metric), or + * True, if there is a load suitable for the + * given resource, false otherwise. + */ + abstract fun runExperiment(load: Int, resource: Int): Boolean + +} diff --git a/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/IOHandler.kt similarity index 99% rename from theodolite/src/main/kotlin/theodolite/util/IOHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/core/IOHandler.kt index 8b580c733ab7ae527d99c676223f4b09b392c6fd..4d2cab0da938b18950def8cfb5cc6f104e110125 100644 --- a/theodolite/src/main/kotlin/theodolite/util/IOHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/IOHandler.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.core import com.google.gson.GsonBuilder import mu.KotlinLogging diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/Results.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/Results.kt new file mode 100644 index 0000000000000000000000000000000000000000..16e6b517e1f570fd17a1b9688aff4f41ec8c9884 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/Results.kt @@ -0,0 +1,127 @@ +package rocks.theodolite.core + +import io.quarkus.runtime.annotations.RegisterForReflection +import rocks.theodolite.core.strategies.Metric + +/** + * Central class that saves the state of an execution of Theodolite. For an execution, it is used to save the result of + * individual experiments. Further, it is used by the RestrictionStrategy to + * perform the [theodolite.strategies.restriction.RestrictionStrategy]. + */ +@RegisterForReflection +class Results (val metric: Metric) { + // (load, resource) -> Boolean map + private val results: MutableMap<Pair<Int, Int>, Boolean> = mutableMapOf() + + // if metric is "demand" : load -> resource + // if metric is "capacity": resource -> load + private var optInstances: MutableMap<Int, Int> = mutableMapOf() + + + /** + * Set the result for an experiment and update the [optInstances] list accordingly. + * + * @param experiment A pair that identifies the experiment by the Load and Resource. + * @param successful the result of the experiment. Successful == true and Unsuccessful == false. + */ + fun setResult(experiment: Pair<Int, Int>, successful: Boolean) { + this.results[experiment] = successful + + when (metric) { + Metric.DEMAND -> + if (successful) { + if (optInstances.containsKey(experiment.first)) { + if (optInstances[experiment.first]!! > experiment.second) { + optInstances[experiment.first] = experiment.second + } + } else { + optInstances[experiment.first] = experiment.second + } + } else if (!optInstances.containsKey(experiment.first)) { + optInstances[experiment.first] = Int.MAX_VALUE + } + Metric.CAPACITY -> + if (successful) { + if (optInstances.containsKey(experiment.second)) { + if (optInstances[experiment.second]!! < experiment.first) { + optInstances[experiment.second] = experiment.first + } + } else { + optInstances[experiment.second] = experiment.first + } + } else if (!optInstances.containsKey(experiment.second)) { + optInstances[experiment.second] = Int.MIN_VALUE + } + } + } + + /** + * Get the result for an experiment. + * + * @param experiment A pair that identifies the experiment by the Load and Resource. + * @return true if the experiment was successful and false otherwise. If the result has not been reported so far, + * null is returned. + * + */ + fun getResult(experiment: Pair<Int, Int>): Boolean? { + return this.results[experiment] + } + + /** + * Get the smallest suitable number of instances for a specified x-Value. + * The x-Value corresponds to the... + * - load, if the metric is "demand". + * - resource, if the metric is "capacity". + * + * @param xValue the Value of the x-dimension of the current metric + * + * @return the smallest suitable number of resources/loads (depending on metric). + * If there is no experiment that has been executed yet, there is no experiment + * for the given [xValue] or there is none marked successful yet, null is returned. + */ + fun getOptYDimensionValue(xValue: Int?): Int? { + if (xValue != null) { + val res = optInstances[xValue] + if (res != Int.MAX_VALUE && res != Int.MIN_VALUE) { + return res + } + } + return null + } + + /** + * Get the largest x-Value that has been tested and reported so far (successful or unsuccessful), + * which is smaller than the specified x-Value. + * + * The x-Value corresponds to the... + * - load, if the metric is "demand". + * - resource, if the metric is "capacity". + * + * @param xValue the Value of the x-dimension of the current metric + * + * @return the largest tested x-Value or null, if there wasn't any tested which is smaller than the [xValue]. + */ + fun getMaxBenchmarkedXDimensionValue(xValue: Int): Int? { + var maxBenchmarkedXValue: Int? = null + for (instance in optInstances) { + val instanceXValue= instance.key + if (instanceXValue <= xValue) { + if (maxBenchmarkedXValue == null) { + maxBenchmarkedXValue = instanceXValue + } else if (maxBenchmarkedXValue < instanceXValue) { + maxBenchmarkedXValue = instanceXValue + } + } + } + return maxBenchmarkedXValue + } + + /** + * Checks whether the results are empty. + * + * @return true if [results] is empty. + */ + fun isEmpty(): Boolean{ + return results.isEmpty() + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/Metric.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/Metric.kt new file mode 100644 index 0000000000000000000000000000000000000000..db161d10c61fae512e28ba059e604835d22aeb96 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/Metric.kt @@ -0,0 +1,11 @@ +package rocks.theodolite.core.strategies + +enum class Metric(val value: String) { + DEMAND("demand"), + CAPACITY("capacity"); + + companion object { + fun from(metric: String): Metric = + values().find { it.value == metric } ?: throw IllegalArgumentException("Requested Metric does not exist") + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/StrategyFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/StrategyFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..d2925c798e29705f3333130e8c9f09e32d7ec31c --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/StrategyFactory.kt @@ -0,0 +1,84 @@ +package rocks.theodolite.core.strategies + +import rocks.theodolite.core.strategies.guessstrategy.PrevInstanceOptGuess +import rocks.theodolite.core.strategies.restrictionstrategy.LowerBoundRestriction +import rocks.theodolite.core.strategies.restrictionstrategy.RestrictionStrategy +import rocks.theodolite.core.strategies.searchstrategy.* +import rocks.theodolite.core.ExperimentRunner +import rocks.theodolite.core.Results + +/** + * Factory for creating [SearchStrategy] and [RestrictionStrategy] strategies. + */ +class StrategyFactory { + + /** + * Create a [SearchStrategy]. + * + * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments. + * @param searchStrategyObject Specifies the [SearchStrategy]. Must either be an object with name 'FullSearch', + * 'LinearSearch', 'BinarySearch', 'RestrictionSearch' or 'InitialGuessSearch'. + * @param results The [Results] saves the state of the Theodolite benchmark run. + * + * @throws IllegalArgumentException if the [SearchStrategy] was not one of the allowed options. + */ + fun createSearchStrategy(executor: ExperimentRunner, name: String, searchStrategy: String, restrictions: List<String>, + guessStrategy: String, results: Results): SearchStrategy { + + var strategy : SearchStrategy = when (name) { + "FullSearch" -> FullSearch(executor) + "LinearSearch" -> LinearSearch(executor) + "BinarySearch" -> BinarySearch(executor) + "RestrictionSearch" -> when (searchStrategy){ + "FullSearch" -> composeSearchRestrictionStrategy(executor, FullSearch(executor), results, restrictions) + "LinearSearch" -> composeSearchRestrictionStrategy(executor, LinearSearch(executor), results, restrictions) + "BinarySearch" -> composeSearchRestrictionStrategy(executor, BinarySearch(executor), results, restrictions) + else -> throw IllegalArgumentException("Search Strategy $searchStrategy for RestrictionSearch not found") + } + "InitialGuessSearch" -> when (guessStrategy){ + "PrevResourceMinGuess" -> InitialGuessSearchStrategy(executor, PrevInstanceOptGuess(), results) + else -> throw IllegalArgumentException("Guess Strategy $guessStrategy not found") + } + else -> throw IllegalArgumentException("Search Strategy not found") + } + + return strategy + } + + /** + * Create a [RestrictionStrategy]. + * + * @param results The [Results] saves the state of the Theodolite benchmark run. + * @param restrictionStrings Specifies the list of [RestrictionStrategy] that are used to restrict the amount + * of Resource for a fixed load or resource (depending on the metric). + * Must equal the string 'LowerBound'. + * + * @throws IllegalArgumentException if param searchStrategyString was not one of the allowed options. + */ + private fun createRestrictionStrategy(results: Results, restrictionStrings: List<String>): Set<RestrictionStrategy> { + return restrictionStrings + .map { restriction -> + when (restriction) { + "LowerBound" -> LowerBoundRestriction(results) + else -> throw IllegalArgumentException("Restriction Strategy $restrictionStrings not found") + } + }.toSet() + } + + /** + * Create a RestrictionSearch, if the provided restriction list is not empty. Otherwise just return the given + * searchStrategy. + * + * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments. + * @param searchStrategy The [SearchStrategy] to use. + * @param results The [Results] saves the state of the Theodolite benchmark run. + * @param restrictions The [RestrictionStrategy]'s to use. + */ + private fun composeSearchRestrictionStrategy(executor: ExperimentRunner, searchStrategy: SearchStrategy, + results: Results, restrictions: List<String>): SearchStrategy { + if(restrictions.isNotEmpty()){ + return RestrictionSearch(executor,searchStrategy,createRestrictionStrategy(results, restrictions)) + } + return searchStrategy + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/GuessStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/GuessStrategy.kt new file mode 100644 index 0000000000000000000000000000000000000000..6ab5c1b6d10da318c4b5b3f24d6cc521ff247e79 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/GuessStrategy.kt @@ -0,0 +1,22 @@ +package rocks.theodolite.core.strategies.guessstrategy + +import io.quarkus.runtime.annotations.RegisterForReflection + +/** + * Base class for the implementation of Guess strategies. Guess strategies are strategies to determine the resource + * demand (demand metric) or load (capacity metric) we start with in our initial guess search strategy. + */ + +@RegisterForReflection +abstract class GuessStrategy { + /** + * Computing the resource demand (demand metric) or load (capacity metric) for the initial guess search strategy + * to start with. + * + * @param valuesToCheck List of all possible resources/loads. + * @param lastOptValue Previous minimal/maximal resource/load value for the given load/resource. + * + * @return the resource/load to start the initial guess search strategy with or null + */ + abstract fun firstGuess(valuesToCheck: List<Int>, lastOptValue: Int?): Int? +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/PrevInstanceOptGuess.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/PrevInstanceOptGuess.kt new file mode 100644 index 0000000000000000000000000000000000000000..3b2d7b1b0e6c4133b939742a83afc55fabb7b101 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/guessstrategy/PrevInstanceOptGuess.kt @@ -0,0 +1,28 @@ +package rocks.theodolite.core.strategies.guessstrategy + + +/** + * [PrevInstanceOptGuess] is a [GuessStrategy] that implements the function [firstGuess], + * where it returns the optimal result of the previous run. + */ + +class PrevInstanceOptGuess() : GuessStrategy(){ + + /** + * If the metric is + * + * - "demand", [valuesToCheck] is a List of resources and [lastOptValue] a resource value. + * - "capacity", [valuesToCheck] is a List of loads and [lastOptValue] a load value. + * + * @param valuesToCheck List of all possible resources/loads. + * @param lastOptValue Previous minimal/maximal resource/load value for the given load/resource. + * + * @return the value of [lastOptValue] if given otherwise the first element of the [valuesToCheck] list or null + */ + override fun firstGuess(valuesToCheck: List<Int>, lastOptValue: Int?): Int? { + + if (lastOptValue != null) return lastOptValue + else if(valuesToCheck.isNotEmpty()) return valuesToCheck[0] + else return null + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestriction.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestriction.kt new file mode 100644 index 0000000000000000000000000000000000000000..2e5a51018fd742abbb18edb1d788a6644e94d2f1 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestriction.kt @@ -0,0 +1,24 @@ +package rocks.theodolite.core.strategies.restrictionstrategy + +import rocks.theodolite.core.Results + +/** + * The [LowerBoundRestriction] sets the lower bound of the resources to be examined in the experiment to the value + * needed to successfully execute the previous smaller load (demand metric), or sets the lower bound of the loads + * to be examined in the experiment to the largest value, which still successfully executed the previous smaller + * resource (capacity metric). + * + * @param results [Result] object used as a basis to restrict the resources. + */ +class LowerBoundRestriction(results: Results) : RestrictionStrategy(results) { + + override fun apply(xValue: Int, yValues: List<Int>): List<Int> { + val maxXValue: Int? = this.results.getMaxBenchmarkedXDimensionValue(xValue) + var lowerBound: Int? = this.results.getOptYDimensionValue(maxXValue) + if (lowerBound == null) { + lowerBound = yValues[0] + } + return yValues.filter { x -> x >= lowerBound } + } + +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/RestrictionStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/RestrictionStrategy.kt new file mode 100644 index 0000000000000000000000000000000000000000..16532c32e2c9c64ac69d1c5ed32f6ec0d3345747 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/RestrictionStrategy.kt @@ -0,0 +1,24 @@ +package rocks.theodolite.core.strategies.restrictionstrategy + +import io.quarkus.runtime.annotations.RegisterForReflection +import rocks.theodolite.core.Results + +/** + * A 'Restriction Strategy' restricts a list of resources or loads depending on the metric based on the current + * results of all previously performed benchmarks. + * + * @param results the [Results] object + */ +@RegisterForReflection +abstract class RestrictionStrategy(val results: Results) { + /** + * Apply the restriction of the given resource list for the given load based on the results object (demand metric), + * or apply the restriction of the given load list for the given resource based on the results object (capacity metric). + * + * @param xValue The value to be examined in the experiment, can be load (demand metric) or resource (capacity metric). + * @param yValues List of values to be restricted, can be resources (demand metric) or loads (capacity metric). + * @return Returns a list containing only elements that have not been filtered out by the + * restriction (possibly empty). + */ + abstract fun apply(xValue: Int, yValues: List<Int>): List<Int> +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/BinarySearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/BinarySearch.kt new file mode 100644 index 0000000000000000000000000000000000000000..7c339c449e85a0fa73484d60a455016931cee473 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/BinarySearch.kt @@ -0,0 +1,108 @@ +package rocks.theodolite.core.strategies.searchstrategy + +import mu.KotlinLogging +import rocks.theodolite.core.ExperimentRunner + +private val logger = KotlinLogging.logger {} + +/** + * Binary-search-like implementation for determining the smallest suitable number of instances. + * + * @param experimentRunner Benchmark executor which runs the individual benchmarks. + */ +class BinarySearch(experimentRunner: ExperimentRunner) : SearchStrategy(experimentRunner) { + override fun findSuitableResource(load: Int, resources: List<Int>): Int? { + val result = binarySearchDemand(load, resources, 0, resources.size - 1) + if (result == -1) { + return null + } + return resources[result] + } + + override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? { + val result = binarySearchCapacity(resource, loads, 0, loads.size - 1) + if (result == -1) { + return null + } + return loads[result] + } + + /** + * Apply binary search for the demand metric. + * + * @param load the load to perform experiments for. + * @param resources the list of resources in which binary search is performed. + * @param lower lower bound for binary search (inclusive). + * @param upper upper bound for binary search (inclusive). + */ + private fun binarySearchDemand(load: Int, resources: List<Int>, lower: Int, upper: Int): Int { + if (lower > upper) { + throw IllegalArgumentException() + } + // special case: length == 1, so lower and upper bounds are the same + if (lower == upper) { + val res = resources[lower] + logger.info { "Running experiment with load '$load' and resource '$res'" } + if (this.experimentRunner.runExperiment(load, res)) return lower + else { + if (lower + 1 == resources.size) return -1 + return lower + 1 + } + } else { + // apply binary search for a list with + // length >= 2 and adjust upper and lower depending on the result for `resources[mid]` + val mid = (upper + lower) / 2 + val res = resources[mid] + logger.info { "Running experiment with load '$load' and resource '$res'" } + if (this.experimentRunner.runExperiment(load, res)) { + // case length = 2 + if (mid == lower) { + return lower + } + return binarySearchDemand(load, resources, lower, mid - 1) + } else { + return binarySearchDemand(load, resources, mid + 1, upper) + } + } + } + + + /** + * Apply binary search for the capacity metric. + * + * @param resource the resource to perform experiments for. + * @param loads the list of loads in which binary search is performed. + * @param lower lower bound for binary search (inclusive). + * @param upper upper bound for binary search (inclusive). + */ + private fun binarySearchCapacity(resource: Int, loads: List<Int>, lower: Int, upper: Int): Int { + if (lower > upper) { + throw IllegalArgumentException() + } + // length = 1, so lower and upper bounds are the same + if (lower == upper) { + val load = loads[lower] + logger.info { "Running experiment with load '$load' and resource '$resource'" } + if (this.experimentRunner.runExperiment(load, resource)) return lower + else { + if (lower + 1 == loads.size) return -1 + return lower - 1 + } + } else { + // apply binary search for a list with + // length > 2 and adjust upper and lower depending on the result for `resources[mid]` + val mid = (upper + lower + 1) / 2 //round to next int + val load = loads[mid] + logger.info { "Running experiment with load '$load' and resource '$resource'" } + if (this.experimentRunner.runExperiment(load, resource)) { + // length = 2, so since we round down mid is equal to lower + if (mid == upper) { + return upper + } + return binarySearchCapacity(resource, loads, mid + 1, upper) + } else { + return binarySearchCapacity(resource, loads, lower, mid - 1) + } + } + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/FullSearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/FullSearch.kt new file mode 100644 index 0000000000000000000000000000000000000000..7cd1dfe08cfef7ea42f0a663bbc80eb63f8ca9fe --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/FullSearch.kt @@ -0,0 +1,39 @@ +package rocks.theodolite.core.strategies.searchstrategy + +import mu.KotlinLogging +import rocks.theodolite.core.ExperimentRunner + +private val logger = KotlinLogging.logger {} + +/** + * [SearchStrategy] that executes an experiment for a load and a resource list (demand metric) or for a resource and a + * load list (capacity metric) in a linear-search-like fashion, but **without stopping** once the desired + * resource (demand) or load (capacity) is found. + * + * @see LinearSearch for a SearchStrategy that stops once the desired resource (demand) or load (capacity) is found. + * + * @param experimentRunner Benchmark executor which runs the individual benchmarks. + */ +class FullSearch(experimentRunner: ExperimentRunner) : SearchStrategy(experimentRunner) { + + override fun findSuitableResource(load: Int, resources: List<Int>): Int? { + var minimalSuitableResources: Int? = null + for (res in resources) { + logger.info { "Running experiment with load '$load' and resources '$res'" } + val result = this.experimentRunner.runExperiment(load, res) + if (result && minimalSuitableResources == null) { + minimalSuitableResources = res + } + } + return minimalSuitableResources + } + + override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? { + var maxSuitableLoad: Int? = null + for (load in loads) { + logger.info { "Running experiment with resources '$resource' and load '$load'" } + if (this.experimentRunner.runExperiment(load, resource)) maxSuitableLoad = load + } + return maxSuitableLoad + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategy.kt new file mode 100644 index 0000000000000000000000000000000000000000..8d257bb329729cab033e10195e7a9df3260aeeb3 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategy.kt @@ -0,0 +1,133 @@ +package rocks.theodolite.core.strategies.searchstrategy + +import mu.KotlinLogging +import rocks.theodolite.core.strategies.guessstrategy.GuessStrategy +import rocks.theodolite.core.ExperimentRunner +import rocks.theodolite.core.Results + +private val logger = KotlinLogging.logger {} + +/** + * Search strategy implementation for determining the smallest suitable resource demand. + * Starting with a resource amount provided by a guess strategy. + * + * @param experimentRunner Benchmark executor which runs the individual benchmarks. + * @param guessStrategy Strategy that provides us with a guess for the first resource amount. + * @param results current results of all previously performed benchmarks. + */ +class InitialGuessSearchStrategy( + experimentRunner: ExperimentRunner, + private val guessStrategy: GuessStrategy, + private var results: Results +) : SearchStrategy(experimentRunner) { + + override fun findSuitableResource(load: Int, resources: List<Int>): Int? { + + var lastLowestResource : Int? = null + + // Getting the lastLowestResource from results and calling firstGuess() with it + if (!results.isEmpty()) { + val maxLoad: Int? = this.results.getMaxBenchmarkedXDimensionValue(load) + lastLowestResource = this.results.getOptYDimensionValue(maxLoad) + } + lastLowestResource = this.guessStrategy.firstGuess(resources, lastLowestResource) + + if (lastLowestResource != null) { + val resourcesToCheck: List<Int> + val startIndex: Int = resources.indexOf(lastLowestResource) + + logger.info { "Running experiment with load '$load' and resources '$lastLowestResource'" } + + // If the first experiment passes, starting downward linear search + // otherwise starting upward linear search + if (this.experimentRunner.runExperiment(load, lastLowestResource)) { + + resourcesToCheck = resources.subList(0, startIndex).reversed() + if (resourcesToCheck.isEmpty()) return lastLowestResource + + var currentMin: Int = lastLowestResource + for (res in resourcesToCheck) { + + logger.info { "Running experiment with load '$load' and resources '$res'" } + if (this.experimentRunner.runExperiment(load, res)) { + currentMin = res + } + } + return currentMin + } + else { + if (resources.size <= startIndex + 1) { + logger.info{ "No more resources left to check." } + return null + } + resourcesToCheck = resources.subList(startIndex + 1, resources.size) + + for (res in resourcesToCheck) { + + logger.info { "Running experiment with load '$load' and resources '$res'" } + if (this.experimentRunner.runExperiment(load, res)) return res + } + } + } + else { + logger.info { "lastLowestResource was null." } + } + return null + } + + override fun findSuitableLoad(resource: Int, loads: List<Int>): Int?{ + + var lastMaxLoad : Int? = null + + // Getting the lastLowestLoad from results and calling firstGuess() with it + if (!results.isEmpty()) { + val maxResource: Int? = this.results.getMaxBenchmarkedXDimensionValue(resource) + lastMaxLoad = this.results.getOptYDimensionValue(maxResource) + } + lastMaxLoad = this.guessStrategy.firstGuess(loads, lastMaxLoad) + + if (lastMaxLoad != null) { + val loadsToCheck: List<Int> + val startIndex: Int = loads.indexOf(lastMaxLoad) + + logger.info { "Running experiment with resource '$resource' and load '$lastMaxLoad'" } + + // If the first experiment passes, starting upwards linear search + // otherwise starting downward linear search + if (!this.experimentRunner.runExperiment(lastMaxLoad, resource)) { + // downward search + + loadsToCheck = loads.subList(0, startIndex).reversed() + if (loadsToCheck.isNotEmpty()) { + for (load in loadsToCheck) { + + logger.info { "Running experiment with resource '$resource' and load '$load'" } + if (this.experimentRunner.runExperiment(load, resource)) { + return load + } + } + } + } + else { + // upward search + if (loads.size <= startIndex + 1) { + return lastMaxLoad + } + loadsToCheck = loads.subList(startIndex + 1, loads.size) + + var currentMax: Int = lastMaxLoad + for (load in loadsToCheck) { + logger.info { "Running experiment with resource '$resource' and load '$load'" } + if (this.experimentRunner.runExperiment(load, resource)) { + currentMax = load + } + } + return currentMax + } + } + else { + logger.info { "lastMaxLoad was null." } + } + return null + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/LinearSearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/LinearSearch.kt new file mode 100644 index 0000000000000000000000000000000000000000..c3276f05e141d15652012952991a47a1fde30ad4 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/LinearSearch.kt @@ -0,0 +1,34 @@ +package rocks.theodolite.core.strategies.searchstrategy + +import mu.KotlinLogging +import rocks.theodolite.core.ExperimentRunner + +private val logger = KotlinLogging.logger {} + +/** + * Linear-search-like implementation for determining the smallest/biggest suitable number of resources/loads, + * depending on the metric. + * + * @param experimentRunner Benchmark executor which runs the individual benchmarks. + */ +class LinearSearch(experimentRunner: ExperimentRunner) : SearchStrategy(experimentRunner) { + + override fun findSuitableResource(load: Int, resources: List<Int>): Int? { + for (res in resources) { + logger.info { "Running experiment with load '$load' and resources '$res'" } + if (this.experimentRunner.runExperiment(load, res)) return res + } + return null + } + + override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? { + var maxSuitableLoad: Int? = null + for (load in loads) { + logger.info { "Running experiment with resources '$resource' and load '$load'" } + if (this.experimentRunner.runExperiment(load, resource)) { + maxSuitableLoad = load + } else break + } + return maxSuitableLoad + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearch.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearch.kt new file mode 100644 index 0000000000000000000000000000000000000000..703a7de8b9e084b2bb55bc9270b9d07ea6adfe83 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearch.kt @@ -0,0 +1,43 @@ +package rocks.theodolite.core.strategies.searchstrategy + +import io.quarkus.runtime.annotations.RegisterForReflection +import rocks.theodolite.core.strategies.restrictionstrategy.RestrictionStrategy +import rocks.theodolite.core.ExperimentRunner + +/** + * Strategy that combines a SearchStrategy and a set of RestrictionStrategy. + * + * @param experimentRunner Benchmark executor which runs the individual benchmarks. + * @param searchStrategy the [SearchStrategy] that is executed as part of this [RestrictionSearch]. + * @param restrictionStrategies the set of [RestrictionStrategy] that are connected conjunctive to restrict the Resource. + * + */ +@RegisterForReflection +class RestrictionSearch( + experimentRunner: ExperimentRunner, + private val searchStrategy: SearchStrategy, + private val restrictionStrategies: Set<RestrictionStrategy> +) : SearchStrategy(experimentRunner) { + + /** + * Restricting the possible resources and calling findSuitableResource of the given [SearchStrategy]. + */ + override fun findSuitableResource(load: Int, resources: List<Int>): Int? { + var restrictedResources = resources + for (strategy in this.restrictionStrategies) { + restrictedResources = restrictedResources.intersect(strategy.apply(load, resources).toSet()).toList() + } + return this.searchStrategy.findSuitableResource(load, restrictedResources) + } + + /** + * Restricting the possible loads and calling findSuitableLoad of the given [SearchStrategy]. + */ + override fun findSuitableLoad(resource: Int, loads: List<Int>): Int? { + var restrictedLoads = loads + for (strategy in this.restrictionStrategies) { + restrictedLoads = restrictedLoads.intersect(strategy.apply(resource, loads).toSet()).toList() + } + return this.searchStrategy.findSuitableLoad(resource, restrictedLoads) + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/SearchStrategy.kt b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/SearchStrategy.kt new file mode 100644 index 0000000000000000000000000000000000000000..d08581ff70c509f54a9b8e5f972bb3661cb0b8f8 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/core/strategies/searchstrategy/SearchStrategy.kt @@ -0,0 +1,63 @@ +package rocks.theodolite.core.strategies.searchstrategy + +import io.quarkus.runtime.annotations.RegisterForReflection +import rocks.theodolite.core.strategies.Metric +import rocks.theodolite.core.ExperimentRunner + +/** + * Base class for the implementation for SearchStrategies. SearchStrategies determine the smallest suitable number + * of resources/loads for a load/resource (depending on the metric). + * + * @param experimentRunner Benchmark executor which runs the individual benchmarks. + * @param guessStrategy Guess strategy for the initial resource amount in case the InitialGuessStrategy is selected. + * @param results the [Results] object. + */ +@RegisterForReflection +abstract class SearchStrategy(val experimentRunner: ExperimentRunner) { + + + /** + * Calling findSuitableResource or findSuitableLoad for each load/resource depending on the chosen metric. + * + * @param loads List of possible loads for the experiments. + * @param resources List of possible resources for the experiments. + * @param metric The [Metric] for the experiments, either "demand" or "capacity". + */ + fun applySearchStrategyByMetric(loads: List<Int>, resources: List<Int>, metric: Metric) { + + when(metric) { + Metric.DEMAND -> + for (load in loads) { + if (experimentRunner.run.get()) { + this.findSuitableResource(load, resources) + } + } + Metric.CAPACITY -> + for (resource in resources) { + if (experimentRunner.run.get()) { + this.findSuitableLoad(resource, loads) + } + } + } + } + + /** + * Find the smallest suitable resource from the specified resource list for the given load. + * + * @param load the load to be tested. + * @param resources List of all possible resources. + * + * @return suitable resource for the specified load, or null if no suitable resource exists. + */ + abstract fun findSuitableResource(load: Int, resources: List<Int>): Int? + + /** + * Find the biggest suitable load from the specified load list for the given resource amount. + * + * @param resource the resource to be tested. + * @param loads List of all possible loads. + * + * @return suitable load for the specified resource amount, or null if no suitable load exists. + */ + abstract fun findSuitableLoad(resource: Int, loads: List<Int>) : Int? +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Action.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Action.kt new file mode 100644 index 0000000000000000000000000000000000000000..bdabb719672abf2975fdf8a0ad59868bbc6c1edf --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Action.kt @@ -0,0 +1,31 @@ +package rocks.theodolite.kubernetes + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import io.quarkus.runtime.annotations.RegisterForReflection + +@JsonDeserialize +@RegisterForReflection +@JsonInclude(JsonInclude.Include.NON_NULL) +class Action { + + @JsonProperty("exec") + @JsonInclude(JsonInclude.Include.NON_NULL) + var execCommand: ExecCommand? = null + @JsonProperty("delete") + @JsonInclude(JsonInclude.Include.NON_NULL) + var deleteCommand: DeleteCommand? = null + + fun exec(client: NamespacedKubernetesClient) { + return if (execCommand != null) { + execCommand?.exec(client= client) !! + } else if (deleteCommand != null) { + deleteCommand?.exec(client= client ) !! + } else { + throw DeploymentFailedException("Could not execute action. The action type must either be 'exec' or 'delete'.") + } + } + +} diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommand.kt similarity index 98% rename from theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommand.kt index 9f0578f7d1456d823a29049daae6dbe886c95e2a..eefacbea9268f44969fd88d7650d5ddc5e00fb8e 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/ActionCommand.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommand.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import io.fabric8.kubernetes.api.model.Status import io.fabric8.kubernetes.client.KubernetesClientException @@ -7,8 +7,6 @@ import io.fabric8.kubernetes.client.dsl.ExecListener import io.fabric8.kubernetes.client.dsl.ExecWatch import io.fabric8.kubernetes.client.utils.Serialization import mu.KotlinLogging -import theodolite.util.ActionCommandFailedException -import theodolite.util.Configuration import java.io.ByteArrayOutputStream import java.time.Duration import java.util.concurrent.CountDownLatch diff --git a/theodolite/src/main/kotlin/theodolite/util/ActionCommandFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommandFailedException.kt similarity index 76% rename from theodolite/src/main/kotlin/theodolite/util/ActionCommandFailedException.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommandFailedException.kt index c1a8fc401961370d2f07bfffe43f0ae4dc441d25..8472b0cc9b46a952dbeb14eb73093c821cd6ed57 100644 --- a/theodolite/src/main/kotlin/theodolite/util/ActionCommandFailedException.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ActionCommandFailedException.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.kubernetes class ActionCommandFailedException(message: String, e: Exception? = null) : DeploymentFailedException(message,e) { } \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeployment.kt similarity index 93% rename from theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeployment.kt index fd01ecd986775ef704949743fef0d19f5492e9a6..df303b3b85175d6133e8bc9e7a2748cf8c46464c 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkDeployment.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeployment.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes /** * A BenchmarkDeployment contains the necessary infrastructure to execute a benchmark. diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeploymentBuilder.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeploymentBuilder.kt new file mode 100644 index 0000000000000000000000000000000000000000..544f8bd5ae227ca682e688dff9fc9df0efec60c3 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/BenchmarkDeploymentBuilder.kt @@ -0,0 +1,25 @@ +package rocks.theodolite.kubernetes + +import rocks.theodolite.kubernetes.patcher.PatcherDefinition +import rocks.theodolite.kubernetes.util.ConfigurationOverride + +/** + * This interface is needed for test purposes. + */ +interface BenchmarkDeploymentBuilder { + + /** + * Builds a Deployment that can be deployed. + * @return a BenchmarkDeployment. + */ + fun buildDeployment( + load: Int, + loadPatcherDefinitions: List<PatcherDefinition>, + resource: Int, + resourcePatcherDefinitions: List<PatcherDefinition>, + configurationOverrides: List<ConfigurationOverride?>, + loadGenerationDelay: Long, + afterTeardownDelay: Long, + waitForResourcesEnabled: Boolean + ): BenchmarkDeployment +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSet.kt similarity index 96% rename from theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSet.kt index eea5b15cb1db7242328033a1bc46fb224d287bc2..43c478b983d879135b00e6208df8bb36b7978c8f 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/ConfigMapResourceSet.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSet.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.api.model.HasMetadata @@ -6,7 +6,6 @@ import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.client.KubernetesClientException import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.DeploymentFailedException import java.lang.IllegalArgumentException @RegisterForReflection diff --git a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Configuration.kt similarity index 90% rename from theodolite/src/main/kotlin/theodolite/util/Configuration.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Configuration.kt index 0a63cfa84de9e60fba04707372ef884d77a1543b..e28e2a2a7644222f656bdebd05d122cd853ac456 100644 --- a/theodolite/src/main/kotlin/theodolite/util/Configuration.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Configuration.kt @@ -1,6 +1,4 @@ -package theodolite.util - -import theodolite.execution.ExecutionModes +package rocks.theodolite.kubernetes // Defaults private const val DEFAULT_NAMESPACE = "default" diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeleteCommand.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeleteCommand.kt new file mode 100644 index 0000000000000000000000000000000000000000..ef4409e5bdebfa8b232d5ed1080e93571cbaa618 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeleteCommand.kt @@ -0,0 +1,49 @@ +package rocks.theodolite.kubernetes + +import com.fasterxml.jackson.annotation.JsonInclude +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import io.fabric8.kubernetes.client.KubernetesClientException +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import io.quarkus.runtime.annotations.RegisterForReflection +import mu.KotlinLogging + +private val logger = KotlinLogging.logger {} + +@JsonDeserialize +@RegisterForReflection +@JsonInclude(JsonInclude.Include.NON_NULL) +class DeleteCommand { + + lateinit var selector: DeleteActionSelector + + fun exec(client: NamespacedKubernetesClient) { + logger.info { "Deleting all resources with apiVersion ${selector.apiVersion} and Kind ${selector.kind} matching regular expression ${selector.nameRegex}" } + val regExp = selector.nameRegex.toRegex() + val k8sManager = K8sManager(client) + client + .genericKubernetesResources(selector.apiVersion, selector.kind) + .inNamespace(client.namespace) + .list() + .items + .filter { regExp.matches(it.metadata.name) } + .forEach{ + logger.info { "Deleting resource ${it.metadata.name} of Kind ${it.kind} and api/version ${it.apiVersion}." } + try { + k8sManager.remove(it) + } catch (e: KubernetesClientException) { + logger.error { "An error occured when deleting resource ${it.metadata.name} of Kind ${it.kind} and api/version ${it.apiVersion}. Error: ${e.message}"} + } + } + } +} + +@JsonDeserialize +@RegisterForReflection +class DeleteActionSelector { + @JsonInclude(JsonInclude.Include.NON_NULL) + lateinit var apiVersion: String + @JsonInclude(JsonInclude.Include.NON_NULL) + lateinit var kind: String + @JsonInclude(JsonInclude.Include.NON_NULL) + lateinit var nameRegex: String +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeploymentFailedException.kt similarity index 75% rename from theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeploymentFailedException.kt index 9f4caedf3db1e09dca7924bf0035c6ace0b835d7..cde0021255b471354e8513139cad0f6e083f804a 100644 --- a/theodolite/src/main/kotlin/theodolite/util/DeploymentFailedException.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/DeploymentFailedException.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.kubernetes open class DeploymentFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e) diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecCommand.kt similarity index 72% rename from theodolite/src/main/kotlin/theodolite/benchmark/Action.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecCommand.kt index 8bd16d04d6a5e5ef3f362ff7d5611bf73e367a7e..b8ce10efcd3e4fb5ea552aa7f922fd81c5c13656 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/Action.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecCommand.kt @@ -1,28 +1,25 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.ActionCommandFailedException -import theodolite.util.Configuration @JsonDeserialize @RegisterForReflection @JsonInclude(JsonInclude.Include.NON_NULL) -class Action { - - lateinit var selector: ActionSelector - lateinit var exec: Command - +class ExecCommand { + lateinit var selector: ExecActionSelector + lateinit var command: Array<String> + var timeoutSeconds: Long = Configuration.TIMEOUT_SECONDS fun exec(client: NamespacedKubernetesClient) { val exitCode = ActionCommand(client = client) .exec( matchLabels = selector.pod.matchLabels, container = selector.container, - timeout = exec.timeoutSeconds, - command = exec.command - ) + timeout = timeoutSeconds, + command = command + ) if (exitCode != 0){ throw ActionCommandFailedException("Error while executing action, finished with exit code $exitCode") } @@ -31,18 +28,14 @@ class Action { @JsonDeserialize @RegisterForReflection -class ActionSelector { +class ExecActionSelector { + @JsonInclude(JsonInclude.Include.NON_NULL) lateinit var pod: PodSelector + @JsonInclude(JsonInclude.Include.NON_NULL) var container: String = "" } @JsonDeserialize @RegisterForReflection class PodSelector { lateinit var matchLabels: Map<String, String> -} -@JsonDeserialize -@RegisterForReflection -class Command { - lateinit var command: Array<String> - var timeoutSeconds: Long = Configuration.TIMEOUT_SECONDS } \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionFailedException.kt similarity index 75% rename from theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionFailedException.kt index 2e181dad35786d386226f8a57dfffbc2c3966754..8924dd18199e0ff937c783873878c6f245d01ea5 100644 --- a/theodolite/src/main/kotlin/theodolite/util/ExecutionFailedException.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionFailedException.kt @@ -1,3 +1,3 @@ -package theodolite.util +package rocks.theodolite.kubernetes open class ExecutionFailedException(message: String, e: Exception? = null) : TheodoliteException(message,e) diff --git a/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionModes.kt similarity index 74% rename from theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionModes.kt index 370b87e062d942a512e059ee4041dca776376ddf..e8e4b642689c455b7be6c32d0bdedad58861238c 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/ExecutionModes.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExecutionModes.kt @@ -1,4 +1,4 @@ -package theodolite.execution +package rocks.theodolite.kubernetes enum class ExecutionModes(val value: String) { OPERATOR("operator"), diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExperimentRunnerImpl.kt similarity index 52% rename from theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExperimentRunnerImpl.kt index 2e938be3a6e503a5e7e3f94c18a9454e173db5b0..e1ce46ea24fc97bb7b0421b8e3507c8e989d654a 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutorImpl.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ExperimentRunnerImpl.kt @@ -1,57 +1,53 @@ -package theodolite.execution +package rocks.theodolite.kubernetes import io.quarkus.runtime.annotations.RegisterForReflection import mu.KotlinLogging -import theodolite.benchmark.Benchmark -import theodolite.benchmark.BenchmarkExecution -import theodolite.evaluation.AnalysisExecutor -import theodolite.execution.operator.EventCreator -import theodolite.util.* +import rocks.theodolite.core.ExperimentRunner +import rocks.theodolite.core.Results +import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo +import rocks.theodolite.kubernetes.util.ConfigurationOverride +import rocks.theodolite.kubernetes.operator.EventCreator +import rocks.theodolite.kubernetes.slo.AnalysisExecutor +import rocks.theodolite.kubernetes.patcher.PatcherDefinition import java.time.Duration import java.time.Instant private val logger = KotlinLogging.logger {} @RegisterForReflection -class BenchmarkExecutorImpl( - benchmark: Benchmark, +class ExperimentRunnerImpl( results: Results, - executionDuration: Duration, - configurationOverrides: List<ConfigurationOverride?>, - slos: List<BenchmarkExecution.Slo>, - repetitions: Int, - executionId: Int, - loadGenerationDelay: Long, - afterTeardownDelay: Long, - executionName: String -) : BenchmarkExecutor( - benchmark, - results, - executionDuration, - configurationOverrides, - slos, - repetitions, - executionId, - loadGenerationDelay, - afterTeardownDelay, - executionName + private val benchmarkDeploymentBuilder: BenchmarkDeploymentBuilder, + private val executionDuration: Duration, + private val configurationOverrides: List<ConfigurationOverride?>, + private val slos: List<Slo>, + private val repetitions: Int, + private val executionId: Int, + private val loadGenerationDelay: Long, + private val afterTeardownDelay: Long, + private val executionName: String, + private val loadPatcherDefinitions: List<PatcherDefinition>, + private val resourcePatcherDefinitions: List<PatcherDefinition>, + private val waitForResourcesEnabled: Boolean +) : ExperimentRunner( + results ) { private val eventCreator = EventCreator() private val mode = Configuration.EXECUTION_MODE - override fun runExperiment(load: LoadDimension, res: Resource): Boolean { + override fun runExperiment(load: Int, resource: Int): Boolean { var result = false val executionIntervals: MutableList<Pair<Instant, Instant>> = ArrayList() for (i in 1.rangeTo(repetitions)) { if (this.run.get()) { logger.info { "Run repetition $i/$repetitions" } - executionIntervals.add(runSingleExperiment(load, res)) + executionIntervals.add(runSingleExperiment( + load, resource)) } else { break } } - /** * Analyse the experiment, if [run] is true, otherwise the experiment was canceled by the user. */ @@ -60,41 +56,44 @@ class BenchmarkExecutorImpl( AnalysisExecutor(slo = it, executionId = executionId) .analyze( load = load, - res = res, - executionIntervals = executionIntervals + resource = resource, + executionIntervals = executionIntervals, + metric = this.results.metric ) } result = (false !in experimentResults) - this.results.setResult(Pair(load, res), result) - } - - if(!this.run.get()) { + this.results.setResult(Pair(load, resource), result) + } else { throw ExecutionFailedException("The execution was interrupted") } - return result } - private fun runSingleExperiment(load: LoadDimension, res: Resource): Pair<Instant, Instant> { - val benchmarkDeployment = benchmark.buildDeployment( + private fun runSingleExperiment(load: Int, resource: Int): Pair<Instant, Instant> { + val benchmarkDeployment = benchmarkDeploymentBuilder.buildDeployment( load, - res, + this.loadPatcherDefinitions, + resource, + this.resourcePatcherDefinitions, this.configurationOverrides, this.loadGenerationDelay, - this.afterTeardownDelay + this.afterTeardownDelay, + this.waitForResourcesEnabled ) - val from = Instant.now() + val from: Instant try { benchmarkDeployment.setup() + from = Instant.now() + this.waitAndLog() if (mode == ExecutionModes.OPERATOR.value) { eventCreator.createEvent( executionName = executionName, type = "NORMAL", reason = "Start experiment", - message = "load: ${load.get()}, resources: ${res.get()}") + message = "load: $load, resources: $resource") } } catch (e: Exception) { this.run.set(false) @@ -104,7 +103,7 @@ class BenchmarkExecutorImpl( executionName = executionName, type = "WARNING", reason = "Start experiment failed", - message = "load: ${load.get()}, resources: ${res.get()}") + message = "load: $load, resources: $resource") } throw ExecutionFailedException("Error during setup the experiment", e) } @@ -130,4 +129,25 @@ class BenchmarkExecutorImpl( } return Pair(from, to) } + + /** + * Wait while the benchmark is running and log the number of minutes executed every 1 minute. + */ + fun waitAndLog() { + logger.info { "Execution of a new experiment started." } + + var secondsRunning = 0L + + while (run.get() && secondsRunning < executionDuration.toSeconds()) { + secondsRunning++ + Thread.sleep(Duration.ofSeconds(1).toMillis()) + + if ((secondsRunning % 60) == 0L) { + logger.info { "Executed: ${secondsRunning / 60} minutes." } + } + } + + logger.debug { "Executor shutdown gracefully." } + + } } \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSet.kt similarity index 96% rename from theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSet.kt index e95a637ab88f11902062de73b0c34603b08aded3..44dacc044e2af477814be0399d23a5b14818bcee 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/FileSystemResourceSet.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSet.kt @@ -1,11 +1,10 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.api.model.HasMetadata import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.DeploymentFailedException import java.io.BufferedReader import java.io.FileInputStream import java.io.FileNotFoundException diff --git a/theodolite/src/main/kotlin/theodolite/k8s/K8sContextFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sContextFactory.kt similarity index 96% rename from theodolite/src/main/kotlin/theodolite/k8s/K8sContextFactory.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sContextFactory.kt index 38224f26a38a241e92b38e8b92a7fa5b4e198f5e..880449d1952247bd7bf1784e083acc14ee59fea5 100644 --- a/theodolite/src/main/kotlin/theodolite/k8s/K8sContextFactory.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sContextFactory.kt @@ -1,4 +1,4 @@ -package theodolite.k8s +package rocks.theodolite.kubernetes import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sManager.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..7856451edf4c31d668288f618fcee46b7246a619 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/K8sManager.kt @@ -0,0 +1,51 @@ +package rocks.theodolite.kubernetes + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import mu.KotlinLogging + +private val logger = KotlinLogging.logger {} + +/** + * This class is used to deploy or remove different Kubernetes resources. + * Supports: Deployments, Services, ConfigMaps, StatefulSets, and CustomResources. + * @param client KubernetesClient used to deploy or remove. + */ +class K8sManager(private val client: NamespacedKubernetesClient) { + + /** + * Deploys different k8s resources using the client. + * @throws IllegalArgumentException if KubernetesResource not supported. + */ + fun deploy(resource: HasMetadata) { + client.resource(resource).createOrReplace() + } + + /** + * Removes different k8s resources using the client. + * @throws KubernetesClientException if an error occurs in the underlying NamespacedKubernetesClient when deleting the resource. + */ + fun remove(resource: HasMetadata, blockUntilDeleted: Boolean = true) { + client.resource(resource).delete() + if(blockUntilDeleted) { + when (resource) { + is Deployment -> { + ResourceByLabelHandler(client = client) + .blockUntilPodsDeleted( + matchLabels = resource.spec.selector.matchLabels + ) + logger.info { "Deployment '${resource.metadata.name}' deleted." } + } + is StatefulSet -> { + ResourceByLabelHandler(client = client) + .blockUntilPodsDeleted( + matchLabels = resource.spec.selector.matchLabels + ) + logger.info { "StatefulSet '$resource.metadata.name' deleted." } + } + } + } + } +} diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeployment.kt similarity index 74% rename from theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeployment.kt index b30032c524b1e421301e0e9d1ffe83772b43d900..28ac651a043134d061123956cea0cfc6d9535ce6 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmarkDeployment.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeployment.kt @@ -1,15 +1,16 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import io.fabric8.kubernetes.api.model.HasMetadata import io.fabric8.kubernetes.api.model.KubernetesResource +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.quarkus.runtime.annotations.RegisterForReflection import mu.KotlinLogging import org.apache.kafka.clients.admin.NewTopic -import theodolite.k8s.K8sManager -import theodolite.k8s.ResourceByLabelHandler -import theodolite.k8s.TopicManager -import theodolite.util.KafkaConfig +import rocks.theodolite.kubernetes.kafka.TopicManager +import rocks.theodolite.kubernetes.model.crd.KafkaConfig +import theodolite.benchmark.RolloutManager import java.time.Duration private val logger = KotlinLogging.logger {} @@ -28,6 +29,7 @@ class KubernetesBenchmarkDeployment( private val sutAfterActions: List<Action>, private val loadGenBeforeActions: List<Action>, private val loadGenAfterActions: List<Action>, + private val rolloutMode: Boolean, val appResources: List<HasMetadata>, val loadGenResources: List<HasMetadata>, private val loadGenerationDelay: Long, @@ -41,25 +43,28 @@ class KubernetesBenchmarkDeployment( private val LAG_EXPORTER_POD_LABEL_NAME = "app.kubernetes.io/name" private val LAG_EXPORTER_POD_LABEL_VALUE = "kafka-exporter" + + /** * Setup a [KubernetesBenchmark] using the [TopicManager] and the [K8sManager]: * - Create the needed topics. * - Deploy the needed resources. */ override fun setup() { + val rolloutManager = RolloutManager(rolloutMode, client) if (this.topics.isNotEmpty()) { val kafkaTopics = this.topics .filter { !it.removeOnly } .map { NewTopic(it.name, it.numPartitions, it.replicationFactor) } kafkaController.createTopics(kafkaTopics) } + sutBeforeActions.forEach { it.exec(client = client) } - appResources.forEach { kubernetesManager.deploy(it) } + rolloutManager.rollout(appResources) logger.info { "Wait ${this.loadGenerationDelay} seconds before starting the load generator." } Thread.sleep(Duration.ofSeconds(this.loadGenerationDelay).toMillis()) loadGenBeforeActions.forEach { it.exec(client = client) } - loadGenResources.forEach { kubernetesManager.deploy(it) } - + rolloutManager.rollout(loadGenResources) } /** @@ -69,14 +74,25 @@ class KubernetesBenchmarkDeployment( * - Remove the [KubernetesResource]s. */ override fun teardown() { - loadGenResources.forEach { kubernetesManager.remove(it) } + val podCleaner = ResourceByLabelHandler(client) + loadGenResources.forEach { kubernetesManager.remove(it, false) } loadGenAfterActions.forEach { it.exec(client = client) } - appResources.forEach { kubernetesManager.remove(it) } + appResources.forEach { kubernetesManager.remove(it,false) } sutAfterActions.forEach { it.exec(client = client) } if (this.topics.isNotEmpty()) { kafkaController.removeTopics(this.topics.map { topic -> topic.name }) } - ResourceByLabelHandler(client).removePods( + + listOf(loadGenResources, appResources) + .forEach { + if (it is Deployment) { + podCleaner.blockUntilPodsDeleted(it.spec.selector.matchLabels) + } else if (it is StatefulSet) { + podCleaner.blockUntilPodsDeleted(it.spec.selector.matchLabels) + } + } + + podCleaner.removePods( labelName = LAG_EXPORTER_POD_LABEL_NAME, labelValue = LAG_EXPORTER_POD_LABEL_VALUE ) diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeploymentBuilder.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeploymentBuilder.kt new file mode 100644 index 0000000000000000000000000000000000000000..67fe92afb8aa4c9edda2474fc6307c16c21a41f6 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/KubernetesBenchmarkDeploymentBuilder.kt @@ -0,0 +1,92 @@ +package rocks.theodolite.kubernetes + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import mu.KotlinLogging +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.patcher.PatchHandler +import rocks.theodolite.kubernetes.util.ConfigurationOverride +import rocks.theodolite.kubernetes.patcher.PatcherDefinition + +private val logger = KotlinLogging.logger {} + +class KubernetesBenchmarkDeploymentBuilder (val kubernetesBenchmark: KubernetesBenchmark, + private var client: NamespacedKubernetesClient) + : BenchmarkDeploymentBuilder { + + + /** + * Builds a deployment. + * First loads all required resources and then patches them to the concrete load and resources for the experiment for the demand metric + * or loads all loads and then patches them to the concrete load and resources for the experiment. + * Afterwards patches additional configurations(cluster depending) into the resources (or loads). + * @param load concrete load that will be benchmarked in this experiment (demand metric), or scaled (capacity metric). + * @param resource concrete resource that will be scaled for this experiment (demand metric), or benchmarked (capacity metric). + * @param configurationOverrides + * @return a [BenchmarkDeployment] + */ + override fun buildDeployment( + load: Int, + loadPatcherDefinitions: List<PatcherDefinition>, + resource: Int, + resourcePatcherDefinitions: List<PatcherDefinition>, + configurationOverrides: List<ConfigurationOverride?>, + loadGenerationDelay: Long, + afterTeardownDelay: Long, + waitForResourcesEnabled: Boolean + ): BenchmarkDeployment { + logger.info { "Using ${this.client.namespace} as namespace." } + + val appResources = loadKubernetesResources(kubernetesBenchmark.sut.resources, this.client).toResourceMap() + val loadGenResources = loadKubernetesResources(kubernetesBenchmark.loadGenerator.resources, this.client).toResourceMap() + + // patch the load dimension the resources + loadPatcherDefinitions.forEach { patcherDefinition -> + loadGenResources[patcherDefinition.resource] = + PatchHandler.patchResource(loadGenResources, patcherDefinition, load.toString()) + } + resourcePatcherDefinitions.forEach { patcherDefinition -> + appResources[patcherDefinition.resource] = + PatchHandler.patchResource(appResources, patcherDefinition, resource.toString()) + } + + // Patch the given overrides + configurationOverrides.forEach { override -> + override?.let { + if (appResources.keys.contains(it.patcher.resource)) { + appResources[it.patcher.resource] = + PatchHandler.patchResource(appResources, override.patcher, override.value) + } else { + loadGenResources[it.patcher.resource] = + PatchHandler.patchResource(loadGenResources, override.patcher, override.value) + } + } + } + + val kafkaConfig = kubernetesBenchmark.kafkaConfig + + return KubernetesBenchmarkDeployment( + sutBeforeActions = kubernetesBenchmark.sut.beforeActions, + sutAfterActions = kubernetesBenchmark.sut.afterActions, + loadGenBeforeActions = kubernetesBenchmark.loadGenerator.beforeActions, + loadGenAfterActions = kubernetesBenchmark.loadGenerator.afterActions, + appResources = appResources.toList().flatMap { it.second }, + loadGenResources = loadGenResources.toList().flatMap { it.second }, + loadGenerationDelay = loadGenerationDelay, + afterTeardownDelay = afterTeardownDelay, + kafkaConfig = if (kafkaConfig != null) mapOf("bootstrap.servers" to kafkaConfig.bootstrapServer) else mapOf(), + topics = kafkaConfig?.topics ?: listOf(), + client = this.client, + rolloutMode = waitForResourcesEnabled + ) + } + +} + +private fun Collection<Pair<String, HasMetadata>>.toResourceMap(): MutableMap<String, List<HasMetadata>> { + return this.toMap() + .toMutableMap() + .map { Pair(it.key, listOf(it.value)) } + .toMap() + .toMutableMap() +} diff --git a/theodolite/src/main/kotlin/theodolite/execution/Main.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Main.kt similarity index 57% rename from theodolite/src/main/kotlin/theodolite/execution/Main.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Main.kt index 17b3d4e7b86f9e430abfb6093e79aa7865cd5923..cbd7c3106b39c4571d559d4071cd4ac16e180bc8 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/Main.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Main.kt @@ -1,9 +1,11 @@ -package theodolite.execution +package rocks.theodolite.kubernetes +import io.fabric8.kubernetes.client.DefaultKubernetesClient +import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.quarkus.runtime.annotations.QuarkusMain import mu.KotlinLogging -import theodolite.execution.operator.TheodoliteOperator -import theodolite.util.Configuration +import rocks.theodolite.kubernetes.operator.TheodoliteOperator +import rocks.theodolite.kubernetes.standalone.TheodoliteStandalone import kotlin.system.exitProcess private val logger = KotlinLogging.logger {} @@ -17,9 +19,12 @@ object Main { val mode = Configuration.EXECUTION_MODE logger.info { "Start Theodolite with mode $mode" } + val namespace = Configuration.NAMESPACE + val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace) + when (mode.lowercase()) { - ExecutionModes.STANDALONE.value -> TheodoliteStandalone().start() - ExecutionModes.OPERATOR.value -> TheodoliteOperator().start() + ExecutionModes.STANDALONE.value -> TheodoliteStandalone(client).start() + ExecutionModes.OPERATOR.value -> TheodoliteOperator(client).start() else -> { logger.error { "MODE $mode not found" } exitProcess(1) diff --git a/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceByLabelHandler.kt similarity index 99% rename from theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceByLabelHandler.kt index 518b8eae211dd064e3c12b0713382bf3b12bb1ba..c65235f5fef304a7644399573380b4147704cb6c 100644 --- a/theodolite/src/main/kotlin/theodolite/k8s/ResourceByLabelHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceByLabelHandler.kt @@ -1,4 +1,4 @@ -package theodolite.k8s +package rocks.theodolite.kubernetes import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.dsl.base.CustomResourceDefinitionContext diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSet.kt similarity index 92% rename from theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSet.kt index 19fc85845ae99c7a5e4f7369db4b6cd383c3131b..9910d0ac89a9b423047f4f20f07a8015cbb24f9a 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSet.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSet.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.api.model.KubernetesResource diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSets.kt similarity index 56% rename from theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSets.kt index 0626a6e24369348d50b60fbb555665c58dd17281..f57835a1e2459b0ce8989a4f1c745cc272e5f1e9 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/ResourceSets.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/ResourceSets.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import com.fasterxml.jackson.annotation.JsonInclude import com.fasterxml.jackson.annotation.JsonProperty @@ -7,11 +7,17 @@ import io.fabric8.kubernetes.api.model.HasMetadata import io.fabric8.kubernetes.api.model.KubernetesResource import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.DeploymentFailedException + +/** + * Loads [KubernetesResource]s. + */ +fun loadKubernetesResources(resourceSet: List<ResourceSets>, client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> { + return resourceSet.flatMap { it.loadResourceSet(client) } +} @JsonDeserialize @RegisterForReflection -class ResourceSets: KubernetesResource { +class ResourceSets : KubernetesResource { @JsonProperty("configMap") @JsonInclude(JsonInclude.Include.NON_NULL) var configMap: ConfigMapResourceSet? = null @@ -20,14 +26,14 @@ class ResourceSets: KubernetesResource { @JsonInclude(JsonInclude.Include.NON_NULL) var fileSystem: FileSystemResourceSet? = null + fun loadResourceSet(client: NamespacedKubernetesClient): Collection<Pair<String, HasMetadata>> { - // TODO Find out whether field access (::configMap) is really what we want to do here (see #362) - return if (::configMap != null) { - configMap?.getResourceSet(client= client) !! - } else if (::fileSystem != null) { - fileSystem?.getResourceSet(client= client ) !! - } else { - throw DeploymentFailedException("Could not load resourceSet.") - } + return if (this.configMap != null) { + configMap?.getResourceSet(client = client)!! + } else if (this.fileSystem != null) { + fileSystem?.getResourceSet(client = client)!! + } else { + throw DeploymentFailedException("Could not load resourceSet.") + } } } \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/RolloutManager.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/RolloutManager.kt new file mode 100644 index 0000000000000000000000000000000000000000..f760bb407ec2a6c4ab2ee08d3521ad72d12dd25d --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/RolloutManager.kt @@ -0,0 +1,39 @@ +package theodolite.benchmark + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.DaemonSet +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.ReplicaSet +import io.fabric8.kubernetes.api.model.apps.StatefulSet +import io.fabric8.kubernetes.api.model.batch.v1.Job +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import rocks.theodolite.kubernetes.K8sManager + +private var SLEEP_TIME_MS = 500L +class RolloutManager(private val blockUntilResourcesReady: Boolean, private val client: NamespacedKubernetesClient) { + + fun rollout(resources: List<HasMetadata>) { + resources + .forEach { K8sManager(client).deploy(it) } + + if (blockUntilResourcesReady) { + resources + .forEach { + when (it) { + is Deployment -> waitFor { client.apps().deployments().withName(it.metadata.name).isReady } + is StatefulSet -> waitFor { client.apps().statefulSets().withName(it.metadata.name).isReady } + is DaemonSet -> waitFor { client.apps().daemonSets().withName(it.metadata.name).isReady } + is ReplicaSet -> waitFor { client.apps().replicaSets().withName(it.metadata.name).isReady } + is Job -> waitFor { client.batch().v1().cronjobs().withName(it.metadata.name).isReady } + } + } + } + } + + private fun waitFor(isResourceReady: () -> Boolean) { + while (!isResourceReady()) { + Thread.sleep(SLEEP_TIME_MS) + } + } + +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Shutdown.kt similarity index 58% rename from theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Shutdown.kt index 29ac39c122f68636e08c6c5ecd5a6c01751edafb..e970c84d345031b79f8afeedf56591e071bb154f 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/Shutdown.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/Shutdown.kt @@ -1,10 +1,9 @@ -package theodolite.execution +package rocks.theodolite.kubernetes +import io.fabric8.kubernetes.client.NamespacedKubernetesClient import mu.KotlinLogging -import theodolite.benchmark.BenchmarkExecution -import theodolite.benchmark.KubernetesBenchmark -import theodolite.util.LoadDimension -import theodolite.util.Resource +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.KubernetesBenchmark private val logger = KotlinLogging.logger {} @@ -14,7 +13,9 @@ private val logger = KotlinLogging.logger {} * @property benchmarkExecution * @property benchmark */ -class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val benchmark: KubernetesBenchmark) { +class Shutdown(private val benchmarkExecution: BenchmarkExecution, + private val benchmark: KubernetesBenchmark, + private val client: NamespacedKubernetesClient) { /** * Run @@ -22,15 +23,19 @@ class Shutdown(private val benchmarkExecution: BenchmarkExecution, private val b */ fun run() { // Build Configuration to teardown + val benchmarkDeploymentBuilder = KubernetesBenchmarkDeploymentBuilder(benchmark, this.client) try { logger.info { "Received shutdown signal -> Shutting down" } val deployment = - benchmark.buildDeployment( - load = LoadDimension(0, emptyList()), - res = Resource(0, emptyList()), + benchmarkDeploymentBuilder.buildDeployment( + load = 0, + loadPatcherDefinitions = emptyList(), + resource = 0, + resourcePatcherDefinitions = emptyList(), configurationOverrides = benchmarkExecution.configOverrides, loadGenerationDelay = 0L, - afterTeardownDelay = 5L + afterTeardownDelay = 5L, + waitForResourcesEnabled = benchmark.waitForResourcesEnabled ) deployment.teardown() logger.info { "Finished teardown of all benchmark resources." } diff --git a/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteException.kt similarity index 72% rename from theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteException.kt index fc7453bae6aaa4c5c526eee72c006562ea887eb5..6a4374c3e3c9435c498c8e15e8c5efaa01fd89cd 100644 --- a/theodolite/src/main/kotlin/theodolite/util/TheodoliteException.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteException.kt @@ -1,3 +1,3 @@ -package theodolite.util +package rocks.theodolite.kubernetes open class TheodoliteException (message: String, e: Exception? = null) : Exception(message,e) \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteExecutor.kt new file mode 100644 index 0000000000000000000000000000000000000000..69615522ba9bbd5ef0944528eacbf1dce318caf9 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/TheodoliteExecutor.kt @@ -0,0 +1,169 @@ +package rocks.theodolite.kubernetes + +import io.fabric8.kubernetes.client.NamespacedKubernetesClient +import mu.KotlinLogging +import rocks.theodolite.core.ExecutionRunner +import rocks.theodolite.core.ExperimentRunner +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.patcher.PatcherDefinitionFactory +import rocks.theodolite.core.strategies.Metric +import rocks.theodolite.core.strategies.StrategyFactory +import rocks.theodolite.core.Config +import rocks.theodolite.core.IOHandler +import rocks.theodolite.core.Results +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.slo.SloFactory +import java.io.File +import java.time.Duration + + +private val logger = KotlinLogging.logger {} + +/** + * The Theodolite executor runs all the experiments defined with the given execution and benchmark configuration. + * + * @property benchmarkExecution Configuration of a execution + * @property benchmark Configuration of a benchmark + * @constructor Create empty Theodolite executor + */ +class TheodoliteExecutor( + private val benchmarkExecution: BenchmarkExecution, + private val benchmark: KubernetesBenchmark, + private val client: NamespacedKubernetesClient +) { + /** + * An executor object, configured with the specified benchmark, evaluation method, experiment duration + * and overrides which are given in the execution. + */ + lateinit var experimentRunner: ExperimentRunner + + /** + * Creates all required components to start Theodolite. + * + * @return a [Config], that contains a list of LoadDimension s, + * a list of Resource s , and the [restrictionSearch]. + * The [SearchStrategy] is configured and able to find the minimum required resource for the given load. + */ + private fun buildConfig(): Config { + val results = Results(Metric.from(benchmarkExecution.execution.metric)) + val strategyFactory = StrategyFactory() + + val executionDuration = Duration.ofSeconds(benchmarkExecution.execution.duration) + + val resourcePatcherDefinition = + PatcherDefinitionFactory().createPatcherDefinition( + benchmarkExecution.resources.resourceType, + this.benchmark.resourceTypes + ) + + val loadDimensionPatcherDefinition = + PatcherDefinitionFactory().createPatcherDefinition( + benchmarkExecution.loads.loadType, + this.benchmark.loadTypes + ) + + val slos = SloFactory().createSlos(this.benchmarkExecution, this.benchmark) + + experimentRunner = + ExperimentRunnerImpl( + benchmarkDeploymentBuilder = KubernetesBenchmarkDeploymentBuilder(this.benchmark,this.client), + results = results, + executionDuration = executionDuration, + configurationOverrides = benchmarkExecution.configOverrides, + slos = slos, + repetitions = benchmarkExecution.execution.repetitions, + executionId = benchmarkExecution.executionId, + loadGenerationDelay = benchmarkExecution.execution.loadGenerationDelay, + afterTeardownDelay = benchmarkExecution.execution.afterTeardownDelay, + executionName = benchmarkExecution.name, + loadPatcherDefinitions = loadDimensionPatcherDefinition, + resourcePatcherDefinitions = resourcePatcherDefinition, + waitForResourcesEnabled = this.benchmark.waitForResourcesEnabled + ) + + if (benchmarkExecution.loads.loadValues != benchmarkExecution.loads.loadValues.sorted()) { + benchmarkExecution.loads.loadValues = benchmarkExecution.loads.loadValues.sorted() + logger.info { + "Load values are not sorted correctly, Theodolite sorts them in ascending order." + + "New order is: ${benchmarkExecution.loads.loadValues}" + } + } + + if (benchmarkExecution.resources.resourceValues != benchmarkExecution.resources.resourceValues.sorted()) { + benchmarkExecution.resources.resourceValues = benchmarkExecution.resources.resourceValues.sorted() + logger.info { + "Load values are not sorted correctly, Theodolite sorts them in ascending order." + + "New order is: ${benchmarkExecution.resources.resourceValues}" + } + } + + return Config( + loads = benchmarkExecution.loads.loadValues, + resources = benchmarkExecution.resources.resourceValues, + searchStrategy = strategyFactory.createSearchStrategy(experimentRunner, benchmarkExecution.execution.strategy.name, + benchmarkExecution.execution.strategy.searchStrategy, benchmarkExecution.execution.strategy.restrictions, + benchmarkExecution.execution.strategy.guessStrategy, results), + metric = Metric.from(benchmarkExecution.execution.metric) + ) + } + + /** + * Sets up the Infrastructure, increments the executionId, calls the [ExecutionRunner] that runs + * all experiments which are specified in the corresponding execution and benchmark objects. + */ + fun setupAndRunExecution() { + setupInfrastructure() + + val ioHandler = IOHandler() + val resultsFolder = ioHandler.getResultFolderURL() + this.benchmarkExecution.executionId = getAndIncrementExecutionID(resultsFolder + "expID.txt") + ioHandler.writeToJSONFile(this.benchmarkExecution, "${resultsFolder}exp${this.benchmarkExecution.executionId}-execution-configuration") + ioHandler.writeToJSONFile( + benchmark, + "${resultsFolder}exp${this.benchmarkExecution.executionId}-benchmark-configuration" + ) + + val config = buildConfig() + + val executionRunner = ExecutionRunner(config.searchStrategy, config.resources, config.loads,config.metric, + this.benchmarkExecution.executionId) + + executionRunner.run() + + teardownInfrastructure() + } + + private fun setupInfrastructure() { + benchmark.infrastructure.beforeActions.forEach { it.exec(client = client) } + val kubernetesManager = K8sManager(this.client) + loadKubernetesResources(benchmark.infrastructure.resources, this.client) + .map { it.second } + .forEach { kubernetesManager.deploy(it) } + } + + private fun teardownInfrastructure() { + val kubernetesManager = K8sManager(this.client) + loadKubernetesResources(benchmark.infrastructure.resources, this.client) + .map { it.second } + .forEach { kubernetesManager.remove(it) } + benchmark.infrastructure.afterActions.forEach { it.exec(client = client) } + } + + private fun getAndIncrementExecutionID(fileURL: String): Int { + val ioHandler = IOHandler() + var executionID = 0 + if (File(fileURL).exists()) { + executionID = ioHandler.readFileAsString(fileURL).toInt() + 1 + } + ioHandler.writeStringToTextFile(fileURL, (executionID).toString()) + return executionID + } + + private fun calculateMetric(xValues: List<Int>, results: Results): List<List<String>> { + return xValues.map { listOf(it.toString(), results.getOptYDimensionValue(it).toString()) } + } + + fun getExecution(): BenchmarkExecution { + return this.benchmarkExecution + } +} diff --git a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/kafka/TopicManager.kt similarity index 98% rename from theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/kafka/TopicManager.kt index ed1e06571d20c53fc82439833c8a31800a48b602..e9a0cb4b3c0863baf54a8dda58b96c81a80af60d 100644 --- a/theodolite/src/main/kotlin/theodolite/k8s/TopicManager.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/kafka/TopicManager.kt @@ -1,4 +1,4 @@ -package theodolite.k8s +package rocks.theodolite.kubernetes.kafka import mu.KotlinLogging import org.apache.kafka.clients.admin.AdminClient diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/BenchmarkExecution.kt similarity index 58% rename from theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/BenchmarkExecution.kt index f2dda487d390c5f771e4f47c0f9c7ebf2cf971e7..167423ec911cd740b0ee0246e8512dde8402f1e9 100644 --- a/theodolite/src/main/kotlin/theodolite/benchmark/BenchmarkExecution.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/BenchmarkExecution.kt @@ -1,9 +1,9 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes.model import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.api.model.KubernetesResource import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.ConfigurationOverride +import rocks.theodolite.kubernetes.util.ConfigurationOverride import kotlin.properties.Delegates /** @@ -12,9 +12,9 @@ import kotlin.properties.Delegates * A BenchmarkExecution consists of: * - A [name]. * - The [benchmark] that should be executed. - * - The [load] that should be checked in the benchmark. + * - The [loads]s that should be checked in the benchmark. * - The [resources] that should be checked in the benchmark. - * - A list of [slos] that are used for the evaluation of the experiments. + * - The [slos] further restrict the Benchmark SLOs for the evaluation of the experiments. * - An [execution] that encapsulates: the strategy, the duration, and the restrictions * for the execution of the benchmark. * - [configOverrides] additional configurations. @@ -28,48 +28,55 @@ class BenchmarkExecution : KubernetesResource { var executionId: Int = 0 lateinit var name: String lateinit var benchmark: String - lateinit var load: LoadDefinition + lateinit var loads: LoadDefinition lateinit var resources: ResourceDefinition - lateinit var slos: List<Slo> + lateinit var slos: List<SloConfiguration> lateinit var execution: Execution lateinit var configOverrides: MutableList<ConfigurationOverride?> /** - * This execution encapsulates the [strategy], the [duration], the [repetitions], and the [restrictions] + * This execution encapsulates the [strategy], the [duration], and the [repetitions], * which are used for the concrete benchmark experiments. */ @JsonDeserialize @RegisterForReflection class Execution : KubernetesResource { - lateinit var strategy: String + var metric = "demand" + lateinit var strategy: Strategy var duration by Delegates.notNull<Long>() var repetitions by Delegates.notNull<Int>() - lateinit var restrictions: List<String> var loadGenerationDelay = 0L var afterTeardownDelay = 5L } /** - * Measurable metric. - * [sloType] determines the type of the metric. - * It is evaluated using the [theodolite.evaluation.ExternalSloChecker] by data measured by Prometheus. - * The evaluation checks if a [threshold] is reached or not. - * [offset] determines the shift in hours by which the start and end timestamps should be shifted. - * The [warmup] determines after which time the metric should be evaluated to avoid starting interferences. - * The [warmup] time unit depends on the Slo: for the lag trend it is in seconds. + * This Strategy encapsulates the [restrictions], [guessStrategy] and [searchStrategy], + * which are used for restricting the resources, the guess Strategy for the + * [theodolite.strategies.searchstrategy.InitialGuessSearchStrategy] and the name of the actual + * [theodolite.strategies.searchstrategy.SearchStrategy] which is used. */ @JsonDeserialize @RegisterForReflection - class Slo : KubernetesResource { - lateinit var sloType: String - lateinit var prometheusUrl: String - var offset by Delegates.notNull<Int>() - lateinit var properties: MutableMap<String, String> + class Strategy : KubernetesResource { + lateinit var name: String + var restrictions = emptyList<String>() + var guessStrategy = "" + var searchStrategy = "" } /** - * Represents a Load that should be created and checked. - * It can be set to [loadValues]. + * Further SLO configurations for the SLOs specified in the Benchmark. + */ + @JsonDeserialize + @RegisterForReflection + class SloConfiguration : KubernetesResource { + lateinit var name: String + var properties: MutableMap<String, String>? = null + } + + /** + * Represents the Loads that should be created and checked if the demand metric is in use or + * represents a Load that can be scaled to [loadValues] if the capacity metric is in use. */ @JsonDeserialize @RegisterForReflection @@ -79,7 +86,8 @@ class BenchmarkExecution : KubernetesResource { } /** - * Represents a resource that can be scaled to [resourceValues]. + * Represents a resource that can be scaled to [resourceValues] if the demand metric is in use or + * represents the Resources that should be created and checked if the capacity metric is in use. */ @JsonDeserialize @RegisterForReflection diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/KubernetesBenchmark.kt new file mode 100644 index 0000000000000000000000000000000000000000..9c1412af7e6a86fbb248e8be7d1a97259a59c8d0 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/KubernetesBenchmark.kt @@ -0,0 +1,77 @@ +package rocks.theodolite.kubernetes.model + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import io.fabric8.kubernetes.api.model.KubernetesResource +import io.quarkus.runtime.annotations.RegisterForReflection +import rocks.theodolite.kubernetes.Action +import rocks.theodolite.kubernetes.ResourceSets +import rocks.theodolite.kubernetes.model.crd.KafkaConfig +import rocks.theodolite.kubernetes.patcher.PatcherDefinition +import kotlin.properties.Delegates + +/** + * Represents a benchmark in Kubernetes. An example for this is the BenchmarkType.yaml + * Contains a of: + * - [name] of the benchmark, + * - [appResource] list of the resources that have to be deployed for the benchmark, + * - [loadGenResource] resource that generates the load, + * - [resourceTypes] types of scaling resources, + * - [loadTypes] types of loads that can be scaled for the benchmark, + * - [kafkaConfig] for the [theodolite.k8s.TopicManager], + * - [namespace] for the client, + * - [path] under which the resource yamls can be found. + * + * This class is used for the parsing(in the [theodolite.execution.TheodoliteStandalone]) and + * for the deserializing in the [theodolite.execution.operator.TheodoliteOperator]. + * @constructor construct an empty Benchmark. + */ +@JsonDeserialize +@RegisterForReflection +class KubernetesBenchmark : KubernetesResource { + lateinit var name: String + var waitForResourcesEnabled = false + lateinit var resourceTypes: List<TypeName> + lateinit var loadTypes: List<TypeName> + lateinit var slos: MutableList<Slo> + var kafkaConfig: KafkaConfig? = null + lateinit var infrastructure: Resources + lateinit var sut: Resources + lateinit var loadGenerator: Resources + + /** + * The TypeName encapsulates a list of [PatcherDefinition] along with a typeName that specifies for what the [PatcherDefinition] should be used. + */ + @RegisterForReflection + @JsonDeserialize + class TypeName { + lateinit var typeName: String + lateinit var patchers: List<PatcherDefinition> + } + + /** + * Measurable metric. + * [sloType] determines the type of the metric. + * It is evaluated using the [theodolite.evaluation.ExternalSloChecker] by data measured by Prometheus. + * The evaluation checks if a [threshold] is reached or not. + * [offset] determines the shift in hours by which the start and end timestamps should be shifted. + * The [warmup] determines after which time the metric should be evaluated to avoid starting interferences. + * The [warmup] time unit depends on the Slo: for the lag trend it is in seconds. + */ + @JsonDeserialize + @RegisterForReflection + class Slo : KubernetesResource { + lateinit var name: String + lateinit var sloType: String + lateinit var prometheusUrl: String + var offset by Delegates.notNull<Int>() + lateinit var properties: MutableMap<String, String> + } + + @JsonDeserialize + @RegisterForReflection + class Resources { + lateinit var resources: List<ResourceSets> + lateinit var beforeActions: List<Action> + lateinit var afterActions: List<Action> + } +} diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRD.kt similarity index 86% rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRD.kt index 0ec6decbdea5e192721a4f9b6d0d85ea65665a5a..f480177e4482ab48df01593fdc10ea459a87ca43 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkCRD.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRD.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.api.model.Namespaced @@ -6,7 +6,7 @@ import io.fabric8.kubernetes.client.CustomResource import io.fabric8.kubernetes.model.annotation.Group import io.fabric8.kubernetes.model.annotation.Kind import io.fabric8.kubernetes.model.annotation.Version -import theodolite.benchmark.KubernetesBenchmark +import rocks.theodolite.kubernetes.model.KubernetesBenchmark @JsonDeserialize @Version("v1") diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkExecutionList.kt similarity index 72% rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkExecutionList.kt index 2b2dcc07f9c37f1712109e3d092f2db0c139e1c8..768cd7c4f7edf2f254905539214177638ad5283c 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkExecutionList.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkExecutionList.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import io.fabric8.kubernetes.client.CustomResourceList diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkState.kt similarity index 77% rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkState.kt index dc2c6f9ba971367c0bb142a54745629eb29c07d5..928a411725f5eaf71839f4b7109b69ff40eb8807 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkState.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkState.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.annotation.JsonValue diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkStatus.kt similarity index 87% rename from theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkStatus.kt index d4a17dbefb6cf3a53d545c32cb18e1d9acd7067f..691e5e1a83da5ccb3897f0b6342ee78ce437ba6b 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/BenchmarkStatus.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkStatus.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.api.model.KubernetesResource diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRD.kt similarity index 86% rename from theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRD.kt index 3be0aaf2a30cd4ef279edd34854eb936cc6e7e7c..df7b0f0c1ca326db21885beb1c714060aa56b251 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionCRD.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRD.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.fabric8.kubernetes.api.model.Namespaced @@ -6,7 +6,7 @@ import io.fabric8.kubernetes.client.CustomResource import io.fabric8.kubernetes.model.annotation.Group import io.fabric8.kubernetes.model.annotation.Kind import io.fabric8.kubernetes.model.annotation.Version -import theodolite.benchmark.BenchmarkExecution +import rocks.theodolite.kubernetes.model.BenchmarkExecution @JsonDeserialize @Version("v1") diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionState.kt similarity index 86% rename from theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionState.kt index 9ce38d9f56a968ccc408966e56609ee4f70570a4..d74d70eb8e91246946923532967534aa46b958f7 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionState.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionState.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.annotation.JsonValue diff --git a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparator.kt similarity index 74% rename from theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparator.kt index 81bf350b58901bc10535f143d5ccdb295b5fe85f..9e859c3e943df4c72a2265941f14ea218b35ab12 100644 --- a/theodolite/src/main/kotlin/theodolite/util/ExecutionStateComparator.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparator.kt @@ -1,7 +1,7 @@ -package theodolite.util +package rocks.theodolite.kubernetes.model.crd -import theodolite.model.crd.ExecutionCRD -import theodolite.model.crd.ExecutionState +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionState class ExecutionStateComparator(private val preferredState: ExecutionState): Comparator<ExecutionCRD> { diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatus.kt similarity index 97% rename from theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatus.kt index 1f843ccf9152676e778bc4ed359776e37205e998..6bec7197ddde61185ca37b3e0e96f471a910a0aa 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/ExecutionStatus.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatus.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.annotation.JsonIgnoreProperties import com.fasterxml.jackson.core.JsonGenerator diff --git a/theodolite/src/main/kotlin/theodolite/util/KafkaConfig.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KafkaConfig.kt similarity index 92% rename from theodolite/src/main/kotlin/theodolite/util/KafkaConfig.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KafkaConfig.kt index 4e72ccb0d86749a6538c26556241ac114ef8d9a4..adde94c5126e370816966e6991670b6d400ba79a 100644 --- a/theodolite/src/main/kotlin/theodolite/util/KafkaConfig.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KafkaConfig.kt @@ -1,8 +1,8 @@ -package theodolite.util +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.KafkaConfig.TopicWrapper +import rocks.theodolite.kubernetes.model.crd.KafkaConfig.TopicWrapper import kotlin.properties.Delegates import kotlin.reflect.KProperty diff --git a/theodolite/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KubernetesBenchmarkList.kt similarity index 72% rename from theodolite/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KubernetesBenchmarkList.kt index 8ad0a493d948bf5f78741052100766dcf6e316ec..be34662bd63b39808099a968ec4b89b5499ef34b 100644 --- a/theodolite/src/main/kotlin/theodolite/model/crd/KubernetesBenchmarkList.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/model/crd/KubernetesBenchmarkList.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import io.fabric8.kubernetes.client.CustomResourceList diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/AbstractStateHandler.kt similarity index 98% rename from theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/AbstractStateHandler.kt index 84343ea7e8d7d420bcf320f36be02c39c41a1945..96593914cf07c427c924a1631a00f76dc3649ed3 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/AbstractStateHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/AbstractStateHandler.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.api.model.HasMetadata import io.fabric8.kubernetes.api.model.KubernetesResourceList diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateChecker.kt similarity index 82% rename from theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateChecker.kt index c20b2ba87e386dc7c0a14245e03bedfb067720e6..c2c7db6cd6c5d6a02132353228714c3a3b19ec80 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateChecker.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateChecker.kt @@ -1,22 +1,24 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.StatefulSet import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.dsl.MixedOperation import io.fabric8.kubernetes.client.dsl.Resource -import theodolite.benchmark.Action -import theodolite.benchmark.ActionSelector -import theodolite.benchmark.KubernetesBenchmark -import theodolite.benchmark.ResourceSets -import theodolite.model.crd.BenchmarkCRD -import theodolite.model.crd.BenchmarkState -import theodolite.model.crd.KubernetesBenchmarkList +import rocks.theodolite.kubernetes.ExecActionSelector +import rocks.theodolite.kubernetes.Action +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.ResourceSets +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD +import rocks.theodolite.kubernetes.model.crd.BenchmarkState +import rocks.theodolite.kubernetes.model.crd.KubernetesBenchmarkList +import rocks.theodolite.kubernetes.loadKubernetesResources + class BenchmarkStateChecker( - private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>, - private val benchmarkStateHandler: BenchmarkStateHandler, - private val client: NamespacedKubernetesClient + private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>, + private val benchmarkStateHandler: BenchmarkStateHandler, + private val client: NamespacedKubernetesClient, ) { @@ -91,7 +93,7 @@ class BenchmarkStateChecker( */ private fun checkIfActionPossible(resourcesSets: List<ResourceSets>, actions: List<Action>): Boolean { return !actions.map { - checkIfResourceIsDeployed(it.selector) || checkIfResourceIsInfrastructure(resourcesSets, it.selector) + it.deleteCommand != null || checkIfResourceIsDeployed(it.execCommand!!.selector) || checkIfResourceIsInfrastructure(resourcesSets, it.execCommand!!.selector) }.contains(false) } @@ -101,7 +103,7 @@ class BenchmarkStateChecker( * @param selector the actionSelector to check * @return true if the required resources are found, else false */ - fun checkIfResourceIsDeployed(selector: ActionSelector): Boolean { + fun checkIfResourceIsDeployed(selector: ExecActionSelector): Boolean { val pods = this.client .pods() .withLabels(selector.pod.matchLabels) @@ -128,8 +130,9 @@ class BenchmarkStateChecker( * @param selector the actionSelector to check * @return true if the required resources are found, else false */ - fun checkIfResourceIsInfrastructure(resourcesSets: List<ResourceSets>, selector: ActionSelector): Boolean { - val resources = resourcesSets.flatMap { it.loadResourceSet(this.client) } + fun checkIfResourceIsInfrastructure(resourcesSets: List<ResourceSets>, selector: ExecActionSelector): Boolean { + val resources = loadKubernetesResources(resourcesSets, this.client) + if (resources.isEmpty()) { return false } @@ -176,9 +179,9 @@ class BenchmarkStateChecker( fun checkResources(benchmark: KubernetesBenchmark): BenchmarkState { return try { val appResources = - benchmark.loadKubernetesResources(resourceSet = benchmark.sut.resources) + loadKubernetesResources(resourceSet = benchmark.sut.resources, this.client) val loadGenResources = - benchmark.loadKubernetesResources(resourceSet = benchmark.loadGenerator.resources) + loadKubernetesResources(resourceSet = benchmark.loadGenerator.resources, this.client) if (appResources.isNotEmpty() && loadGenResources.isNotEmpty()) { BenchmarkState.READY } else { @@ -188,6 +191,8 @@ class BenchmarkStateChecker( BenchmarkState.PENDING } } + + } private fun <K, V> Map<K, V>.containsMatchLabels(matchLabels: Map<V, V>): Boolean { diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateHandler.kt similarity index 80% rename from theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateHandler.kt index 3b46859737d86a34b58a5514c0ae31ae215b9c7d..9a272b43f911bf523adf7c64c5ab34793b7a7dc5 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/BenchmarkStateHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateHandler.kt @@ -1,7 +1,9 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.client.NamespacedKubernetesClient -import theodolite.model.crd.* +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD +import rocks.theodolite.kubernetes.model.crd.BenchmarkState +import rocks.theodolite.kubernetes.model.crd.ExecutionState class BenchmarkStateHandler(val client: NamespacedKubernetesClient) : AbstractStateHandler<BenchmarkCRD>( diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ClusterSetup.kt similarity index 84% rename from theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ClusterSetup.kt index e67be01ea80178b6d6bfb01b32bfd28c111addb9..a84bacb8296d62b8d6863046561dc797443e6084 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/ClusterSetup.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ClusterSetup.kt @@ -1,21 +1,21 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.client.KubernetesClientException import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.dsl.MixedOperation import io.fabric8.kubernetes.client.dsl.Resource import mu.KotlinLogging -import theodolite.execution.Shutdown -import theodolite.k8s.K8sContextFactory -import theodolite.k8s.ResourceByLabelHandler -import theodolite.model.crd.* +import rocks.theodolite.kubernetes.K8sContextFactory +import rocks.theodolite.kubernetes.ResourceByLabelHandler +import rocks.theodolite.kubernetes.model.crd.* +import rocks.theodolite.kubernetes.Shutdown private val logger = KotlinLogging.logger {} class ClusterSetup( - private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>, - private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>, - private val client: NamespacedKubernetesClient + private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>, + private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>, + private val client: NamespacedKubernetesClient ) { private val serviceMonitorContext = K8sContextFactory().create( @@ -53,7 +53,7 @@ class ClusterSetup( if (benchmark != null) { execution.spec.name = execution.metadata.name benchmark.spec.name = benchmark.metadata.name - Shutdown(execution.spec, benchmark.spec).run() + Shutdown(execution.spec, benchmark.spec, client).run() } else { throw IllegalStateException("Execution with state ${ExecutionState.RUNNING.value} was found, but no corresponding benchmark. " + "Could not initialize cluster.") diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/EventCreator.kt similarity index 83% rename from theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/EventCreator.kt index fab098ebd5fe765a455d787ddb7fcbfbb6c9ffc7..6803da62f045efcaf1b5504a33b42b2200d16baa 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/EventCreator.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/EventCreator.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.api.model.EventBuilder import io.fabric8.kubernetes.api.model.EventSource @@ -6,14 +6,14 @@ import io.fabric8.kubernetes.api.model.ObjectReference import io.fabric8.kubernetes.client.DefaultKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient import mu.KotlinLogging -import theodolite.util.Configuration +import rocks.theodolite.kubernetes.Configuration import java.time.Instant import java.util.* import kotlin.NoSuchElementException private val logger = KotlinLogging.logger {} class EventCreator { - val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(Configuration.NAMESPACE) + private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(Configuration.NAMESPACE) fun createEvent(executionName: String, type: String, message: String, reason: String) { val uuid = UUID.randomUUID().toString() @@ -34,15 +34,15 @@ class EventCreator { event.source = source event.involvedObject = objectRef - client.v1().events().inNamespace(Configuration.NAMESPACE).createOrReplace(event) + this.client.v1().events().inNamespace(Configuration.NAMESPACE).createOrReplace(event) } catch (e: NoSuchElementException) { logger.warn {"Could not create event: type: $type, message: $message, reason: $reason, no corresponding execution found."} } } private fun buildObjectReference(executionName: String): ObjectReference { - val exec = TheodoliteOperator() - .getExecutionClient(client = client) + val exec = TheodoliteOperator(this.client) + .getExecutionClient() .list() .items .first{it.metadata.name == executionName} diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandler.kt similarity index 91% rename from theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandler.kt index 25c627a350e3939530c4b453ec6db846b546cc08..58120d25d7e26daab015c01fece85cf72344bffa 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionEventHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandler.kt @@ -1,11 +1,12 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import com.google.gson.Gson import com.google.gson.GsonBuilder import io.fabric8.kubernetes.client.informers.ResourceEventHandler import mu.KotlinLogging -import theodolite.benchmark.BenchmarkExecution -import theodolite.model.crd.* +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionState private val logger = KotlinLogging.logger {} @@ -18,8 +19,8 @@ private val logger = KotlinLogging.logger {} * @see BenchmarkExecution */ class ExecutionEventHandler( - private val controller: TheodoliteController, - private val stateHandler: ExecutionStateHandler + private val controller: TheodoliteController, + private val stateHandler: ExecutionStateHandler ) : ResourceEventHandler<ExecutionCRD> { private val gson: Gson = GsonBuilder().enableComplexMapKeySerialization().create() diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionStateHandler.kt similarity index 92% rename from theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionStateHandler.kt index 340044e5be954d4d7673120e5bf2cba5aed02d92..6264b574d2be297865fab3b2a4d020bc57c56678 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/ExecutionStateHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/ExecutionStateHandler.kt @@ -1,9 +1,9 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.api.model.MicroTime import io.fabric8.kubernetes.client.NamespacedKubernetesClient -import theodolite.model.crd.ExecutionCRD -import theodolite.model.crd.ExecutionState +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionState import java.lang.Thread.sleep import java.time.Instant import java.util.concurrent.atomic.AtomicBoolean diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/LeaderElector.kt similarity index 97% rename from theodolite/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/LeaderElector.kt index 558d06ce03074c38741b6c0a72c6ffa6eff96019..8a713d040e931a0e60266059c4faa44fdf5bddbc 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/LeaderElector.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/LeaderElector.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.client.DefaultKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/StateHandler.kt similarity index 90% rename from theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/StateHandler.kt index 28563ac5a640d0226224b812a8e0691cde83942a..eaa3b39ec1391cb1e27573dfc85345add4c32330 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/StateHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/StateHandler.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator private const val MAX_RETRIES: Int = 5 diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteController.kt similarity index 69% rename from theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteController.kt index d9cb33b189da02b807301dde8550f2ae532d7e5a..67a9a40fe260c8105e30fef3c9c44436b7a37c5e 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteController.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteController.kt @@ -1,14 +1,19 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator +import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.dsl.MixedOperation import io.fabric8.kubernetes.client.dsl.Resource import mu.KotlinLogging -import theodolite.benchmark.BenchmarkExecution -import theodolite.benchmark.KubernetesBenchmark -import theodolite.execution.TheodoliteExecutor -import theodolite.model.crd.* -import theodolite.patcher.ConfigOverrideModifier -import theodolite.util.ExecutionStateComparator +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionState +import rocks.theodolite.kubernetes.model.crd.KubernetesBenchmarkList +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.TheodoliteExecutor +import rocks.theodolite.kubernetes.model.crd.* +import rocks.theodolite.kubernetes.patcher.ConfigOverrideModifier +import rocks.theodolite.kubernetes.model.crd.ExecutionStateComparator +import rocks.theodolite.kubernetes.loadKubernetesResources import java.lang.Thread.sleep private val logger = KotlinLogging.logger {} @@ -25,10 +30,12 @@ const val CREATED_BY_LABEL_VALUE = "theodolite" */ class TheodoliteController( - private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>, - private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>, - private val executionStateHandler: ExecutionStateHandler, - private val benchmarkStateChecker: BenchmarkStateChecker + private val client: NamespacedKubernetesClient, + private val executionCRDClient: MixedOperation<ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>>, + private val benchmarkCRDClient: MixedOperation<BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>>, + private val executionStateHandler: ExecutionStateHandler, + private val benchmarkStateChecker: BenchmarkStateChecker, + ) { lateinit var executor: TheodoliteExecutor @@ -68,28 +75,28 @@ class TheodoliteController( private fun runExecution(execution: BenchmarkExecution, benchmark: KubernetesBenchmark) { try { val modifier = ConfigOverrideModifier( - execution = execution, - resources = benchmark.loadKubernetesResources(benchmark.sut.resources).map { it.first } - + benchmark.loadKubernetesResources(benchmark.loadGenerator.resources).map { it.first } - ) - modifier.setAdditionalLabels( - labelValue = execution.name, - labelName = DEPLOYED_FOR_EXECUTION_LABEL_NAME - ) - modifier.setAdditionalLabels( - labelValue = benchmark.name, - labelName = DEPLOYED_FOR_BENCHMARK_LABEL_NAME - ) - modifier.setAdditionalLabels( - labelValue = CREATED_BY_LABEL_VALUE, - labelName = CREATED_BY_LABEL_NAME - ) + execution = execution, + resources = loadKubernetesResources(benchmark.sut.resources, this.client).map { it.first } + + loadKubernetesResources(benchmark.loadGenerator.resources, this.client).map { it.first } + ) + modifier.setAdditionalLabels( + labelValue = execution.name, + labelName = DEPLOYED_FOR_EXECUTION_LABEL_NAME + ) + modifier.setAdditionalLabels( + labelValue = benchmark.name, + labelName = DEPLOYED_FOR_BENCHMARK_LABEL_NAME + ) + modifier.setAdditionalLabels( + labelValue = CREATED_BY_LABEL_VALUE, + labelName = CREATED_BY_LABEL_NAME + ) - executionStateHandler.setExecutionState(execution.name, ExecutionState.RUNNING) - executionStateHandler.startDurationStateTimer(execution.name) + executionStateHandler.setExecutionState(execution.name, ExecutionState.RUNNING) + executionStateHandler.startDurationStateTimer(execution.name) - executor = TheodoliteExecutor(execution, benchmark) - executor.run() + executor = TheodoliteExecutor(execution, benchmark, this.client) + executor.setupAndRunExecution() when (executionStateHandler.getExecutionState(execution.name)) { ExecutionState.RESTART -> runExecution(execution, benchmark) ExecutionState.RUNNING -> { @@ -119,7 +126,7 @@ class TheodoliteController( if (restart) { executionStateHandler.setExecutionState(this.executor.getExecution().name, ExecutionState.RESTART) } - this.executor.executor.run.set(false) + this.executor.experimentRunner.run.set(false) } /** diff --git a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteOperator.kt similarity index 62% rename from theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteOperator.kt index ada30ec945dd602dabe3ddb5f0e635a4eeea7b5f..bdaa2692d374b4002a1f890f706e2c1ec0d8733c 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/operator/TheodoliteOperator.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/operator/TheodoliteOperator.kt @@ -1,20 +1,18 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator -import io.fabric8.kubernetes.client.DefaultKubernetesClient import io.fabric8.kubernetes.client.NamespacedKubernetesClient import io.fabric8.kubernetes.client.dsl.MixedOperation import io.fabric8.kubernetes.client.dsl.Resource import io.fabric8.kubernetes.client.informers.SharedInformerFactory import io.fabric8.kubernetes.internal.KubernetesDeserializer import mu.KotlinLogging -import theodolite.model.crd.BenchmarkCRD -import theodolite.model.crd.BenchmarkExecutionList -import theodolite.model.crd.ExecutionCRD -import theodolite.model.crd.KubernetesBenchmarkList -import theodolite.util.Configuration +import rocks.theodolite.kubernetes.Configuration +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD +import rocks.theodolite.kubernetes.model.crd.BenchmarkExecutionList +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.crd.KubernetesBenchmarkList -private const val DEFAULT_NAMESPACE = "default" private const val EXECUTION_SINGULAR = "execution" private const val BENCHMARK_SINGULAR = "benchmark" private const val API_VERSION = "v1" @@ -27,10 +25,7 @@ private val logger = KotlinLogging.logger {} * * **See Also:** [Kubernetes Operator Pattern](https://kubernetes.io/docs/concepts/extend-kubernetes/operator/) */ -class TheodoliteOperator { - private val namespace = Configuration.NAMESPACE - - private val client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace) +class TheodoliteOperator(private val client: NamespacedKubernetesClient) { private lateinit var controller: TheodoliteController private lateinit var executionStateHandler: ExecutionStateHandler private lateinit var benchmarkStateHandler: BenchmarkStateHandler @@ -39,7 +34,7 @@ class TheodoliteOperator { fun start() { LeaderElector( - client = client, + client = this.client, name = Configuration.COMPONENT_NAME ).getLeadership(::startOperator) } @@ -48,7 +43,7 @@ class TheodoliteOperator { * Start the operator. */ private fun startOperator() { - logger.info { "Becoming the leading operator. Use namespace '$namespace'." } + logger.info { "Becoming the leading operator. Use namespace '${this.client.namespace}'." } client.use { KubernetesDeserializer.registerCustomKind( "$GROUP/$API_VERSION", @@ -63,28 +58,26 @@ class TheodoliteOperator { ) ClusterSetup( - executionCRDClient = getExecutionClient(client), - benchmarkCRDClient = getBenchmarkClient(client), - client = client + executionCRDClient = getExecutionClient(), + benchmarkCRDClient = getBenchmarkClient(), + client = this.client ).clearClusterState() controller = getController( - client = client, - executionStateHandler = getExecutionStateHandler(client = client), - benchmarkStateChecker = getBenchmarkStateChecker(client = client) + executionStateHandler = getExecutionStateHandler(), + benchmarkStateChecker = getBenchmarkStateChecker() ) - getExecutionEventHandler(controller, client).startAllRegisteredInformers() + getExecutionEventHandler(controller).startAllRegisteredInformers() controller.run() } } - fun getExecutionEventHandler( - controller: TheodoliteController, - client: NamespacedKubernetesClient + private fun getExecutionEventHandler( + controller: TheodoliteController, ): SharedInformerFactory { - val factory = client.informers() - .inNamespace(client.namespace) + val factory = this.client.informers() + .inNamespace(this.client.namespace) factory.sharedIndexInformerForCustomResource( ExecutionCRD::class.java, @@ -92,46 +85,46 @@ class TheodoliteOperator { ).addEventHandler( ExecutionEventHandler( controller = controller, - stateHandler = ExecutionStateHandler(client) + stateHandler = ExecutionStateHandler(this.client) ) ) return factory } - fun getExecutionStateHandler(client: NamespacedKubernetesClient): ExecutionStateHandler { + fun getExecutionStateHandler(): ExecutionStateHandler { if (!::executionStateHandler.isInitialized) { - this.executionStateHandler = ExecutionStateHandler(client = client) + this.executionStateHandler = ExecutionStateHandler(client = this.client) } return executionStateHandler } - fun getBenchmarkStateHandler(client: NamespacedKubernetesClient) : BenchmarkStateHandler { + fun getBenchmarkStateHandler() : BenchmarkStateHandler { if (!::benchmarkStateHandler.isInitialized) { - this.benchmarkStateHandler = BenchmarkStateHandler(client = client) + this.benchmarkStateHandler = BenchmarkStateHandler(client = this.client) } return benchmarkStateHandler } - fun getBenchmarkStateChecker(client: NamespacedKubernetesClient) : BenchmarkStateChecker { + fun getBenchmarkStateChecker() : BenchmarkStateChecker { if (!::benchmarkStateChecker.isInitialized) { this.benchmarkStateChecker = BenchmarkStateChecker( - client = client, - benchmarkStateHandler = getBenchmarkStateHandler(client = client), - benchmarkCRDClient = getBenchmarkClient(client = client)) + client = this.client, + benchmarkStateHandler = getBenchmarkStateHandler(), + benchmarkCRDClient = getBenchmarkClient()) } return benchmarkStateChecker } fun getController( - client: NamespacedKubernetesClient, - executionStateHandler: ExecutionStateHandler, - benchmarkStateChecker: BenchmarkStateChecker + executionStateHandler: ExecutionStateHandler, + benchmarkStateChecker: BenchmarkStateChecker ): TheodoliteController { if (!::controller.isInitialized) { this.controller = TheodoliteController( - benchmarkCRDClient = getBenchmarkClient(client), - executionCRDClient = getExecutionClient(client), + client = this.client, + benchmarkCRDClient = getBenchmarkClient(), + executionCRDClient = getExecutionClient(), executionStateHandler = executionStateHandler, benchmarkStateChecker = benchmarkStateChecker ) @@ -139,21 +132,21 @@ class TheodoliteOperator { return this.controller } - fun getExecutionClient(client: NamespacedKubernetesClient): MixedOperation< + fun getExecutionClient(): MixedOperation< ExecutionCRD, BenchmarkExecutionList, Resource<ExecutionCRD>> { - return client.customResources( + return this.client.customResources( ExecutionCRD::class.java, BenchmarkExecutionList::class.java ) } - fun getBenchmarkClient(client: NamespacedKubernetesClient): MixedOperation< + fun getBenchmarkClient(): MixedOperation< BenchmarkCRD, KubernetesBenchmarkList, Resource<BenchmarkCRD>> { - return client.customResources( + return this.client.customResources( BenchmarkCRD::class.java, KubernetesBenchmarkList::class.java ) diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..a20a26b351e730de60497ac014b3aba855ac01f5 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcher.kt @@ -0,0 +1,30 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.client.utils.Serialization + +/** + * A Patcher is able to modify values of a Kubernetes resource, see [Patcher]. + * + * An AbstractPatcher is created with up to three parameters. + * + * + * + * **For example** to patch the load dimension of a load generator, the patcher should be created as follow: + * + * k8sResource: `uc-1-workload-generator.yaml` + * container: `workload` + * variableName: `NUM_SENSORS` + * + */ +abstract class AbstractPatcher : Patcher { + + override fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata> { + return resources + .map { Serialization.clone(it)} + .map { patchSingleResource(it, value) } + } + + abstract fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata + +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifier.kt similarity index 89% rename from theodolite/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifier.kt index 8f77b1b95f3bf5cc9422cda55cb261048cebaeb6..c45808b5a81e5ffdfa5fd09b263ae49312a8d7fa 100644 --- a/theodolite/src/main/kotlin/theodolite/patcher/ConfigOverrideModifier.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifier.kt @@ -1,8 +1,7 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher -import theodolite.benchmark.BenchmarkExecution -import theodolite.util.ConfigurationOverride -import theodolite.util.PatcherDefinition +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.util.ConfigurationOverride /** * The ConfigOverrideModifier makes it possible to update the configuration overrides of an execution. diff --git a/theodolite/src/main/kotlin/theodolite/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt similarity index 56% rename from theodolite/src/main/kotlin/theodolite/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt index bdc107910edc8ddfb41e7757c775977086a25a26..d884c9ee1b6925bc985ad1da69a46f6589917b01 100644 --- a/theodolite/src/main/kotlin/theodolite/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcher.kt @@ -1,6 +1,6 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher -import io.fabric8.kubernetes.api.model.KubernetesResource +import io.fabric8.kubernetes.api.model.HasMetadata /** * The DataVolumeLoadGeneratorReplicaPatcher takes the total load that should be generated @@ -10,29 +10,29 @@ import io.fabric8.kubernetes.api.model.KubernetesResource * The number of instances are set for the load generator and the given variable is set to the * load per instance. * - * @property k8sResource Kubernetes resource to be patched. * @property maxVolume per load generator instance * @property container Container to be patched. * @property variableName Name of the environment variable to be patched. */ class DataVolumeLoadGeneratorReplicaPatcher( - k8sResource: KubernetesResource, private val maxVolume: Int, - container: String, - variableName: String -) : AbstractPatcher(k8sResource) { + private val container: String, + private val variableName: String +) : Patcher { - private val replicaPatcher = ReplicaPatcher(k8sResource) - private val envVarPatcher = EnvVarPatcher(k8sResource, container, variableName) + override fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata> { + return resources.flatMap { patchSingeResource(it, value)} + } - override fun <T> patch(value: T) { + fun patchSingeResource(k8sResource: HasMetadata, value: String): List<HasMetadata> { + var resource = k8sResource // calculate number of load generator instances and load per instance - val load = Integer.parseInt(value.toString()) + val load = Integer.parseInt(value) val loadGenInstances = (load + maxVolume - 1) / maxVolume val loadPerInstance = load / loadGenInstances // Patch instance values and load value of generators - replicaPatcher.patch(loadGenInstances.toString()) - envVarPatcher.patch(loadPerInstance.toString()) + val resourceList = ReplicaPatcher().patch(listOf(resource), loadGenInstances.toString()) + return EnvVarPatcher(this.container, this.variableName).patch(resourceList, loadPerInstance.toString()) } } diff --git a/theodolite/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcher.kt similarity index 77% rename from theodolite/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcher.kt index 416aec74a3af9b74594f5e6cd018682bf91cbf63..33d6c8d9b6f5f82a49e7cd414e4b273708c0e68a 100644 --- a/theodolite/src/main/kotlin/theodolite/patcher/EnvVarPatcher.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcher.kt @@ -1,30 +1,31 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher import io.fabric8.kubernetes.api.model.Container import io.fabric8.kubernetes.api.model.EnvVar -import io.fabric8.kubernetes.api.model.KubernetesResource +import io.fabric8.kubernetes.api.model.HasMetadata import io.fabric8.kubernetes.api.model.apps.Deployment /** * The EnvVarPatcher allows to modify the value of an environment variable * - * @property k8sResource Kubernetes resource to be patched. * @property container Container to be patched. * @property variableName Name of the environment variable to be patched. */ class EnvVarPatcher( - private val k8sResource: KubernetesResource, private val container: String, private val variableName: String -) : AbstractPatcher(k8sResource) { +) : AbstractPatcher() { - override fun <String> patch(value: String) { - if (k8sResource is Deployment) { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { this.setEnv( - k8sResource, this.container, - mapOf(this.variableName to value) as Map<kotlin.String, kotlin.String> + resource, this.container, + mapOf(this.variableName to value) ) + return resource } + return resource } /** diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..7f54416501bc742499a958566a179b7fad320318 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcher.kt @@ -0,0 +1,37 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet +import io.fabric8.kubernetes.client.utils.Serialization + +/** + * The Image patcher allows to change the image of a container. + * + * @param container Container to be patched. + */ +class ImagePatcher( + private val container: String) : + AbstractPatcher() { + + override fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata> { + return resources + .map { Serialization.clone(it) } + .map { patchSingleResource(it, value as kotlin.String) } + } + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { + (resource).spec.template.spec.containers.filter { it.name == container }.forEach { + it.image = value + } + return resource + } else if (resource is StatefulSet) { + (resource).spec.template.spec.containers.filter { it.name == container }.forEach { + it.image = value + } + return resource + } + return resource + } +} diff --git a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/InvalidPatcherConfigurationException.kt similarity index 53% rename from theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/InvalidPatcherConfigurationException.kt index d02948ad341207051c4653ba9400ac0ffe5b03aa..88ad707ec48b0c2c2b3a62cc46f004ced64dbb69 100644 --- a/theodolite/src/main/kotlin/theodolite/util/InvalidPatcherConfigurationException.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/InvalidPatcherConfigurationException.kt @@ -1,3 +1,5 @@ -package theodolite.util +package rocks.theodolite.kubernetes.patcher + +import rocks.theodolite.kubernetes.DeploymentFailedException class InvalidPatcherConfigurationException(message: String, e: Exception? = null) : DeploymentFailedException(message,e) diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..8bb5be97e780479884e6cb8e551c03340b04f8e6 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcher.kt @@ -0,0 +1,50 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.ConfigMap +import io.fabric8.kubernetes.api.model.GenericKubernetesResource +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.Service +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet + +class LabelPatcher( + val variableName: String) : + AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + when (resource) { + is Deployment -> { + if (resource.metadata.labels == null) { + resource.metadata.labels = mutableMapOf() + } + resource.metadata.labels[this.variableName] = value + } + is StatefulSet -> { + if (resource.metadata.labels == null) { + resource.metadata.labels = mutableMapOf() + } + resource.metadata.labels[this.variableName] = value + } + is Service -> { + if (resource.metadata.labels == null) { + resource.metadata.labels = mutableMapOf() + } + resource.metadata.labels[this.variableName] = value + + } + is ConfigMap -> { + if (resource.metadata.labels == null) { + resource.metadata.labels = mutableMapOf() + } + resource.metadata.labels[this.variableName] = value + } + is GenericKubernetesResource -> { + if (resource.metadata.labels == null) { + resource.metadata.labels = mutableMapOf() + } + resource.metadata.labels[this.variableName] = value + } + } + return resource + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..725c9cf8a6a87c23119812c0a5d5ad3280a42e3c --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcher.kt @@ -0,0 +1,33 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet + +/** + * This patcher is able to set the `spec.selector.matchLabels` for a `Deployment` or `StatefulSet` Kubernetes resource. + * + * @property variableName The matchLabel which should be set + */ +class MatchLabelPatcher( + val variableName: String) : + AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + when (resource) { + is Deployment -> { + if (resource.spec.selector.matchLabels == null) { + resource.spec.selector.matchLabels = mutableMapOf() + } + resource.spec.selector.matchLabels[this.variableName] = value + } + is StatefulSet -> { + if (resource.spec.selector.matchLabels == null) { + resource.spec.selector.matchLabels = mutableMapOf() + } + resource.spec.selector.matchLabels[this.variableName] = value + } + } + return resource + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..a6416a7e77841fa869de7ce2c248882fb486572c --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcher.kt @@ -0,0 +1,35 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.ConfigMap +import io.fabric8.kubernetes.api.model.GenericKubernetesResource +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.Service +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet + +class NamePatcher : AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + when (resource) { + is Deployment -> { + resource.metadata.name = value + } + is StatefulSet -> { + resource.metadata.name = value + } + is Service -> { + resource.metadata.name = value + } + is ConfigMap -> { + resource.metadata.name = value + } + is io.fabric8.kubernetes.api.model.networking.v1.Ingress -> { + resource.metadata.name = value + } + is GenericKubernetesResource -> { + resource.metadata.name = value + } + } + return resource + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..c3b5ba1a07afa41dd604f2335baf6b58e362f293 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcher.kt @@ -0,0 +1,22 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment + +/** + * The Node selector patcher make it possible to set the NodeSelector of a Kubernetes deployment. + * + * @param variableName The `label-key` of the node for which the `label-value` is to be patched. + */ +class NodeSelectorPatcher( + private val variableName: String) : + AbstractPatcher() { + + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { + resource.spec.template.spec.nodeSelector = mapOf(variableName to value) + } + return resource + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..e3b0105768ec339758fd89233a09da233145d641 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt @@ -0,0 +1,23 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment +import kotlin.math.pow + +class NumNestedGroupsLoadGeneratorReplicaPatcher( + private val numSensors: String, + private val loadGenMaxRecords: String, +) : AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { + val approxNumSensors = numSensors.toDouble().pow(Integer.parseInt(value).toDouble()) + val loadGenInstances = + (approxNumSensors + loadGenMaxRecords.toDouble() - 1) / loadGenMaxRecords.toDouble() + resource.spec.replicas = loadGenInstances.toInt() + + } + return resource + } +} + diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..6bb2750bb1ca923aa05022884ef7054772a987c6 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt @@ -0,0 +1,21 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment + + +class NumSensorsLoadGeneratorReplicaPatcher( + private val loadGenMaxRecords: String, +) : AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { + val loadGenInstances = + (Integer.parseInt(value) + loadGenMaxRecords.toInt() - 1) / loadGenMaxRecords.toInt() + resource.spec.replicas = loadGenInstances + + } + return resource + } + +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatchHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatchHandler.kt new file mode 100644 index 0000000000000000000000000000000000000000..6873d9ec84cd02b85b2342bbd37d429c706a47ab --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatchHandler.kt @@ -0,0 +1,20 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +class PatchHandler { + companion object { + private fun getResourcesToPatch(resources: MutableMap<String, List<HasMetadata>>, patcherDefinition: PatcherDefinition): List<HasMetadata> { + return resources[patcherDefinition.resource] + ?: throw InvalidPatcherConfigurationException("Could not find resource ${patcherDefinition.resource}") + + } + fun patchResource( + resources: MutableMap<String, List<HasMetadata>>, + patcherDefinition: PatcherDefinition, + value: String, + ): List<HasMetadata> { + val resToPatch = getResourcesToPatch(resources, patcherDefinition) + return PatcherFactory.createPatcher(patcherDefinition).patch(resToPatch,value) + } + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/patcher/Patcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/Patcher.kt similarity index 68% rename from theodolite/src/main/kotlin/theodolite/patcher/Patcher.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/Patcher.kt index 84b886cb4f06b3e667eb8b8aeaa622e1ee54852e..310b370b97d065fc1ea0c3f7edd81577816ff69c 100644 --- a/theodolite/src/main/kotlin/theodolite/patcher/Patcher.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/Patcher.kt @@ -1,5 +1,6 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher +import io.fabric8.kubernetes.api.model.HasMetadata import io.quarkus.runtime.annotations.RegisterForReflection /** @@ -13,8 +14,7 @@ interface Patcher { * The patch method modifies a value in the definition of a * Kubernetes resource. * - * @param T The type of value * @param value The value to be used. */ - fun <T> patch(value: T) + fun patch(resources: List<HasMetadata>, value: String) : List<HasMetadata> } diff --git a/theodolite/src/main/kotlin/theodolite/util/PatcherDefinition.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinition.kt similarity index 93% rename from theodolite/src/main/kotlin/theodolite/util/PatcherDefinition.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinition.kt index fd2ac209a52e0d516ffa9ec07e465fa076ae665a..653ed9e03caf86c661e6a52ed59501b478eea7b5 100644 --- a/theodolite/src/main/kotlin/theodolite/util/PatcherDefinition.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinition.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.kubernetes.patcher import com.fasterxml.jackson.databind.annotation.JsonDeserialize import com.fasterxml.jackson.databind.annotation.JsonSerialize diff --git a/theodolite/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactory.kt similarity index 83% rename from theodolite/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactory.kt index 6a1f993e2ac327ec242a8a5bafc3e6cc43475710..be9dcd11b08edf58462f0a1e71c7c3ab548fa66a 100644 --- a/theodolite/src/main/kotlin/theodolite/patcher/PatcherDefinitionFactory.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactory.kt @@ -1,7 +1,6 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher -import theodolite.util.PatcherDefinition -import theodolite.util.TypeName +import rocks.theodolite.kubernetes.model.KubernetesBenchmark /** * The PatcherDefinition Factory creates a [PatcherDefinition]s. @@ -20,7 +19,7 @@ class PatcherDefinitionFactory { * @return A list of PatcherDefinitions which corresponds to the * value of the requiredType. */ - fun createPatcherDefinition(requiredType: String, patcherTypes: List<TypeName>): List<PatcherDefinition> { + fun createPatcherDefinition(requiredType: String, patcherTypes: List<KubernetesBenchmark.TypeName>): List<PatcherDefinition> { return patcherTypes.firstOrNull { type -> type.typeName == requiredType } ?.patchers ?: throw IllegalArgumentException("typeName $requiredType not found.") } diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..a4dcf68d2b4ec12facb26755e9f63e298725e195 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/PatcherFactory.kt @@ -0,0 +1,89 @@ +package rocks.theodolite.kubernetes.patcher + +/** + * The Patcher factory creates [Patcher]s + * + * @constructor Creates an empty PatcherFactory. + */ +class PatcherFactory { + + companion object { + /** + * Create patcher based on the given [PatcherDefinition] and + * the list of KubernetesResources. + * + * @param patcherDefinition The [PatcherDefinition] for which are + * [Patcher] should be created. + * @param k8sResources List of all available Kubernetes resources. + * This is a list of pairs<String, KubernetesResource>: + * The frist corresponds to the filename where the resource is defined. + * The second corresponds to the concrete [KubernetesResource] that should be patched. + * @return The created [Patcher]. + * @throws IllegalArgumentException if no patcher can be created. + */ + fun createPatcher( + patcherDefinition: PatcherDefinition, + ): Patcher { + + return try { + when (patcherDefinition.type) { + "ReplicaPatcher" -> ReplicaPatcher( + ) + "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher( + loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!, + numSensors = patcherDefinition.properties["numSensors"]!! + ) + "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher( + loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!! + ) + "DataVolumeLoadGeneratorReplicaPatcher" -> DataVolumeLoadGeneratorReplicaPatcher( + maxVolume = patcherDefinition.properties["maxVolume"]!!.toInt(), + container = patcherDefinition.properties["container"]!!, + variableName = patcherDefinition.properties["variableName"]!! + ) + "EnvVarPatcher" -> EnvVarPatcher( + container = patcherDefinition.properties["container"]!!, + variableName = patcherDefinition.properties["variableName"]!! + ) + "NodeSelectorPatcher" -> NodeSelectorPatcher( + variableName = patcherDefinition.properties["variableName"]!! + ) + "ResourceLimitPatcher" -> ResourceLimitPatcher( + container = patcherDefinition.properties["container"]!!, + limitedResource = patcherDefinition.properties["limitedResource"]!! + ) + "ResourceRequestPatcher" -> ResourceRequestPatcher( + container = patcherDefinition.properties["container"]!!, + requestedResource = patcherDefinition.properties["requestedResource"]!! + ) + "SchedulerNamePatcher" -> SchedulerNamePatcher() + "LabelPatcher" -> LabelPatcher( + variableName = patcherDefinition.properties["variableName"]!! + ) + "MatchLabelPatcher" -> MatchLabelPatcher( + variableName = patcherDefinition.properties["variableName"]!! + ) + "TemplateLabelPatcher" -> TemplateLabelPatcher( + variableName = patcherDefinition.properties["variableName"]!! + ) + "ImagePatcher" -> ImagePatcher( + container = patcherDefinition.properties["container"]!! + ) + "NamePatcher" -> NamePatcher() + "ServiceSelectorPatcher" -> ServiceSelectorPatcher( + variableName = patcherDefinition.properties["label"]!! + ) + "rocks.theodolite.kubernetes.patcher.VolumesConfigMapPatcher" -> VolumesConfigMapPatcher( + volumeName = patcherDefinition.properties["volumeName"]!! + ) + else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.") + } + } catch (e: NullPointerException) { + throw InvalidPatcherConfigurationException( + "Could not create patcher with type ${patcherDefinition.type}" + + " Probably a required patcher argument was not specified.", e + ) + } + } + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..8637b1299e878c4424e7fcaf4eac3bc901428541 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcher.kt @@ -0,0 +1,18 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment + +/** + * The Replica [Patcher] modifies the number of replicas for the given Kubernetes deployment. + * + */ +class ReplicaPatcher : AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { + resource.spec.replicas = Integer.parseInt(value) + } + return resource + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt similarity index 62% rename from theodolite/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt index 9dcdffa0407dd4fdaf2d9b0a898bcdf6cebe5a8b..7450e2edfa20f570742fe0336d0d27c76ec83aa2 100644 --- a/theodolite/src/main/kotlin/theodolite/patcher/ResourceLimitPatcher.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcher.kt @@ -1,12 +1,8 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher -import io.fabric8.kubernetes.api.model.Container -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.Quantity -import io.fabric8.kubernetes.api.model.ResourceRequirements +import io.fabric8.kubernetes.api.model.* import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.StatefulSet -import theodolite.util.InvalidPatcherConfigurationException /** * The Resource limit [Patcher] set resource limits for deployments and statefulSets. @@ -16,30 +12,31 @@ import theodolite.util.InvalidPatcherConfigurationException * @param limitedResource The resource to be limited (e.g. **cpu or memory**) */ class ResourceLimitPatcher( - private val k8sResource: KubernetesResource, private val container: String, private val limitedResource: String -) : AbstractPatcher(k8sResource) { +) : AbstractPatcher() { - override fun <String> patch(value: String) { - when (k8sResource) { + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + when (resource) { is Deployment -> { - k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach { - setLimits(it, value as kotlin.String) + resource.spec.template.spec.containers.filter { it.name == container }.forEach { + setLimits(it, value) } } is StatefulSet -> { - k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach { - setLimits(it, value as kotlin.String) + resource.spec.template.spec.containers.filter { it.name == container }.forEach { + setLimits(it, value) } } else -> { - throw InvalidPatcherConfigurationException("ResourceLimitPatcher not applicable for $k8sResource") + throw InvalidPatcherConfigurationException("ResourceLimitPatcher is not applicable for $resource") } } + return resource } - private fun setLimits(container: Container, value: String) { + + private fun setLimits(container: Container, value: String) { when { container.resources == null -> { val resource = ResourceRequirements() diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt similarity index 62% rename from theodolite/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt index 24cdde40f7f78bd67d115b2dc44f47e180f51ee2..bdcdc9527e8fa4dad9f85917be7d5c1c2fe67c2e 100644 --- a/theodolite/src/main/kotlin/theodolite/patcher/ResourceRequestPatcher.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcher.kt @@ -1,44 +1,39 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher -import io.fabric8.kubernetes.api.model.Container -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.Quantity -import io.fabric8.kubernetes.api.model.ResourceRequirements +import io.fabric8.kubernetes.api.model.* import io.fabric8.kubernetes.api.model.apps.Deployment import io.fabric8.kubernetes.api.model.apps.StatefulSet -import theodolite.util.InvalidPatcherConfigurationException /** * The Resource request [Patcher] set resource limits for deployments and statefulSets. * - * @param k8sResource Kubernetes resource to be patched. * @param container Container to be patched. * @param requestedResource The resource to be requested (e.g. **cpu or memory**) */ class ResourceRequestPatcher( - private val k8sResource: KubernetesResource, private val container: String, private val requestedResource: String -) : AbstractPatcher(k8sResource) { +) : AbstractPatcher() { - override fun <String> patch(value: String) { - when (k8sResource) { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + when (resource) { is Deployment -> { - k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach { - setRequests(it, value as kotlin.String) + resource.spec.template.spec.containers.filter { it.name == container }.forEach { + setRequests(it, value) } } is StatefulSet -> { - k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach { - setRequests(it, value as kotlin.String) + resource.spec.template.spec.containers.filter { it.name == container }.forEach { + setRequests(it, value) } } else -> { - throw InvalidPatcherConfigurationException("ResourceRequestPatcher not applicable for $k8sResource") + throw InvalidPatcherConfigurationException("ResourceRequestPatcher is not applicable for $resource") } } + return resource } - private fun setRequests(container: Container, value: String) { when { container.resources == null -> { diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..c5ac16cdfe25f6b2fd2e4d0a2fb27000f885ffe7 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcher.kt @@ -0,0 +1,20 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment + +/** + * The Scheduler name [Patcher] make it possible to set the scheduler which should + * be used to deploy the given deployment. + * @param k8sResource Kubernetes resource to be patched. + */ +class SchedulerNamePatcher : AbstractPatcher() { + + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { + resource.spec.template.spec.schedulerName = value + } + return resource + } +} diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ServiceSelectorPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ServiceSelectorPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..b38ae4108748f85e7ac60f3ee3aa8c5d28281432 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/ServiceSelectorPatcher.kt @@ -0,0 +1,19 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.Service + +class ServiceSelectorPatcher( + private var variableName: String + ) : AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Service) { + if (resource.spec.selector == null) { + resource.spec.selector = mutableMapOf() + } + resource.spec.selector[this.variableName] = value + } + return resource + } + } \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..534809cf8c36fb2065cbe3c0823294b346ac05f6 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcher.kt @@ -0,0 +1,34 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet + +/** + * This patcher is able to set the field `spec.template.metadata.labels` for a `Deployment` or `StatefulSet` Kubernetes resource. + * + * @property variableName The label which should be set + */ +class TemplateLabelPatcher( + val variableName: String) : + AbstractPatcher() { + + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + when (resource) { + is Deployment -> { + if (resource.spec.template.metadata.labels == null) { + resource.spec.template.metadata.labels = mutableMapOf() + } + resource.spec.template.metadata.labels[this.variableName] = value + } + is StatefulSet -> { + if (resource.spec.template.metadata.labels == null) { + resource.spec.template.metadata.labels = mutableMapOf() + } + resource.spec.template.metadata.labels[this.variableName] = value + } + } + return resource + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcher.kt new file mode 100644 index 0000000000000000000000000000000000000000..54a459a19b35e74839de647761e8ac22f839ca2d --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcher.kt @@ -0,0 +1,44 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.fabric8.kubernetes.api.model.apps.StatefulSet + +class VolumesConfigMapPatcher(private var volumeName: String +) : AbstractPatcher() { + + override fun patchSingleResource(resource: HasMetadata, value: String): HasMetadata { + if (resource is Deployment) { + if (resource.spec.template.spec.volumes == null) { + resource.spec.template.spec.volumes = mutableListOf() + } + val volumeMounts = resource.spec.template.spec.volumes + + for (mount in volumeMounts) { + try { + if (mount.configMap.name == volumeName) { + mount.configMap.name = value + } + } catch (_: NullPointerException) { + } + } + } + if (resource is StatefulSet) { + if (resource.spec.template.spec.volumes == null) { + resource.spec.template.spec.volumes = mutableListOf() + } + val volumeMounts = resource.spec.template.spec.volumes + + for (mount in volumeMounts) { + try { + if (mount.configMap.name == volumeName) { + mount.configMap.name = value + } + } catch (_: NullPointerException) { + } + } + } + + return resource + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt similarity index 76% rename from theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt index b3cc174d2945bf13bc1cc29d4e60d8c9bfbaf7eb..96c5a43b85c0db5600d813f9e799903927a53ec3 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/AnalysisExecutor.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/AnalysisExecutor.kt @@ -1,10 +1,8 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo -import theodolite.benchmark.BenchmarkExecution -import theodolite.util.EvaluationFailedException -import theodolite.util.IOHandler -import theodolite.util.LoadDimension -import theodolite.util.Resource +import rocks.theodolite.core.strategies.Metric +import rocks.theodolite.core.IOHandler +import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo import java.text.Normalizer import java.time.Duration import java.time.Instant @@ -16,8 +14,8 @@ import java.util.regex.Pattern * @param slo Slo that is used for the analysis. */ class AnalysisExecutor( - private val slo: BenchmarkExecution.Slo, - private val executionId: Int + private val slo: Slo, + private val executionId: Int ) { private val fetcher = MetricFetcher( @@ -29,17 +27,17 @@ class AnalysisExecutor( * Analyses an experiment via prometheus data. * First fetches data from prometheus, then documents them and afterwards evaluate it via a [slo]. * @param load of the experiment. - * @param res of the experiment. + * @param resource of the experiment. * @param executionIntervals list of start and end points of experiments * @return true if the experiment succeeded. */ - fun analyze(load: LoadDimension, res: Resource, executionIntervals: List<Pair<Instant, Instant>>): Boolean { + fun analyze(load: Int, resource: Int, executionIntervals: List<Pair<Instant, Instant>>, metric: Metric): Boolean { var repetitionCounter = 1 try { val ioHandler = IOHandler() val resultsFolder = ioHandler.getResultFolderURL() - val fileURL = "${resultsFolder}exp${executionId}_${load.get()}_${res.get()}_${slo.sloType.toSlug()}" + val fileURL = "${resultsFolder}exp${executionId}_${load}_${resource}_${slo.sloType.toSlug()}" val prometheusData = executionIntervals .map { interval -> @@ -50,9 +48,9 @@ class AnalysisExecutor( ) } - prometheusData.forEach { data -> + prometheusData.forEach{ data -> ioHandler.writeToCSVFile( - fileURL = "${fileURL}_${repetitionCounter++}", + fileURL = "${fileURL}_${slo.name}_${repetitionCounter++}", data = data.getResultAsList(), columns = listOf("labels", "timestamp", "value") ) @@ -61,13 +59,15 @@ class AnalysisExecutor( val sloChecker = SloCheckerFactory().create( sloType = slo.sloType, properties = slo.properties, - load = load + load = load, + resource = resource, + metric = metric ) return sloChecker.evaluate(prometheusData) } catch (e: Exception) { - throw EvaluationFailedException("Evaluation failed for resource '${res.get()}' and load '${load.get()}", e) + throw EvaluationFailedException("Evaluation failed for resource '$resource' and load '$load ", e) } } diff --git a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/EvaluationFailedException.kt similarity index 52% rename from theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/EvaluationFailedException.kt index ebdf5a37b4e82c8d4b1870d065f5e77133154735..564ec926aeba501c55675ba3d25cfa8ebf50b68b 100644 --- a/theodolite/src/main/kotlin/theodolite/util/EvaluationFailedException.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/EvaluationFailedException.kt @@ -1,3 +1,5 @@ -package theodolite.util +package rocks.theodolite.kubernetes.slo + +import rocks.theodolite.kubernetes.ExecutionFailedException class EvaluationFailedException(message: String, e: Exception? = null) : ExecutionFailedException(message,e) diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/ExternalSloChecker.kt similarity index 94% rename from theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/ExternalSloChecker.kt index 7587e8326df98f3c45c016bfd3b2d7db8077e6d1..01b21c845a614ba42581c182d975da5ad645b474 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/ExternalSloChecker.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/ExternalSloChecker.kt @@ -1,8 +1,8 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo import khttp.post import mu.KotlinLogging -import theodolite.util.PrometheusResponse +import rocks.theodolite.kubernetes.util.PrometheusResponse import java.net.ConnectException /** diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/MetricFetcher.kt similarity index 96% rename from theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/MetricFetcher.kt index b6a1857cba513f663876f88d7a7d69ad02c0bc40..962564475d0ad0b56bad8cf99daf12329950eaf3 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/MetricFetcher.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/MetricFetcher.kt @@ -1,10 +1,10 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo import com.google.gson.Gson import khttp.get import khttp.responses.Response import mu.KotlinLogging -import theodolite.util.PrometheusResponse +import rocks.theodolite.kubernetes.util.PrometheusResponse import java.net.ConnectException import java.time.Duration import java.time.Instant diff --git a/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/PrometheusResponse.kt similarity index 98% rename from theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/PrometheusResponse.kt index 9b0b0dd4e0a5a48072ca576e874cb850c5f8df3b..5222a78bde342fea4a94c69bf1e42e132d0bc706 100644 --- a/theodolite/src/main/kotlin/theodolite/util/PrometheusResponse.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/PrometheusResponse.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.kubernetes.util import io.quarkus.runtime.annotations.RegisterForReflection import java.util.* diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloChecker.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloChecker.kt similarity index 81% rename from theodolite/src/main/kotlin/theodolite/evaluation/SloChecker.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloChecker.kt index 82f903f5be868731d58ebefd6279d5d438bd5eab..f4ac163547421d5f0f07d2511c2e3eeeebdb35b0 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/SloChecker.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloChecker.kt @@ -1,6 +1,6 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo -import theodolite.util.PrometheusResponse +import rocks.theodolite.kubernetes.util.PrometheusResponse /** * A SloChecker can be used to evaluate data from Prometheus. diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt similarity index 95% rename from theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt index f57cebfcb13d0e86919ec15a0a479d1258e318a6..810675f159169f31314289d08a59fcc15bf8a243 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/SloCheckerFactory.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloCheckerFactory.kt @@ -1,6 +1,7 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo + +import rocks.theodolite.core.strategies.Metric -import theodolite.util.LoadDimension /** * Factory used to potentially create different [SloChecker]s. @@ -41,7 +42,9 @@ class SloCheckerFactory { fun create( sloType: String, properties: MutableMap<String, String>, - load: LoadDimension + load: Int, + resource: Int, + metric: Metric ): SloChecker { return when (SloTypes.from(sloType)) { SloTypes.GENERIC -> ExternalSloChecker( @@ -76,7 +79,7 @@ class SloCheckerFactory { throw IllegalArgumentException("Threshold ratio needs to be an Double greater or equal 0.0") } // cast to int, as rounding is not really necessary - val threshold = (load.get() * thresholdRatio).toInt() + val threshold = (load * thresholdRatio).toInt() ExternalSloChecker( externalSlopeURL = properties["externalSloUrl"] diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloConfigHandler.kt similarity index 86% rename from theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloConfigHandler.kt index 089f40dc6b5ef7d8ac4b063cae68e5e9621d1f50..ed18e4a0b4027ce4284cc83ff4c9520738ec2ba7 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/SloConfigHandler.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloConfigHandler.kt @@ -1,7 +1,7 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo -import theodolite.benchmark.BenchmarkExecution -import theodolite.util.InvalidPatcherConfigurationException +import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo +import rocks.theodolite.kubernetes.patcher.InvalidPatcherConfigurationException import javax.enterprise.context.ApplicationScoped private const val DEFAULT_CONSUMER_LAG_METRIC_BASE = "kafka_consumergroup_lag" @@ -11,7 +11,7 @@ private const val DEFAULT_DROPPED_RECORDS_QUERY = "sum by(job) (kafka_streams_st @ApplicationScoped class SloConfigHandler { companion object { - fun getQueryString(slo: BenchmarkExecution.Slo): String { + fun getQueryString(slo: Slo): String { return when (slo.sloType.lowercase()) { SloTypes.GENERIC.value -> slo.properties["promQLQuery"] ?: throw IllegalArgumentException("promQLQuery expected") SloTypes.LAG_TREND.value, SloTypes.LAG_TREND_RATIO.value -> slo.properties["promQLQuery"] ?: diff --git a/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloFactory.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..047f8a657de8aba6f032d36e8b84d7046d5e0209 --- /dev/null +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloFactory.kt @@ -0,0 +1,24 @@ +package rocks.theodolite.kubernetes.slo + +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo + +class SloFactory { + + fun createSlos(execution: BenchmarkExecution, benchmark: KubernetesBenchmark): List<Slo> { + var benchmarkSlos = benchmark.slos + var executionSlos = execution.slos + + for(executionSlo in executionSlos) { + for(i in 0 until benchmarkSlos.size) { + if(executionSlo.name == benchmarkSlos[i].name && executionSlo.properties != null) { + for (executionProperty in executionSlo.properties!!) { + benchmarkSlos[i].properties[executionProperty.key] = executionProperty.value + } + } + } + } + return benchmarkSlos + } +} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloJson.kt similarity index 78% rename from theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloJson.kt index 205389276f2c1adef6cba6c745baf99744c8d2dd..653ad6b5f998014a0f5b9e8b7397bcd3ce51f729 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/SloJson.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloJson.kt @@ -1,7 +1,7 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo import com.google.gson.Gson -import theodolite.util.PromResult +import rocks.theodolite.kubernetes.util.PromResult class SloJson constructor( val results: List<List<PromResult>>, diff --git a/theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloTypes.kt similarity index 91% rename from theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloTypes.kt index 812b50de779d2f3abfd5788b8aee145edc959e6c..07cbcd634ec7b46bd0e66a52f62989660575765f 100644 --- a/theodolite/src/main/kotlin/theodolite/evaluation/SloTypes.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/slo/SloTypes.kt @@ -1,4 +1,4 @@ -package theodolite.evaluation +package rocks.theodolite.kubernetes.slo enum class SloTypes(val value: String) { GENERIC("generic"), diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/standalone/TheodoliteStandalone.kt similarity index 73% rename from theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/standalone/TheodoliteStandalone.kt index 1bbf3e01f461a19dbe588aedd41be63b84c86162..8cf3959b95374183a989a0217d754aea7eab716a 100644 --- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteStandalone.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/standalone/TheodoliteStandalone.kt @@ -1,14 +1,18 @@ -package theodolite.execution +package rocks.theodolite.kubernetes.standalone +import io.fabric8.kubernetes.client.NamespacedKubernetesClient import mu.KotlinLogging -import theodolite.benchmark.BenchmarkExecution -import theodolite.benchmark.KubernetesBenchmark -import theodolite.util.YamlParserFromFile -import theodolite.util.EvaluationFailedException -import theodolite.util.ExecutionFailedException +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.TheodoliteExecutor +import rocks.theodolite.kubernetes.util.YamlParserFromFile +import rocks.theodolite.kubernetes.slo.EvaluationFailedException +import rocks.theodolite.kubernetes.ExecutionFailedException +import rocks.theodolite.kubernetes.Shutdown import kotlin.concurrent.thread import kotlin.system.exitProcess + private val logger = KotlinLogging.logger {} @@ -27,7 +31,7 @@ private val logger = KotlinLogging.logger {} * * @constructor Create empty Theodolite yaml executor */ -class TheodoliteStandalone { +class TheodoliteStandalone (private val client: NamespacedKubernetesClient) { private val parser = YamlParserFromFile() fun start() { @@ -48,11 +52,11 @@ class TheodoliteStandalone { // Add shutdown hook // Use thread{} with start = false, else the thread will start right away - val shutdown = thread(start = false) { Shutdown(benchmarkExecution, benchmark).run() } + val shutdown = thread(start = false) { Shutdown(benchmarkExecution, benchmark, client).run() } Runtime.getRuntime().addShutdownHook(shutdown) try { - TheodoliteExecutor(benchmarkExecution, benchmark).run() + TheodoliteExecutor(benchmarkExecution, benchmark, client).setupAndRunExecution() } catch (e: EvaluationFailedException) { logger.error { "Evaluation failed with error: ${e.message}" } }catch (e: ExecutionFailedException) { diff --git a/theodolite/src/main/kotlin/theodolite/util/ConfigurationOverride.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/ConfigurationOverride.kt similarity index 81% rename from theodolite/src/main/kotlin/theodolite/util/ConfigurationOverride.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/ConfigurationOverride.kt index 537b44721bb344c2cd7af71d29dc4fa3da5a7a33..4b054d61c15c13b2058fd4848dd69fc4633610c8 100644 --- a/theodolite/src/main/kotlin/theodolite/util/ConfigurationOverride.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/ConfigurationOverride.kt @@ -1,7 +1,8 @@ -package theodolite.util +package rocks.theodolite.kubernetes.util import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.quarkus.runtime.annotations.RegisterForReflection +import rocks.theodolite.kubernetes.patcher.PatcherDefinition /** * Representation of a configuration override. diff --git a/theodolite/src/main/kotlin/theodolite/util/Parser.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/Parser.kt similarity index 89% rename from theodolite/src/main/kotlin/theodolite/util/Parser.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/Parser.kt index e435b1cbbf18b9f860ceda69f5f7ec66e64c9375..65cd6a39303d3f0f0814c7197bbe15b4919be5d7 100644 --- a/theodolite/src/main/kotlin/theodolite/util/Parser.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/Parser.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.kubernetes.util /** * Interface for parsers. diff --git a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromFile.kt similarity index 92% rename from theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromFile.kt index 58ca925e6aeeaca4f2f35c97c027ee2d24188e50..f6a1179a880631dea7471b68b34c0823400aaadc 100644 --- a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromFile.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromFile.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.kubernetes.util import org.yaml.snakeyaml.Yaml import org.yaml.snakeyaml.constructor.Constructor diff --git a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromString.kt similarity index 90% rename from theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt rename to theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromString.kt index 99c81f1ed674b2aa21f6aec7b3e0dff1b8c86840..288414422963ad3de8f6b853b949b4af7939bf6a 100644 --- a/theodolite/src/main/kotlin/theodolite/util/YamlParserFromString.kt +++ b/theodolite/src/main/kotlin/rocks/theodolite/kubernetes/util/YamlParserFromString.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.kubernetes.util import org.yaml.snakeyaml.Yaml import org.yaml.snakeyaml.constructor.Constructor diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt deleted file mode 100644 index cf2fac7337d79c1c5daf2b0fac070200cf27f9a5..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/benchmark/Benchmark.kt +++ /dev/null @@ -1,31 +0,0 @@ -package theodolite.benchmark - -import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.ConfigurationOverride -import theodolite.util.LoadDimension -import theodolite.util.Resource - -/** - * A Benchmark contains: - * - The [Resource]s that can be scaled for the benchmark. - * - The [LoadDimension]s that can be scaled the benchmark. - * - additional [ConfigurationOverride]s. - */ -@RegisterForReflection -interface Benchmark { - - fun setupInfrastructure() - fun teardownInfrastructure() - - /** - * Builds a Deployment that can be deployed. - * @return a BenchmarkDeployment. - */ - fun buildDeployment( - load: LoadDimension, - res: Resource, - configurationOverrides: List<ConfigurationOverride?>, - loadGenerationDelay: Long, - afterTeardownDelay: Long - ): BenchmarkDeployment -} diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt b/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt deleted file mode 100644 index 6857b9bf8918593dbe5085f40eb28fd8bd809d85..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/benchmark/KubernetesBenchmark.kt +++ /dev/null @@ -1,144 +0,0 @@ -package theodolite.benchmark - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import io.fabric8.kubernetes.api.model.HasMetadata -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.client.DefaultKubernetesClient -import io.fabric8.kubernetes.client.NamespacedKubernetesClient -import io.quarkus.runtime.annotations.RegisterForReflection -import mu.KotlinLogging -import theodolite.k8s.K8sManager -import theodolite.patcher.PatcherFactory -import theodolite.util.* - - -private val logger = KotlinLogging.logger {} - -private var DEFAULT_NAMESPACE = "default" -private var DEFAULT_THEODOLITE_APP_RESOURCES = "./benchmark-resources" - -/** - * Represents a benchmark in Kubernetes. An example for this is the BenchmarkType.yaml - * Contains a of: - * - [name] of the benchmark, - * - [appResource] list of the resources that have to be deployed for the benchmark, - * - [loadGenResource] resource that generates the load, - * - [resourceTypes] types of scaling resources, - * - [loadTypes] types of loads that can be scaled for the benchmark, - * - [kafkaConfig] for the [theodolite.k8s.TopicManager], - * - [namespace] for the client, - * - [path] under which the resource yamls can be found. - * - * This class is used for the parsing(in the [theodolite.execution.TheodoliteStandalone]) and - * for the deserializing in the [theodolite.execution.operator.TheodoliteOperator]. - * @constructor construct an empty Benchmark. - */ -@JsonDeserialize -@RegisterForReflection -class KubernetesBenchmark : KubernetesResource, Benchmark { - lateinit var name: String - lateinit var resourceTypes: List<TypeName> - lateinit var loadTypes: List<TypeName> - var kafkaConfig: KafkaConfig? = null - lateinit var infrastructure: Resources - lateinit var sut: Resources - lateinit var loadGenerator: Resources - private var namespace = System.getenv("NAMESPACE") ?: DEFAULT_NAMESPACE - - @Transient - private var client: NamespacedKubernetesClient = DefaultKubernetesClient().inNamespace(namespace) - - /** - * Loads [KubernetesResource]s. - * It first loads them via the [YamlParserFromFile] to check for their concrete type and afterwards initializes them using - * the [K8sResourceLoader] - */ - @Deprecated("Use `loadResourceSet` from `ResourceSets`") - fun loadKubernetesResources(resourceSet: List<ResourceSets>): Collection<Pair<String, HasMetadata>> { - return loadResources(resourceSet) - } - - private fun loadResources(resourceSet: List<ResourceSets>): Collection<Pair<String, HasMetadata>> { - return resourceSet.flatMap { it.loadResourceSet(this.client) } - } - - override fun setupInfrastructure() { - this.infrastructure.beforeActions.forEach { it.exec(client = client) } - val kubernetesManager = K8sManager(this.client) - loadResources(this.infrastructure.resources) - .map { it.second } - .forEach { kubernetesManager.deploy(it) } - } - - override fun teardownInfrastructure() { - val kubernetesManager = K8sManager(this.client) - loadResources(this.infrastructure.resources) - .map { it.second } - .forEach { kubernetesManager.remove(it) } - this.infrastructure.afterActions.forEach { it.exec(client = client) } - } - - /** - * Builds a deployment. - * First loads all required resources and then patches them to the concrete load and resources for the experiment. - * Afterwards patches additional configurations(cluster depending) into the resources. - * @param load concrete load that will be benchmarked in this experiment. - * @param res concrete resource that will be scaled for this experiment. - * @param configurationOverrides - * @return a [BenchmarkDeployment] - */ - override fun buildDeployment( - load: LoadDimension, - res: Resource, - configurationOverrides: List<ConfigurationOverride?>, - loadGenerationDelay: Long, - afterTeardownDelay: Long - ): BenchmarkDeployment { - logger.info { "Using $namespace as namespace." } - - val appResources = loadResources(this.sut.resources) - val loadGenResources = loadResources(this.loadGenerator.resources) - - val patcherFactory = PatcherFactory() - - // patch the load dimension the resources - load.getType().forEach { patcherDefinition -> - patcherFactory.createPatcher(patcherDefinition, loadGenResources).patch(load.get().toString()) - } - res.getType().forEach { patcherDefinition -> - patcherFactory.createPatcher(patcherDefinition, appResources).patch(res.get().toString()) - } - - // Patch the given overrides - configurationOverrides.forEach { override -> - override?.let { - patcherFactory.createPatcher(it.patcher, appResources + loadGenResources).patch(override.value) - } - } - - val kafkaConfig = this.kafkaConfig - - return KubernetesBenchmarkDeployment( - sutBeforeActions = sut.beforeActions, - sutAfterActions = sut.afterActions, - loadGenBeforeActions = loadGenerator.beforeActions, - loadGenAfterActions = loadGenerator.afterActions, - appResources = appResources.map { it.second }, - loadGenResources = loadGenResources.map { it.second }, - loadGenerationDelay = loadGenerationDelay, - afterTeardownDelay = afterTeardownDelay, - kafkaConfig = if (kafkaConfig != null) mapOf("bootstrap.servers" to kafkaConfig.bootstrapServer) else mapOf(), - topics = kafkaConfig?.topics ?: listOf(), - client = this.client - ) - } - - /** - * This function can be used to set the Kubernetes client manually. This is for example necessary for testing. - * - * @param client - */ - fun setClient(client: NamespacedKubernetesClient) { - this.client = client - } -} diff --git a/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt b/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt deleted file mode 100644 index fccbd2c41a646a2ef85ef77c65763e7f793d1e91..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/benchmark/Resources.kt +++ /dev/null @@ -1,14 +0,0 @@ -package theodolite.benchmark - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import io.quarkus.runtime.annotations.RegisterForReflection - -@JsonDeserialize -@RegisterForReflection -class Resources { - - lateinit var resources: List<ResourceSets> - lateinit var beforeActions: List<Action> - lateinit var afterActions: List<Action> - -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt deleted file mode 100644 index 3238f447be06ce6486bb7f6ca1758700f36ba558..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/execution/BenchmarkExecutor.kt +++ /dev/null @@ -1,70 +0,0 @@ -package theodolite.execution - -import mu.KotlinLogging -import theodolite.benchmark.Benchmark -import theodolite.benchmark.BenchmarkExecution -import theodolite.util.ConfigurationOverride -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results -import java.time.Duration -import java.util.concurrent.atomic.AtomicBoolean - -private val logger = KotlinLogging.logger {} - -/** - * The Benchmark Executor runs a single experiment. - * - * @property benchmark - * @property results - * @property executionDuration - * @constructor Create empty Benchmark executor - */ -abstract class BenchmarkExecutor( - val benchmark: Benchmark, - val results: Results, - val executionDuration: Duration, - val configurationOverrides: List<ConfigurationOverride?>, - val slos: List<BenchmarkExecution.Slo>, - val repetitions: Int, - val executionId: Int, - val loadGenerationDelay: Long, - val afterTeardownDelay: Long, - val executionName: String -) { - - var run: AtomicBoolean = AtomicBoolean(true) - - /** - * Run a experiment for the given parametrization, evaluate the - * experiment and save the result. - * - * @param load load to be tested. - * @param res resources to be tested. - * @return True, if the number of resources are suitable for the - * given load, false otherwise. - */ - abstract fun runExperiment(load: LoadDimension, res: Resource): Boolean - - /** - * Wait while the benchmark is running and log the number of minutes executed every 1 minute. - * - */ - fun waitAndLog() { - logger.info { "Execution of a new experiment started." } - - var secondsRunning = 0L - - while (run.get() && secondsRunning < executionDuration.toSeconds()) { - secondsRunning++ - Thread.sleep(Duration.ofSeconds(1).toMillis()) - - if ((secondsRunning % 60) == 0L) { - logger.info { "Executed: ${secondsRunning / 60} minutes." } - } - } - - logger.debug { "Executor shutdown gracefully." } - - } -} diff --git a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt b/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt deleted file mode 100644 index 8596576e0a7984c32b6dabf90c6bbf06961d2bb1..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/execution/TheodoliteExecutor.kt +++ /dev/null @@ -1,164 +0,0 @@ -package theodolite.execution - -import mu.KotlinLogging -import theodolite.benchmark.BenchmarkExecution -import theodolite.benchmark.KubernetesBenchmark -import theodolite.patcher.PatcherDefinitionFactory -import theodolite.strategies.StrategyFactory -import theodolite.strategies.searchstrategy.CompositeStrategy -import theodolite.util.* -import java.io.File -import java.time.Duration - - -private val logger = KotlinLogging.logger {} - -/** - * The Theodolite executor runs all the experiments defined with the given execution and benchmark configuration. - * - * @property config Configuration of a execution - * @property kubernetesBenchmark Configuration of a benchmark - * @constructor Create empty Theodolite executor - */ -class TheodoliteExecutor( - private val config: BenchmarkExecution, - private val kubernetesBenchmark: KubernetesBenchmark -) { - /** - * An executor object, configured with the specified benchmark, evaluation method, experiment duration - * and overrides which are given in the execution. - */ - lateinit var executor: BenchmarkExecutor - - /** - * Creates all required components to start Theodolite. - * - * @return a [Config], that contains a list of [LoadDimension]s, - * a list of [Resource]s , and the [CompositeStrategy]. - * The [CompositeStrategy] is configured and able to find the minimum required resource for the given load. - */ - private fun buildConfig(): Config { - val results = Results() - val strategyFactory = StrategyFactory() - - val executionDuration = Duration.ofSeconds(config.execution.duration) - - val resourcePatcherDefinition = - PatcherDefinitionFactory().createPatcherDefinition( - config.resources.resourceType, - this.kubernetesBenchmark.resourceTypes - ) - - val loadDimensionPatcherDefinition = - PatcherDefinitionFactory().createPatcherDefinition( - config.load.loadType, - this.kubernetesBenchmark.loadTypes - ) - - executor = - BenchmarkExecutorImpl( - benchmark = kubernetesBenchmark, - results = results, - executionDuration = executionDuration, - configurationOverrides = config.configOverrides, - slos = config.slos, - repetitions = config.execution.repetitions, - executionId = config.executionId, - loadGenerationDelay = config.execution.loadGenerationDelay, - afterTeardownDelay = config.execution.afterTeardownDelay, - executionName = config.name - ) - - if (config.load.loadValues != config.load.loadValues.sorted()) { - config.load.loadValues = config.load.loadValues.sorted() - logger.info { - "Load values are not sorted correctly, Theodolite sorts them in ascending order." + - "New order is: ${config.load.loadValues}" - } - } - - if (config.resources.resourceValues != config.resources.resourceValues.sorted()) { - config.resources.resourceValues = config.resources.resourceValues.sorted() - logger.info { - "Load values are not sorted correctly, Theodolite sorts them in ascending order." + - "New order is: ${config.resources.resourceValues}" - } - } - - return Config( - loads = config.load.loadValues.map { load -> LoadDimension(load, loadDimensionPatcherDefinition) }, - resources = config.resources.resourceValues.map { resource -> - Resource( - resource, - resourcePatcherDefinition - ) - }, - compositeStrategy = CompositeStrategy( - benchmarkExecutor = executor, - searchStrategy = strategyFactory.createSearchStrategy(executor, config.execution.strategy), - restrictionStrategies = strategyFactory.createRestrictionStrategy( - results, - config.execution.restrictions - ) - ) - ) - } - - fun getExecution(): BenchmarkExecution { - return this.config - } - - /** - * Run all experiments which are specified in the corresponding - * execution and benchmark objects. - */ - fun run() { - kubernetesBenchmark.setupInfrastructure() - - val ioHandler = IOHandler() - val resultsFolder = ioHandler.getResultFolderURL() - this.config.executionId = getAndIncrementExecutionID(resultsFolder + "expID.txt") - ioHandler.writeToJSONFile(this.config, "${resultsFolder}exp${this.config.executionId}-execution-configuration") - ioHandler.writeToJSONFile( - kubernetesBenchmark, - "${resultsFolder}exp${this.config.executionId}-benchmark-configuration" - ) - - val config = buildConfig() - // execute benchmarks for each load - try { - for (load in config.loads) { - if (executor.run.get()) { - config.compositeStrategy.findSuitableResource(load, config.resources) - } - } - } finally { - ioHandler.writeToJSONFile( - config.compositeStrategy.benchmarkExecutor.results, - "${resultsFolder}exp${this.config.executionId}-result" - ) - // Create expXYZ_demand.csv file - ioHandler.writeToCSVFile( - "${resultsFolder}exp${this.config.executionId}_demand", - calculateDemandMetric(config.loads, config.compositeStrategy.benchmarkExecutor.results), - listOf("load","resources") - ) - } - kubernetesBenchmark.teardownInfrastructure() - } - - private fun getAndIncrementExecutionID(fileURL: String): Int { - val ioHandler = IOHandler() - var executionID = 0 - if (File(fileURL).exists()) { - executionID = ioHandler.readFileAsString(fileURL).toInt() + 1 - } - ioHandler.writeStringToTextFile(fileURL, (executionID).toString()) - return executionID - } - - private fun calculateDemandMetric(loadDimensions: List<LoadDimension>, results: Results): List<List<String>> { - return loadDimensions.map { listOf(it.get().toString(), results.getMinRequiredInstances(it).get().toString()) } - } - -} diff --git a/theodolite/src/main/kotlin/theodolite/k8s/K8sManager.kt b/theodolite/src/main/kotlin/theodolite/k8s/K8sManager.kt deleted file mode 100644 index 5b4880b45db76d9e68e87fda0ece5b04966439c8..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/k8s/K8sManager.kt +++ /dev/null @@ -1,52 +0,0 @@ -package theodolite.k8s - -import io.fabric8.kubernetes.api.model.ConfigMap -import io.fabric8.kubernetes.api.model.HasMetadata -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.Service -import io.fabric8.kubernetes.api.model.apps.Deployment -import io.fabric8.kubernetes.api.model.apps.StatefulSet -import io.fabric8.kubernetes.client.NamespacedKubernetesClient -import mu.KotlinLogging - -private val logger = KotlinLogging.logger {} - -/** - * This class is used to deploy or remove different Kubernetes resources. - * Supports: Deployments, Services, ConfigMaps, StatefulSets, and CustomResources. - * @param client KubernetesClient used to deploy or remove. - */ -class K8sManager(private val client: NamespacedKubernetesClient) { - - /** - * Deploys different k8s resources using the client. - * @throws IllegalArgumentException if KubernetesResource not supported. - */ - fun deploy(resource: HasMetadata) { - client.resource(resource).createOrReplace() - } - - /** - * Removes different k8s resources using the client. - * @throws IllegalArgumentException if KubernetesResource not supported. - */ - fun remove(resource: HasMetadata) { - client.resource(resource).delete() - when (resource) { - is Deployment -> { - ResourceByLabelHandler(client = client) - .blockUntilPodsDeleted( - matchLabels = resource.spec.selector.matchLabels - ) - logger.info { "Deployment '${resource.metadata.name}' deleted." } - } - is StatefulSet -> { - ResourceByLabelHandler(client = client) - .blockUntilPodsDeleted( - matchLabels = resource.spec.selector.matchLabels - ) - logger.info { "StatefulSet '$resource.metadata.name' deleted." } - } - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt deleted file mode 100644 index df80e9cbd2503685a7dbed35db5319920dfc42cb..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/AbstractPatcher.kt +++ /dev/null @@ -1,24 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource - -/** - * A Patcher is able to modify values of a Kubernetes resource, see [Patcher]. - * - * An AbstractPatcher is created with up to three parameters. - * - * @param k8sResource The Kubernetes resource to be patched. - * @param container *(optional)* The name of the container to be patched - * @param variableName *(optional)* The variable name to be patched - * - * - * **For example** to patch the load dimension of a load generator, the patcher should be created as follow: - * - * k8sResource: `uc-1-workload-generator.yaml` - * container: `workload` - * variableName: `NUM_SENSORS` - * - */ -abstract class AbstractPatcher( - k8sResource: KubernetesResource -) : Patcher diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ImagePatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/ImagePatcher.kt deleted file mode 100644 index 8f6753372076c119324dc962112928253633b6b0..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/ImagePatcher.kt +++ /dev/null @@ -1,27 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment -import io.fabric8.kubernetes.api.model.apps.StatefulSet - -/** - * The Image patcher allows to change the image of a container. - * - * @param k8sResource Kubernetes resource to be patched. - * @param container Container to be patched. - */ -class ImagePatcher(private val k8sResource: KubernetesResource, private val container: String) : - AbstractPatcher(k8sResource) { - - override fun <String> patch(imagePath: String) { - if (k8sResource is Deployment) { - k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach { - it.image = imagePath as kotlin.String - } - } else if (k8sResource is StatefulSet) { - k8sResource.spec.template.spec.containers.filter { it.name == container }.forEach { - it.image = imagePath as kotlin.String - } - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/LabelPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/LabelPatcher.kt deleted file mode 100644 index 2f8c703afa9e826a79f0785abef493d2d448ac74..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/LabelPatcher.kt +++ /dev/null @@ -1,49 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.ConfigMap -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.Service -import io.fabric8.kubernetes.api.model.apps.Deployment -import io.fabric8.kubernetes.api.model.apps.StatefulSet -import io.fabric8.kubernetes.client.CustomResource - -class LabelPatcher(private val k8sResource: KubernetesResource, val variableName: String) : - AbstractPatcher(k8sResource) { - - override fun <String> patch(labelValue: String) { - if (labelValue is kotlin.String) { - when (k8sResource) { - is Deployment -> { - if (k8sResource.metadata.labels == null) { - k8sResource.metadata.labels = mutableMapOf() - } - k8sResource.metadata.labels[this.variableName] = labelValue - } - is StatefulSet -> { - if (k8sResource.metadata.labels == null) { - k8sResource.metadata.labels = mutableMapOf() - } - k8sResource.metadata.labels[this.variableName] = labelValue - } - is Service -> { - if (k8sResource.metadata.labels == null) { - k8sResource.metadata.labels = mutableMapOf() - } - k8sResource.metadata.labels[this.variableName] = labelValue - } - is ConfigMap -> { - if (k8sResource.metadata.labels == null) { - k8sResource.metadata.labels = mutableMapOf() - } - k8sResource.metadata.labels[this.variableName] = labelValue - } - is CustomResource<*, *> -> { - if (k8sResource.metadata.labels == null) { - k8sResource.metadata.labels = mutableMapOf() - } - k8sResource.metadata.labels[this.variableName] = labelValue - } - } - } - } -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/patcher/MatchLabelPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/MatchLabelPatcher.kt deleted file mode 100644 index 30ff73b5da3b551119ad085adbc982180e4fc066..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/MatchLabelPatcher.kt +++ /dev/null @@ -1,34 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment -import io.fabric8.kubernetes.api.model.apps.StatefulSet - -/** - * This patcher is able to set the `spec.selector.matchLabels` for a `Deployment` or `StatefulSet` Kubernetes resource. - * - * @property k8sResource The Kubernetes manifests to patch - * @property variableName The matchLabel which should be set - */ -class MatchLabelPatcher(private val k8sResource: KubernetesResource, val variableName: String) : - AbstractPatcher(k8sResource) { - - override fun <String> patch(labelValue: String) { - if (labelValue is kotlin.String) { - when (k8sResource) { - is Deployment -> { - if (k8sResource.spec.selector.matchLabels == null) { - k8sResource.spec.selector.matchLabels = mutableMapOf() - } - k8sResource.spec.selector.matchLabels[this.variableName] = labelValue - } - is StatefulSet -> { - if (k8sResource.spec.selector.matchLabels == null) { - k8sResource.spec.selector.matchLabels = mutableMapOf() - } - k8sResource.spec.selector.matchLabels[this.variableName] = labelValue - } - } - } - } -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt deleted file mode 100644 index 0e8cd553a6c6a9ed6fa2c8cc1b84e4cfebe79d73..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/NodeSelectorPatcher.kt +++ /dev/null @@ -1,19 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment - -/** - * The Node selector patcher make it possible to set the NodeSelector of a Kubernetes deployment. - * - * @param k8sResource Kubernetes resource to be patched. - * @param variableName The `label-key` of the node for which the `label-value` is to be patched. - */ -class NodeSelectorPatcher(private val k8sResource: KubernetesResource, private val variableName: String) : - AbstractPatcher(k8sResource) { - override fun <String> patch(value: String) { - if (k8sResource is Deployment) { - k8sResource.spec.template.spec.nodeSelector = mapOf(variableName to value as kotlin.String) - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt deleted file mode 100644 index c617917e6894c3a30779dd4257a96365ded35481..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/NumNestedGroupsLoadGeneratorReplicaPatcher.kt +++ /dev/null @@ -1,23 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment -import kotlin.math.pow - -class NumNestedGroupsLoadGeneratorReplicaPatcher( - private val k8sResource: KubernetesResource, - private val numSensors: String, - private val loadGenMaxRecords: String -) : - AbstractPatcher(k8sResource) { - override fun <String> patch(value: String) { - if (k8sResource is Deployment) { - if (value is kotlin.String) { - val approxNumSensors = numSensors.toDouble().pow(Integer.parseInt(value).toDouble()) - val loadGenInstances = - (approxNumSensors + loadGenMaxRecords.toDouble() - 1) / loadGenMaxRecords.toDouble() - this.k8sResource.spec.replicas = loadGenInstances.toInt() - } - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt deleted file mode 100644 index 86bb37db3cb9fd0d3bca1690d5eb4e622329a9bc..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/NumSensorsLoadGeneratorReplicaPatcher.kt +++ /dev/null @@ -1,21 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment - - -class NumSensorsLoadGeneratorReplicaPatcher( - private val k8sResource: KubernetesResource, - private val loadGenMaxRecords: String -) : - AbstractPatcher(k8sResource) { - override fun <String> patch(value: String) { - if (k8sResource is Deployment) { - if (value is kotlin.String) { - val loadGenInstances = - (Integer.parseInt(value) + loadGenMaxRecords.toInt() - 1) / loadGenMaxRecords.toInt() - this.k8sResource.spec.replicas = loadGenInstances - } - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt b/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt deleted file mode 100644 index e92de4dba7de298c9df76600f2c6785f5878103e..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/PatcherFactory.kt +++ /dev/null @@ -1,103 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import theodolite.util.InvalidPatcherConfigurationException -import theodolite.util.PatcherDefinition - -/** - * The Patcher factory creates [Patcher]s - * - * @constructor Creates an empty PatcherFactory. - */ -class PatcherFactory { - /** - * Create patcher based on the given [PatcherDefinition] and - * the list of KubernetesResources. - * - * @param patcherDefinition The [PatcherDefinition] for which are - * [Patcher] should be created. - * @param k8sResources List of all available Kubernetes resources. - * This is a list of pairs<String, KubernetesResource>: - * The frist corresponds to the filename where the resource is defined. - * The second corresponds to the concrete [KubernetesResource] that should be patched. - * @return The created [Patcher]. - * @throws IllegalArgumentException if no patcher can be created. - */ - fun createPatcher( - patcherDefinition: PatcherDefinition, - k8sResources: Collection<Pair<String, KubernetesResource>> - ): Patcher { - val resource = - k8sResources.filter { it.first == patcherDefinition.resource } - .map { resource -> resource.second } - .firstOrNull() - ?: throw InvalidPatcherConfigurationException("Could not find resource ${patcherDefinition.resource}") - - return try { - when (patcherDefinition.type) { - "ReplicaPatcher" -> ReplicaPatcher( - k8sResource = resource - ) - "NumNestedGroupsLoadGeneratorReplicaPatcher" -> NumNestedGroupsLoadGeneratorReplicaPatcher( - k8sResource = resource, - loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!!, - numSensors = patcherDefinition.properties["numSensors"]!! - ) - "NumSensorsLoadGeneratorReplicaPatcher" -> NumSensorsLoadGeneratorReplicaPatcher( - k8sResource = resource, - loadGenMaxRecords = patcherDefinition.properties["loadGenMaxRecords"]!! - ) - "DataVolumeLoadGeneratorReplicaPatcher" -> DataVolumeLoadGeneratorReplicaPatcher( - k8sResource = resource, - maxVolume = patcherDefinition.properties["maxVolume"]!!.toInt(), - container = patcherDefinition.properties["container"]!!, - variableName = patcherDefinition.properties["variableName"]!! - ) - "EnvVarPatcher" -> EnvVarPatcher( - k8sResource = resource, - container = patcherDefinition.properties["container"]!!, - variableName = patcherDefinition.properties["variableName"]!! - ) - "NodeSelectorPatcher" -> NodeSelectorPatcher( - k8sResource = resource, - variableName = patcherDefinition.properties["variableName"]!! - ) - "ResourceLimitPatcher" -> ResourceLimitPatcher( - k8sResource = resource, - container = patcherDefinition.properties["container"]!!, - limitedResource = patcherDefinition.properties["limitedResource"]!! - ) - "ResourceRequestPatcher" -> ResourceRequestPatcher( - k8sResource = resource, - container = patcherDefinition.properties["container"]!!, - requestedResource = patcherDefinition.properties["requestedResource"]!! - ) - "SchedulerNamePatcher" -> SchedulerNamePatcher( - k8sResource = resource - ) - "LabelPatcher" -> LabelPatcher( - k8sResource = resource, - variableName = patcherDefinition.properties["variableName"]!! - ) - "MatchLabelPatcher" -> MatchLabelPatcher( - k8sResource = resource, - variableName = patcherDefinition.properties["variableName"]!! - ) - "TemplateLabelPatcher" -> TemplateLabelPatcher( - k8sResource = resource, - variableName = patcherDefinition.properties["variableName"]!! - ) - "ImagePatcher" -> ImagePatcher( - k8sResource = resource, - container = patcherDefinition.properties["container"]!! - ) - else -> throw InvalidPatcherConfigurationException("Patcher type ${patcherDefinition.type} not found.") - } - } catch (e: NullPointerException) { - throw InvalidPatcherConfigurationException( - "Could not create patcher with type ${patcherDefinition.type}" + - " Probably a required patcher argument was not specified.", e - ) - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt deleted file mode 100644 index 4cc35f2ed74f9e366c266c3f98f1b3d36d4ba1b8..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/ReplicaPatcher.kt +++ /dev/null @@ -1,19 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment - -/** - * The Replica [Patcher] modifies the number of replicas for the given Kubernetes deployment. - * - * @param k8sResource Kubernetes resource to be patched. - */ -class ReplicaPatcher(private val k8sResource: KubernetesResource) : AbstractPatcher(k8sResource) { - override fun <String> patch(value: String) { - if (k8sResource is Deployment) { - if (value is kotlin.String) { - this.k8sResource.spec.replicas = Integer.parseInt(value) - } - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt deleted file mode 100644 index 348f0c50090a34c91221d3e099c3532375a578da..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/SchedulerNamePatcher.kt +++ /dev/null @@ -1,17 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment - -/** - * The Scheduler name [Patcher] make it possible to set the scheduler which should - * be used to deploy the given deployment. - * @param k8sResource Kubernetes resource to be patched. - */ -class SchedulerNamePatcher(private val k8sResource: KubernetesResource) : Patcher { - override fun <String> patch(value: String) { - if (k8sResource is Deployment) { - k8sResource.spec.template.spec.schedulerName = value as kotlin.String - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/patcher/TemplateLabelPatcher.kt b/theodolite/src/main/kotlin/theodolite/patcher/TemplateLabelPatcher.kt deleted file mode 100644 index a524e5c40f90ccf98dc95003cc33dcfceb6f8598..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/patcher/TemplateLabelPatcher.kt +++ /dev/null @@ -1,34 +0,0 @@ -package theodolite.patcher - -import io.fabric8.kubernetes.api.model.KubernetesResource -import io.fabric8.kubernetes.api.model.apps.Deployment -import io.fabric8.kubernetes.api.model.apps.StatefulSet - -/** - * This patcher is able to set the field `spec.template.metadata.labels` for a `Deployment` or `StatefulSet` Kubernetes resource. - * - * @property k8sResource The Kubernetes manifests to patch - * @property variableName The label which should be set - */ -class TemplateLabelPatcher(private val k8sResource: KubernetesResource, val variableName: String) : - AbstractPatcher(k8sResource) { - - override fun <String> patch(labelValue: String) { - if (labelValue is kotlin.String) { - when (k8sResource) { - is Deployment -> { - if (k8sResource.spec.template.metadata.labels == null) { - k8sResource.spec.template.metadata.labels = mutableMapOf() - } - k8sResource.spec.template.metadata.labels[this.variableName] = labelValue - } - is StatefulSet -> { - if (k8sResource.spec.template.metadata.labels == null) { - k8sResource.spec.template.metadata.labels = mutableMapOf() - } - k8sResource.spec.template.metadata.labels[this.variableName] = labelValue - } - } - } - } -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt b/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt deleted file mode 100644 index 829370e8ce1c181c1a4cb9fdd8ccf0ecefd48d3d..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/StrategyFactory.kt +++ /dev/null @@ -1,54 +0,0 @@ -package theodolite.strategies - -import theodolite.execution.BenchmarkExecutor -import theodolite.strategies.restriction.LowerBoundRestriction -import theodolite.strategies.restriction.RestrictionStrategy -import theodolite.strategies.searchstrategy.BinarySearch -import theodolite.strategies.searchstrategy.FullSearch -import theodolite.strategies.searchstrategy.LinearSearch -import theodolite.strategies.searchstrategy.SearchStrategy -import theodolite.util.Results - -/** - * Factory for creating [SearchStrategy] and [RestrictionStrategy] strategies. - */ -class StrategyFactory { - - /** - * Create a [SearchStrategy]. - * - * @param executor The [theodolite.execution.BenchmarkExecutor] that executes individual experiments. - * @param searchStrategyString Specifies the [SearchStrategy]. Must either be the string 'LinearSearch', - * or 'BinarySearch'. - * - * @throws IllegalArgumentException if the [SearchStrategy] was not one of the allowed options. - */ - fun createSearchStrategy(executor: BenchmarkExecutor, searchStrategyString: String): SearchStrategy { - return when (searchStrategyString) { - "FullSearch" -> FullSearch(executor) - "LinearSearch" -> LinearSearch(executor) - "BinarySearch" -> BinarySearch(executor) - else -> throw IllegalArgumentException("Search Strategy $searchStrategyString not found") - } - } - - /** - * Create a [RestrictionStrategy]. - * - * @param results The [Results] saves the state of the Theodolite benchmark run. - * @param restrictionStrings Specifies the list of [RestrictionStrategy] that are used to restrict the amount - * of [theodolite.util.Resource] for a fixed LoadDimension. Must equal the string - * 'LowerBound'. - * - * @throws IllegalArgumentException if param searchStrategyString was not one of the allowed options. - */ - fun createRestrictionStrategy(results: Results, restrictionStrings: List<String>): Set<RestrictionStrategy> { - return restrictionStrings - .map { restriction -> - when (restriction) { - "LowerBound" -> LowerBoundRestriction(results) - else -> throw IllegalArgumentException("Restriction Strategy $restrictionStrings not found") - } - }.toSet() - } -} diff --git a/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt b/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt deleted file mode 100644 index 13bfedfe055f2bd428137f89b2986f3967ec797c..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/restriction/LowerBoundRestriction.kt +++ /dev/null @@ -1,24 +0,0 @@ -package theodolite.strategies.restriction - -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results - -/** - * The [LowerBoundRestriction] sets the lower bound of the resources to be examined to the value - * needed to successfully execute the next smaller load. - * - * @param results [Result] object used as a basis to restrict the resources. - */ -class LowerBoundRestriction(results: Results) : RestrictionStrategy(results) { - - override fun apply(load: LoadDimension, resources: List<Resource>): List<Resource> { - val maxLoad: LoadDimension? = this.results.getMaxBenchmarkedLoad(load) - var lowerBound: Resource? = this.results.getMinRequiredInstances(maxLoad) - if (lowerBound == null) { - lowerBound = resources[0] - } - return resources.filter { x -> x.get() >= lowerBound.get() } - } - -} diff --git a/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt deleted file mode 100644 index 1ab7302d7898daad729b1c94c32d97138b5cdcf4..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/restriction/RestrictionStrategy.kt +++ /dev/null @@ -1,25 +0,0 @@ -package theodolite.strategies.restriction - -import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results - -/** - * A 'Restriction Strategy' restricts a list of resources based on the current - * results of all previously performed benchmarks. - * - * @param results the [Results] object - */ -@RegisterForReflection -abstract class RestrictionStrategy(val results: Results) { - /** - * Apply the restriction of the given resource list for the given load based on the results object. - * - * @param load [LoadDimension] for which a subset of resources are required. - * @param resources List of [Resource]s to be restricted. - * @return Returns a list containing only elements that have not been filtered out by the - * restriction (possibly empty). - */ - abstract fun apply(load: LoadDimension, resources: List<Resource>): List<Resource> -} diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt deleted file mode 100644 index 28e8194c699cd074026c8cb7e6f3ce4ec347023b..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/BinarySearch.kt +++ /dev/null @@ -1,61 +0,0 @@ -package theodolite.strategies.searchstrategy - -import mu.KotlinLogging -import theodolite.execution.BenchmarkExecutor -import theodolite.util.LoadDimension -import theodolite.util.Resource - -private val logger = KotlinLogging.logger {} - -/** - * Binary-search-like implementation for determining the smallest suitable number of instances. - * - * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. - */ -class BinarySearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) { - override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { - val result = binarySearch(load, resources, 0, resources.size - 1) - if (result == -1) { - return null - } - return resources[result] - } - - /** - * Apply binary search. - * - * @param load the load dimension to perform experiments for - * @param resources the list in which binary search is performed - * @param lower lower bound for binary search (inclusive) - * @param upper upper bound for binary search (inclusive) - */ - private fun binarySearch(load: LoadDimension, resources: List<Resource>, lower: Int, upper: Int): Int { - if (lower > upper) { - throw IllegalArgumentException() - } - // special case: length == 1 or 2 - if (lower == upper) { - val res = resources[lower] - logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } - if (this.benchmarkExecutor.runExperiment(load, resources[lower])) return lower - else { - if (lower + 1 == resources.size) return -1 - return lower + 1 - } - } else { - // apply binary search for a list with - // length > 2 and adjust upper and lower depending on the result for `resources[mid]` - val mid = (upper + lower) / 2 - val res = resources[mid] - logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } - if (this.benchmarkExecutor.runExperiment(load, resources[mid])) { - if (mid == lower) { - return lower - } - return binarySearch(load, resources, lower, mid - 1) - } else { - return binarySearch(load, resources, mid + 1, upper) - } - } - } -} diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt deleted file mode 100644 index d6ace6f564239e73a0d59f8eb7900f50018482c5..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/CompositeStrategy.kt +++ /dev/null @@ -1,30 +0,0 @@ -package theodolite.strategies.searchstrategy - -import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.execution.BenchmarkExecutor -import theodolite.strategies.restriction.RestrictionStrategy -import theodolite.util.LoadDimension -import theodolite.util.Resource - -/** - * Composite strategy that combines a SearchStrategy and a set of RestrictionStrategy. - * - * @param searchStrategy the [SearchStrategy] that is executed as part of this [CompositeStrategy]. - * @param restrictionStrategies the set of [RestrictionStrategy] that are connected conjunctive to restrict the [Resource] - * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. - */ -@RegisterForReflection -class CompositeStrategy( - benchmarkExecutor: BenchmarkExecutor, - private val searchStrategy: SearchStrategy, - val restrictionStrategies: Set<RestrictionStrategy> -) : SearchStrategy(benchmarkExecutor) { - - override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { - var restrictedResources = resources.toList() - for (strategy in this.restrictionStrategies) { - restrictedResources = restrictedResources.intersect(strategy.apply(load, resources).toSet()).toList() - } - return this.searchStrategy.findSuitableResource(load, restrictedResources) - } -} diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt deleted file mode 100644 index 83c4abbdf44f1a1c2f3a27714d796580feedee49..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/FullSearch.kt +++ /dev/null @@ -1,31 +0,0 @@ -package theodolite.strategies.searchstrategy - -import mu.KotlinLogging -import theodolite.execution.BenchmarkExecutor -import theodolite.util.LoadDimension -import theodolite.util.Resource - -private val logger = KotlinLogging.logger {} - -/** - * [SearchStrategy] that executes experiment for provides resources in a linear-search-like fashion, but **without - * stopping** once a suitable resource amount is found. - * - * @see LinearSearch for a SearchStrategy that stops once a suitable resource amount is found. - * - * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. - */ -class FullSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) { - - override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { - var minimalSuitableResources: Resource? = null - for (res in resources) { - logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } - val result = this.benchmarkExecutor.runExperiment(load, res) - if (result && minimalSuitableResources == null) { - minimalSuitableResources = res - } - } - return minimalSuitableResources - } -} diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt deleted file mode 100644 index 786a3baf159e94841c1f76c696f030718e8f768f..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/GuessStrategy.kt +++ /dev/null @@ -1,22 +0,0 @@ -package theodolite.strategies.searchstrategy - -import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.util.Resource - -/** - * Base class for the implementation of Guess strategies. Guess strategies are strategies to determine the resource - * demand we start with in our initial guess search strategy. - */ - -@RegisterForReflection -abstract class GuessStrategy { - /** - * Computing the resource demand for the initial guess search strategy to start with. - * - * @param resources List of all possible [Resource]s. - * @param lastLowestResource Previous resource demand needed for the given load. - * - * @return Returns the resource demand to start the initial guess search strategy with or null - */ - abstract fun firstGuess(resources: List<Resource>, lastLowestResource: Resource?): Resource? -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt deleted file mode 100644 index d97fb62cc9d37dd50122199e5d089c491784e511..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/InitialGuessSearchStrategy.kt +++ /dev/null @@ -1,93 +0,0 @@ -package theodolite.strategies.searchstrategy - -import mu.KotlinLogging -import theodolite.execution.BenchmarkExecutor -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results - -private val logger = KotlinLogging.logger {} - -/** - * Search strategy implementation for determining the smallest suitable resource demand. - * Starting with a resource amount provided by a guess strategy. - * - * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. - * @param guessStrategy Strategy that provides us with a guess for the first resource amount. - * @param results current results of all previously performed benchmarks. - */ -class InitialGuessSearchStrategy(benchmarkExecutor: BenchmarkExecutor, guessStrategy: GuessStrategy, results: Results) : - SearchStrategy(benchmarkExecutor, guessStrategy, results) { - - override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { - - if(resources.isEmpty()) { - logger.info { "You need to specify resources to be checked for the InitialGuessSearchStrategy to work." } - return null - } - - if(guessStrategy == null){ - logger.info { "Your InitialGuessSearchStrategy doesn't have a GuessStrategy. This is not supported." } - return null - } - - if(results == null){ - logger.info { "The results need to be initialized." } - return null - } - - - var lastLowestResource : Resource? = null - - // Getting the lastLowestResource from results and calling firstGuess() with it - if (!results.isEmpty()) { - val maxLoad: LoadDimension? = this.results.getMaxBenchmarkedLoad(load) - lastLowestResource = this.results.getMinRequiredInstances(maxLoad) - if (lastLowestResource.get() == Int.MAX_VALUE) lastLowestResource = null - } - lastLowestResource = this.guessStrategy.firstGuess(resources, lastLowestResource) - - if (lastLowestResource != null) { - val resourcesToCheck: List<Resource> - val startIndex: Int = resources.indexOf(lastLowestResource) - - logger.info { "Running experiment with load '${load.get()}' and resources '${lastLowestResource.get()}'" } - - // If the first experiment passes, starting downward linear search - // otherwise starting upward linear search - if (this.benchmarkExecutor.runExperiment(load, lastLowestResource)) { - - resourcesToCheck = resources.subList(0, startIndex).reversed() - if (resourcesToCheck.isEmpty()) return lastLowestResource - - var currentMin: Resource = lastLowestResource - for (res in resourcesToCheck) { - - logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } - if (this.benchmarkExecutor.runExperiment(load, res)) { - currentMin = res - } - } - return currentMin - } - else { - if (resources.size <= startIndex + 1) { - logger.info{ "No more resources left to check." } - return null - } - resourcesToCheck = resources.subList(startIndex + 1, resources.size) - - for (res in resourcesToCheck) { - - logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } - if (this.benchmarkExecutor.runExperiment(load, res)) return res - } - } - } - else { - logger.info { "InitialGuessSearchStrategy called without lastLowestResource value, which is needed as a " + - "starting point!" } - } - return null - } -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt deleted file mode 100644 index 85deaf6fa75437199bfc560404eb5b40bb4a986a..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/LinearSearch.kt +++ /dev/null @@ -1,25 +0,0 @@ -package theodolite.strategies.searchstrategy - -import mu.KotlinLogging -import theodolite.execution.BenchmarkExecutor -import theodolite.util.LoadDimension -import theodolite.util.Resource - -private val logger = KotlinLogging.logger {} - -/** - * Linear-search-like implementation for determining the smallest suitable number of instances. - * - * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. - */ -class LinearSearch(benchmarkExecutor: BenchmarkExecutor) : SearchStrategy(benchmarkExecutor) { - - override fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? { - for (res in resources) { - - logger.info { "Running experiment with load '${load.get()}' and resources '${res.get()}'" } - if (this.benchmarkExecutor.runExperiment(load, res)) return res - } - return null - } -} diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt deleted file mode 100644 index 413eecea27279cd79bad155fbb7d5d18b674a12e..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/PrevResourceMinGuess.kt +++ /dev/null @@ -1,24 +0,0 @@ -package theodolite.strategies.searchstrategy - -import theodolite.util.Resource - -/** - * This Guess strategy takes the minimal resource demand of the previous load, which is given as an argument for the - * firstGuess function. - */ - -class PrevResourceMinGuess() : GuessStrategy(){ - - /** - * @param resources List of all possible [Resource]s. - * @param lastLowestResource Previous resource demand needed for the given load. - * - * @return the value of lastLowestResource if given otherwise the first element of the resource list or null - */ - override fun firstGuess(resources: List<Resource>, lastLowestResource: Resource?): Resource? { - - if (lastLowestResource != null) return lastLowestResource - else if(resources.isNotEmpty()) return resources[0] - else return null - } -} \ No newline at end of file diff --git a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt b/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt deleted file mode 100644 index 97c723f2cfe459081cbb327f6860e48319c8f4f1..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/strategies/searchstrategy/SearchStrategy.kt +++ /dev/null @@ -1,28 +0,0 @@ -package theodolite.strategies.searchstrategy - -import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.execution.BenchmarkExecutor -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results - -/** - * Base class for the implementation for SearchStrategies. SearchStrategies determine the smallest suitable number of instances. - * - * @param benchmarkExecutor Benchmark executor which runs the individual benchmarks. - * @param guessStrategy Guess strategy for the initial resource amount in case the InitialGuessStrategy is selected. - * @param results the [Results] object. - */ -@RegisterForReflection -abstract class SearchStrategy(val benchmarkExecutor: BenchmarkExecutor, val guessStrategy: GuessStrategy? = null, - val results: Results? = null) { - /** - * Find smallest suitable resource from the specified resource list for the given load. - * - * @param load the [LoadDimension] to be tested. - * @param resources List of all possible [Resource]s. - * - * @return suitable resource for the specified load, or null if no suitable resource exists. - */ - abstract fun findSuitableResource(load: LoadDimension, resources: List<Resource>): Resource? -} diff --git a/theodolite/src/main/kotlin/theodolite/util/Config.kt b/theodolite/src/main/kotlin/theodolite/util/Config.kt deleted file mode 100644 index afbf784e9d6d72939615e367b54891ecd95a3608..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/util/Config.kt +++ /dev/null @@ -1,18 +0,0 @@ -package theodolite.util - -import io.quarkus.runtime.annotations.RegisterForReflection -import theodolite.strategies.searchstrategy.CompositeStrategy - -/** - * Config class that represents a configuration of a theodolite run. - * - * @param loads the [LoadDimension] of the execution - * @param resources the [Resource] of the execution - * @param compositeStrategy the [CompositeStrategy] of the execution - */ -@RegisterForReflection -data class Config( - val loads: List<LoadDimension>, - val resources: List<Resource>, - val compositeStrategy: CompositeStrategy -) diff --git a/theodolite/src/main/kotlin/theodolite/util/LoadDimension.kt b/theodolite/src/main/kotlin/theodolite/util/LoadDimension.kt deleted file mode 100644 index cf26da979b05f0a2bd82289ce371715ea0d67c93..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/util/LoadDimension.kt +++ /dev/null @@ -1,26 +0,0 @@ -package theodolite.util - -import io.quarkus.runtime.annotations.RegisterForReflection - -/** - * Representation of the load dimensions for a execution of theodolite. - * - * @param number the value of this [LoadDimension] - * @param type [PatcherDefinition] of this [LoadDimension] - */ -@RegisterForReflection -data class LoadDimension(private val number: Int, private val type: List<PatcherDefinition>) { - /** - * @return the value of this load dimension. - */ - fun get(): Int { - return this.number - } - - /** - * @return the list of [PatcherDefinition] - */ - fun getType(): List<PatcherDefinition> { - return this.type - } -} diff --git a/theodolite/src/main/kotlin/theodolite/util/Resource.kt b/theodolite/src/main/kotlin/theodolite/util/Resource.kt deleted file mode 100644 index 1d6410aa4288e19817e3ba48bfd1bc0d85d006a2..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/util/Resource.kt +++ /dev/null @@ -1,24 +0,0 @@ -package theodolite.util - -import io.quarkus.runtime.annotations.RegisterForReflection - -/** - * Representation of the resources for an execution of Theodolite. - */ -@RegisterForReflection -data class Resource(private val number: Int, private val type: List<PatcherDefinition>) { - - /** - * @return the value of this resource. - */ - fun get(): Int { - return this.number - } - - /** - * @return the list of [PatcherDefinition] - */ - fun getType(): List<PatcherDefinition> { - return this.type - } -} diff --git a/theodolite/src/main/kotlin/theodolite/util/Results.kt b/theodolite/src/main/kotlin/theodolite/util/Results.kt deleted file mode 100644 index 2221c2e64f6dbc1776122f20793aa8d04d621d9d..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/util/Results.kt +++ /dev/null @@ -1,95 +0,0 @@ -package theodolite.util - -import io.quarkus.runtime.annotations.RegisterForReflection - -/** - * Central class that saves the state of an execution of Theodolite. For an execution, it is used to save the result of - * individual experiments. Further, it is used by the RestrictionStrategy to - * perform the [theodolite.strategies.restriction.RestrictionStrategy]. - */ -@RegisterForReflection -class Results { - private val results: MutableMap<Pair<LoadDimension, Resource>, Boolean> = mutableMapOf() - - /** - * Set the result for an experiment. - * - * @param experiment A pair that identifies the experiment by the [LoadDimension] and [Resource]. - * @param successful the result of the experiment. Successful == true and Unsuccessful == false. - */ - fun setResult(experiment: Pair<LoadDimension, Resource>, successful: Boolean) { - this.results[experiment] = successful - } - - /** - * Get the result for an experiment. - * - * @param experiment A pair that identifies the experiment by the [LoadDimension] and [Resource]. - * @return true if the experiment was successful and false otherwise. If the result has not been reported so far, - * null is returned. - * - * @see Resource - */ - fun getResult(experiment: Pair<LoadDimension, Resource>): Boolean? { - return this.results[experiment] - } - - /** - * Get the smallest suitable number of instances for a specified [LoadDimension]. - * - * @param load the [LoadDimension] - * - * @return the smallest suitable number of resources. If the experiment was not executed yet, - * a @see Resource with the constant Int.MAX_VALUE as value is returned. - * If no experiments have been marked as either successful or unsuccessful - * yet, a Resource with the constant value Int.MIN_VALUE is returned. - */ - fun getMinRequiredInstances(load: LoadDimension?): Resource { - if (this.results.isEmpty()) { - return Resource(Int.MIN_VALUE, emptyList()) - } - - var minRequiredInstances = Resource(Int.MAX_VALUE, emptyList()) - for (experiment in results) { - // Get all successful experiments for requested load - if (experiment.key.first == load && experiment.value) { - if (experiment.key.second.get() < minRequiredInstances.get()) { - // Found new smallest resources - minRequiredInstances = experiment.key.second - } - } - } - return minRequiredInstances - } - - /** - * Get the largest [LoadDimension] that has been reported executed successfully (or unsuccessfully) so far, for a - * [LoadDimension] and is smaller than the given [LoadDimension]. - * - * @param load the [LoadDimension] - * - * @return the largest [LoadDimension] or null, if there is none for this [LoadDimension] - */ - fun getMaxBenchmarkedLoad(load: LoadDimension): LoadDimension? { - var maxBenchmarkedLoad: LoadDimension? = null - for (experiment in results) { - if (experiment.key.first.get() <= load.get()) { - if (maxBenchmarkedLoad == null) { - maxBenchmarkedLoad = experiment.key.first - } else if (maxBenchmarkedLoad.get() < experiment.key.first.get()) { - maxBenchmarkedLoad = experiment.key.first - } - } - } - return maxBenchmarkedLoad - } - - /** - * Checks whether the results are empty. - * - * @return true if [results] is empty. - */ - fun isEmpty(): Boolean{ - return results.isEmpty() - } -} diff --git a/theodolite/src/main/kotlin/theodolite/util/TypeName.kt b/theodolite/src/main/kotlin/theodolite/util/TypeName.kt deleted file mode 100644 index f20fc7c9ce6757be75d9317e76c23a68b09914bd..0000000000000000000000000000000000000000 --- a/theodolite/src/main/kotlin/theodolite/util/TypeName.kt +++ /dev/null @@ -1,14 +0,0 @@ -package theodolite.util - -import com.fasterxml.jackson.databind.annotation.JsonDeserialize -import io.quarkus.runtime.annotations.RegisterForReflection - -/** - * The TypeName encapsulates a list of [PatcherDefinition] along with a typeName that specifies for what the [PatcherDefinition] should be used. - */ -@RegisterForReflection -@JsonDeserialize -class TypeName { - lateinit var typeName: String - lateinit var patchers: List<PatcherDefinition> -} diff --git a/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/IOHandlerTest.kt similarity index 96% rename from theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/core/IOHandlerTest.kt index 3b31f389bdeb35e6016a56a98abb1e13bf83ae18..65e84d7dd37eb5b68f77bc2d47d212db2f720a90 100644 --- a/theodolite/src/test/kotlin/theodolite/util/IOHandlerTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/core/IOHandlerTest.kt @@ -1,4 +1,4 @@ -package theodolite.util +package rocks.theodolite.core import com.google.gson.GsonBuilder import io.quarkus.test.junit.QuarkusTest @@ -69,14 +69,14 @@ internal class IOHandlerTest { fun testWriteToJSONFile() { temporaryFolder.create() val folder = temporaryFolder.newFolder(FOLDER_URL) - val testContent = Resource(0, emptyList()) + val testContentResource = 0 IOHandler().writeToJSONFile( fileURL = "${folder.absolutePath}/test-file.json", - objectToSave = testContent + objectToSave = testContentResource ) - val expected = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create().toJson(testContent) + val expected = GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create().toJson(testContentResource) assertEquals( expected, diff --git a/theodolite/src/test/kotlin/rocks/theodolite/core/ResultsTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/ResultsTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..2dbeb44b90f780975af884028335a7e398c7cfdc --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/core/ResultsTest.kt @@ -0,0 +1,91 @@ +package rocks.theodolite.core + +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertNotNull +import org.junit.jupiter.api.Test +import rocks.theodolite.core.strategies.Metric + +@QuarkusTest +internal class ResultsTest { + + @Test + fun testMinRequiredInstancesWhenSuccessfulDemand() { + val results = Results(Metric.from("demand")) + results.setResult(Pair(10000, 1), true) + results.setResult(Pair(10000, 2), true) + results.setResult(Pair(20000, 1), false) + results.setResult(Pair(20000, 2), true) + + val minRequiredInstances = results.getOptYDimensionValue(20000) + + assertNotNull(minRequiredInstances) + assertEquals(2, minRequiredInstances) + } + + @Test + fun testGetMaxBenchmarkedLoadWhenAllSuccessfulDemand() { + val results = Results(Metric.from("demand")) + results.setResult(Pair(10000, 1), true) + results.setResult(Pair(10000, 2), true) + + val test1 = results.getMaxBenchmarkedXDimensionValue(100000) + + assertNotNull(test1) + assertEquals(10000, test1) + } + + @Test + fun testGetMaxBenchmarkedLoadWhenLargestNotSuccessfulDemand() { + val results = Results(Metric.from("demand")) + results.setResult(Pair(10000, 1), true) + results.setResult(Pair(10000, 2), true) + results.setResult(Pair(20000, 1), false) + + val test2 = results.getMaxBenchmarkedXDimensionValue(100000) + + assertNotNull(test2) + assertEquals(20000, test2) + } + + @Test + fun testMaxRequiredInstancesWhenSuccessfulCapacity() { + val results = Results(Metric.from("capacity")) + results.setResult(Pair(10000, 1), true) + results.setResult(Pair(20000, 1), false) + results.setResult(Pair(10000, 2), true) + results.setResult(Pair(20000, 2), true) + + val maxRequiredInstances = results.getOptYDimensionValue(2) + + assertNotNull(maxRequiredInstances) + assertEquals(20000, maxRequiredInstances) + } + + + @Test + fun testGetMaxBenchmarkedLoadWhenAllSuccessfulCapacity() { + val results = Results(Metric.from("capacity")) + results.setResult(Pair(10000, 1), true) + results.setResult(Pair(10000, 2), true) + + val test1 = results.getMaxBenchmarkedXDimensionValue(5) + + assertNotNull(test1) + assertEquals(2, test1) + } + + @Test + fun testGetMaxBenchmarkedLoadWhenLargestNotSuccessfulCapacity() { + val results = Results(Metric.from("capacity")) + results.setResult(Pair(10000, 1), true) + results.setResult(Pair(20000, 1), true) + results.setResult(Pair(10000, 2), false) + + + val test2 = results.getMaxBenchmarkedXDimensionValue(5) + + assertNotNull(test2) + assertEquals(2, test2) + } +} diff --git a/theodolite/src/test/kotlin/theodolite/strategies/restriction/LowerBoundRestrictionTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestrictionTest.kt similarity index 53% rename from theodolite/src/test/kotlin/theodolite/strategies/restriction/LowerBoundRestrictionTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestrictionTest.kt index b368647e314a4d803b444268c8218aefbee00ad4..79fadb4867a155ee7b4dc86e4bb165947a4f15a4 100644 --- a/theodolite/src/test/kotlin/theodolite/strategies/restriction/LowerBoundRestrictionTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/restrictionstrategy/LowerBoundRestrictionTest.kt @@ -1,25 +1,21 @@ -package theodolite.strategies.restriction +package rocks.theodolite.core.strategies.restrictionstrategy import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertNotNull import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results +import rocks.theodolite.core.strategies.Metric +import rocks.theodolite.core.strategies.restrictionstrategy.LowerBoundRestriction +import rocks.theodolite.core.Results internal class LowerBoundRestrictionTest { @Test fun testNoPreviousResults() { - val results = Results() + val results = Results(Metric.from("demand")) val strategy = LowerBoundRestriction(results) - val load = buildLoadDimension(10000) - val resources = listOf( - buildResourcesDimension(1), - buildResourcesDimension(2), - buildResourcesDimension(3) - ) + val load = 10000 + val resources = listOf(1, 2, 3) val restriction = strategy.apply(load, resources) assertEquals(3, restriction.size) @@ -28,17 +24,13 @@ internal class LowerBoundRestrictionTest { @Test fun testWithSuccessfulPreviousResults() { - val results = Results() + val results = Results(Metric.from("demand")) results.setResult(10000, 1, true) results.setResult(20000, 1, false) results.setResult(20000, 2, true) val strategy = LowerBoundRestriction(results) - val load = buildLoadDimension(30000) - val resources = listOf( - buildResourcesDimension(1), - buildResourcesDimension(2), - buildResourcesDimension(3) - ) + val load = 30000 + val resources = listOf(1, 2, 3) val restriction = strategy.apply(load, resources) assertEquals(2, restriction.size) @@ -49,70 +41,54 @@ internal class LowerBoundRestrictionTest { @Disabled fun testWithNoSuccessfulPreviousResults() { // This test is currently not implemented this way, but might later be the desired behavior. - val results = Results() + val results = Results(Metric.from("demand")) results.setResult(10000, 1, true) results.setResult(20000, 1, false) results.setResult(20000, 2, false) results.setResult(20000, 3, false) val strategy = LowerBoundRestriction(results) - val load = buildLoadDimension(30000) - val resources = listOf( - buildResourcesDimension(1), - buildResourcesDimension(2), - buildResourcesDimension(3) - ) + val load = 30000 + val resources = listOf(1, 2, 3) val restriction = strategy.apply(load, resources) assertEquals(0, restriction.size) - assertEquals(emptyList<Resource>(), restriction) + assertEquals(emptyList<Int>(), restriction) } @Test fun testNoPreviousResults2() { - val results = Results() + val results = Results(Metric.from("demand")) results.setResult(10000, 1, true) results.setResult(20000, 2, true) results.setResult(10000, 1, false) results.setResult(20000, 2, true) - val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList())) + val minRequiredInstances = results.getOptYDimensionValue(20000) assertNotNull(minRequiredInstances) - assertEquals(2, minRequiredInstances!!.get()) + assertEquals(2, minRequiredInstances!!) } @Test @Disabled fun testMinRequiredInstancesWhenNotSuccessful() { // This test is currently not implemented this way, but might later be the desired behavior. - val results = Results() + val results = Results(Metric.from("demand")) results.setResult(10000, 1, true) results.setResult(20000, 2, true) results.setResult(10000, 1, false) results.setResult(20000, 2, false) - val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList())) + val minRequiredInstances = results.getOptYDimensionValue(20000) assertNotNull(minRequiredInstances) - assertEquals(2, minRequiredInstances!!.get()) + assertEquals(2, minRequiredInstances!!) } - private fun buildLoadDimension(load: Int): LoadDimension { - return LoadDimension(load, emptyList()) - } - private fun buildResourcesDimension(resources: Int): Resource { - return Resource(resources, emptyList()) - } - private fun Results.setResult(load: Int, resources: Int, successful: Boolean) { - this.setResult( - Pair( - buildLoadDimension(load), - buildResourcesDimension(resources) - ), - successful - ) + private fun Results.setResult(load: Int, resource: Int, successful: Boolean) { + this.setResult(Pair(load, resource),successful) } } diff --git a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategyTest.kt similarity index 52% rename from theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategyTest.kt index 1af6f548b219697009c688ace712a9f7f5620bd0..820dc7564aac2497a2884ca004f15110bc5465f7 100644 --- a/theodolite/src/test/kotlin/theodolite/InitialGuessSearchStrategyTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/InitialGuessSearchStrategyTest.kt @@ -1,15 +1,15 @@ -package theodolite +package rocks.theodolite.core.strategies.searchstrategy import io.quarkus.test.junit.QuarkusTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import theodolite.benchmark.BenchmarkExecution -import theodolite.strategies.searchstrategy.InitialGuessSearchStrategy -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results +import rocks.theodolite.core.strategies.Metric import mu.KotlinLogging -import theodolite.strategies.searchstrategy.PrevResourceMinGuess +import rocks.theodolite.kubernetes.TestBenchmarkDeploymentBuilder +import rocks.theodolite.kubernetes.TestExperimentRunnerImpl +import rocks.theodolite.core.strategies.guessstrategy.PrevInstanceOptGuess +import rocks.theodolite.core.Results +import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo private val logger = KotlinLogging.logger {} @@ -27,23 +27,23 @@ class InitialGuessSearchStrategyTest { arrayOf(false, false, false, false, false, false, true), arrayOf(false, false, false, false, false, false, false) ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) } - val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } - val results = Results() - val benchmark = TestBenchmark() - val guessStrategy = PrevResourceMinGuess() - val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() - val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) + val mockLoads: List<Int> = (0..6).toList() + val mockResources: List<Int> = (0..6).toList() + val results = Results(Metric.from("demand")) + val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder() + val guessStrategy = PrevInstanceOptGuess() + val sloChecker = Slo() + val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results) - val actual: ArrayList<Resource?> = ArrayList() - val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) }) + val actual: ArrayList<Int?> = ArrayList() + val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6)) expected.add(null) for (load in mockLoads) { - val returnVal : Resource? = strategy.findSuitableResource(load, mockResources) + val returnVal : Int? = strategy.findSuitableResource(load, mockResources) if(returnVal != null) { - logger.info { "returnVal '${returnVal.get()}'" } + logger.info { "returnVal '${returnVal}'" } } else { logger.info { "returnVal is null." } @@ -65,23 +65,23 @@ class InitialGuessSearchStrategyTest { arrayOf(false, false, false, false, false, false, true), arrayOf(false, false, false, false, false, false, false) ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) } - val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } - val results = Results() - val benchmark = TestBenchmark() - val guessStrategy = PrevResourceMinGuess() - val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() - val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) + val mockLoads: List<Int> = (0..6).toList() + val mockResources: List<Int> = (0..6).toList() + val results = Results(Metric.from("demand")) + val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder() + val guessStrategy = PrevInstanceOptGuess() + val sloChecker = Slo() + val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor,guessStrategy, results) - val actual: ArrayList<Resource?> = ArrayList() - val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 1, 4, 6).map { x -> Resource(x, emptyList()) }) + val actual: ArrayList<Int?> = ArrayList() + val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 1, 4, 6)) expected.add(null) for (load in mockLoads) { - val returnVal : Resource? = strategy.findSuitableResource(load, mockResources) + val returnVal : Int? = strategy.findSuitableResource(load, mockResources) if(returnVal != null) { - logger.info { "returnVal '${returnVal.get()}'" } + logger.info { "returnVal '${returnVal}'" } } else { logger.info { "returnVal is null." } @@ -103,24 +103,24 @@ class InitialGuessSearchStrategyTest { arrayOf(false, false, false, false, false, false, true), arrayOf(false, false, false, false, false, false, false) ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) } - val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } - val results = Results() - val benchmark = TestBenchmark() - val guessStrategy = PrevResourceMinGuess() - val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() - val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) + val mockLoads: List<Int> = (0..6).toList() + val mockResources: List<Int> = (0..6).toList() + val results = Results(Metric.from("demand")) + val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder() + val guessStrategy = PrevInstanceOptGuess() + val sloChecker = Slo() + val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5) val strategy = InitialGuessSearchStrategy(benchmarkExecutor, guessStrategy, results) - val actual: ArrayList<Resource?> = ArrayList() - var expected: ArrayList<Resource?> = ArrayList(listOf(2, 3, 0, 4, 6).map { x -> Resource(x, emptyList()) }) + val actual: ArrayList<Int?> = ArrayList() + var expected: ArrayList<Int?> = ArrayList(listOf(2, 3, 0, 4, 6)) expected.add(null) expected = ArrayList(listOf(null) + expected) for (load in mockLoads) { - val returnVal : Resource? = strategy.findSuitableResource(load, mockResources) + val returnVal : Int? = strategy.findSuitableResource(load, mockResources) if(returnVal != null) { - logger.info { "returnVal '${returnVal.get()}'" } + logger.info { "returnVal '${returnVal}'" } } else { logger.info { "returnVal is null." } diff --git a/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearchTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearchTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..bae944801fcacf40431559a0e7ddeb78923d2173 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/core/strategies/searchstrategy/RestrictionSearchTest.kt @@ -0,0 +1,148 @@ +package rocks.theodolite.core.strategies.searchstrategy + +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Test +import rocks.theodolite.kubernetes.TestBenchmarkDeploymentBuilder +import rocks.theodolite.kubernetes.TestExperimentRunnerImpl +import rocks.theodolite.core.strategies.Metric +import rocks.theodolite.core.strategies.restrictionstrategy.LowerBoundRestriction +import rocks.theodolite.core.Results +import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo + +@QuarkusTest +class RestrictionSearchTest { + + + @Test + fun restrictionSearchTestLinearSearch() { + val mockResults = arrayOf( + arrayOf(true, true, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true), + arrayOf(false, false, false, true, true, true, true), + arrayOf(false, false, false, false, true, true, true), + arrayOf(false, false, false, false, false, false, true), + arrayOf(false, false, false, false, false, false, false) + ) + val mockLoads: List<Int> = (0..6).toList() + val mockResources: List<Int> = (0..6).toList() + val results = Results(Metric.from("demand")) + val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder() + val sloChecker = Slo() + val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5) + val linearSearch = LinearSearch(benchmarkExecutor) + val lowerBoundRestriction = LowerBoundRestriction(results) + val strategy = + RestrictionSearch(benchmarkExecutor, linearSearch, setOf(lowerBoundRestriction)) + + val actual: ArrayList<Int?> = ArrayList() + val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6)) + expected.add(null) + + for (load in mockLoads) { + actual.add(strategy.findSuitableResource(load, mockResources)) + } + + assertEquals(actual, expected) + } + + @Test + fun restrictionSearchTestFullSearch() { + val mockResults = arrayOf( + arrayOf(true, true, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true), + arrayOf(false, false, false, true, true, true, true), + arrayOf(false, false, false, false, true, true, true), + arrayOf(false, false, false, false, false, false, true), + arrayOf(false, false, false, false, false, false, false) + ) + val mockLoads: List<Int> = (0..6).toList() + val mockResources: List<Int> = (0..6).toList() + val results = Results(Metric.from("demand")) + val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder() + val sloChecker = Slo() + val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 5) + val fullSearch = FullSearch(benchmarkExecutor) + val lowerBoundRestriction = LowerBoundRestriction(results) + val strategy = + RestrictionSearch(benchmarkExecutor, fullSearch, setOf(lowerBoundRestriction)) + + val actual: ArrayList<Int?> = ArrayList() + val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6)) + expected.add(null) + + for (load in mockLoads) { + actual.add(strategy.findSuitableResource(load, mockResources)) + } + + assertEquals(actual, expected) + } + + @Test + fun restrictionSearchTestBinarySearch() { + val mockResults = arrayOf( + arrayOf(true, true, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true), + arrayOf(false, false, false, true, true, true, true), + arrayOf(false, false, false, false, true, true, true), + arrayOf(false, false, false, false, false, false, true), + arrayOf(false, false, false, false, false, false, false) + ) + val mockLoads: List<Int> = (0..6).toList() + val mockResources: List<Int> = (0..6).toList() + val results = Results(Metric.from("demand")) + val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder() + val sloChecker = Slo() + val benchmarkExecutorImpl = + TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 0) + val binarySearch = BinarySearch(benchmarkExecutorImpl) + val lowerBoundRestriction = LowerBoundRestriction(results) + val strategy = RestrictionSearch(benchmarkExecutorImpl, binarySearch, setOf(lowerBoundRestriction)) + + val actual: ArrayList<Int?> = ArrayList() + val expected: ArrayList<Int?> = ArrayList(listOf(0, 2, 2, 3, 4, 6)) + expected.add(null) + + for (load in mockLoads) { + actual.add(strategy.findSuitableResource(load, mockResources)) + } + + assertEquals(actual, expected) + } + + @Test + fun restrictionSearchTestBinarySearch2() { + val mockResults = arrayOf( + arrayOf(true, true, true, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true, true), + arrayOf(false, false, true, true, true, true, true, true), + arrayOf(false, false, false, true, true, true, true, true), + arrayOf(false, false, false, false, true, true, true, true), + arrayOf(false, false, false, false, false, false, true, true), + arrayOf(false, false, false, false, false, false, false, true) + ) + val mockLoads: List<Int> = (0..6).toList() + val mockResources: List<Int> = (0..7).toList() + val results = Results(Metric.from("demand")) + val benchmarkDeploymentBuilder = TestBenchmarkDeploymentBuilder() + val sloChecker = Slo() + val benchmarkExecutor = TestExperimentRunnerImpl(results, mockResults, benchmarkDeploymentBuilder, listOf(sloChecker), 0, 0, 0) + val binarySearch = BinarySearch(benchmarkExecutor) + val lowerBoundRestriction = LowerBoundRestriction(results) + val strategy = + RestrictionSearch(benchmarkExecutor, binarySearch, setOf(lowerBoundRestriction)) + + val actual: ArrayList<Int?> = ArrayList() + val expected: ArrayList<Int?> = + ArrayList(listOf(0, 2, 2, 3, 4, 6, 7)) + + for (load in mockLoads) { + actual.add(strategy.findSuitableResource(load, mockResources)) + } + + assertEquals(actual, expected) + } +} diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ActionCommandTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ActionCommandTest.kt similarity index 77% rename from theodolite/src/test/kotlin/theodolite/benchmark/ActionCommandTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ActionCommandTest.kt index 47f0e52f45e46e3cda093ff1b9722071f22ef7e8..008bc302f1ba9a246b7bd898aec712f305c5b288 100644 --- a/theodolite/src/test/kotlin/theodolite/benchmark/ActionCommandTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ActionCommandTest.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import io.fabric8.kubernetes.api.model.Pod import io.fabric8.kubernetes.api.model.PodBuilder @@ -8,9 +8,9 @@ import io.fabric8.kubernetes.client.utils.Utils import io.quarkus.test.junit.QuarkusTest import org.junit.jupiter.api.* import org.junit.jupiter.api.Assertions.assertEquals -import theodolite.execution.operator.TheodoliteController -import theodolite.execution.operator.TheodoliteOperator -import theodolite.util.ActionCommandFailedException +import rocks.theodolite.kubernetes.operator.TheodoliteController +import rocks.theodolite.kubernetes.operator.TheodoliteOperator + @QuarkusTest class ActionCommandTest { @@ -20,11 +20,10 @@ class ActionCommandTest { @BeforeEach fun setUp() { server.before() - val operator = TheodoliteOperator() + val operator = TheodoliteOperator(server.client) this.controller = operator.getController( - client = server.client, - executionStateHandler = operator.getExecutionStateHandler(client = server.client), - benchmarkStateChecker = operator.getBenchmarkStateChecker(client = server.client) + executionStateHandler = operator.getExecutionStateHandler(), + benchmarkStateChecker = operator.getBenchmarkStateChecker() ) val pod: Pod = PodBuilder().withNewMetadata() @@ -100,12 +99,12 @@ class ActionCommandTest { @Test fun testActionSuccess() { val action = Action() - action.selector = ActionSelector() - action.selector.pod = PodSelector() - action.selector.pod.matchLabels = mapOf("app" to "pod") - action.exec = Command() - action.exec.command = arrayOf("ls") - action.exec.timeoutSeconds = 10L + action.execCommand = ExecCommand() + action.execCommand!!.selector = ExecActionSelector() + action.execCommand!!.selector.pod = PodSelector() + action.execCommand!!.selector.pod.matchLabels = mutableMapOf("app" to "pod") + action.execCommand!!.command = arrayOf("ls") + action.execCommand!!.timeoutSeconds = 10L action.exec(server.client) assertEquals( @@ -116,12 +115,12 @@ class ActionCommandTest { @Test fun testActionFailed() { val action = Action() - action.selector = ActionSelector() - action.selector.pod = PodSelector() - action.selector.pod.matchLabels = mapOf("app" to "pod") - action.exec = Command() - action.exec.command = arrayOf("error-command") - action.exec.timeoutSeconds = 10L + action.execCommand = ExecCommand() + action.execCommand!!.selector = ExecActionSelector() + action.execCommand!!.selector.pod = PodSelector() + action.execCommand!!.selector.pod.matchLabels = mapOf("app" to "pod") + action.execCommand!!.command = arrayOf("error-command") + action.execCommand!!.timeoutSeconds = 10L assertThrows<ActionCommandFailedException> { run { action.exec(server.client) } } } diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSetTest.kt similarity index 95% rename from theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSetTest.kt index 33a4572e368655744185312ff2352b1294d7bef6..87058706c1a315c98ba098e6c5835f3a57343112 100644 --- a/theodolite/src/test/kotlin/theodolite/benchmark/ConfigMapResourceSetTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ConfigMapResourceSetTest.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import com.fasterxml.jackson.databind.ObjectMapper import io.fabric8.kubernetes.api.model.* @@ -19,16 +19,11 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.assertThrows -import org.mockito.kotlin.mock import registerResource -import theodolite.TestBenchmark -import theodolite.execution.operator.BenchmarkCRDummy -import theodolite.execution.operator.ExecutionClient -import theodolite.execution.operator.ExecutionEventHandler -import theodolite.execution.operator.ExecutionStateHandler -import theodolite.model.crd.BenchmarkCRD -import theodolite.model.crd.ExecutionCRD -import theodolite.util.DeploymentFailedException +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRDummy +import rocks.theodolite.kubernetes.operator.ExecutionClient +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD import java.io.FileInputStream // TODO move somewhere else diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/ErrorChannelMessage.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ErrorChannelMessage.kt similarity index 94% rename from theodolite/src/test/kotlin/theodolite/benchmark/ErrorChannelMessage.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ErrorChannelMessage.kt index df57a2529653a39ccbde14b4a91d30352224457e..4181b7cbb90fd0c6bd2db78753560092d7ea60ca 100644 --- a/theodolite/src/test/kotlin/theodolite/benchmark/ErrorChannelMessage.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ErrorChannelMessage.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import io.fabric8.mockwebserver.internal.WebSocketMessage import java.nio.charset.StandardCharsets diff --git a/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSetTest.kt similarity index 97% rename from theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSetTest.kt index 6a31875d00c8f578dcc475c3de21e130c595f673..1c5f32159713e7ace6857caf0f97b43c90cb36e0 100644 --- a/theodolite/src/test/kotlin/theodolite/benchmark/FileSystemResourceSetTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/FileSystemResourceSetTest.kt @@ -1,4 +1,4 @@ -package theodolite.benchmark +package rocks.theodolite.kubernetes import io.fabric8.kubernetes.api.model.* import io.fabric8.kubernetes.api.model.apps.Deployment @@ -13,9 +13,8 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.io.TempDir import registerResource -import theodolite.model.crd.BenchmarkCRD -import theodolite.model.crd.ExecutionCRD -import theodolite.util.DeploymentFailedException +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD import java.io.FileInputStream import java.nio.file.Files import java.nio.file.Path diff --git a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/K8sManagerTest.kt similarity index 99% rename from theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/K8sManagerTest.kt index ee80d55caf995642f6fff04cfeeb66bc08ab93d3..90dd01626a7c18e0b6f8d6018aae54297e758464 100644 --- a/theodolite/src/test/kotlin/theodolite/k8s/K8sManagerTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/K8sManagerTest.kt @@ -1,4 +1,4 @@ -package theodolite.k8s +package rocks.theodolite.kubernetes import io.fabric8.kubernetes.api.model.* import io.fabric8.kubernetes.api.model.apps.Deployment diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ResourceSetsTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ResourceSetsTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..f0a6c120ca6c3397e8d41cd9f42b536b3e053caf --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/ResourceSetsTest.kt @@ -0,0 +1,132 @@ +package rocks.theodolite.kubernetes + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.dataformat.yaml.YAMLFactory +import io.fabric8.kubernetes.api.model.ConfigMap +import io.fabric8.kubernetes.api.model.ConfigMapBuilder +import io.fabric8.kubernetes.api.model.HasMetadata +import io.fabric8.kubernetes.client.server.mock.KubernetesServer +import io.quarkus.test.junit.QuarkusTest +import io.quarkus.test.kubernetes.client.KubernetesTestServer +import io.quarkus.test.kubernetes.client.WithKubernetesTestServer +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.Assertions.assertTrue +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.assertThrows +import org.junit.jupiter.api.io.TempDir +import java.nio.file.Files +import java.nio.file.Path + +@QuarkusTest +@WithKubernetesTestServer +internal class ResourceSetsTest { + + @KubernetesTestServer + private lateinit var server: KubernetesServer + + @TempDir + @JvmField + final var tempDir: Path? = null + + private val objectMapper: ObjectMapper = ObjectMapper(YAMLFactory()) + + @BeforeEach + fun setUp() { + server.before() + } + + @AfterEach + fun tearDown() { + server.after() + } + + private fun deployAndGetResource(vararg resources: HasMetadata): ConfigMapResourceSet { + val configMap = ConfigMapBuilder() + .withNewMetadata().withName(resources[0].metadata.name).endMetadata() + .let { + resources.foldIndexed(it) { i, b, r -> + b.addToData("resource_$i.yaml", objectMapper.writeValueAsString(r)) + } + } + .build() + + server.client.configMaps().createOrReplace(configMap) + + val resourceSet = ConfigMapResourceSet() + resourceSet.name = resources[0].metadata.name + + return resourceSet + } + + private fun copyTestResourceFile(fileName: String, tempDir: Path) { + val stream = javaClass.getResourceAsStream("/k8s-resource-files/$fileName") + ?: throw IllegalArgumentException("File does not exist") + val target = tempDir.resolve(fileName) + Files.copy(stream, target) + } + + @Test + fun testLoadConfigMap() { + val resource = ConfigMapBuilder() + .withNewMetadata() + .withName("test-configmap") + .endMetadata() + .build() + deployAndGetResource(resource) + + val yamlString = + """ + configMap: + name: test-configmap + files: + """ + + val resourcesSet: ResourceSets = objectMapper.readValue(yamlString, ResourceSets::class.java) + assertTrue(resourcesSet.fileSystem == null) + assertTrue(resourcesSet.configMap != null) + + val configMap = resourcesSet.loadResourceSet(server.client) + assertEquals(1, configMap.size) + assertTrue(configMap.toList().first().second is ConfigMap) + assertTrue(configMap.toList().first().second.toString().contains(other = resource.metadata.name)) + + assertEquals(configMap.elementAt(0).second, resource) + } + + @Test + fun testLoadFileSystem(@TempDir tempDir: Path) { + copyTestResourceFile("test-deployment.yaml", tempDir) + + val resourceSet = FileSystemResourceSet() + resourceSet.path = tempDir.toString() + resourceSet.files = listOf("test-deployment.yaml") + assertEquals(1, resourceSet.getResourceSet(server.client).size) + + val yamlString = + """ + fileSystem: + path: ${resourceSet.path} + files: + - test-deployment.yaml + """ + + val resourcesSet: ResourceSets = objectMapper.readValue(yamlString, ResourceSets::class.java) + assertTrue(resourcesSet.fileSystem != null) + assertTrue(resourcesSet.configMap == null) + + val fileSystem = resourcesSet.loadResourceSet(server.client) + assertEquals(fileSystem.size, 1) + assertTrue(fileSystem.elementAt(0).second is HasMetadata) + } + + @Test + fun testEmptyResourceSets() { + val resourceSet = ResourceSets() + + assertThrows<DeploymentFailedException> { + resourceSet.loadResourceSet(server.client) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmarkDeployment.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeployment.kt similarity index 56% rename from theodolite/src/test/kotlin/theodolite/TestBenchmarkDeployment.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeployment.kt index 68b08c294128368ee1b65549aa85c877bd4bf313..92bc2fd26a8c5e9d77b0729731b3e65833b3dd08 100644 --- a/theodolite/src/test/kotlin/theodolite/TestBenchmarkDeployment.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeployment.kt @@ -1,6 +1,6 @@ -package theodolite +package rocks.theodolite.kubernetes -import theodolite.benchmark.BenchmarkDeployment +import rocks.theodolite.kubernetes.BenchmarkDeployment class TestBenchmarkDeployment : BenchmarkDeployment { override fun setup() {} diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeploymentBuilder.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeploymentBuilder.kt new file mode 100644 index 0000000000000000000000000000000000000000..cc7c9d6ae9a5fe158f7ba9243f23442acde001ee --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestBenchmarkDeploymentBuilder.kt @@ -0,0 +1,21 @@ +package rocks.theodolite.kubernetes + + +import rocks.theodolite.kubernetes.util.ConfigurationOverride +import rocks.theodolite.kubernetes.patcher.PatcherDefinition + +class TestBenchmarkDeploymentBuilder(): BenchmarkDeploymentBuilder { + + override fun buildDeployment( + load: Int, + loadPatcherDefinitions: List<PatcherDefinition>, + resource: Int, + resourcePatcherDefinitions: List<PatcherDefinition>, + configurationOverrides: List<ConfigurationOverride?>, + loadGenerationDelay: Long, + afterTeardownDelay: Long, + waitForResourcesEnabled: Boolean + ): BenchmarkDeployment { + return TestBenchmarkDeployment() + } +} diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestExperimentRunnerImpl.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestExperimentRunnerImpl.kt new file mode 100644 index 0000000000000000000000000000000000000000..896beed83e0c9436c3aadc83b1e395df06b1f5b2 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/TestExperimentRunnerImpl.kt @@ -0,0 +1,24 @@ +package rocks.theodolite.kubernetes + +import rocks.theodolite.core.Results +import rocks.theodolite.kubernetes.model.KubernetesBenchmark.Slo +import rocks.theodolite.core.ExperimentRunner + +class TestExperimentRunnerImpl( + results: Results, + private val mockResults: Array<Array<Boolean>>, + private val benchmarkDeploymentBuilder: TestBenchmarkDeploymentBuilder, + private val slo: List<Slo>, + private val executionId: Int, + private val loadGenerationDelay: Long, + private val afterTeardownDelay: Long +) : ExperimentRunner( + results +) { + + override fun runExperiment(load: Int, resource: Int): Boolean { + val result = this.mockResults[load][resource] + this.results.setResult(Pair(load, resource), result) + return result + } +} diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRDummy.kt similarity index 75% rename from theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRDummy.kt index cbddbfbfc5d6f838677c6d04b0a0c79f59d8bc66..2bd52d55bb3acd3e37d53d22a1a434d53c1fff95 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkCRDummy.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/BenchmarkCRDummy.kt @@ -1,9 +1,6 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.model.crd -import theodolite.benchmark.KubernetesBenchmark -import theodolite.benchmark.Resources -import theodolite.model.crd.BenchmarkCRD -import theodolite.util.KafkaConfig +import rocks.theodolite.kubernetes.model.KubernetesBenchmark class BenchmarkCRDummy(name: String) { @@ -20,15 +17,16 @@ class BenchmarkCRDummy(name: String) { kafkaConfig.bootstrapServer = "" kafkaConfig.topics = emptyList() + benchmarkCR.spec = benchmark benchmarkCR.metadata.name = name benchmarkCR.kind = "Benchmark" benchmarkCR.apiVersion = "v1" + benchmark.waitForResourcesEnabled = false - - benchmark.infrastructure = Resources() - benchmark.sut = Resources() - benchmark.loadGenerator = Resources() + benchmark.infrastructure = KubernetesBenchmark.Resources() + benchmark.sut = KubernetesBenchmark.Resources() + benchmark.loadGenerator = KubernetesBenchmark.Resources() benchmark.infrastructure.resources = emptyList() benchmark.sut.resources = emptyList() @@ -43,6 +41,7 @@ class BenchmarkCRDummy(name: String) { benchmark.resourceTypes = emptyList() benchmark.loadTypes = emptyList() + benchmark.slos = mutableListOf() benchmark.kafkaConfig = kafkaConfig benchmark.name = benchmarkCR.metadata.name } diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/CRDExecutionTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/CRDExecutionTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..a7de76acfe7aac9b92628e87b9911599a13ab438 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/CRDExecutionTest.kt @@ -0,0 +1,86 @@ +package rocks.theodolite.kubernetes.model.crd + +import io.fabric8.kubernetes.api.model.KubernetesResourceList +import io.fabric8.kubernetes.client.dsl.MixedOperation +import io.fabric8.kubernetes.client.dsl.Resource +import io.fabric8.kubernetes.client.server.mock.KubernetesServer +import io.quarkus.test.junit.QuarkusTest +import io.quarkus.test.kubernetes.client.KubernetesTestServer +import io.quarkus.test.kubernetes.client.WithKubernetesTestServer +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import org.mockito.kotlin.mock +import rocks.theodolite.kubernetes.operator.ExecutionEventHandler +import rocks.theodolite.kubernetes.operator.ExecutionStateHandler +import rocks.theodolite.kubernetes.operator.TheodoliteController +import rocks.theodolite.kubernetes.util.ConfigurationOverride +import java.io.FileInputStream + + +// TODO move somewhere else +typealias ExecutionClient = MixedOperation<ExecutionCRD, KubernetesResourceList<ExecutionCRD>, Resource<ExecutionCRD>> + +@WithKubernetesTestServer +@QuarkusTest +internal class CRDExecutionTest { + + @KubernetesTestServer + private lateinit var server: KubernetesServer + + lateinit var executionClient: ExecutionClient + + lateinit var controller: TheodoliteController + + lateinit var stateHandler: ExecutionStateHandler + + lateinit var eventHandler: ExecutionEventHandler + + @BeforeEach + fun setUp() { + server.before() + + this.server.client + .apiextensions().v1() + .customResourceDefinitions() + .load(FileInputStream("crd/crd-execution.yaml")) + .create() + + this.executionClient = this.server.client.resources(ExecutionCRD::class.java) + + this.controller = mock() + this.stateHandler = ExecutionStateHandler(server.client) + this.eventHandler = ExecutionEventHandler(this.controller, this.stateHandler) + } + + @AfterEach + fun tearDown() { + server.after() + } + + @Test + fun checkParsingCRDTest(){ + // BenchmarkExecution from yaml + val execution = executionClient.load(ClassLoader.getSystemResourceAsStream("k8s-resource-files/test-execution.yaml")).create().spec + + assertEquals(0, execution.executionId) + assertEquals("test", execution.name) + assertEquals("uc1-kstreams", execution.benchmark) + assertEquals(mutableListOf<ConfigurationOverride?>(), execution.configOverrides) + + assertEquals("NumSensors", execution.loads.loadType) + assertEquals(listOf(25000, 50000, 75000, 100000, 125000, 150000),execution.loads.loadValues) + + assertEquals("Instances", execution.resources.resourceType) + assertEquals(listOf(1, 2, 3, 4, 5), execution.resources.resourceValues) + + assertEquals("demand", execution.execution.metric) + assertEquals(300, execution.execution.duration) + assertEquals(1, execution.execution.repetitions) + + assertEquals("RestrictionSearch", execution.execution.strategy.name) + assertEquals("LinearSearch", execution.execution.strategy.searchStrategy) + assertEquals(listOf("LowerBound"), execution.execution.strategy.restrictions) + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRDummy.kt similarity index 78% rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRDummy.kt index 9274e283b48a6fd9b30d5ce0aff3cb8b995e0ce5..871471ee941f5cf2d254fb2bd70556f161d8d4de 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionCRDummy.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionCRDummy.kt @@ -1,9 +1,6 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.model.crd -import theodolite.benchmark.BenchmarkExecution -import theodolite.model.crd.ExecutionCRD -import theodolite.model.crd.ExecutionStatus -import theodolite.model.crd.ExecutionState +import rocks.theodolite.kubernetes.model.BenchmarkExecution class ExecutionCRDummy(name: String, benchmark: String) { @@ -36,16 +33,24 @@ class ExecutionCRDummy(name: String, benchmark: String) { resourceDef.resourceType = "" resourceDef.resourceValues = emptyList() + val strat = BenchmarkExecution.Strategy() + strat.name = "" + strat.restrictions = emptyList() + strat.guessStrategy = "" + strat.searchStrategy = "" + + val exec = BenchmarkExecution.Execution() exec.afterTeardownDelay = 0 exec.duration = 0 exec.loadGenerationDelay = 0 exec.repetitions = 1 - exec.restrictions = emptyList() - exec.strategy = "" + exec.metric = "" + exec.strategy = strat + execution.benchmark = benchmark - execution.load = loadType + execution.loads = loadType execution.resources = resourceDef execution.slos = emptyList() execution.execution = exec diff --git a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparatorTest.kt similarity index 86% rename from theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparatorTest.kt index ae80312afd2c128f0f542306a8ffda7f3f53876b..14186ef408acd3233ce866102497bc56af1cdfda 100644 --- a/theodolite/src/test/kotlin/theodolite/util/ExecutionStateComparatorTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStateComparatorTest.kt @@ -1,10 +1,8 @@ -package theodolite.util +package rocks.theodolite.kubernetes.model.crd import io.quarkus.test.junit.QuarkusTest import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.Test -import theodolite.execution.operator.ExecutionCRDummy -import theodolite.model.crd.ExecutionState @QuarkusTest diff --git a/theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatusTest.kt similarity index 99% rename from theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatusTest.kt index 157bc1c03cc40375c928677189f549052e1e134d..4c9326ac2e99dd7dd9707d4db25cb2e9e360ddf9 100644 --- a/theodolite/src/test/kotlin/theodolite/model/crd/ExecutionStatusTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/model/crd/ExecutionStatusTest.kt @@ -1,4 +1,4 @@ -package theodolite.model.crd +package rocks.theodolite.kubernetes.model.crd import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.exc.InvalidFormatException diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateCheckerTest.kt similarity index 84% rename from theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateCheckerTest.kt index 528cfac8066c28bf6382fb97cddf280b3c1de622..465233a5d47e0c3963371a1fd0cc891aac74a42a 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/BenchmarkStateCheckerTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/BenchmarkStateCheckerTest.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import com.google.gson.Gson import io.fabric8.kubernetes.api.model.ConfigMapBuilder @@ -13,8 +13,13 @@ import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test import org.junit.jupiter.api.Assertions.* -import theodolite.benchmark.* -import theodolite.model.crd.BenchmarkState +import rocks.theodolite.kubernetes.model.crd.BenchmarkState +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRDummy +import rocks.theodolite.kubernetes.ConfigMapResourceSet +import rocks.theodolite.kubernetes.ExecActionSelector +import rocks.theodolite.kubernetes.PodSelector +import rocks.theodolite.kubernetes.ResourceSets internal class BenchmarkStateCheckerTest { private val server = KubernetesServer(false, false) @@ -26,17 +31,17 @@ internal class BenchmarkStateCheckerTest { fun setUp() { server.before() serverCrud.before() - val operator = TheodoliteOperator() + val operator = TheodoliteOperator(serverCrud.client) checker = BenchmarkStateChecker( client = server.client, - benchmarkCRDClient = operator.getBenchmarkClient(server.client), - benchmarkStateHandler = operator.getBenchmarkStateHandler(server.client) + benchmarkCRDClient = operator.getBenchmarkClient(), + benchmarkStateHandler = operator.getBenchmarkStateHandler() ) checkerCrud = BenchmarkStateChecker( client = serverCrud.client, - benchmarkCRDClient = operator.getBenchmarkClient(serverCrud.client), - benchmarkStateHandler = operator.getBenchmarkStateHandler(serverCrud.client) + benchmarkCRDClient = operator.getBenchmarkClient(), + benchmarkStateHandler = operator.getBenchmarkStateHandler() ) val pod: Pod = PodBuilder().withNewMetadata() @@ -105,9 +110,9 @@ internal class BenchmarkStateCheckerTest { .build() } - private fun getActionSelector(label: Pair<String, String>): ActionSelector { + private fun getActionSelector(label: Pair<String, String>): ExecActionSelector { val podSelector = PodSelector() - val actionSelector = ActionSelector() + val actionSelector = ExecActionSelector() actionSelector.pod = podSelector // pod with matching labels are deployed @@ -162,16 +167,17 @@ internal class BenchmarkStateCheckerTest { @Test fun checkResources() { - val benchmark = BenchmarkCRDummy( + val benchmarkCR = BenchmarkCRDummy( name = "test-benchmark" ) - benchmark.getCR().spec.setClient(serverCrud.client) - val resourceSet = Resources() + val benchmark = benchmarkCR.getCR().spec + + val resourceSet = KubernetesBenchmark.Resources() resourceSet.resources = listOf(createAndDeployConfigmapResourceSet()) - benchmark.getCR().spec.infrastructure = resourceSet - benchmark.getCR().spec.loadGenerator = resourceSet - benchmark.getCR().spec.sut = resourceSet + benchmark.infrastructure = resourceSet + benchmark.loadGenerator = resourceSet + benchmark.sut = resourceSet - assertEquals(BenchmarkState.READY,checkerCrud.checkResources(benchmark.getCR().spec)) + assertEquals(BenchmarkState.READY,checkerCrud.checkResources(benchmark)) } } \ No newline at end of file diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ControllerTest.kt similarity index 91% rename from theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ControllerTest.kt index 7d40f7e45d6aa2c93206a1bad22754fe93b0c100..3120d7420065cfe254d1ed76735ddc8b35d2bc21 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ControllerTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ControllerTest.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import com.google.gson.Gson import com.google.gson.GsonBuilder @@ -10,11 +10,10 @@ import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test -import theodolite.benchmark.BenchmarkExecution -import theodolite.benchmark.KubernetesBenchmark -import theodolite.model.crd.BenchmarkCRD -import theodolite.model.crd.BenchmarkState -import theodolite.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.model.crd.* + @QuarkusTest class ControllerTest { @@ -32,11 +31,10 @@ class ControllerTest { @BeforeEach fun setUp() { server.before() - val operator = TheodoliteOperator() + val operator = TheodoliteOperator(server.client) this.controller = operator.getController( - client = server.client, - executionStateHandler = operator.getExecutionStateHandler(client = server.client), - benchmarkStateChecker = operator.getBenchmarkStateChecker(client = server.client) + executionStateHandler = operator.getExecutionStateHandler(), + benchmarkStateChecker = operator.getBenchmarkStateChecker() ) // benchmark diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTest.kt similarity index 98% rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTest.kt index c08e0565375de84a228a28b6d68a0b713af97d0f..e794ae1638bd6c7f265b3b7ffb08c2494ba76a37 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTest.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.api.model.KubernetesResourceList import io.fabric8.kubernetes.client.dsl.MixedOperation @@ -16,8 +16,8 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import org.mockito.kotlin.* -import theodolite.model.crd.ExecutionCRD -import theodolite.model.crd.ExecutionState +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionState import java.io.FileInputStream import java.util.stream.Stream diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTestWithInformer.kt similarity index 98% rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTestWithInformer.kt index adddc705616935e5440c1c601615ce9a065df4c4..63a669fe67c66b644b6acbabedc5d79afff8ee31 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerTestWithInformer.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerTestWithInformer.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.client.dsl.Resource import io.fabric8.kubernetes.client.server.mock.KubernetesServer @@ -11,8 +11,8 @@ import org.junit.jupiter.params.ParameterizedTest import org.junit.jupiter.params.provider.Arguments import org.junit.jupiter.params.provider.MethodSource import org.mockito.kotlin.* -import theodolite.model.crd.ExecutionCRD -import theodolite.model.crd.ExecutionState +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionState import java.io.FileInputStream import java.util.concurrent.CountDownLatch import java.util.stream.Stream diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerWrapper.kt similarity index 63% rename from theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerWrapper.kt index 5dbc515a7799dd51e6395153f13d80650587d7fa..43ff721bd0f964065243188465849354bc7f8b23 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/ExecutionEventHandlerWrapper.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/ExecutionEventHandlerWrapper.kt @@ -1,13 +1,14 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.client.informers.ResourceEventHandler -import theodolite.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.operator.ExecutionEventHandler +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD class ExecutionEventHandlerWrapper( - private val executionEventHandler: ExecutionEventHandler, - private val afterOnAddCallback: () -> Unit, - private val afterOnUpdateCallback: () -> Unit, - private val afterOnDeleteCallback: () -> Unit + private val executionEventHandler: ExecutionEventHandler, + private val afterOnAddCallback: () -> Unit, + private val afterOnUpdateCallback: () -> Unit, + private val afterOnDeleteCallback: () -> Unit ) : ResourceEventHandler<ExecutionCRD> { override fun onAdd(execution: ExecutionCRD) { diff --git a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/StateHandlerTest.kt similarity index 90% rename from theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/StateHandlerTest.kt index ba65356b65b6ac23ca56c268bb003815917cf162..ebef641d1e0a699ab5e220b0846be654fbefc672 100644 --- a/theodolite/src/test/kotlin/theodolite/execution/operator/StateHandlerTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/operator/StateHandlerTest.kt @@ -1,4 +1,4 @@ -package theodolite.execution.operator +package rocks.theodolite.kubernetes.operator import io.fabric8.kubernetes.client.server.mock.KubernetesServer import io.quarkus.test.junit.QuarkusTest @@ -10,9 +10,9 @@ import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test -import theodolite.k8s.K8sManager -import theodolite.model.crd.ExecutionCRD -import theodolite.model.crd.ExecutionState +import rocks.theodolite.kubernetes.K8sManager +import rocks.theodolite.kubernetes.model.crd.ExecutionCRD +import rocks.theodolite.kubernetes.model.crd.ExecutionState @QuarkusTest @WithKubernetesTestServer diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..cb92423305fd3f724753225d95150d5198f1d306 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/AbstractPatcherTest.kt @@ -0,0 +1,98 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.* +import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder +import io.fabric8.kubernetes.api.model.apps.StatefulSetBuilder +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.Test + +@QuarkusTest +abstract class AbstractPatcherTest { + + lateinit var resource: List<HasMetadata> + lateinit var patcher: Patcher + lateinit var value: String + + fun createDeployment(): HasMetadata { + return DeploymentBuilder() + .withNewMetadata() + .withName("dummy") + .endMetadata() + .withNewSpec() + .withNewSelector() + .withMatchLabels<String, String>(mapOf("labelName" to "labelValue")) + .endSelector() + .withNewTemplate() + .withNewMetadata() + .withLabels<String, String>(mapOf("labelName" to "labelValue")) + .endMetadata() + .withNewSpec() + .withContainers( + ContainerBuilder() + .withName("container") + .withImage("test-image") + .build()) + .addNewVolume() + .withName("test-volume") + .withNewConfigMap() + .withName("test-configmap") + .endConfigMap() + .endVolume() + .endSpec() + .endTemplate() + .endSpec() + .build() + } + + fun createStateFulSet(): HasMetadata { + return StatefulSetBuilder() + .withNewMetadata() + .withName("dummy") + .endMetadata() + .withNewSpec() + .withNewSelector() + .withMatchLabels<String, String>(mapOf("labelName" to "labelValue")) + .endSelector() + .withNewTemplate() + .withNewMetadata() + .withLabels<String, String>(mapOf("labelName" to "labelValue")) + .endMetadata() + .withNewSpec() + .addNewVolume() + .withName("test-volume") + .withNewConfigMap() + .withName("test-configmap") + .endConfigMap() + .endVolume() + .endSpec() + .endTemplate() + .endSpec() + .build() + } + + fun createService(): HasMetadata { + return ServiceBuilder() + .withNewMetadata() + .withName("dummy") + .endMetadata() + .build() + } + + fun createConfigMap(): HasMetadata { + return ConfigMapBuilder() + .withNewMetadata() + .withName("dummy") + .endMetadata() + .withData<String, String>(mapOf("application.properties" to "propA = valueA")) + .build() + } + + fun patch() { + resource = patcher.patch(resource, value) + } + + @Test + abstract fun validate() + + +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifierTest.kt similarity index 82% rename from theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifierTest.kt index 1db1122e1caa5a783159ecaba849b99963e3c2a9..6172454008266c987b335999b7d8bbe67bb0fc02 100644 --- a/theodolite/src/test/kotlin/theodolite/patcher/ConfigOverrideModifierTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ConfigOverrideModifierTest.kt @@ -1,13 +1,13 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher import io.quarkus.test.junit.QuarkusTest import org.junit.jupiter.api.Assertions import org.junit.jupiter.api.BeforeEach import org.junit.jupiter.api.Test -import theodolite.benchmark.BenchmarkExecution -import theodolite.benchmark.KubernetesBenchmark -import theodolite.execution.operator.BenchmarkCRDummy -import theodolite.execution.operator.ExecutionCRDummy +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.KubernetesBenchmark +import rocks.theodolite.kubernetes.model.crd.BenchmarkCRDummy +import rocks.theodolite.kubernetes.model.crd.ExecutionCRDummy @QuarkusTest class ConfigOverrideModifierTest { diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..6c9be1b9a59f963c8996e520b55e16caf24cbf6c --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/DataVolumeLoadGeneratorReplicaPatcherTest.kt @@ -0,0 +1,28 @@ +package theodolite.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test +import rocks.theodolite.kubernetes.patcher.AbstractPatcherTest + +import rocks.theodolite.kubernetes.patcher.VolumesConfigMapPatcher + +@QuarkusTest +internal class DataVolumeLoadGeneratorReplicaPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = VolumesConfigMapPatcher((resource.first() as Deployment).spec.template.spec.volumes[0].configMap.name) + value = "new-configMapName" + } + + @Test + override fun validate() { + patch() + resource.forEach { + assert((it as Deployment).spec.template.spec.volumes[0].configMap.name == value) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..83cd056ac1b56b13fb8f211a2d926f1272c9fb0e --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/EnvVarPatcherTest.kt @@ -0,0 +1,34 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.EnvVarBuilder +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* +import org.junit.jupiter.api.BeforeEach + +@QuarkusTest +internal class EnvVarPatcherTest : AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = EnvVarPatcher(variableName = "testEnv", container = "container") + value = "testValue" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + val envVar = EnvVarBuilder().withName("testEnv").withValue("testValue").build() + resource.forEach { + assertTrue((it as Deployment).spec.template.spec.containers[0].env.contains(envVar)) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..7b3f803a4e13039b7bb40aec6259f7d9a4fdbb57 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ImagePatcherTest.kt @@ -0,0 +1,32 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class ImagePatcherTest: AbstractPatcherTest(){ + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = ImagePatcher(container = "container") + value = "testValue" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.template.spec.containers[0].image == value) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..652dda47cef34a7a95e54c36cbe9af9c897b84a1 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/LabelPatcherTest.kt @@ -0,0 +1,37 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class LabelPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = LabelPatcher("labelName") + value = "labelValue" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).metadata.labels.containsKey("labelName")) + assertTrue(it.metadata.labels.get("labelName")=="labelValue") + } + } + + @Test + fun getVariableName() { + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..a5711a762ab65fc39edf731c21d085d0936a5a93 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/MatchLabelPatcherTest.kt @@ -0,0 +1,37 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class MatchLabelPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = MatchLabelPatcher("labelName") + value = "labelValue" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.selector.matchLabels.containsKey("labelName")) + assertTrue(it.spec.selector.matchLabels.get("labelName")=="labelValue") + } + } + + @Test + fun getVariableName() { + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..cb1308cb73dc127661b2c2741fdc3e0460fcfde4 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NamePatcherTest.kt @@ -0,0 +1,32 @@ +package rocks.theodolite.kubernetes.patcher + +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class NamePatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = NamePatcher() + value = "newName" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + println(it.toString()) + assertTrue(it.toString().contains("name=$value")) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..ca8f83518a5bcd96837de96b1879c0de2e9a5773 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NodeSelectorPatcherTest.kt @@ -0,0 +1,35 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class NodeSelectorPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = NodeSelectorPatcher("nodeName") + value = "nodeValue" + + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.template.spec.nodeSelector.containsKey("nodeName")) + assertTrue(it.spec.template.spec.nodeSelector["nodeName"] == value) + } + } + +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..8940e288fae79f10e5dcd728121a2dbbf0aaa180 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumNestedGroupsLoadGeneratorReplicaPatcherTest.kt @@ -0,0 +1,32 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class NumNestedGroupsLoadGeneratorReplicaPatcherTest : AbstractPatcherTest(){ + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = NumNestedGroupsLoadGeneratorReplicaPatcher("10", "500") + value = "2" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.replicas == 1) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..e3bb6ffff4938bcaeb4a0db6487bd4741da75850 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/NumSensorsLoadGeneratorReplicaPatcherTest.kt @@ -0,0 +1,32 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class NumSensorsLoadGeneratorReplicaPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = NumSensorsLoadGeneratorReplicaPatcher("10") + value = "2" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.replicas == 1) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactoryTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactoryTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..010fa1e25fb89619c8954b1bafa52c5389d0a2f3 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/PatcherDefinitionFactoryTest.kt @@ -0,0 +1,22 @@ +package rocks.theodolite.kubernetes.patcher + +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +internal class PatcherDefinitionFactoryTest { + + @BeforeEach + fun setUp() { + } + + @AfterEach + fun tearDown() { + } + + @Test + fun createPatcherDefinition() { + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..852002a07cfb756086afbc6d0573fc548f945683 --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ReplicaPatcherTest.kt @@ -0,0 +1,32 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class ReplicaPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = ReplicaPatcher() + value = "5" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.replicas == 5) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/theodolite/patcher/ResourceLimitPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcherTest.kt similarity index 83% rename from theodolite/src/test/kotlin/theodolite/patcher/ResourceLimitPatcherTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcherTest.kt index 2769f2fef607a03d820b0821969db98894944cb3..b0af74d1e207ee10fac548f27267356711943dd0 100644 --- a/theodolite/src/test/kotlin/theodolite/patcher/ResourceLimitPatcherTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceLimitPatcherTest.kt @@ -1,5 +1,6 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher +import io.fabric8.kubernetes.api.model.HasMetadata import io.fabric8.kubernetes.client.server.mock.KubernetesServer import io.quarkus.test.junit.QuarkusTest import io.quarkus.test.kubernetes.client.KubernetesTestServer @@ -7,8 +8,6 @@ import io.quarkus.test.kubernetes.client.WithKubernetesTestServer import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.Disabled import org.junit.jupiter.api.Test -import theodolite.patcher.PatcherFactory -import theodolite.util.PatcherDefinition /** * Resource patcher test @@ -25,8 +24,6 @@ import theodolite.util.PatcherDefinition @Disabled class ResourceLimitPatcherTest { - val patcherFactory = PatcherFactory() - @KubernetesTestServer private lateinit var server: KubernetesServer @@ -51,15 +48,8 @@ class ResourceLimitPatcherTest { "container" to "uc-application" ) - patcherFactory.createPatcher( - patcherDefinition = defCPU, - k8sResources = listOf(Pair("/cpu-memory-deployment.yaml", k8sResource)) - ).patch(value = cpuValue) - - patcherFactory.createPatcher( - patcherDefinition = defMEM, - k8sResources = listOf(Pair("/cpu-memory-deployment.yaml", k8sResource)) - ).patch(value = memValue) + PatchHandler.patchResource(mutableMapOf(Pair("cpu-memory-deployment.yaml", listOf(k8sResource as HasMetadata))), defCPU, cpuValue) + PatchHandler.patchResource(mutableMapOf(Pair("cpu-memory-deployment.yaml", listOf(k8sResource as HasMetadata))), defMEM, memValue) k8sResource.spec.template.spec.containers.filter { it.name == defCPU.properties["container"]!! } .forEach { diff --git a/theodolite/src/test/kotlin/theodolite/patcher/ResourceRequestPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcherTest.kt similarity index 84% rename from theodolite/src/test/kotlin/theodolite/patcher/ResourceRequestPatcherTest.kt rename to theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcherTest.kt index dba91eb65d4474d38f64d7fdd7f7ab981f8eb30f..a076e541e742e97ffa95dccff925892dd63ff17a 100644 --- a/theodolite/src/test/kotlin/theodolite/patcher/ResourceRequestPatcherTest.kt +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/ResourceRequestPatcherTest.kt @@ -1,4 +1,4 @@ -package theodolite.patcher +package rocks.theodolite.kubernetes.patcher import io.fabric8.kubernetes.client.server.mock.KubernetesServer import io.quarkus.test.junit.QuarkusTest @@ -6,7 +6,6 @@ import io.quarkus.test.kubernetes.client.KubernetesTestServer import io.quarkus.test.kubernetes.client.WithKubernetesTestServer import io.smallrye.common.constraint.Assert.assertTrue import org.junit.jupiter.api.Test -import theodolite.util.PatcherDefinition /** * Resource patcher test @@ -25,8 +24,6 @@ class ResourceRequestPatcherTest { @KubernetesTestServer private lateinit var server: KubernetesServer - val patcherFactory = PatcherFactory() - fun applyTest(fileName: String) { val cpuValue = "50m" val memValue = "3Gi" @@ -48,14 +45,8 @@ class ResourceRequestPatcherTest { "container" to "application" ) - patcherFactory.createPatcher( - patcherDefinition = defCPU, - k8sResources = listOf(Pair("/cpu-memory-deployment.yaml", k8sResource)) - ).patch(value = cpuValue) - patcherFactory.createPatcher( - patcherDefinition = defMEM, - k8sResources = listOf(Pair("/cpu-memory-deployment.yaml", k8sResource)) - ).patch(value = memValue) + PatchHandler.patchResource(mutableMapOf(Pair("/cpu-memory-deployment.yaml", listOf(k8sResource))), defCPU, cpuValue) + PatchHandler.patchResource(mutableMapOf(Pair("/cpu-memory-deployment.yaml", listOf(k8sResource))), defMEM, memValue) k8sResource.spec.template.spec.containers.filter { it.name == defCPU.properties["container"]!! } .forEach { @@ -87,4 +78,4 @@ class ResourceRequestPatcherTest { // Case 4: In the given YAML declaration neither `Resource Request` nor `Request Limit` is defined applyTest("/no-resources-deployment.yaml") } -} +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..2b2021ec5853af4a2ef087a21bde87fb5bdc847e --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/SchedulerNamePatcherTest.kt @@ -0,0 +1,32 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class SchedulerNamePatcherTest : AbstractPatcherTest(){ + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = SchedulerNamePatcher() + value = "testScheduler" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.template.spec.schedulerName == value) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..94073b9f34d6b76d69d82e4ea40ed047a68655ff --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/TemplateLabelPatcherTest.kt @@ -0,0 +1,30 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class TemplateLabelPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = TemplateLabelPatcher( "labelName") + value = "labelValue" + } + + + @Test + override fun validate() { + patch() + resource.forEach { + assertTrue((it as Deployment).spec.template.metadata.labels.containsKey("labelName")) + assertTrue(it.spec.template.metadata.labels["labelName"] =="labelValue") + } + } + +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcherTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcherTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..db3fc812e426c0f74cf68d35a158f32a3ec0bc3f --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/patcher/VolumesConfigMapPatcherTest.kt @@ -0,0 +1,33 @@ +package rocks.theodolite.kubernetes.patcher + +import io.fabric8.kubernetes.api.model.apps.Deployment +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.AfterEach +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +import org.junit.jupiter.api.Assertions.* + +@QuarkusTest +internal class VolumesConfigMapPatcherTest: AbstractPatcherTest() { + + @BeforeEach + fun setUp() { + resource = listOf(createDeployment()) + patcher = VolumesConfigMapPatcher("test-configmap") + value = "patchedVolumeName" + } + + @AfterEach + fun tearDown() { + } + + @Test + override fun validate() { + patch() + resource.forEach { + println((it as Deployment).spec.template.spec.volumes[0].configMap.name) + assertTrue((it as Deployment).spec.template.spec.volumes[0].configMap.name == value) + } + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloFactoryTest.kt b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloFactoryTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..de9d4c60dbad069ccb1229bebb4a4751cf96d98d --- /dev/null +++ b/theodolite/src/test/kotlin/rocks/theodolite/kubernetes/slo/SloFactoryTest.kt @@ -0,0 +1,69 @@ +package rocks.theodolite.kubernetes.slo + +import io.quarkus.test.junit.QuarkusTest +import org.junit.jupiter.api.Assertions +import org.junit.jupiter.api.Test +import rocks.theodolite.kubernetes.model.BenchmarkExecution +import rocks.theodolite.kubernetes.model.KubernetesBenchmark + +@QuarkusTest +internal class SloFactoryTest { + + @Test + fun overwriteSloTest() { + + val benchmark = KubernetesBenchmark() + val execution = BenchmarkExecution() + + // Define Benchmark SLOs + val slo = KubernetesBenchmark.Slo() + slo.name="test" + slo.sloType="lag trend" + slo.prometheusUrl="test.de" + slo.offset=0 + + val benchmarkSloProperties = mutableMapOf<String, String>() + benchmarkSloProperties["threshold"] = "2000" + benchmarkSloProperties["externalSloUrl"] = "http://localhost:80/evaluate-slope" + benchmarkSloProperties["warmup"] = "60" + + slo.properties=benchmarkSloProperties + + benchmark.slos = mutableListOf(slo) + + + // Define Execution SLOs, benchmark SLO values for these properties should be overwritten + val sloConfig = BenchmarkExecution.SloConfiguration() + sloConfig.name = "test" + + val executionSloProperties = mutableMapOf<String, String>() + // overwriting properties 'threshold' and 'warmup' and adding property 'extensionTest' + executionSloProperties["threshold"] = "3000" + executionSloProperties["warmup"] = "80" + executionSloProperties["extensionTest"] = "extended" + + sloConfig.properties = executionSloProperties + + // SLO has 'name' that isn't defined in the benchmark, therefore it will be ignored by the SloFactory + val sloConfig2 = BenchmarkExecution.SloConfiguration() + sloConfig2.name = "test2" + sloConfig2.properties = executionSloProperties + + execution.slos = listOf(sloConfig, sloConfig2) + + val sloFactory = SloFactory() + val combinedSlos = sloFactory.createSlos(execution,benchmark) + + Assertions.assertEquals(1, combinedSlos.size) + Assertions.assertEquals("test", combinedSlos[0].name) + Assertions.assertEquals("lag trend", combinedSlos[0].sloType) + Assertions.assertEquals("test.de", combinedSlos[0].prometheusUrl) + Assertions.assertEquals(0, combinedSlos[0].offset) + + Assertions.assertEquals(4, combinedSlos[0].properties.size) + Assertions.assertEquals("3000", combinedSlos[0].properties["threshold"]) + Assertions.assertEquals("http://localhost:80/evaluate-slope", combinedSlos[0].properties["externalSloUrl"]) + Assertions.assertEquals("80", combinedSlos[0].properties["warmup"]) + Assertions.assertEquals("extended", combinedSlos[0].properties["extensionTest"]) + } +} \ No newline at end of file diff --git a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt b/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt deleted file mode 100644 index 580d9e747bde687a91ffb1bce2e7c9dfb6f166a2..0000000000000000000000000000000000000000 --- a/theodolite/src/test/kotlin/theodolite/CompositeStrategyTest.kt +++ /dev/null @@ -1,117 +0,0 @@ -package theodolite - -import io.quarkus.test.junit.QuarkusTest -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Test -import theodolite.benchmark.BenchmarkExecution -import theodolite.strategies.restriction.LowerBoundRestriction -import theodolite.strategies.searchstrategy.BinarySearch -import theodolite.strategies.searchstrategy.CompositeStrategy -import theodolite.strategies.searchstrategy.LinearSearch -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results - -@QuarkusTest -class CompositeStrategyTest { - - @Test - fun testEnd2EndLinearSearch() { - val mockResults = arrayOf( - arrayOf(true, true, true, true, true, true, true), - arrayOf(false, false, true, true, true, true, true), - arrayOf(false, false, true, true, true, true, true), - arrayOf(false, false, false, true, true, true, true), - arrayOf(false, false, false, false, true, true, true), - arrayOf(false, false, false, false, false, false, true), - arrayOf(false, false, false, false, false, false, false) - ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) } - val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } - val results = Results() - val benchmark = TestBenchmark() - val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() - val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 5) - val linearSearch = LinearSearch(benchmarkExecutor) - val lowerBoundRestriction = LowerBoundRestriction(results) - val strategy = - CompositeStrategy(benchmarkExecutor, linearSearch, setOf(lowerBoundRestriction)) - - val actual: ArrayList<Resource?> = ArrayList() - val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) }) - expected.add(null) - - for (load in mockLoads) { - actual.add(strategy.findSuitableResource(load, mockResources)) - } - - assertEquals(actual, expected) - } - - @Test - fun testEnd2EndBinarySearch() { - val mockResults = arrayOf( - arrayOf(true, true, true, true, true, true, true), - arrayOf(false, false, true, true, true, true, true), - arrayOf(false, false, true, true, true, true, true), - arrayOf(false, false, false, true, true, true, true), - arrayOf(false, false, false, false, true, true, true), - arrayOf(false, false, false, false, false, false, true), - arrayOf(false, false, false, false, false, false, false) - ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) } - val mockResources: List<Resource> = (0..6).map { number -> Resource(number, emptyList()) } - val results = Results() - val benchmark = TestBenchmark() - val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() - val benchmarkExecutorImpl = - TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0) - val binarySearch = BinarySearch(benchmarkExecutorImpl) - val lowerBoundRestriction = LowerBoundRestriction(results) - val strategy = - CompositeStrategy(benchmarkExecutorImpl, binarySearch, setOf(lowerBoundRestriction)) - - val actual: ArrayList<Resource?> = ArrayList() - val expected: ArrayList<Resource?> = ArrayList(listOf(0, 2, 2, 3, 4, 6).map { x -> Resource(x, emptyList()) }) - expected.add(null) - - for (load in mockLoads) { - actual.add(strategy.findSuitableResource(load, mockResources)) - } - - assertEquals(actual, expected) - } - - @Test - fun testEnd2EndBinarySearch2() { - val mockResults = arrayOf( - arrayOf(true, true, true, true, true, true, true, true), - arrayOf(false, false, true, true, true, true, true, true), - arrayOf(false, false, true, true, true, true, true, true), - arrayOf(false, false, false, true, true, true, true, true), - arrayOf(false, false, false, false, true, true, true, true), - arrayOf(false, false, false, false, false, false, true, true), - arrayOf(false, false, false, false, false, false, false, true) - ) - val mockLoads: List<LoadDimension> = (0..6).map { number -> LoadDimension(number, emptyList()) } - val mockResources: List<Resource> = (0..7).map { number -> Resource(number, emptyList()) } - val results = Results() - val benchmark = TestBenchmark() - val sloChecker: BenchmarkExecution.Slo = BenchmarkExecution.Slo() - val benchmarkExecutor = TestBenchmarkExecutorImpl(mockResults, benchmark, results, listOf(sloChecker), 0, 0, 0) - val binarySearch = BinarySearch(benchmarkExecutor) - val lowerBoundRestriction = LowerBoundRestriction(results) - val strategy = - CompositeStrategy(benchmarkExecutor, binarySearch, setOf(lowerBoundRestriction)) - - val actual: ArrayList<Resource?> = ArrayList() - val expected: ArrayList<Resource?> = - ArrayList(listOf(0, 2, 2, 3, 4, 6, 7).map { x -> Resource(x, emptyList()) }) - - for (load in mockLoads) { - actual.add(strategy.findSuitableResource(load, mockResources)) - } - - assertEquals(actual, expected) - } -} diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt b/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt deleted file mode 100644 index b08c1a18a3013e1573e4892f01698b5e509f9609..0000000000000000000000000000000000000000 --- a/theodolite/src/test/kotlin/theodolite/TestBenchmark.kt +++ /dev/null @@ -1,26 +0,0 @@ -package theodolite - -import theodolite.benchmark.Benchmark -import theodolite.benchmark.BenchmarkDeployment -import theodolite.util.ConfigurationOverride -import theodolite.util.LoadDimension -import theodolite.util.Resource - -class TestBenchmark : Benchmark { - - override fun setupInfrastructure() { - } - - override fun teardownInfrastructure() { - } - - override fun buildDeployment( - load: LoadDimension, - res: Resource, - configurationOverrides: List<ConfigurationOverride?>, - loadGenerationDelay: Long, - afterTeardownDelay: Long - ): BenchmarkDeployment { - return TestBenchmarkDeployment() - } -} diff --git a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt b/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt deleted file mode 100644 index 2efddc48cb93a0870d1716c58a7018145c16e2ff..0000000000000000000000000000000000000000 --- a/theodolite/src/test/kotlin/theodolite/TestBenchmarkExecutorImpl.kt +++ /dev/null @@ -1,38 +0,0 @@ -package theodolite - -import theodolite.benchmark.Benchmark -import theodolite.benchmark.BenchmarkExecution -import theodolite.execution.BenchmarkExecutor -import theodolite.util.LoadDimension -import theodolite.util.Resource -import theodolite.util.Results -import java.time.Duration - -class TestBenchmarkExecutorImpl( - private val mockResults: Array<Array<Boolean>>, - benchmark: Benchmark, - results: Results, - slo: List<BenchmarkExecution.Slo>, - executionId: Int, - loadGenerationDelay: Long, - afterTeardownDelay: Long -) : - BenchmarkExecutor( - benchmark, - results, - executionDuration = Duration.ofSeconds(1), - configurationOverrides = emptyList(), - slos = slo, - repetitions = 1, - executionId = executionId, - loadGenerationDelay = loadGenerationDelay, - afterTeardownDelay = afterTeardownDelay, - executionName = "test-execution" - ) { - - override fun runExperiment(load: LoadDimension, res: Resource): Boolean { - val result = this.mockResults[load.get()][res.get()] - this.results.setResult(Pair(load, res), result) - return result - } -} diff --git a/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt b/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt deleted file mode 100644 index 9cfc2ae78e7a8846e3f0fa136699509145e5de22..0000000000000000000000000000000000000000 --- a/theodolite/src/test/kotlin/theodolite/util/ResultsTest.kt +++ /dev/null @@ -1,75 +0,0 @@ -package theodolite.util - -import io.quarkus.test.junit.QuarkusTest -import org.junit.jupiter.api.Assertions.assertEquals -import org.junit.jupiter.api.Assertions.assertNotNull -import org.junit.jupiter.api.Disabled -import org.junit.jupiter.api.Test - -@QuarkusTest -internal class ResultsTest { - - @Test - fun testMinRequiredInstancesWhenSuccessful() { - val results = Results() - results.setResult(10000, 1, true) - results.setResult(10000, 2, true) - results.setResult(20000, 1, false) - results.setResult(20000, 2, true) - - val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList())) - - assertNotNull(minRequiredInstances) - assertEquals(2, minRequiredInstances!!.get()) - } - - @Test - @Disabled - fun testMinRequiredInstancesWhenNotSuccessful() { - // This test is currently not implemented this way, but might later be the desired behavior. - val results = Results() - results.setResult(10000, 1, true) - results.setResult(10000, 2, true) - results.setResult(20000, 1, false) - results.setResult(20000, 2, false) - - val minRequiredInstances = results.getMinRequiredInstances(LoadDimension(20000, emptyList())) - - assertNotNull(minRequiredInstances) - assertEquals(2, minRequiredInstances!!.get()) - } - - private fun Results.setResult(load: Int, resources: Int, successful: Boolean) { - this.setResult( - Pair( - LoadDimension(load, emptyList()), - Resource(resources, emptyList()) - ), - successful - ) - } - - - @Test - fun testGetMaxBenchmarkedLoadWhenAllSuccessful() { - val results = Results() - results.setResult(10000, 1, true) - results.setResult(10000, 2, true) - - val test1 = results.getMaxBenchmarkedLoad(LoadDimension(100000, emptyList()))!!.get() - - assertEquals(10000, test1) - } - - @Test - fun testGetMaxBenchmarkedLoadWhenLargestNotSuccessful() { - val results = Results() - results.setResult(10000, 1, true) - results.setResult(10000, 2, true) - results.setResult(20000, 1, false) - - val test2 = results.getMaxBenchmarkedLoad(LoadDimension(100000, emptyList()))!!.get() - - assertEquals(20000, test2) - } -} diff --git a/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml b/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml index ea9ee8471d3da1dc6011348bd978696bd0fa6f36..ad26f6c658c72231887a8e3cd4c5dc17cc787641 100644 --- a/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml +++ b/theodolite/src/test/resources/k8s-resource-files/test-benchmark.yaml @@ -3,6 +3,7 @@ kind: benchmark metadata: name: example-benchmark spec: + waitForResourcesEnabled: false sut: resources: - configMap: @@ -33,6 +34,15 @@ spec: resource: "uc1-load-generator-deployment.yaml" properties: loadGenMaxRecords: "15000" + slos: + - name: "lag trend" + sloType: "lag trend" + prometheusUrl: "http://prometheus-operated:9090" + offset: 0 + properties: + threshold: 3000 + externalSloUrl: "http://localhost:80/evaluate-slope" + warmup: 60 # in seconds kafkaConfig: bootstrapServer: "theodolite-kafka-kafka-bootstrap:9092" topics: diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml index 1407a9952b7454053d204454841d51cfb4d7dbf4..077c4ab410e3fc78a9bb47c563c2b237b922c1ba 100644 --- a/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml +++ b/theodolite/src/test/resources/k8s-resource-files/test-execution-1.yaml @@ -5,24 +5,26 @@ metadata: spec: name: test benchmark: "uc1-kstreams" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: resourceType: "Instances" resourceValues: [1, 2, 3, 4, 5] slos: - - sloType: "lag trend" + - name: "lag trend" threshold: 2000 prometheusUrl: "http://prometheus-operated:9090" externalSloUrl: "http://localhost:80/evaluate-slope" offset: 0 warmup: 60 # in seconds execution: - strategy: "LinearSearch" + strategy: + name: "RestrictionSearch" + restrictions: + - "LowerBound" + searchStrategy: "LinearSearch" duration: 300 # in seconds repetitions: 1 loadGenerationDelay: 30 # in seconds - restrictions: - - "LowerBound" configOverrides: [] diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml index c075702da218397352f1dc1e5b283534fbb4d718..504a73fe3b325368301897cacdc922e7f6e70430 100644 --- a/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml +++ b/theodolite/src/test/resources/k8s-resource-files/test-execution-update.yaml @@ -5,25 +5,23 @@ metadata: spec: name: test benchmark: "uc1-kstreams-update" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: resourceType: "Instances" resourceValues: [1, 2, 3, 4, 5] slos: - - sloType: "lag trend" - prometheusUrl: "http://prometheus-operated:9090" - offset: 0 + - name: "lag trend" properties: threshold: 2000 - externalSloUrl: "http://localhost:80/evaluate-slope" - warmup: 60 # in seconds execution: - strategy: "LinearSearch" + strategy: + name: "RestrictionSearch" + restrictions: + - "LowerBound" + searchStrategy: "LinearSearch" duration: 300 # in seconds repetitions: 1 loadGenerationDelay: 30 # in seconds - restrictions: - - "LowerBound" configOverrides: [] diff --git a/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml b/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml index e12c851da5d8a79f57b1fa59b86239c219370c0f..2bd0bfc4b3602c52fc3cc5cce9729777c21f4ac4 100644 --- a/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml +++ b/theodolite/src/test/resources/k8s-resource-files/test-execution.yaml @@ -5,25 +5,23 @@ metadata: spec: name: test benchmark: "uc1-kstreams" - load: + loads: loadType: "NumSensors" loadValues: [25000, 50000, 75000, 100000, 125000, 150000] resources: resourceType: "Instances" resourceValues: [1, 2, 3, 4, 5] slos: - - sloType: "lag trend" - prometheusUrl: "http://prometheus-operated:9090" - offset: 0 + - name: "lag trend" properties: threshold: 2000 - externalSloUrl: "http://localhost:80/evaluate-slope" - warmup: 60 # in seconds execution: - strategy: "LinearSearch" + strategy: + name: "RestrictionSearch" + restrictions: + - "LowerBound" + searchStrategy: "LinearSearch" duration: 300 # in seconds repetitions: 1 loadGenerationDelay: 30 # in seconds - restrictions: - - "LowerBound" configOverrides: []