diff --git a/contrib/executor/jmeterd/build/agent/Dockerfile b/contrib/executor/jmeterd/build/agent/Dockerfile index cd95cc2aaf8..93810c7b213 100644 --- a/contrib/executor/jmeterd/build/agent/Dockerfile +++ b/contrib/executor/jmeterd/build/agent/Dockerfile @@ -8,7 +8,5 @@ WORKDIR /root/ COPY ./contrib/executor/jmeterd/scripts/entrypoint.sh /executor_entrypoint.sh COPY scripts/jmeter-master.sh /executor_entrypoint_master.sh -ADD ./contrib/executor/jmeterd/plugins/ ${JMETER_CUSTOM_PLUGINS_FOLDER} -ADD ./contrib/executor/jmeterd/lib ${JMETER_HOME}/lib/ ENTRYPOINT ["/bin/runner"] diff --git a/contrib/executor/jmeterd/build/agent/local.Dockerfile b/contrib/executor/jmeterd/build/agent/local.Dockerfile index 9db38bb0e42..d7111030899 100644 --- a/contrib/executor/jmeterd/build/agent/local.Dockerfile +++ b/contrib/executor/jmeterd/build/agent/local.Dockerfile @@ -11,7 +11,6 @@ ENV ENTRYPOINT_CMD="/executor_entrypoint.sh" COPY dist/runner /bin/runner COPY scripts/entrypoint.sh /executor_entrypoint.sh COPY scripts/jmeter-master.sh /executor_entrypoint_master.sh -ADD plugins/ ${JMETER_CUSTOM_PLUGINS_FOLDER} ADD lib/ ${JMETER_HOME}/lib/ ENTRYPOINT ["/bin/runner"] diff --git a/contrib/executor/jmeterd/build/slaves/Dockerfile b/contrib/executor/jmeterd/build/slaves/Dockerfile index c368d28db00..fbb471dee99 100644 --- a/contrib/executor/jmeterd/build/slaves/Dockerfile +++ b/contrib/executor/jmeterd/build/slaves/Dockerfile @@ -4,8 +4,6 @@ FROM kubeshop/jmeter:5.5 EXPOSE 1099 60001 ENV SSL_DISABLED true -ADD plugins/ ${JMETER_CUSTOM_PLUGINS_FOLDER} -ADD lib/ ${JMETER_HOME}/lib COPY ./scripts/jmeter-slaves.sh /jmeter_slaves_entrypoint.sh RUN chmod +x /jmeter_slaves_entrypoint.sh diff --git a/contrib/executor/jmeterd/cmd/agent/main.go b/contrib/executor/jmeterd/cmd/agent/main.go index 8120f008c3e..cb61a04966f 100644 --- a/contrib/executor/jmeterd/cmd/agent/main.go +++ b/contrib/executor/jmeterd/cmd/agent/main.go @@ -16,12 +16,12 @@ func main() { ctx := context.Background() params, err := envs.LoadTestkubeVariables() if err != nil { - output.PrintError(os.Stderr, errors.Errorf("could not initialize JMeter Executor environment variables: %v", err)) + output.PrintError(os.Stderr, errors.Errorf("could not initialize Distributed JMeter Executor environment variables: %v", err)) os.Exit(1) } r, err := runner.NewRunner(ctx, params) if err != nil { - output.PrintError(os.Stderr, errors.Wrap(err, "error instantiating JMeter Executor")) + output.PrintError(os.Stderr, errors.Wrap(err, "error instantiating Distributed JMeter Executor")) os.Exit(1) } agent.Run(ctx, r, os.Args) diff --git a/contrib/executor/jmeterd/examples/executor.yaml b/contrib/executor/jmeterd/examples/executor.yaml index 24ed407e2db..176bda2d9e7 100644 --- a/contrib/executor/jmeterd/examples/executor.yaml +++ b/contrib/executor/jmeterd/examples/executor.yaml @@ -1,11 +1,11 @@ apiVersion: executor.testkube.io/v1 kind: Executor metadata: - name: jmeter-executor + name: jmeterd-executor namespace: testkube spec: features: - artifacts - image: kubeshop/testkube-jmeter-executor:dev-008 + image: kubeshop/testkube-jmeterd-executor:dev-008 types: - - jmeter/test + - jmeterd/test diff --git a/contrib/executor/jmeterd/pkg/jmeter_env/env.go b/contrib/executor/jmeterd/pkg/jmeterenv/env.go similarity index 75% rename from contrib/executor/jmeterd/pkg/jmeter_env/env.go rename to contrib/executor/jmeterd/pkg/jmeterenv/env.go index cedfa895174..fb968ab1b38 100644 --- a/contrib/executor/jmeterd/pkg/jmeter_env/env.go +++ b/contrib/executor/jmeterd/pkg/jmeterenv/env.go @@ -1,4 +1,4 @@ -package jmeter_env +package jmeterenv import ( "strings" @@ -22,15 +22,15 @@ func ExtractSlaveEnvVariables(variables map[string]testkube.Variable) map[string slaveVariables := make(map[string]testkube.Variable) // Iterate through the variables to extract slave environment variables. - for varName, v := range variables { + for k, v := range variables { switch { - case strings.HasPrefix(varName, SlavesPrefix): - slaveVariables[varName] = v - delete(variables, varName) // Remove slave variable from the main variables map. - case strings.HasPrefix(varName, MasterPrefix): + case strings.HasPrefix(k, SlavesPrefix): + slaveVariables[k] = v + delete(variables, k) // Remove slave variable from the main variables map. + case strings.HasPrefix(k, MasterPrefix): continue default: - slaveVariables[varName] = v + slaveVariables[k] = v } } return slaveVariables diff --git a/contrib/executor/jmeterd/pkg/runner/mapper.go b/contrib/executor/jmeterd/pkg/runner/mapper.go new file mode 100644 index 00000000000..078cf287113 --- /dev/null +++ b/contrib/executor/jmeterd/pkg/runner/mapper.go @@ -0,0 +1,82 @@ +package runner + +import ( + "fmt" + + "github.com/kubeshop/testkube/contrib/executor/jmeter/pkg/parser" + "github.com/kubeshop/testkube/pkg/api/v1/testkube" +) + +func mapResultsToExecutionResults(out []byte, results parser.Results) (result testkube.ExecutionResult) { + result.Status = testkube.ExecutionStatusPassed + if results.HasError { + result.Status = testkube.ExecutionStatusFailed + result.ErrorMessage = results.LastErrorMessage + } + + result.Output = string(out) + result.OutputType = "text/plain" + + for _, r := range results.Results { + result.Steps = append( + result.Steps, + testkube.ExecutionStepResult{ + Name: r.Label, + Duration: r.Duration.String(), + Status: mapResultStatus(r), + AssertionResults: []testkube.AssertionResult{{ + Name: r.Label, + Status: mapResultStatus(r), + }}, + }) + } + + return result +} + +func mapTestResultsToExecutionResults(out []byte, results parser.TestResults) (result testkube.ExecutionResult) { + result.Status = testkube.ExecutionStatusPassed + + result.Output = string(out) + result.OutputType = "text/plain" + + samples := append(results.HTTPSamples, results.Samples...) + for _, r := range samples { + if !r.Success { + result.Status = testkube.ExecutionStatusFailed + if r.AssertionResult != nil { + result.ErrorMessage = r.AssertionResult.FailureMessage + } + } + + result.Steps = append( + result.Steps, + testkube.ExecutionStepResult{ + Name: r.Label, + Duration: fmt.Sprintf("%dms", r.Time), + Status: mapTestResultStatus(r.Success), + AssertionResults: []testkube.AssertionResult{{ + Name: r.Label, + Status: mapTestResultStatus(r.Success), + }}, + }) + } + + return result +} + +func mapResultStatus(result parser.Result) string { + if result.Success { + return string(testkube.PASSED_ExecutionStatus) + } + + return string(testkube.FAILED_ExecutionStatus) +} + +func mapTestResultStatus(success bool) string { + if success { + return string(testkube.PASSED_ExecutionStatus) + } + + return string(testkube.FAILED_ExecutionStatus) +} diff --git a/contrib/executor/jmeterd/pkg/runner/runner.go b/contrib/executor/jmeterd/pkg/runner/runner.go index aa76bde27b6..b5df6c4a566 100644 --- a/contrib/executor/jmeterd/pkg/runner/runner.go +++ b/contrib/executor/jmeterd/pkg/runner/runner.go @@ -10,7 +10,7 @@ import ( "github.com/pkg/errors" "github.com/kubeshop/testkube/contrib/executor/jmeter/pkg/parser" - "github.com/kubeshop/testkube/contrib/executor/jmeterd/pkg/jmeter_env" + "github.com/kubeshop/testkube/contrib/executor/jmeterd/pkg/jmeterenv" "github.com/kubeshop/testkube/contrib/executor/jmeterd/pkg/slaves" "github.com/kubeshop/testkube/pkg/api/v1/testkube" "github.com/kubeshop/testkube/pkg/envs" @@ -24,11 +24,11 @@ import ( "github.com/kubeshop/testkube/pkg/ui" ) -func NewRunner(ctx context.Context, params envs.Params) (*JMeterRunner, error) { +func NewRunner(ctx context.Context, params envs.Params) (*JMeterDRunner, error) { output.PrintLog(fmt.Sprintf("%s Preparing test runner", ui.IconTruck)) var err error - r := &JMeterRunner{ + r := &JMeterDRunner{ Params: params, } @@ -40,15 +40,15 @@ func NewRunner(ctx context.Context, params envs.Params) (*JMeterRunner, error) { return r, nil } -// JMeterRunner runner -type JMeterRunner struct { +// JMeterDRunner runner +type JMeterDRunner struct { Params envs.Params Scraper scraper.Scraper } -var _ runner.Runner = &JMeterRunner{} +var _ runner.Runner = &JMeterDRunner{} -func (r *JMeterRunner) Run(ctx context.Context, execution testkube.Execution) (result testkube.ExecutionResult, err error) { +func (r *JMeterDRunner) Run(ctx context.Context, execution testkube.Execution) (result testkube.ExecutionResult, err error) { if r.Scraper != nil { defer r.Scraper.Close() } @@ -84,7 +84,7 @@ func (r *JMeterRunner) Run(ctx context.Context, execution testkube.Execution) (r output.PrintLog(fmt.Sprintf("execution arg before %s", execution.Args)) execution.Args = execution.Args[:len(execution.Args)-1] - output.PrintLog(fmt.Sprintf("execution arg afrer %s", execution.Args)) + output.PrintLogf("execution arg afrer %s", execution.Args) output.PrintLogf("%s It is a directory test - trying to find file from the last executor argument %s in directory %s", ui.IconWorld, scriptName, path) // sanity checking for test script @@ -97,11 +97,11 @@ func (r *JMeterRunner) Run(ctx context.Context, execution testkube.Execution) (r path = scriptFile } - slavesEnvVariables := jmeter_env.ExtractSlaveEnvVariables(envManager.Variables) + slavesEnvVariables := jmeterenv.ExtractSlaveEnvVariables(envManager.Variables) // compose parameters passed to JMeter with -J params := make([]string, 0, len(envManager.Variables)) for _, value := range envManager.Variables { - if value.Name == jmeter_env.MasterOverrideJvmArgs || value.Name == jmeter_env.MasterAdditionalJvmArgs { + if value.Name == jmeterenv.MasterOverrideJvmArgs || value.Name == jmeterenv.MasterAdditionalJvmArgs { //Skip JVM ARGS to be appended in the command continue } @@ -134,7 +134,7 @@ func (r *JMeterRunner) Run(ctx context.Context, execution testkube.Execution) (r } // recreate output directory with wide permissions so JMeter can create report files if err = os.Mkdir(outputDir, 0777); err != nil { - return *result.Err(errors.Errorf("could not create directory %s: %v", runPath, err)), nil + return *result.Err(errors.Errorf("error creating directory %s: %v", runPath, err)), nil } jtlPath := filepath.Join(outputDir, "report.jtl") @@ -159,19 +159,19 @@ func (r *JMeterRunner) Run(ctx context.Context, execution testkube.Execution) (r } } - sl, err := slaves.NewClient(execution, r.Params, slavesEnvVariables) + slavesClient, err := slaves.NewClient(execution, r.Params, slavesEnvVariables) if err != nil { return *result.WithErrors(errors.Errorf("Getting error while creating slaves client: %v", err)), nil } //creating slaves provided in SLAVES_COUNT env variable - slavesNameIpMap, err := sl.CreateSlaves() + slavesNameIpMap, err := slavesClient.CreateSlaves(ctx) if err != nil { return *result.WithErrors(errors.Errorf("Getting error while creating slaves nodes: %v", err)), nil } - defer sl.DeleteSlaves(slavesNameIpMap) + defer slavesClient.DeleteSlaves(ctx, slavesNameIpMap) - args = append(args, fmt.Sprintf("-R %v", GetSlavesIpString(slavesNameIpMap))) + args = append(args, fmt.Sprintf("-R %v", slavesClient.GetSlavesIpString(slavesNameIpMap))) for i := range args { if args[i] == "" { @@ -223,9 +223,9 @@ func (r *JMeterRunner) Run(ctx context.Context, execution testkube.Execution) (r return *result.WithErrors(errors.Errorf("parsing jtl report error: %v", err)), nil } - executionResult = MapTestResultsToExecutionResults(out, testResults) + executionResult = mapTestResultsToExecutionResults(out, testResults) } else { - executionResult = MapResultsToExecutionResults(out, results) + executionResult = mapResultsToExecutionResults(out, results) } output.PrintLogf("%s Mapped JMeter results to Execution Results...", ui.IconCheckMark) @@ -259,89 +259,7 @@ func getEntryPoint() (entrypoint string) { return filepath.Join(wd, "scripts/entrypoint.sh") } -func MapResultsToExecutionResults(out []byte, results parser.Results) (result testkube.ExecutionResult) { - result.Status = testkube.ExecutionStatusPassed - if results.HasError { - result.Status = testkube.ExecutionStatusFailed - result.ErrorMessage = results.LastErrorMessage - } - - result.Output = string(out) - result.OutputType = "text/plain" - - for _, r := range results.Results { - result.Steps = append( - result.Steps, - testkube.ExecutionStepResult{ - Name: r.Label, - Duration: r.Duration.String(), - Status: MapResultStatus(r), - AssertionResults: []testkube.AssertionResult{{ - Name: r.Label, - Status: MapResultStatus(r), - }}, - }) - } - - return result -} - -func MapTestResultsToExecutionResults(out []byte, results parser.TestResults) (result testkube.ExecutionResult) { - result.Status = testkube.ExecutionStatusPassed - - result.Output = string(out) - result.OutputType = "text/plain" - - samples := append(results.HTTPSamples, results.Samples...) - for _, r := range samples { - if !r.Success { - result.Status = testkube.ExecutionStatusFailed - if r.AssertionResult != nil { - result.ErrorMessage = r.AssertionResult.FailureMessage - } - } - - result.Steps = append( - result.Steps, - testkube.ExecutionStepResult{ - Name: r.Label, - Duration: fmt.Sprintf("%dms", r.Time), - Status: MapTestResultStatus(r.Success), - AssertionResults: []testkube.AssertionResult{{ - Name: r.Label, - Status: MapTestResultStatus(r.Success), - }}, - }) - } - - return result -} - -func MapResultStatus(result parser.Result) string { - if result.Success { - return string(testkube.PASSED_ExecutionStatus) - } - - return string(testkube.FAILED_ExecutionStatus) -} - -func MapTestResultStatus(success bool) string { - if success { - return string(testkube.PASSED_ExecutionStatus) - } - - return string(testkube.FAILED_ExecutionStatus) -} - // GetType returns runner type -func (r *JMeterRunner) GetType() runner.Type { +func (r *JMeterDRunner) GetType() runner.Type { return runner.TypeMain } - -func GetSlavesIpString(podNameIpMap map[string]string) string { - podIps := []string{} - for _, ip := range podNameIpMap { - podIps = append(podIps, ip) - } - return strings.Join(podIps, ",") -} diff --git a/contrib/executor/jmeterd/pkg/slaves/slave_client.go b/contrib/executor/jmeterd/pkg/slaves/client.go similarity index 75% rename from contrib/executor/jmeterd/pkg/slaves/slave_client.go rename to contrib/executor/jmeterd/pkg/slaves/client.go index 47bf6cea386..60205b71506 100644 --- a/contrib/executor/jmeterd/pkg/slaves/slave_client.go +++ b/contrib/executor/jmeterd/pkg/slaves/client.go @@ -3,9 +3,10 @@ package slaves import ( "context" "fmt" + "strings" "time" - "github.com/kubeshop/testkube/contrib/executor/jmeterd/pkg/jmeter_env" + "github.com/kubeshop/testkube/contrib/executor/jmeterd/pkg/jmeterenv" "github.com/kubeshop/testkube/pkg/api/v1/testkube" "github.com/kubeshop/testkube/pkg/envs" "github.com/kubeshop/testkube/pkg/executor/output" @@ -21,8 +22,8 @@ const ( ) type Interface interface { - CreateSlaves(replicaCount int) error - DeleteSlaves(podName string) error + CreateSlaves(ctx context.Context) error + DeleteSlaves(ctx context.Context, slaveNameIpMap map[string]string) error } type Client struct { @@ -51,8 +52,8 @@ func NewClient(execution testkube.Execution, envParams envs.Params, slavesEnvVar // creating slaves as per count provided in the SLAVES_CLOUNT env variable. // Default SLAVES_COUNT would be 1 if not provided in the env variables -func (client *Client) CreateSlaves() (map[string]string, error) { - slavesCount, err := getSlavesCount(client.envVariables[jmeter_env.SlavesCount]) +func (client *Client) CreateSlaves(ctx context.Context) (map[string]string, error) { + slavesCount, err := getSlavesCount(client.envVariables[jmeterenv.SlavesCount]) if err != nil { return nil, errors.Errorf("Getting error while fetching slaves count from env variable SLAVES_COUNT : %v", err) } @@ -64,7 +65,7 @@ func (client *Client) CreateSlaves() (map[string]string, error) { podIPAddresses := make(map[string]string) for i := 1; i <= slavesCount; i++ { - go client.createSlavePod(i, podIPAddressChan, errorChan) + go client.createSlavePod(ctx, i, podIPAddressChan, errorChan) } for i := 0; i < slavesCount; i++ { @@ -84,7 +85,7 @@ func (client *Client) CreateSlaves() (map[string]string, error) { } // created slaves pod and send its ipaddress on the podIPAddressChan channel when pod is in the ready state -func (client *Client) createSlavePod(currentSlavesCount int, podIPAddressChan chan<- map[string]string, errorChan chan<- error) { +func (client *Client) createSlavePod(ctx context.Context, currentSlavesCount int, podIPAddressChan chan<- map[string]string, errorChan chan<- error) { slavePod, err := getSlavePodConfiguration(client.execution.Name, client.execution, client.envVariables, client.envParams) if err != nil { @@ -93,14 +94,14 @@ func (client *Client) createSlavePod(currentSlavesCount int, podIPAddressChan ch } slavePod.Name = fmt.Sprintf("%s-%v-%v", slavePod.Name, currentSlavesCount, client.execution.Id) - p, err := client.clientSet.CoreV1().Pods(client.namespace).Create(context.Background(), slavePod, metav1.CreateOptions{}) + p, err := client.clientSet.CoreV1().Pods(client.namespace).Create(ctx, slavePod, metav1.CreateOptions{}) if err != nil { errorChan <- err return } // Wait for the pod to become ready - conditionFunc := isPodReady(context.Background(), client.clientSet, p.Name, client.namespace) + conditionFunc := isPodReady(ctx, client.clientSet, p.Name, client.namespace) err = wait.PollImmediate(time.Second, podsTimeout, conditionFunc) if err != nil { @@ -108,7 +109,7 @@ func (client *Client) createSlavePod(currentSlavesCount int, podIPAddressChan ch return } - p, err = client.clientSet.CoreV1().Pods(client.namespace).Get(context.Background(), p.Name, metav1.GetOptions{}) + p, err = client.clientSet.CoreV1().Pods(client.namespace).Get(ctx, p.Name, metav1.GetOptions{}) if err != nil { errorChan <- err return @@ -119,10 +120,10 @@ func (client *Client) createSlavePod(currentSlavesCount int, podIPAddressChan ch podIPAddressChan <- podNameIpMap } -func (client *Client) DeleteSlaves(slaveNameIpMap map[string]string) error { +func (client *Client) DeleteSlaves(ctx context.Context, slaveNameIpMap map[string]string) error { for slaveName := range slaveNameIpMap { output.PrintLog(fmt.Sprintf("Deleting slave %v", slaveName)) - err := client.clientSet.CoreV1().Pods(client.namespace).Delete(context.Background(), slaveName, metav1.DeleteOptions{}) + err := client.clientSet.CoreV1().Pods(client.namespace).Delete(ctx, slaveName, metav1.DeleteOptions{}) if err != nil { output.PrintLogf("Error deleting slave pods %v", err.Error()) return err @@ -131,3 +132,11 @@ func (client *Client) DeleteSlaves(slaveNameIpMap map[string]string) error { } return nil } + +func (client *Client) GetSlavesIpString(podNameIpMap map[string]string) string { + podIps := []string{} + for _, ip := range podNameIpMap { + podIps = append(podIps, ip) + } + return strings.Join(podIps, ",") +} diff --git a/contrib/executor/jmeterd/pkg/slaves/slave_utils.go b/contrib/executor/jmeterd/pkg/slaves/utils.go similarity index 89% rename from contrib/executor/jmeterd/pkg/slaves/slave_utils.go rename to contrib/executor/jmeterd/pkg/slaves/utils.go index 2109e169c2a..d20302da8f5 100644 --- a/contrib/executor/jmeterd/pkg/slaves/slave_utils.go +++ b/contrib/executor/jmeterd/pkg/slaves/utils.go @@ -106,16 +106,20 @@ func getSlavePodConfiguration(testName string, runnerExecution testkube.Executio return nil, err } + podName := fmt.Sprintf("%s-jmeter-slave", testName) + if err != nil { + return nil, err + } return &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ - Name: fmt.Sprintf("%s-jmeter-slave", testName), + Name: podName, }, Spec: v1.PodSpec{ RestartPolicy: v1.RestartPolicyAlways, InitContainers: []v1.Container{ { - Name: fmt.Sprintf("%s-init-container", testName), - Image: "kubeshop/testkube-init-executor:1.13.12", + Name: "init", + Image: "kubeshop/testkube-init-executor:1.14.3", Command: []string{"/bin/runner", string(runnerExecutionStr)}, Env: getSlaveRunnerEnv(envParams, runnerExecution), ImagePullPolicy: v1.PullIfNotPresent, @@ -129,7 +133,7 @@ func getSlavePodConfiguration(testName string, runnerExecution testkube.Executio }, Containers: []v1.Container{ { - Name: fmt.Sprintf("%s-slave", testName), + Name: "main", Image: "kubeshop/testkube-jmeterd-slaves:999.0.0", Env: getSlaveConfigurationEnv(envVariables), ImagePullPolicy: v1.PullIfNotPresent, @@ -190,7 +194,11 @@ func isPodReady(ctx context.Context, c kubernetes.Interface, podName, namespace } for _, condition := range pod.Status.Conditions { - if condition.Type == v1.PodReady && condition.Status == v1.ConditionTrue && pod.Status.Phase == v1.PodRunning && pod.Status.PodIP != "" { + isReadyType := condition.Type == v1.PodReady + isConditionTrue := condition.Status == v1.ConditionTrue + isRunningPhase := pod.Status.Phase == v1.PodRunning + ipNotEmpty := pod.Status.PodIP != "" + if isReadyType && isConditionTrue && isRunningPhase && ipNotEmpty { return true, nil } } @@ -200,7 +208,7 @@ func isPodReady(ctx context.Context, c kubernetes.Interface, podName, namespace func getSlavesCount(count testkube.Variable) (int, error) { if count.Value == "" { - output.PrintLog(fmt.Sprintf("Slaves count not provided in the SLAVES_COUNT env variable. Creating pod with default slaves %v", defaultSlavesCount)) + output.PrintLogf("Slaves count not provided in the SLAVES_COUNT env variable. Defaulting to %v slaves", defaultSlavesCount) return defaultSlavesCount, nil } diff --git a/contrib/executor/jmeterd/plugins/jmeter-plugins-functions-2.1.jar b/contrib/executor/jmeterd/plugins/jmeter-plugins-functions-2.1.jar deleted file mode 100644 index 03de89be6dc..00000000000 Binary files a/contrib/executor/jmeterd/plugins/jmeter-plugins-functions-2.1.jar and /dev/null differ diff --git a/contrib/executor/jmeterd/plugins/jmeter-plugins-manager-1.3.jar b/contrib/executor/jmeterd/plugins/jmeter-plugins-manager-1.3.jar deleted file mode 100644 index 933c3d545eb..00000000000 Binary files a/contrib/executor/jmeterd/plugins/jmeter-plugins-manager-1.3.jar and /dev/null differ