Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Initial changes for distributed jmeter #4289

Merged
merged 24 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
07c0884
feat: Initial changes for distributed jmeter
hiteshwani Aug 23, 2023
6590692
Merge branch 'kubeshop:develop' into djmeter-support
hiteshwani Aug 23, 2023
ad02af0
Added jmeter slaves script and Dockerfile
hiteshwani Aug 24, 2023
f4c6bbc
Removed duplicate files and imported from existing jmeter executor
hiteshwani Aug 24, 2023
e1c6d1e
Add secret refs for git username and token for slave pods
hiteshwani Aug 24, 2023
e82eb4c
Merge pull request #1 from infracloudio/git-secret-env
hiteshwani Aug 28, 2023
e12ae8e
Support for user provided plugins (#2)
parauliya Aug 31, 2023
4df9514
Merge branch 'kubeshop:develop' into djmeter-support
hiteshwani Sep 1, 2023
705d3a6
Merge branch 'kubeshop:develop' into djmeter-support
hiteshwani Sep 5, 2023
973991b
Merge branch 'kubeshop:develop' into djmeter-support
hiteshwani Sep 6, 2023
46cc5c9
Update README file for Jmeterd
Sep 6, 2023
73cc659
Changed base image to kubeshop/jmeter and removed tests (#5)
hiteshwani Sep 7, 2023
69c5b29
Support for user.properties file (#3)
parauliya Sep 7, 2023
8c38ea7
Addressed review comments
Sep 8, 2023
afccd30
Merge branch 'kubeshop:develop' into djmeter-support
hiteshwani Sep 11, 2023
79225ea
Merge pull request #4 from infracloudio/jmeterd-readme
parauliya Sep 12, 2023
b349121
Fixed review comments of Dejan
Sep 12, 2023
6481e39
Merge pull request #6 from infracloudio/fix_review_comments
parauliya Sep 12, 2023
33cb979
Refactored slaves pod configuration and added validation for pod name…
hiteshwani Sep 13, 2023
51f3664
Update README file of Distributor JMeter
Sep 14, 2023
50675e5
Adding a new example in a new folder named giflow under the examples …
Sep 14, 2023
a77a721
Merge pull request #9 from infracloudio/jmeterd-readme
parauliya Sep 14, 2023
9d80a36
Remove plugins from /lib
hiteshwani Sep 14, 2023
9bb9cc7
Merge pull request #10 from infracloudio/lib-plugin-remove
parauliya Sep 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions contrib/executor/jmeterd/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
.git
.gitignore
.golangci.yml
CODE_OF_CONDUCT.md
CONTRIBUTING.md
LICENSE
Makefile
README.md
temp
data
6 changes: 6 additions & 0 deletions contrib/executor/jmeterd/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# used if storage backend is behind HTTPS, should be set to false for local development
RUNNER_SSL=false
# used to enable/disable scrapper, should be set to false for local development
RUNNER_SCRAPPERENABLED=false
# path to the data/ directory where JMeter will run and store results
RUNNER_DATADIR=./data
35 changes: 35 additions & 0 deletions contrib/executor/jmeterd/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
### Go template
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
vendor/

### JetBrains
.idea
*.iml

# Helm
Chart.lock

.DS_Store
bin/
site
dist/
data/
temp/

.vscode

### Environment
.env
29 changes: 29 additions & 0 deletions contrib/executor/jmeterd/.golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
run:
timeout: 5m

linters:
disable-all: true
enable:
- errcheck
- goimports
- govet
- staticcheck
- revive
- unused
- errname
- errorlint
- gocyclo
- gofmt
- goimports
- misspell
- predeclared

linters-settings:
govet:
check-shadowing: true
lll:
line-length: 150
misspell:
locale: US
goimports:
local-prefixes: github.com/kubeshop/testkube,github.com/kubeshop/testkube-executor-jmeter
30 changes: 30 additions & 0 deletions contrib/executor/jmeterd/CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# testkube (by Kubeshop) Community Code of Conduct

Testkube follows the CNCF Code of Conduct. The text of the CNCF CoC is replicated below. If you notice that this is out of date, please file an issue.

If you notice a violation of the Code of Conduct at an event or meeting, in Slack, or in another communication mechanism, reach out to the Testkube Code of Conduct Committee. You can reach us by email at [email protected] Your anonymity will be protected.

# CNCF Community Code of Conduct v1.0

## Contributor Code of Conduct

As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.

We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, ethnicity, age, religion, or nationality.

## Examples of unacceptable behavior by participants include:

- The use of sexualized language or imagery
- Personal attacks
- Trolling or insulting/derogatory comments
- Public or private harassment
- Publishing other's private information, such as physical or electronic addresses, without explicit permission
- Other unethical or unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. By adopting this Code of Conduct, project maintainers commit themselves to fairly and consistently applying these principles to every aspect of managing this project. Project maintainers who do not follow or enforce the Code of Conduct may be permanently removed from the project team.

This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.

Instances of abusive, harassing, or otherwise unacceptable behavior in Testkube may be reported by contacting the Testkube Code of Conduct Committee via [email protected].

This Code of Conduct is adapted from the Contributor Covenant (https://contributor-covenant.org), version 1.2.0, available at https://contributor-covenant.org/version/1/2/0/
44 changes: 44 additions & 0 deletions contrib/executor/jmeterd/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Contribution to Testkube

Thanks for reaching out contribution 🎉

If you're new in Open-source community there is nice guide how to start contributing to projects:
https://github.com/firstcontributions/first-contributions

## Code of Conduct

This project and everyone participating in it is governed by the Testkube [code of conduct](CODE_OF_CONDUCT.md)

## Have questions or idea?

We're using github discussions for managing pre-development ideas and clarifications, feel free to add one at our [Q&A discussion page](https://github.com/kubeshop/testkube/discussions/categories/q-a)

New ideas should be placed in [Ideas discussion page](https://github.com/kubeshop/testkube/discussions/categories/ideas)



## General guidance for contributing to Testkube project

You're very welcome to help in testkube development, there is a lot of incoming work to do :).

We're trying hard to limit technical debt from the beginning so we defined simple rules into Testkube repo to help with it.

### For golang based components

- Always use gofmt (there is only one true way of doing code formatting ;) ).
- Follow golang good practices (proverbs) in your code.
- Tests are your friend (we will target 80% CC in our code).
- Use clean names, don't brake basic design patterns and rules.

### For infrastructure / Kubernetes based components

- We're using helm charts to build and share Testkube
- Comment non-obvious decisions
- Use current Helm/Kubernetes versions


## How can I help?

- By fixing [one of many Issues](https://github.com/kubeshop/testkube/issues) - simply fork our repo and create new Pull Request with new code changes.
- By helping to reach out valid results [from discussions](https://github.com/kubeshop/testkube/discussions)

21 changes: 21 additions & 0 deletions contrib/executor/jmeterd/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 Kubeshop

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
64 changes: 64 additions & 0 deletions contrib/executor/jmeterd/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
REPOSITORY ?= kubeshop
NAME ?= testkube-jmeterd-executor
SLAVES_NAME ?= testkube-jmeterd-slaves
LOCAL_TAG ?= 999.0.0
BIN_DIR ?= $(HOME)/bin

.PHONY: build
build:
go build -o $(BIN_DIR)/$(NAME) cmd/agent/main.go

.PHONY: build-local-linux
build-local-linux:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o dist/runner cmd/agent/main.go

.PHONY: run
run:
EXECUTOR_PORT=8082 go run cmd/agent/main.go ${run_args}

.PHONY: docker-build
docker-build:
docker build -t $(REPOSITORY)/$(NAME) -f build/agent/Dockerfile .

.PHONY: docker-build-local
docker-build-local: build-local-linux
docker build -t $(REPOSITORY)/$(NAME):$(LOCAL_TAG) -f build/agent/local.Dockerfile .

docker-build-slaves:
docker build -t $(REPOSITORY)/$(SLAVES_NAME):$(LOCAL_TAG) -f build/slaves/Dockerfile .

.PHONY: kind-load-local
kind-load-local: build-local-linux
kind load docker-image kubeshop/testkube-jmeterd-executor:999.0.0

.PHONY: test
test:
go test ./... -cover

.PHONY: integration-test
integration-test:
INTEGRATION=y gotestsum --format short-verbose -- -run _Integration -cover ./...

.PHONY: cover
cover:
@go test -failfast -count=1 -v -tags test -coverprofile=./testCoverage.txt ./... && go tool cover -html=./testCoverage.txt -o testCoverage.html && rm ./testCoverage.txt
open testCoverage.html

.PHONY: version-bump
version-bump: version-bump-patch

.PHONY: version-bump-patch
version-bump-patch:
go run cmd/tools/main.go bump -k patch

.PHONY: version-bump-minor
version-bump-minor:
go run cmd/tools/main.go bump -k minor

.PHONY: version-bump-major
version-bump-major:
go run cmd/tools/main.go bump -k major

.PHONY: version-bump-dev
version-bump-dev:
go run cmd/tools/main.go bump --dev
136 changes: 136 additions & 0 deletions contrib/executor/jmeterd/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
![Testkube Logo](https://raw.githubusercontent.com/kubeshop/testkube/main/assets/testkube-color-gray.png)

[![Go Report Card](https://goreportcard.com/badge/github.com/kubeshop/testkube-executor-jmeter)](https://goreportcard.com/report/github.com/kubeshop/testkube-executor-jmeter)
[![Go Reference](https://pkg.go.dev/badge/github.com/kubeshop/testkube-executor-jmeter.svg)](https://pkg.go.dev/github.com/kubeshop/testkube-executor-jmeter)
[![License](https://img.shields.io/github/license/kubeshop/testkube-executor-jmeter)]()

# JMeter Executor

## What is an Executor?

Executor is nothing more than a program wrapped into Docker container which gets JSON (testube.Execution) OpenAPI based document as an input and returns a stream of JSON output lines (testkube.ExecutorOutput),
where each output line is simply wrapped in this JSON, similar to the structured logging idea.

## Intro

It's basic JMeter executor able to run simple JMeter scenarios writer in JMX format.
Please define your JMeter file as file (string, or git file).

Project directory is not implemented yet.

## Plugins

The following plugins are installed by default:
* [JMeter Plugins Common Classes 0.6](https://javadoc.io/doc/kg.apc/jmeter-plugins-cmn-jmeter/latest/index.html)
* [JMeter Plugins Manager 1.3](https://jmeter-plugins.org/wiki/PluginsManager/)
* [Custom JMeter Functions 2.1](https://jmeter-plugins.org/wiki/Functions/)

You can add more JMeter plugins either when creating or executing a JMeter test by leveraging Testkube's [copy files](https://docs.testkube.io/articles/running-tests#mapping-local-files) functionality.

JMeter Plugin JAR files need to be copied to the `uploads` directory in the Executor container.

Example:
```shell
kubectl testkube create test \
--file test.jmx \
--copy-files "/source/path/to/jmeter-plugins-functions-2.1.jar:plugins/jmeter-plugins-functions-2.1.jar" \
--name jmeter-test \
--type jmeter/test
```

## Local development

### Prerequisites

Make sure the following tools are installed on your machine and available in your PATH:
* [JMeter](https://jmeter.apache.org/download_jmeter.cgi) - pure Java application designed to load test functional behavior and measure performance

### Setup
1. Create a directory called `data/` where JMeter will run and store results (best practice is to create it in the project root because it is git-ignored)
2. Create a JMeter XML project file and save it as a file named `test-content` in the newly created `data/` directory
3. Create an execution JSON file and save it as a file named `execution.json` based on the template below (best practice is to save it in the `temp/` folder in the project root because it is git-ignored)
```json
{
"id": "jmeter-test",
"args": [],
"variables": {},
"content": {
"type": "string"
}
}
```
4. You need to provide the `RUNNER_SCRAPPERENABLED`, `RUNNER_SSL` and `RUNNER_DATADIR` environment variables and run the Executor using the `make run run_args="-f|--file <path>"` make command where `-f|--file <path>` argument is the path to the `execution.json` file you created in step 3.
```bash
RUNNER_SCRAPPERENABLED=false RUNNER_SSL=false RUNNER_DATADIR="./data" make run run_args="-f temp/execution.json"
```

#### Execution JSON

Execution JSON stores information required for an Executor to run the configured tests.

Breakdown of the Execution JSON:
```json
{
"args": ["-n", "-t", "test.jmx"],
"variables": {
"example": {
"type": "basic",
"name": "example",
"value": "some-value"
}
},
"content": {
"type": "string"
}
}
```
* **args** - array of strings which will be passed to JMeter as arguments
* example: `["-n", "-t", "test.jmx"]`
* **variables** - map of variables which will be passed to JMeter as arguments
* example: `{"example": {"type": "basic", "name": "example", "value": "some-value"}}`
* **content.type** - used to specify that JMeter XML is provided as a text file

#### Environment Variables
```bash
RUNNER_SSL=false # used if storage backend is behind HTTPS, should be set to false for local development
RUNNER_SCRAPPERENABLED=false # used to enable/disable scrapper, should be set to false for local development
RUNNER_DATADIR=<path-to-data-dir> # path to the data/ directory where JMeter will run and store results
```

## Testing in Kubernetes

### Prerequisites
* Kubernetes cluster with Testkube installed (best practice is to install it in the `testkube` namespace)

### Guide

After validating locally that the Executor changes work as expected, next step is to test whether Testkube can successfully schedule a Test using the new Executor image.

NOTE: The following commands assume that Testkube is installed in the `testkube` namespace, if you have it installed in a different namespace, please adjust the `--namespace` flag accordingly.

The following steps need to be executed in order for Testkube to use the new Executor image:
1. Build the new Executor image using the `make docker-build-local` command. By default, the image will be tagged as `kubeshop/testkube-executor-jmeter:999.0.0` unless a `LOCAL_TAG` environment variable is provided before the command.
2. Now you need to make the image accessible in Kubernetes, there are a couple of approaches:
* *kind* - `kind load docker-image <image-name> --name <kind cluster name>` (e.g. `kind load docker-image testkube-executor-jmeter:999.0.0 --name testkube-k8s-cluster`)
* *minikube* - `minikube image load <image-name> --profile <minikube profile>` (e.g. `minikube image load testkube-executor-jmeter:999.0.0 --profile k8s-cluster-test`)
* *Docker Desktop* - just by building the image locally, it becomes accessible in the Docker Desktop Kubernetes cluster
* *other* - you can push the image to a registry and then Testkube will pull it in Kubernetes (assuming it has credentials for it if needed)
3. Edit the Job Template and change the `imagePullPolicy` to `IfNotPresent`
* Edit the ConfigMap `testkube-api-server` either by running `kubectl edit configmap testkube-api-server --namespace testkube` or by using a tool like Monokle
* Find the `job-template.yml` key and change the `imagePullPolicy` field in the `containers` section to `IfNotPresent`
4. Edit the Executors configuration and change the base image to use the newly created image:
* Edit the ConfigMap `testkube-api-server` either by running `kubectl edit configmap testkube-api-server --namespace testkube` or by using a tool like Monokle
* Find the `executors.json` key and change the `executor.image` field to use the newly created image for the JMeter Executor (`name` field is `jmeter-executor`)
5. Restart the API Server by running `kubectl rollout restart deployment testkube-api-server --namespace testkube`

Testkube should now use the new image for the Executor and you can schedule a Test with your preferred method.

### Supported Environment Variables

1. **MASTER_OVERRIDE_JVM_ARGS / SLAVES_OVERRIDE_JVM_ARGS**: Used to override default memory options for JMeter master/slaves. Example: `MASTER_OVERRIDE_JVM_ARGS=-Xmn256m -Xms512m -Xmx512m`.

2. **SLAVES_COUNT**: Specifies the number of slaves required for distributed JMeter tests. Example: `SLAVES_COUNT=3`.

3. **MASTER_ADDITIONAL_JVM_ARGS / SLAVES_ADDITIONAL_JMETER_ARGS**: Allows exporting additional JVM arguments for slaves/master. Example: `MASTER_ADDITIONAL_JVM_ARGS=-Xmx1024m -Xms512m -XX:MaxMetaspaceSize=256m`.

4. **SLAVES_ADDITIONAL_JMETER_ARGS**: Provides additional JVM arguments for JMeter server / slaves. Example: `SLAVES_ADDITIONAL_JMETER_ARGS=jmeter-server -Jserver.rmi.ssl.disable=true -Dserver_port=60000`.
Loading