neoload 1.3.19.dev1__tar.gz → 1.3.19.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/PKG-INFO +55 -1
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/README.md +54 -0
- neoload-1.3.19.dev2/examples/as-code-demo/default.yaml +140 -0
- neoload-1.3.19.dev2/neoload/commands/__init__.py +2 -0
- neoload-1.3.19.dev2/neoload/commands/checkvu.py +98 -0
- neoload-1.3.19.dev2/neoload/commands/validate.py +19 -0
- neoload-1.3.19.dev2/neoload/neoload_cli_lib/checkvu_runner.py +189 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/schema_validation.py +18 -0
- neoload-1.3.19.dev2/neoload/version.py +1 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload.egg-info/PKG-INFO +55 -1
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload.egg-info/SOURCES.txt +4 -0
- neoload-1.3.19.dev2/tests/commands/test_checkvu.py +207 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_validate.py +25 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/conftest.py +2 -1
- neoload-1.3.19.dev1/neoload/commands/__init__.py +0 -2
- neoload-1.3.19.dev1/neoload/commands/validate.py +0 -29
- neoload-1.3.19.dev1/neoload/version.py +0 -1
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/.github/workflows/python-integration-tests.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/.github/workflows/python-package.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/.github/workflows/python-post-release-changelog-pr.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/.github/workflows/python-release.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/.gitignore +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/.travis.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/CHANGELOG.md +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/LICENSE +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/MANIFEST.in +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/docker/Dockerfile +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/aws/.nlignore +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/aws/buildspec.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/azure_devops/.nlignore +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/azure_devops/Azure_DevOps_Pipeline_NeoLoad_CLI.jpg +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/azure_devops/Azure_DevOps_Pipeline_NeoLoad_SLA_jUnit.jpg +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/azure_devops/README.md +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/azure_devops/neoload-cli-docker.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/azure_devops/neoload-cli-dyninfra.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/bamboo-specs/.nlignore +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/bamboo-specs/Bamboo_Pipeline_NeoLoad_SLA_jUnit.jpg +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/bamboo-specs/README.md +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/bamboo-specs/bamboo-v1.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/bamboo-specs/bamboo-v2.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/github/neoload-github-actions-demo.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/gitlab/.nlignore +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/gitlab/openshift.gitlab-ci.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/jenkins/Jenkinsfile_dyninfra +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/examples/pipelines/jenkins/Jenkinsfile_slafails +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/__main__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/config.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/docker.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/fastfail.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/login.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/logout.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/logs.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/logs_url.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/project.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/report.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/run.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/status.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/stop.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/test_results.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/test_settings.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/wait.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/workspaces.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/commands/zones.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/bad_as_code_exception.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/cli_exception.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/config_global.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/displayer.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/docker_lib.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/filtering.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/hooks.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/logs_tools.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/logs_traduction_map.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/name_resolver.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/neoLoad_project.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/paths.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/rest_crud.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/running_tools.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/tools.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/neoload_cli_lib/user_data.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/builtin_console_summary.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/builtin_transactions_csv.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/common.js +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/external_data.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/general_details.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/header.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/hits_per_second.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/running_vus.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/styles.css +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/transactions.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/common/workload_characteristics.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/custom_transactions_export.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/sample-custom-report.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/sample-trends-report.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/trends/general_details.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/trends/transaction_trends.html.j2 +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/resources/jinja/trends/trends.js +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload/version_manager.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload.egg-info/dependency_links.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload.egg-info/entry_points.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload.egg-info/requires.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/neoload.egg-info/top_level.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/notes/PSB_20200421_TODO.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/notes/acceptance.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/pull_request_template.md +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/pytest.ini +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/requirements.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/resources/as-code.latest.schema.json +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/setup.cfg +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/setup.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/sonar-project.properties +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/docker/test_docker_cleanups.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/docker/test_docker_connections.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/docker/test_docker_hooks.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/fastfail/test_fastfail_slas.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/project/test_upload.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/project/test_upload_with_password.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/conftest.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/test_report.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/test_report_json_output.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/test_report_templates.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/test_report_transactions.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/test_report_trends.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/test_trends_json_output.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/report/test_trends_templates.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/status/test_status_with_names.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_config.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_login.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_logout.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_logs/test_logs.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_logs_url.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_results/test_result_delete.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_results/test_result_ls.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_results/test_result_patch.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_results/test_result_put.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_run.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_settings/test_create.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_settings/test_createorpatch.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_settings/test_delete.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_settings/test_ls.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_settings/test_patch.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/test_settings/test_put.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/wait/test_wait.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/workspaces/test_workspace_ls.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/workspaces/test_workspace_use.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/commands/zones/test_zones.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/helpers/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/helpers/test_utils.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/expected/fastfail.log +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/expected/junit-sla.xml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/expected/run.log +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/expected/summary.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/runAllScripts.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/cleanup.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/project.upload.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/results.delete.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/results.patch.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/results.put.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/run.fastfail.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/run.oneliner.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/run.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/settings.create.delete.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/settings.patch.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/settings.put.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/validate.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/wait.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/integration/scripts/zones.ls.test.sh +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_SchemaValidation.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_displayer.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_docker.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_etag_caching.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_filtering.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_include_resolution.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_rest_crud.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_running_tools.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_tools.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_user_data.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_cli_lib/test_validator_selection.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/.nlignore +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/broken_yaml.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/circular_includes/a.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/circular_includes/b.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/empty.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1/.gitlab-ci.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1/.nlignore +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1/data/cities.csv +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1/default.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1/paths/geosearch_get.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1/slas/prod.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1/slas/uat.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_1.zip +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/example_2.zip +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/invalid_to_schema.yaml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/neoload_projects/simpledemo.yml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/expected_neoload_junit_slas.xml +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/expected_summary_text_no_sla.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/expected_summary_text_with_sla.txt +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/jinja/__init__.py +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_custom_report.html +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_custom_report_filtered.html +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_custom_transactions.csv +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_report.json +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_report_filtered.json +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_template_transactions.json +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_template_transactions_csv.csv +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_template_trends.html +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/expected_trends.json +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/raw_expected_custom_report.html +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/resources/report/raw_expected_report.json +0 -0
- {neoload-1.3.19.dev1 → neoload-1.3.19.dev2}/tests/test_readme.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neoload
|
|
3
|
-
Version: 1.3.19.
|
|
3
|
+
Version: 1.3.19.dev2
|
|
4
4
|
Summary: A command-line native utility for launching and observing NeoLoad performance tests
|
|
5
5
|
Home-page: https://github.com/Neotys-Labs/neoload-cli
|
|
6
6
|
Author: Neotys
|
|
@@ -86,6 +86,8 @@ NOTE: On the Windows command line, replace the `\` line-continuation characters
|
|
|
86
86
|
- [Exporting Transaction CSV data](#exporting-transaction-csv-data)
|
|
87
87
|
- [View zones](#view-zones)
|
|
88
88
|
- [Create local Docker infrastructure to run a test](#create-local-docker-infrastructure-to-run-a-test)
|
|
89
|
+
- [Examples](#examples)
|
|
90
|
+
- [As-Code Demo Project](#as-code-demo-project)
|
|
89
91
|
- [Continuous Testing Examples](#continuous-testing-examples)
|
|
90
92
|
- [Support for fast-fail based on SLAs](#support-for-fast-fail-based-on-slas)
|
|
91
93
|
- [Packaging the CLI with Build Agents](#packaging-the-cli-with-build-agents)
|
|
@@ -213,6 +215,24 @@ Pressing `Ctrl+C` causes the CLI to attempt to stop the test gracefully.
|
|
|
213
215
|
neoload stop # Sends the stop signal to the test and waits until it ends.
|
|
214
216
|
```
|
|
215
217
|
|
|
218
|
+
## CheckVU an as-code project
|
|
219
|
+
This command runs a CheckVU on an as-code project: it executes a single virtual user to verify that the project runs. It is meant to support fast iteration on as-code projects (generate -> checkvu -> fix).
|
|
220
|
+
|
|
221
|
+
It delegates to a standalone headless CheckVU JAR and streams the JAR's output and exit code directly.
|
|
222
|
+
|
|
223
|
+
```
|
|
224
|
+
Usage: neoload checkvu [OPTIONS] PROJECT_FILE
|
|
225
|
+
Help: neoload checkvu --help
|
|
226
|
+
neoload checkvu default.yaml
|
|
227
|
+
neoload checkvu -u myUser default.yaml
|
|
228
|
+
```
|
|
229
|
+
- `PROJECT_FILE` is a path to an as-code yaml file. The CLI validates it against the as-code schema first (same as `neoload validate`), using `-s, --as-code-schema` to override the default schema.
|
|
230
|
+
- `-e, --engine-jar <path-or-url>` resolves the CheckVU JAR: a local file path or a download URL. If omitted, a previously cached JAR is reused, otherwise a default URL is used to download the latest JAR.
|
|
231
|
+
- `-j, --java` selects the java executable; by default `JAVA_HOME/bin/java` then `java` on the PATH. Java 21+ is required and verified before running.
|
|
232
|
+
- `-w, --work-dir <path>` sets the directory used for engine files and logs. Defaults to a temporary directory deleted afterwards unless `--keep-temp-work-dir` is set; a directory you supply yourself is never deleted.
|
|
233
|
+
- `--app-proxy`, `--app-proxy-username` and `--app-proxy-bypass` configure the proxy used for application traffic. The proxy password is set with `NEOLOAD_CHECK_VU_APP_PROXY_PASSWORD` environment variable instead so it never shows up in the process list or CI logs.
|
|
234
|
+
- `--controller-properties` and `--load-generator-properties` are advanced options to merge a `.properties` file into the JAR's embedded `controller.properties` / `agent.properties`.
|
|
235
|
+
|
|
216
236
|
## Reporting
|
|
217
237
|
|
|
218
238
|
The NeoLoad CLI provides basic support for viewing and exporting test results.
|
|
@@ -394,6 +414,40 @@ Help: neoload config --help
|
|
|
394
414
|
```
|
|
395
415
|
The configuration lets you customize the CLI's behavior. For now, it is only used by the `docker` command (see above).
|
|
396
416
|
|
|
417
|
+
## Examples
|
|
418
|
+
|
|
419
|
+
### As-Code Demo Project
|
|
420
|
+
|
|
421
|
+
[`examples/as-code-demo`](examples/as-code-demo) contains a NeoLoad As-Code YAML project that works out-of-the-box:
|
|
422
|
+
no NeoLoad Web project, no manual scenario setup - just point NeoLoad at
|
|
423
|
+
[`default.yaml`](examples/as-code-demo/default.yaml) and run.
|
|
424
|
+
|
|
425
|
+
Target: [Tricentis Demo Web Shop](https://demowebshop.tricentis.com/) (nopCommerce demo).
|
|
426
|
+
|
|
427
|
+
The `BuyAsGuest` user path walks through a typical guest purchase:
|
|
428
|
+
|
|
429
|
+
1. Open the shop home page
|
|
430
|
+
2. Browse a product category
|
|
431
|
+
3. Add a product to the cart (quantity randomised per iteration via a variable)
|
|
432
|
+
4. View the cart
|
|
433
|
+
5. Check out as a guest
|
|
434
|
+
6. View product details
|
|
435
|
+
|
|
436
|
+
It uses two variables (`product_id`, `quantity`) and a single population (`GuestShoppers`)
|
|
437
|
+
|
|
438
|
+
Run CheckVU against the project:
|
|
439
|
+
```
|
|
440
|
+
neoload checkvu examples/as-code-demo/default.yaml
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
Run the full test:
|
|
444
|
+
```
|
|
445
|
+
neoload login $NLW_TOKEN \
|
|
446
|
+
test-settings --zone defaultzone --lgs 1 createorpatch DemoWebShopTest \
|
|
447
|
+
project --path examples/as-code-demo/default.yaml upload DemoWebShopTest \
|
|
448
|
+
run --scenario DemoWebShop
|
|
449
|
+
```
|
|
450
|
+
|
|
397
451
|
## Continuous Testing Examples
|
|
398
452
|
The main goal of the NeoLoad CLI is to standardize how load tests are executed across development, non-prod, and production environments.
|
|
399
453
|
The instructions above can be run from a contributor workstation, but they can also be easily translated to various continuous build and deployment platforms. Examples are provided for:
|
|
@@ -47,6 +47,8 @@ NOTE: On the Windows command line, replace the `\` line-continuation characters
|
|
|
47
47
|
- [Exporting Transaction CSV data](#exporting-transaction-csv-data)
|
|
48
48
|
- [View zones](#view-zones)
|
|
49
49
|
- [Create local Docker infrastructure to run a test](#create-local-docker-infrastructure-to-run-a-test)
|
|
50
|
+
- [Examples](#examples)
|
|
51
|
+
- [As-Code Demo Project](#as-code-demo-project)
|
|
50
52
|
- [Continuous Testing Examples](#continuous-testing-examples)
|
|
51
53
|
- [Support for fast-fail based on SLAs](#support-for-fast-fail-based-on-slas)
|
|
52
54
|
- [Packaging the CLI with Build Agents](#packaging-the-cli-with-build-agents)
|
|
@@ -174,6 +176,24 @@ Pressing `Ctrl+C` causes the CLI to attempt to stop the test gracefully.
|
|
|
174
176
|
neoload stop # Sends the stop signal to the test and waits until it ends.
|
|
175
177
|
```
|
|
176
178
|
|
|
179
|
+
## CheckVU an as-code project
|
|
180
|
+
This command runs a CheckVU on an as-code project: it executes a single virtual user to verify that the project runs. It is meant to support fast iteration on as-code projects (generate -> checkvu -> fix).
|
|
181
|
+
|
|
182
|
+
It delegates to a standalone headless CheckVU JAR and streams the JAR's output and exit code directly.
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
Usage: neoload checkvu [OPTIONS] PROJECT_FILE
|
|
186
|
+
Help: neoload checkvu --help
|
|
187
|
+
neoload checkvu default.yaml
|
|
188
|
+
neoload checkvu -u myUser default.yaml
|
|
189
|
+
```
|
|
190
|
+
- `PROJECT_FILE` is a path to an as-code yaml file. The CLI validates it against the as-code schema first (same as `neoload validate`), using `-s, --as-code-schema` to override the default schema.
|
|
191
|
+
- `-e, --engine-jar <path-or-url>` resolves the CheckVU JAR: a local file path or a download URL. If omitted, a previously cached JAR is reused, otherwise a default URL is used to download the latest JAR.
|
|
192
|
+
- `-j, --java` selects the java executable; by default `JAVA_HOME/bin/java` then `java` on the PATH. Java 21+ is required and verified before running.
|
|
193
|
+
- `-w, --work-dir <path>` sets the directory used for engine files and logs. Defaults to a temporary directory deleted afterwards unless `--keep-temp-work-dir` is set; a directory you supply yourself is never deleted.
|
|
194
|
+
- `--app-proxy`, `--app-proxy-username` and `--app-proxy-bypass` configure the proxy used for application traffic. The proxy password is set with `NEOLOAD_CHECK_VU_APP_PROXY_PASSWORD` environment variable instead so it never shows up in the process list or CI logs.
|
|
195
|
+
- `--controller-properties` and `--load-generator-properties` are advanced options to merge a `.properties` file into the JAR's embedded `controller.properties` / `agent.properties`.
|
|
196
|
+
|
|
177
197
|
## Reporting
|
|
178
198
|
|
|
179
199
|
The NeoLoad CLI provides basic support for viewing and exporting test results.
|
|
@@ -355,6 +375,40 @@ Help: neoload config --help
|
|
|
355
375
|
```
|
|
356
376
|
The configuration lets you customize the CLI's behavior. For now, it is only used by the `docker` command (see above).
|
|
357
377
|
|
|
378
|
+
## Examples
|
|
379
|
+
|
|
380
|
+
### As-Code Demo Project
|
|
381
|
+
|
|
382
|
+
[`examples/as-code-demo`](examples/as-code-demo) contains a NeoLoad As-Code YAML project that works out-of-the-box:
|
|
383
|
+
no NeoLoad Web project, no manual scenario setup - just point NeoLoad at
|
|
384
|
+
[`default.yaml`](examples/as-code-demo/default.yaml) and run.
|
|
385
|
+
|
|
386
|
+
Target: [Tricentis Demo Web Shop](https://demowebshop.tricentis.com/) (nopCommerce demo).
|
|
387
|
+
|
|
388
|
+
The `BuyAsGuest` user path walks through a typical guest purchase:
|
|
389
|
+
|
|
390
|
+
1. Open the shop home page
|
|
391
|
+
2. Browse a product category
|
|
392
|
+
3. Add a product to the cart (quantity randomised per iteration via a variable)
|
|
393
|
+
4. View the cart
|
|
394
|
+
5. Check out as a guest
|
|
395
|
+
6. View product details
|
|
396
|
+
|
|
397
|
+
It uses two variables (`product_id`, `quantity`) and a single population (`GuestShoppers`)
|
|
398
|
+
|
|
399
|
+
Run CheckVU against the project:
|
|
400
|
+
```
|
|
401
|
+
neoload checkvu examples/as-code-demo/default.yaml
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
Run the full test:
|
|
405
|
+
```
|
|
406
|
+
neoload login $NLW_TOKEN \
|
|
407
|
+
test-settings --zone defaultzone --lgs 1 createorpatch DemoWebShopTest \
|
|
408
|
+
project --path examples/as-code-demo/default.yaml upload DemoWebShopTest \
|
|
409
|
+
run --scenario DemoWebShop
|
|
410
|
+
```
|
|
411
|
+
|
|
358
412
|
## Continuous Testing Examples
|
|
359
413
|
The main goal of the NeoLoad CLI is to standardize how load tests are executed across development, non-prod, and production environments.
|
|
360
414
|
The instructions above can be run from a contributor workstation, but they can also be easily translated to various continuous build and deployment platforms. Examples are provided for:
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# =============================================================================
|
|
2
|
+
# NeoLoad As-Code demo project - Tricentis Demo Web Shop
|
|
3
|
+
# -----------------------------------------------------------------------------
|
|
4
|
+
# Target : https://demowebshop.tricentis.com/ (nopCommerce demo)
|
|
5
|
+
# Scenario: add a product to the cart -> checkout as guest -> view details
|
|
6
|
+
#
|
|
7
|
+
# Out-of-the-box usage (from the repo root, via neoload-cli):
|
|
8
|
+
# Run CheckVU against the project:
|
|
9
|
+
# neoload checkvu examples/as-code-demo/default.yaml
|
|
10
|
+
# Run the full test:
|
|
11
|
+
# neoload login $NLW_TOKEN \
|
|
12
|
+
# test-settings --zone defaultzone --lgs 1 createorpatch DemoWebShopTest \
|
|
13
|
+
# project --path examples/as-code-demo/default.yaml upload DemoWebShopTest \
|
|
14
|
+
# run --scenario DemoWebShop
|
|
15
|
+
#
|
|
16
|
+
# =============================================================================
|
|
17
|
+
name: DemoWebShop
|
|
18
|
+
|
|
19
|
+
# --- Server under test -------------------------------------------------------
|
|
20
|
+
servers:
|
|
21
|
+
- name: demowebshop
|
|
22
|
+
host: demowebshop.tricentis.com
|
|
23
|
+
scheme: https
|
|
24
|
+
port: 443
|
|
25
|
+
|
|
26
|
+
# --- Variables -------------------------------
|
|
27
|
+
variables:
|
|
28
|
+
# Product added to the cart. "13" = "Computing and Internet" book in the demo shop.
|
|
29
|
+
- constant:
|
|
30
|
+
name: product_id
|
|
31
|
+
value: "13"
|
|
32
|
+
# Quantity added to the cart, randomised per iteration.
|
|
33
|
+
- random_number:
|
|
34
|
+
name: quantity
|
|
35
|
+
description: Number of items added to the cart
|
|
36
|
+
min: 1
|
|
37
|
+
max: 3
|
|
38
|
+
change_policy: each_iteration
|
|
39
|
+
|
|
40
|
+
# --- User path ---------------------------------------------------------------
|
|
41
|
+
user_paths:
|
|
42
|
+
- name: BuyAsGuest
|
|
43
|
+
description: Browse the shop, add a product, check out as a guest and view details
|
|
44
|
+
|
|
45
|
+
actions:
|
|
46
|
+
steps:
|
|
47
|
+
|
|
48
|
+
# 1) Open the shop home page ------------------------------------------------
|
|
49
|
+
- transaction:
|
|
50
|
+
name: 01_Home
|
|
51
|
+
steps:
|
|
52
|
+
- request:
|
|
53
|
+
server: demowebshop
|
|
54
|
+
url: /
|
|
55
|
+
assertions:
|
|
56
|
+
- contains: Tricentis Demo Web Shop
|
|
57
|
+
- think_time: 3s
|
|
58
|
+
|
|
59
|
+
# 2) Browse a category and open a product ----------------------------------
|
|
60
|
+
- transaction:
|
|
61
|
+
name: 02_Browse
|
|
62
|
+
steps:
|
|
63
|
+
- request:
|
|
64
|
+
server: demowebshop
|
|
65
|
+
url: /books
|
|
66
|
+
assertions:
|
|
67
|
+
- contains: Books
|
|
68
|
+
- think_time: 2s
|
|
69
|
+
|
|
70
|
+
# 3) Add the product to the cart (AJAX POST) -------------------------------
|
|
71
|
+
- transaction:
|
|
72
|
+
name: 03_AddToCart
|
|
73
|
+
steps:
|
|
74
|
+
- request:
|
|
75
|
+
server: demowebshop
|
|
76
|
+
url: /addproducttocart/catalog/${product_id}/1/${quantity}
|
|
77
|
+
method: POST
|
|
78
|
+
headers:
|
|
79
|
+
- name: X-Requested-With
|
|
80
|
+
value: XMLHttpRequest
|
|
81
|
+
assertions:
|
|
82
|
+
- contains: success
|
|
83
|
+
- think_time: 2s
|
|
84
|
+
|
|
85
|
+
# 4) View the cart ---------------------------------------------------------
|
|
86
|
+
- transaction:
|
|
87
|
+
name: 04_ViewCart
|
|
88
|
+
steps:
|
|
89
|
+
- request:
|
|
90
|
+
server: demowebshop
|
|
91
|
+
url: /cart
|
|
92
|
+
assertions:
|
|
93
|
+
- contains: Shopping cart
|
|
94
|
+
- think_time: 2s
|
|
95
|
+
|
|
96
|
+
# 5) Checkout as guest -----------------------------------------------------
|
|
97
|
+
- transaction:
|
|
98
|
+
name: 05_CheckoutAsGuest
|
|
99
|
+
steps:
|
|
100
|
+
- request:
|
|
101
|
+
server: demowebshop
|
|
102
|
+
url: /login/checkoutasguest?returnUrl=%2Fcart
|
|
103
|
+
method: POST
|
|
104
|
+
headers:
|
|
105
|
+
- name: Content-Type
|
|
106
|
+
value: application/x-www-form-urlencoded
|
|
107
|
+
- request:
|
|
108
|
+
server: demowebshop
|
|
109
|
+
url: /onepagecheckout
|
|
110
|
+
assertions:
|
|
111
|
+
- contains: Checkout
|
|
112
|
+
- think_time: 3s
|
|
113
|
+
|
|
114
|
+
# 6) View product details --------------------------------------------------
|
|
115
|
+
- transaction:
|
|
116
|
+
name: 06_ViewDetails
|
|
117
|
+
steps:
|
|
118
|
+
- request:
|
|
119
|
+
server: demowebshop
|
|
120
|
+
url: /computing-and-internet
|
|
121
|
+
assertions:
|
|
122
|
+
- contains: Computing and Internet
|
|
123
|
+
- think_time: 2s
|
|
124
|
+
|
|
125
|
+
# --- Population -----------------------------------
|
|
126
|
+
populations:
|
|
127
|
+
- name: GuestShoppers
|
|
128
|
+
user_paths:
|
|
129
|
+
- name: BuyAsGuest
|
|
130
|
+
|
|
131
|
+
# --- Scenario (used for the full test run) ------------------------------------
|
|
132
|
+
scenarios:
|
|
133
|
+
- name: DemoWebShop
|
|
134
|
+
description: Light constant load used for the manual test run on cloud/on-site LG
|
|
135
|
+
populations:
|
|
136
|
+
- name: GuestShoppers
|
|
137
|
+
constant_load:
|
|
138
|
+
users: 5
|
|
139
|
+
rampup: 30s
|
|
140
|
+
duration: 5m
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import click
|
|
5
|
+
|
|
6
|
+
from neoload_cli_lib import checkvu_runner, cli_exception
|
|
7
|
+
import neoload_cli_lib.schema_validation as schema_validation
|
|
8
|
+
from neoload_cli_lib.schema_validation import __default_schema_url
|
|
9
|
+
|
|
10
|
+
__yaml_extensions = (".yaml", ".yml")
|
|
11
|
+
|
|
12
|
+
@click.command()
|
|
13
|
+
@click.option('-e', '--engine-jar',
|
|
14
|
+
help="CheckVU engine JAR to run: a local file, for air-gapped or pinned setups, or a download URL. "
|
|
15
|
+
"Defaults to the cached JAR, otherwise the release URL for this version.",
|
|
16
|
+
metavar="PATH|URL")
|
|
17
|
+
@click.option('-j', '--java', help="Path to the java executable to use. "
|
|
18
|
+
"Defaults to JAVA_HOME/bin/java, then java on the PATH.", metavar="PATH")
|
|
19
|
+
@click.option('-u', '--user-path', help="Run only the specified user path. If omitted, all user paths in the file "
|
|
20
|
+
"are executed sequentially. An unknown name fails and lists the user paths "
|
|
21
|
+
"found in the file.", metavar="NAME")
|
|
22
|
+
@click.option('-s', '--as-code-schema', default=__default_schema_url, show_default=True,
|
|
23
|
+
help="NeoLoad as-code schema (URL or local path) to validate PROJECT_FILE "
|
|
24
|
+
"against. Defaults to the schema published for this release on Github.",
|
|
25
|
+
metavar="PATH|URL")
|
|
26
|
+
@click.option('--ssl-cert', default="",
|
|
27
|
+
help="Path to SSL certificate or write False to disable certificate checking. "
|
|
28
|
+
"Used both for schema validation and the JAR download.")
|
|
29
|
+
@click.option('--controller-properties',
|
|
30
|
+
help="Advanced. Path to controller.properties file merged additively into the Controller "
|
|
31
|
+
"configuration; only the keys you set are overridden, other embedded values are kept.",
|
|
32
|
+
metavar="PATH")
|
|
33
|
+
@click.option('--load-generator-properties',
|
|
34
|
+
help="Advanced. Path to agent.properties file merged additively into the Load Generator "
|
|
35
|
+
"configuration; only the keys you set are overridden.",
|
|
36
|
+
metavar="PATH")
|
|
37
|
+
@click.option('--app-proxy',
|
|
38
|
+
help="Proxy used to reach the tested applications, as host:port (e.g. myproxy.corp:8080). "
|
|
39
|
+
"Applies to both HTTP and HTTPS application traffic (User Path validation / Load Generator "
|
|
40
|
+
"traffic). Not used for NeoLoad Web API calls. CheckVU CLI download proxy uses the standard "
|
|
41
|
+
"HTTPS_PROXY, HTTP_PROXY and NO_PROXY variables instead.",
|
|
42
|
+
metavar="HOST:PORT")
|
|
43
|
+
@click.option('--app-proxy-username',
|
|
44
|
+
help="Username for --app-proxy authentication (optional). The password is read from environment "
|
|
45
|
+
"variable NEOLOAD_CHECK_VU_APP_PROXY_PASSWORD; there is no flag for it, so it is never "
|
|
46
|
+
"exposed in the process list or CI logs.",
|
|
47
|
+
metavar="USERNAME")
|
|
48
|
+
@click.option('--app-proxy-bypass',
|
|
49
|
+
help="Comma-separated hosts that bypass --app-proxy (e.g. localhost,internal.corp).",
|
|
50
|
+
metavar="HOSTS")
|
|
51
|
+
@click.option('-w', '--work-dir',
|
|
52
|
+
help="Directory for engine scratch files and logs. Defaults to a temporary directory. "
|
|
53
|
+
"A directory you supply is never deleted.",
|
|
54
|
+
metavar="PATH")
|
|
55
|
+
@click.option('--keep-temp-work-dir', is_flag=True, default=False,
|
|
56
|
+
help="Keep the temporary work directory after the run instead of deleting it. "
|
|
57
|
+
"Equivalent to setting CHECKVU_CLI_KEEP_TEMP_WORK_DIR=1. "
|
|
58
|
+
"Has no effect when --work-dir is already set, since that directory is never auto-deleted.")
|
|
59
|
+
@click.argument('project_file')
|
|
60
|
+
def cli(engine_jar, java, user_path, as_code_schema, ssl_cert,
|
|
61
|
+
controller_properties, load_generator_properties,
|
|
62
|
+
app_proxy, app_proxy_username, app_proxy_bypass, work_dir, keep_temp_work_dir,
|
|
63
|
+
project_file):
|
|
64
|
+
""" Validate the User Paths of a NeoLoad as-code Project locally.
|
|
65
|
+
|
|
66
|
+
Runs each User Path once against the application and reports whether
|
|
67
|
+
it completes without blocking errors. This is not a load test: no
|
|
68
|
+
Population, no Scenario, no Result. Exits 0 when every User Path passes, 1
|
|
69
|
+
otherwise, and always writes a JSON output.
|
|
70
|
+
|
|
71
|
+
PROJECT_FILE is the as-code Project YAML file. Its parent directory is the
|
|
72
|
+
Project root; colocated assets such as CSV files must live under that
|
|
73
|
+
root.
|
|
74
|
+
"""
|
|
75
|
+
if not project_file.lower().endswith(__yaml_extensions):
|
|
76
|
+
raise cli_exception.CliException("Project file must be a yaml (\".yaml\", \".yml\") file: " + project_file)
|
|
77
|
+
if not os.path.isfile(project_file):
|
|
78
|
+
raise cli_exception.CliException("Project file not found: " + project_file)
|
|
79
|
+
print(schema_validation.validate_path(project_file, as_code_schema, ssl_cert), flush=True)
|
|
80
|
+
|
|
81
|
+
java_executable = checkvu_runner.resolve_java(java)
|
|
82
|
+
checkvu_runner.check_java_version(java_executable)
|
|
83
|
+
|
|
84
|
+
resolved_jar = checkvu_runner.resolve_jar(engine_jar, ssl_cert)
|
|
85
|
+
|
|
86
|
+
command = checkvu_runner.build_command(
|
|
87
|
+
java_executable, resolved_jar, project_file,
|
|
88
|
+
user_path=user_path,
|
|
89
|
+
controller_properties=controller_properties,
|
|
90
|
+
load_generator_properties=load_generator_properties,
|
|
91
|
+
app_proxy=app_proxy,
|
|
92
|
+
app_proxy_username=app_proxy_username,
|
|
93
|
+
app_proxy_bypass=app_proxy_bypass,
|
|
94
|
+
work_dir=work_dir,
|
|
95
|
+
keep_temp_work_dir=keep_temp_work_dir,
|
|
96
|
+
)
|
|
97
|
+
exit_code = checkvu_runner.run_checkvu(command)
|
|
98
|
+
sys.exit(exit_code)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import neoload_cli_lib.schema_validation as schema_validation
|
|
3
|
+
from neoload_cli_lib.schema_validation import __default_schema_url
|
|
4
|
+
|
|
5
|
+
@click.command()
|
|
6
|
+
@click.option('-s', '--as-code-schema', default=None,
|
|
7
|
+
help="NeoLoad as-code schema (URL or local path) to validate FILE against. "
|
|
8
|
+
"Defaults to the schema published for this release on Github.",
|
|
9
|
+
metavar="PATH|URL")
|
|
10
|
+
@click.option('--schema-url', 'schema_url', default=None, hidden=True,
|
|
11
|
+
help="Deprecated alias for --as-code-schema, kept for backward compatibility.")
|
|
12
|
+
@click.option('--refresh', is_flag=True, help="THIS OPTION IS NOW USELESS", hidden=True)
|
|
13
|
+
@click.option('--ssl-cert', default="", help="Path to SSL certificate or write False to disable certificate checking")
|
|
14
|
+
@click.argument('file')
|
|
15
|
+
def cli(file, refresh, as_code_schema, schema_url, ssl_cert):
|
|
16
|
+
"""Verify that the yaml FILE matches the neoload as-code file format"""
|
|
17
|
+
# -s/--as-code-schema (new) takes priority over --schema-url (deprecated alias)
|
|
18
|
+
resolved_schema = as_code_schema or schema_url or __default_schema_url
|
|
19
|
+
print(schema_validation.validate_path(file, resolved_schema, ssl_cert))
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import re
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
from neoload_cli_lib import cli_exception, paths
|
|
8
|
+
|
|
9
|
+
MIN_JAVA_VERSION = 21
|
|
10
|
+
|
|
11
|
+
# Default download URL pointing at the "latest" CheckVU JAR
|
|
12
|
+
# TODO: set this once we have public jar url
|
|
13
|
+
# use --engine-jar for now
|
|
14
|
+
DEFAULT_JAR_URL = ""
|
|
15
|
+
|
|
16
|
+
CACHE_DIR_NAME = "checkvu"
|
|
17
|
+
CACHE_JAR_NAME = "neoload-checkvu-cli.jar"
|
|
18
|
+
|
|
19
|
+
__java_version_pattern = re.compile(r'version "(\d+)(?:\.(\d+))?')
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def get_cache_dir():
|
|
23
|
+
return os.path.join(paths.get_config_dir(), CACHE_DIR_NAME)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def get_cached_jar_path():
|
|
27
|
+
return os.path.join(get_cache_dir(), CACHE_JAR_NAME)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def resolve_java(java_option=None):
|
|
31
|
+
"""Return the path to a usable java executable, raising if none is found."""
|
|
32
|
+
if java_option:
|
|
33
|
+
return java_option
|
|
34
|
+
java_home = os.environ.get("JAVA_HOME")
|
|
35
|
+
if java_home:
|
|
36
|
+
candidate = os.path.join(java_home, "bin", "java")
|
|
37
|
+
resolved = shutil.which(candidate) or (candidate if os.path.isfile(candidate) else None)
|
|
38
|
+
if resolved:
|
|
39
|
+
return resolved
|
|
40
|
+
found = shutil.which("java")
|
|
41
|
+
if found:
|
|
42
|
+
return found
|
|
43
|
+
raise cli_exception.CliException(
|
|
44
|
+
"No Java runtime found. CheckVU requires Java {0} or later.\n"
|
|
45
|
+
"Install a JDK {0}+ and either add it to your PATH, set JAVA_HOME, "
|
|
46
|
+
"or pass --java <path-to-java>.".format(MIN_JAVA_VERSION))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def parse_java_major_version(version_output):
|
|
50
|
+
"""Extract the major Java version from `java -version` output, or None."""
|
|
51
|
+
match = __java_version_pattern.search(version_output)
|
|
52
|
+
if match is None:
|
|
53
|
+
return None
|
|
54
|
+
major = int(match.group(1))
|
|
55
|
+
# Legacy versions 1.x -> x
|
|
56
|
+
if major == 1 and match.group(2) is not None:
|
|
57
|
+
return int(match.group(2))
|
|
58
|
+
return major
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def check_java_version(java):
|
|
62
|
+
"""Runs `java -version` and enforces the minimum supported major version.
|
|
63
|
+
`java -version` writes to stderr, so we merge stderr into stdout to capture it.
|
|
64
|
+
"""
|
|
65
|
+
try:
|
|
66
|
+
completed = subprocess.run(
|
|
67
|
+
[java, "-version"],
|
|
68
|
+
stdout=subprocess.PIPE,
|
|
69
|
+
stderr=subprocess.STDOUT,
|
|
70
|
+
universal_newlines=True)
|
|
71
|
+
except OSError as err:
|
|
72
|
+
raise cli_exception.CliException(
|
|
73
|
+
"Unable to run '{0}': {1}\n"
|
|
74
|
+
"Install a JDK {2}+ and either add it to your PATH, set JAVA_HOME, "
|
|
75
|
+
"or pass --java <path-to-java>.".format(java, str(err), MIN_JAVA_VERSION))
|
|
76
|
+
|
|
77
|
+
output = completed.stdout or ""
|
|
78
|
+
major = parse_java_major_version(output)
|
|
79
|
+
if major is None:
|
|
80
|
+
raise cli_exception.CliException(
|
|
81
|
+
"Could not determine the Java version from '{0} -version':\n{1}".format(java, output.strip()))
|
|
82
|
+
if major < MIN_JAVA_VERSION:
|
|
83
|
+
raise cli_exception.CliException(
|
|
84
|
+
"CheckVU requires Java {0} or later, but '{1}' reports major version {2}.\n"
|
|
85
|
+
"Install a JDK {0}+ and either add it to your PATH, set JAVA_HOME, "
|
|
86
|
+
"or pass --java <path-to-java>.".format(MIN_JAVA_VERSION, java, major))
|
|
87
|
+
return major
|
|
88
|
+
|
|
89
|
+
def is_url(spec):
|
|
90
|
+
return spec is not None and '://' in spec
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
# TODO cache invalidation according to project version ?
|
|
94
|
+
def resolve_jar(engine_jar=None, ssl_cert=''):
|
|
95
|
+
"""Resolves the CheckVU fat JAR from --engine-jar (a local file, or a download URL).
|
|
96
|
+
Resolution order:
|
|
97
|
+
1. --engine-jar
|
|
98
|
+
2. cached JAR if exists
|
|
99
|
+
3. DEFAULT_JAR_URL -> download + cache
|
|
100
|
+
4. error
|
|
101
|
+
"""
|
|
102
|
+
cache_path = get_cached_jar_path()
|
|
103
|
+
|
|
104
|
+
if engine_jar:
|
|
105
|
+
if is_url(engine_jar):
|
|
106
|
+
return download_jar(engine_jar, cache_path, ssl_cert)
|
|
107
|
+
if not os.path.isfile(engine_jar):
|
|
108
|
+
raise cli_exception.CliException("CheckVU JAR not found at '{0}'.".format(engine_jar))
|
|
109
|
+
return engine_jar
|
|
110
|
+
|
|
111
|
+
if os.path.isfile(cache_path):
|
|
112
|
+
return cache_path
|
|
113
|
+
|
|
114
|
+
if DEFAULT_JAR_URL:
|
|
115
|
+
return download_jar(DEFAULT_JAR_URL, cache_path, ssl_cert)
|
|
116
|
+
|
|
117
|
+
raise cli_exception.CliException(
|
|
118
|
+
"No CheckVU JAR available. Provide one with --engine-jar <path-to-neoload-checkvu-cli.jar|download-url>.\n")
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def download_jar(url, destination, ssl_cert=''):
|
|
122
|
+
"""Download the CheckVU JAR to the cache, showing a progress bar when interactive."""
|
|
123
|
+
import requests
|
|
124
|
+
from tqdm import tqdm
|
|
125
|
+
from neoload_cli_lib import tools
|
|
126
|
+
|
|
127
|
+
verify = tools.ssl_cert_to_verify(ssl_cert)
|
|
128
|
+
os.makedirs(os.path.dirname(destination), exist_ok=True)
|
|
129
|
+
partial_destination = destination + ".part"
|
|
130
|
+
print("Downloading JAR from " + url + "\n")
|
|
131
|
+
try:
|
|
132
|
+
with requests.get(url, stream=True, verify=verify) as response:
|
|
133
|
+
response.raise_for_status()
|
|
134
|
+
total_bytes = int(response.headers.get("content-length", 0))
|
|
135
|
+
progress_bar = None
|
|
136
|
+
if tools.is_user_interactive():
|
|
137
|
+
progress_bar = tqdm(desc=CACHE_JAR_NAME, total=total_bytes, unit="B",
|
|
138
|
+
unit_scale=True, leave=False, dynamic_ncols=True)
|
|
139
|
+
with open(partial_destination, "wb") as stream:
|
|
140
|
+
for chunk in response.iter_content(chunk_size=1024 * 64):
|
|
141
|
+
if chunk:
|
|
142
|
+
stream.write(chunk)
|
|
143
|
+
if progress_bar is not None:
|
|
144
|
+
progress_bar.update(len(chunk))
|
|
145
|
+
if progress_bar is not None:
|
|
146
|
+
progress_bar.close()
|
|
147
|
+
os.replace(partial_destination, destination)
|
|
148
|
+
except Exception as err:
|
|
149
|
+
if os.path.isfile(partial_destination):
|
|
150
|
+
os.remove(partial_destination)
|
|
151
|
+
raise cli_exception.CliException(
|
|
152
|
+
"Failed to download the CheckVU JAR from '{0}':\n{1}".format(url, str(err)))
|
|
153
|
+
return destination
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def build_command(java, jar, project_file, user_path=None,
|
|
157
|
+
controller_properties=None, load_generator_properties=None,
|
|
158
|
+
app_proxy=None, app_proxy_username=None, app_proxy_bypass=None,
|
|
159
|
+
work_dir=None, keep_temp_work_dir=False):
|
|
160
|
+
command = [java, "-jar", jar]
|
|
161
|
+
if user_path:
|
|
162
|
+
command.extend(["--user-path", user_path])
|
|
163
|
+
if controller_properties:
|
|
164
|
+
command.extend(["--controller-properties", controller_properties])
|
|
165
|
+
if load_generator_properties:
|
|
166
|
+
command.extend(["--load-generator-properties", load_generator_properties])
|
|
167
|
+
if app_proxy:
|
|
168
|
+
command.extend(["--app-proxy", app_proxy])
|
|
169
|
+
if app_proxy_username:
|
|
170
|
+
command.extend(["--app-proxy-username", app_proxy_username])
|
|
171
|
+
if app_proxy_bypass:
|
|
172
|
+
command.extend(["--app-proxy-bypass", app_proxy_bypass])
|
|
173
|
+
if work_dir:
|
|
174
|
+
command.extend(["--work-dir", work_dir])
|
|
175
|
+
if keep_temp_work_dir:
|
|
176
|
+
command.append("--keep-temp-work-dir")
|
|
177
|
+
command.append(project_file)
|
|
178
|
+
return command
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def run_checkvu(command):
|
|
182
|
+
"""Run the JAR, inheriting stdio so the CLI output is the JAR output, and return its exit code."""
|
|
183
|
+
sys.stdout.flush()
|
|
184
|
+
sys.stderr.flush()
|
|
185
|
+
try:
|
|
186
|
+
completed = subprocess.run(command, stdout=sys.stdout, stderr=sys.stderr, stdin=sys.stdin)
|
|
187
|
+
except OSError as err:
|
|
188
|
+
raise cli_exception.CliException("Failed to run CheckVU: {0}".format(str(err)))
|
|
189
|
+
return completed.returncode
|
|
@@ -307,3 +307,21 @@ def get_json_schema_by_spec(schema_spec, ssl_cert):
|
|
|
307
307
|
raise bad_as_code_exception.BadAsCodeSchemaException('Could not load schema from provided file spec: %s' % schema_spec)
|
|
308
308
|
|
|
309
309
|
return json_schema_spec
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
def validate_path(file, schema_url, ssl_cert=''):
|
|
313
|
+
"""Validates an as-code yaml file against the schema from NLCLI_FORCE_SCHEMA
|
|
314
|
+
or downloaded from given URL or from the defautl URL."""
|
|
315
|
+
force_schema = os.environ.get('NLCLI_FORCE_SCHEMA')
|
|
316
|
+
if force_schema is not None and len(force_schema) > 0:
|
|
317
|
+
schema_url = force_schema
|
|
318
|
+
|
|
319
|
+
path = os.path.abspath(file)
|
|
320
|
+
try:
|
|
321
|
+
if os.path.isdir(path):
|
|
322
|
+
validate_yaml_dir(path, schema_url, ssl_cert)
|
|
323
|
+
return 'All yaml files underneath the path provided are valid.'
|
|
324
|
+
validate_yaml(file, schema_url, ssl_cert)
|
|
325
|
+
return 'Yaml file is valid.'
|
|
326
|
+
except Exception as err:
|
|
327
|
+
raise cli_exception.CliException(str(err))
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.3.19.dev2"
|