neoload 1.3.19.dev2__tar.gz → 1.4.0__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.dev2 → neoload-1.4.0}/PKG-INFO +11 -28
- {neoload-1.3.19.dev2 → neoload-1.4.0}/README.md +10 -27
- neoload-1.4.0/neoload/commands/__init__.py +2 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/project.py +44 -3
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/report.py +3 -16
- neoload-1.4.0/neoload/commands/validate.py +30 -0
- neoload-1.4.0/neoload/neoload_cli_lib/resources.py +14 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/schema_validation.py +65 -28
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/user_data.py +48 -18
- {neoload-1.3.19.dev2/examples/as-code-demo → neoload-1.4.0/neoload/resources/templates}/default.yaml +2 -4
- neoload-1.4.0/neoload/version.py +1 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload.egg-info/PKG-INFO +11 -28
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload.egg-info/SOURCES.txt +4 -4
- neoload-1.4.0/tests/commands/project/test_project_create.py +52 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_validate.py +9 -32
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/conftest.py +1 -2
- neoload-1.4.0/tests/neoload_cli_lib/test_SchemaValidation.py +149 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_include_resolution.py +7 -0
- neoload-1.4.0/tests/resources/jinja/__init__.py +0 -0
- neoload-1.3.19.dev2/neoload/commands/__init__.py +0 -2
- neoload-1.3.19.dev2/neoload/commands/checkvu.py +0 -98
- neoload-1.3.19.dev2/neoload/commands/validate.py +0 -19
- neoload-1.3.19.dev2/neoload/neoload_cli_lib/checkvu_runner.py +0 -189
- neoload-1.3.19.dev2/neoload/version.py +0 -1
- neoload-1.3.19.dev2/tests/commands/test_checkvu.py +0 -207
- neoload-1.3.19.dev2/tests/neoload_cli_lib/test_SchemaValidation.py +0 -43
- {neoload-1.3.19.dev2 → neoload-1.4.0}/.github/workflows/python-integration-tests.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/.github/workflows/python-package.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/.github/workflows/python-post-release-changelog-pr.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/.github/workflows/python-release.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/.gitignore +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/.travis.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/CHANGELOG.md +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/LICENSE +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/MANIFEST.in +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/docker/Dockerfile +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/aws/.nlignore +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/aws/buildspec.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/azure_devops/.nlignore +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/azure_devops/Azure_DevOps_Pipeline_NeoLoad_CLI.jpg +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/azure_devops/Azure_DevOps_Pipeline_NeoLoad_SLA_jUnit.jpg +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/azure_devops/README.md +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/azure_devops/neoload-cli-docker.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/azure_devops/neoload-cli-dyninfra.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/bamboo-specs/.nlignore +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/bamboo-specs/Bamboo_Pipeline_NeoLoad_SLA_jUnit.jpg +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/bamboo-specs/README.md +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/bamboo-specs/bamboo-v1.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/bamboo-specs/bamboo-v2.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/github/neoload-github-actions-demo.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/gitlab/.nlignore +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/gitlab/openshift.gitlab-ci.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/jenkins/Jenkinsfile_dyninfra +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/examples/pipelines/jenkins/Jenkinsfile_slafails +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/__main__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/config.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/docker.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/fastfail.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/login.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/logout.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/logs.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/logs_url.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/run.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/status.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/stop.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/test_results.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/test_settings.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/wait.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/workspaces.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/commands/zones.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/bad_as_code_exception.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/cli_exception.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/config_global.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/displayer.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/docker_lib.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/filtering.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/hooks.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/logs_tools.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/logs_traduction_map.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/name_resolver.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/neoLoad_project.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/paths.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/rest_crud.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/running_tools.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/neoload_cli_lib/tools.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/builtin_console_summary.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/builtin_transactions_csv.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/common.js +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/external_data.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/general_details.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/header.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/hits_per_second.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/running_vus.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/styles.css +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/transactions.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/common/workload_characteristics.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/custom_transactions_export.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/sample-custom-report.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/sample-trends-report.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/trends/general_details.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/trends/transaction_trends.html.j2 +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/resources/jinja/trends/trends.js +0 -0
- {neoload-1.3.19.dev2/tests → neoload-1.4.0/neoload/resources/templates}/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload/version_manager.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload.egg-info/dependency_links.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload.egg-info/entry_points.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload.egg-info/requires.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/neoload.egg-info/top_level.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/notes/PSB_20200421_TODO.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/notes/acceptance.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/pull_request_template.md +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/pytest.ini +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/requirements.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/resources/as-code.latest.schema.json +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/setup.cfg +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/setup.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/sonar-project.properties +0 -0
- {neoload-1.3.19.dev2/tests/resources → neoload-1.4.0/tests}/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/docker/test_docker_cleanups.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/docker/test_docker_connections.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/docker/test_docker_hooks.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/fastfail/test_fastfail_slas.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/project/test_upload.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/project/test_upload_with_password.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/conftest.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/test_report.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/test_report_json_output.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/test_report_templates.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/test_report_transactions.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/test_report_trends.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/test_trends_json_output.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/report/test_trends_templates.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/status/test_status_with_names.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_config.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_login.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_logout.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_logs/test_logs.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_logs_url.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_results/test_result_delete.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_results/test_result_ls.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_results/test_result_patch.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_results/test_result_put.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_run.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_settings/test_create.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_settings/test_createorpatch.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_settings/test_delete.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_settings/test_ls.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_settings/test_patch.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/test_settings/test_put.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/wait/test_wait.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/workspaces/test_workspace_ls.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/workspaces/test_workspace_use.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/commands/zones/test_zones.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/helpers/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/helpers/test_utils.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/expected/fastfail.log +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/expected/junit-sla.xml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/expected/run.log +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/expected/summary.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/runAllScripts.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/cleanup.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/project.upload.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/results.delete.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/results.patch.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/results.put.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/run.fastfail.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/run.oneliner.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/run.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/settings.create.delete.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/settings.patch.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/settings.put.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/validate.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/wait.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/integration/scripts/zones.ls.test.sh +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_displayer.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_docker.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_etag_caching.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_filtering.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_rest_crud.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_running_tools.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_tools.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_user_data.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_cli_lib/test_validator_selection.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/.nlignore +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/broken_yaml.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/circular_includes/a.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/circular_includes/b.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/empty.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1/.gitlab-ci.yml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1/.nlignore +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1/data/cities.csv +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1/default.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1/paths/geosearch_get.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1/slas/prod.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1/slas/uat.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_1.zip +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/example_2.zip +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/invalid_to_schema.yaml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/neoload_projects/simpledemo.yml +0 -0
- {neoload-1.3.19.dev2/tests/resources/jinja → neoload-1.4.0/tests/resources}/__init__.py +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/expected_neoload_junit_slas.xml +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/expected_summary_text_no_sla.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/expected_summary_text_with_sla.txt +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_custom_report.html +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_custom_report_filtered.html +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_custom_transactions.csv +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_report.json +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_report_filtered.json +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_template_transactions.json +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_template_transactions_csv.csv +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_template_trends.html +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/expected_trends.json +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/raw_expected_custom_report.html +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/resources/report/raw_expected_report.json +0 -0
- {neoload-1.3.19.dev2 → neoload-1.4.0}/tests/test_readme.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neoload
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
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
|
|
@@ -215,24 +215,6 @@ Pressing `Ctrl+C` causes the CLI to attempt to stop the test gracefully.
|
|
|
215
215
|
neoload stop # Sends the stop signal to the test and waits until it ends.
|
|
216
216
|
```
|
|
217
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
|
-
|
|
236
218
|
## Reporting
|
|
237
219
|
|
|
238
220
|
The NeoLoad CLI provides basic support for viewing and exporting test results.
|
|
@@ -418,9 +400,14 @@ The configuration lets you customize the CLI's behavior. For now, it is only use
|
|
|
418
400
|
|
|
419
401
|
### As-Code Demo Project
|
|
420
402
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
403
|
+
Create a starter NeoLoad As-Code YAML project with:
|
|
404
|
+
|
|
405
|
+
```
|
|
406
|
+
neoload project create DemoWebShop
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
This scaffolds `DemoWebShop/default.yaml` from the bundled Demo Web Shop template —
|
|
410
|
+
no NeoLoad Web project, no manual scenario setup.
|
|
424
411
|
|
|
425
412
|
Target: [Tricentis Demo Web Shop](https://demowebshop.tricentis.com/) (nopCommerce demo).
|
|
426
413
|
|
|
@@ -435,16 +422,12 @@ The `BuyAsGuest` user path walks through a typical guest purchase:
|
|
|
435
422
|
|
|
436
423
|
It uses two variables (`product_id`, `quantity`) and a single population (`GuestShoppers`)
|
|
437
424
|
|
|
438
|
-
Run CheckVU against the project:
|
|
439
|
-
```
|
|
440
|
-
neoload checkvu examples/as-code-demo/default.yaml
|
|
441
|
-
```
|
|
442
|
-
|
|
443
425
|
Run the full test:
|
|
444
426
|
```
|
|
427
|
+
neoload project create DemoWebShop
|
|
445
428
|
neoload login $NLW_TOKEN \
|
|
446
429
|
test-settings --zone defaultzone --lgs 1 createorpatch DemoWebShopTest \
|
|
447
|
-
project --path
|
|
430
|
+
project --path DemoWebShop/default.yaml upload DemoWebShopTest \
|
|
448
431
|
run --scenario DemoWebShop
|
|
449
432
|
```
|
|
450
433
|
|
|
@@ -176,24 +176,6 @@ Pressing `Ctrl+C` causes the CLI to attempt to stop the test gracefully.
|
|
|
176
176
|
neoload stop # Sends the stop signal to the test and waits until it ends.
|
|
177
177
|
```
|
|
178
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
|
-
|
|
197
179
|
## Reporting
|
|
198
180
|
|
|
199
181
|
The NeoLoad CLI provides basic support for viewing and exporting test results.
|
|
@@ -379,9 +361,14 @@ The configuration lets you customize the CLI's behavior. For now, it is only use
|
|
|
379
361
|
|
|
380
362
|
### As-Code Demo Project
|
|
381
363
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
364
|
+
Create a starter NeoLoad As-Code YAML project with:
|
|
365
|
+
|
|
366
|
+
```
|
|
367
|
+
neoload project create DemoWebShop
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
This scaffolds `DemoWebShop/default.yaml` from the bundled Demo Web Shop template —
|
|
371
|
+
no NeoLoad Web project, no manual scenario setup.
|
|
385
372
|
|
|
386
373
|
Target: [Tricentis Demo Web Shop](https://demowebshop.tricentis.com/) (nopCommerce demo).
|
|
387
374
|
|
|
@@ -396,16 +383,12 @@ The `BuyAsGuest` user path walks through a typical guest purchase:
|
|
|
396
383
|
|
|
397
384
|
It uses two variables (`product_id`, `quantity`) and a single population (`GuestShoppers`)
|
|
398
385
|
|
|
399
|
-
Run CheckVU against the project:
|
|
400
|
-
```
|
|
401
|
-
neoload checkvu examples/as-code-demo/default.yaml
|
|
402
|
-
```
|
|
403
|
-
|
|
404
386
|
Run the full test:
|
|
405
387
|
```
|
|
388
|
+
neoload project create DemoWebShop
|
|
406
389
|
neoload login $NLW_TOKEN \
|
|
407
390
|
test-settings --zone defaultzone --lgs 1 createorpatch DemoWebShopTest \
|
|
408
|
-
project --path
|
|
391
|
+
project --path DemoWebShop/default.yaml upload DemoWebShopTest \
|
|
409
392
|
run --scenario DemoWebShop
|
|
410
393
|
```
|
|
411
394
|
|
|
@@ -4,18 +4,30 @@ import click
|
|
|
4
4
|
import urllib.parse as urlparse
|
|
5
5
|
from commands import test_settings
|
|
6
6
|
from pathlib import Path
|
|
7
|
-
from neoload_cli_lib import user_data, tools, rest_crud, neoLoad_project
|
|
7
|
+
from neoload_cli_lib import user_data, tools, rest_crud, neoLoad_project, cli_exception, resources
|
|
8
|
+
|
|
9
|
+
__template_namespace = 'resources.templates'
|
|
10
|
+
__template_filename = 'default.yaml'
|
|
11
|
+
__project_yaml_name = 'default.yaml'
|
|
8
12
|
|
|
9
13
|
|
|
10
14
|
@click.command()
|
|
11
|
-
@click.argument("command", required=True, type=click.Choice(['up', 'upload', 'meta']))
|
|
15
|
+
@click.argument("command", required=True, type=click.Choice(['create', 'up', 'upload', 'meta']))
|
|
12
16
|
@click.option("--path", "-p", type=click.Path(exists=True), default=os.getcwd(),
|
|
13
17
|
help="Path of project folder, zip or yml file. . is default value")
|
|
14
18
|
@click.option("--save", "-s", type=click.Path(exists=False),
|
|
15
19
|
help="Path to a (non-existent) file ending in .zip to preserve what was uploaded")
|
|
16
20
|
@click.argument("name_or_id", type=str, required=False)
|
|
17
21
|
def cli(command, name_or_id, path, save):
|
|
18
|
-
"""
|
|
22
|
+
"""
|
|
23
|
+
create # Create a local as-code project folder from the demo yaml template.
|
|
24
|
+
upload # Upload a project to NeoLoad Web test settings (alias: up) .
|
|
25
|
+
meta # Display project metadata from the current test settings .
|
|
26
|
+
"""
|
|
27
|
+
if command == "create":
|
|
28
|
+
create_local_project(name_or_id)
|
|
29
|
+
return
|
|
30
|
+
|
|
19
31
|
rest_crud.set_current_command()
|
|
20
32
|
if not name_or_id or name_or_id == "cur":
|
|
21
33
|
name_or_id = user_data.get_meta(test_settings.meta_key)
|
|
@@ -75,3 +87,32 @@ def meta_data(setting_id):
|
|
|
75
87
|
|
|
76
88
|
def get_endpoint(settings_id: str):
|
|
77
89
|
return rest_crud.base_endpoint_with_workspace() + '/tests/' + settings_id + "/project"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def create_local_project(project_name):
|
|
93
|
+
if project_name is None:
|
|
94
|
+
raise cli_exception.CliException("Missing project name. Usage: neoload project create <project-name>")
|
|
95
|
+
project_name = project_name.strip()
|
|
96
|
+
if not project_name or project_name in ('.', '..'):
|
|
97
|
+
raise cli_exception.CliException(f"Invalid project name: '{project_name}'.")
|
|
98
|
+
if os.path.sep in project_name or (os.path.altsep and os.path.altsep in project_name):
|
|
99
|
+
raise cli_exception.CliException(
|
|
100
|
+
f"Invalid project name: '{project_name}'. Use a single folder name, not a path."
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
if os.path.exists(project_name):
|
|
104
|
+
raise cli_exception.CliException(
|
|
105
|
+
f"Cannot create project '{project_name}': path already exists."
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
yaml_path = os.path.join(project_name, __project_yaml_name)
|
|
109
|
+
try:
|
|
110
|
+
template = resources.get_resource_as_string(__template_namespace, __template_filename)
|
|
111
|
+
os.mkdir(project_name)
|
|
112
|
+
with open(yaml_path, 'w', encoding='utf-8') as yaml_file:
|
|
113
|
+
yaml_file.write(template)
|
|
114
|
+
except OSError as err:
|
|
115
|
+
raise cli_exception.CliException(f"Failed to create project '{project_name}': {err}") from err
|
|
116
|
+
|
|
117
|
+
print(f"Project '{project_name}' created successfully.")
|
|
118
|
+
print(f" {yaml_path}")
|
|
@@ -8,7 +8,7 @@ import statistics
|
|
|
8
8
|
import math
|
|
9
9
|
import time
|
|
10
10
|
|
|
11
|
-
from neoload_cli_lib import tools, rest_crud, user_data, displayer, cli_exception
|
|
11
|
+
from neoload_cli_lib import tools, rest_crud, user_data, displayer, cli_exception, resources
|
|
12
12
|
from dateutil.relativedelta import relativedelta
|
|
13
13
|
|
|
14
14
|
import logging
|
|
@@ -165,19 +165,6 @@ def parse_filter_spec(filter_spec):
|
|
|
165
165
|
return ret
|
|
166
166
|
|
|
167
167
|
|
|
168
|
-
def get_resource_as_string(namespace, file):
|
|
169
|
-
try:
|
|
170
|
-
import importlib.resources as pkg_resources
|
|
171
|
-
except ImportError:
|
|
172
|
-
# Try backported to PY<37 `importlib_resources`.
|
|
173
|
-
import importlib_resources as pkg_resources
|
|
174
|
-
|
|
175
|
-
logging.debug({'namespace': namespace, 'file': file})
|
|
176
|
-
if hasattr(pkg_resources, 'files'): # files is present from Python 3.9
|
|
177
|
-
return pkg_resources.files(namespace).joinpath(file).read_text()
|
|
178
|
-
return pkg_resources.read_text(namespace, file)
|
|
179
|
-
|
|
180
|
-
|
|
181
168
|
def split_path(path):
|
|
182
169
|
sep = os.path.sep
|
|
183
170
|
if sep not in path: sep = '/' # try internal posix style
|
|
@@ -1131,11 +1118,11 @@ def unique(seq, idfun=None):
|
|
|
1131
1118
|
|
|
1132
1119
|
|
|
1133
1120
|
def get_builtin_template_transaction_csv():
|
|
1134
|
-
return get_resource_as_string('resources.jinja', 'builtin_transactions_csv.j2').strip()
|
|
1121
|
+
return resources.get_resource_as_string('resources.jinja', 'builtin_transactions_csv.j2').strip()
|
|
1135
1122
|
|
|
1136
1123
|
|
|
1137
1124
|
def get_builtin_template_console_summary():
|
|
1138
|
-
return get_resource_as_string('resources.jinja', 'builtin_console_summary.j2').strip()
|
|
1125
|
+
return resources.get_resource_as_string('resources.jinja', 'builtin_console_summary.j2').strip()
|
|
1139
1126
|
|
|
1140
1127
|
|
|
1141
1128
|
def print_extended_help():
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from neoload_cli_lib import cli_exception
|
|
3
|
+
import neoload_cli_lib.schema_validation as schema_validation
|
|
4
|
+
import os
|
|
5
|
+
|
|
6
|
+
@click.command()
|
|
7
|
+
@click.option('--schema-url', help="The URL (or local path) to the as-code schema. "
|
|
8
|
+
"When omitted, download schemas/v<schemaVersion>/as-code.schema.json from neoload-models (v3). "
|
|
9
|
+
"If schemaVersion is absent, use schemas/v3.0/as-code.schema.json.",
|
|
10
|
+
metavar="URL", default=None)
|
|
11
|
+
@click.option('--refresh', is_flag=True, help="THIS OPTION IS NOW USELESS", hidden=True)
|
|
12
|
+
@click.option('--ssl-cert', default="", help="Path to SSL certificate or write False to disable certificate checking")
|
|
13
|
+
@click.argument('file')
|
|
14
|
+
def cli(file, refresh, schema_url, ssl_cert):
|
|
15
|
+
"""Verify that the yaml FILE matches the neoload as-code file format"""
|
|
16
|
+
|
|
17
|
+
force_schema = os.environ.get('NLCLI_FORCE_SCHEMA')
|
|
18
|
+
if force_schema is not None and len(force_schema) > 0:
|
|
19
|
+
schema_url = force_schema
|
|
20
|
+
|
|
21
|
+
path = os.path.abspath(file)
|
|
22
|
+
try:
|
|
23
|
+
if os.path.isdir(path):
|
|
24
|
+
schema_validation.validate_yaml_dir(path, schema_url, ssl_cert)
|
|
25
|
+
print('All yaml files underneath the path provided are valid.')
|
|
26
|
+
else:
|
|
27
|
+
schema_validation.validate_yaml(file, schema_url, ssl_cert)
|
|
28
|
+
print('Yaml file is valid.')
|
|
29
|
+
except Exception as err:
|
|
30
|
+
raise cli_exception.CliException(str(err))
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def get_resource_as_string(namespace, file):
|
|
5
|
+
try:
|
|
6
|
+
import importlib.resources as pkg_resources
|
|
7
|
+
except ImportError:
|
|
8
|
+
# Try backported to PY<37 `importlib_resources`.
|
|
9
|
+
import importlib_resources as pkg_resources
|
|
10
|
+
|
|
11
|
+
logging.debug({'namespace': namespace, 'file': file})
|
|
12
|
+
if hasattr(pkg_resources, 'files'): # files is present from Python 3.9
|
|
13
|
+
return pkg_resources.files(namespace).joinpath(file).read_text(encoding='utf-8')
|
|
14
|
+
return pkg_resources.read_text(namespace, file, encoding='utf-8')
|
|
@@ -16,10 +16,12 @@ import gitignorefile
|
|
|
16
16
|
from neoload_cli_lib.neoLoad_project import is_not_to_be_included
|
|
17
17
|
|
|
18
18
|
YAML_NOT_CONFIRM_MESSAGE = "YAML does not confirm to NeoLoad DSL schema."
|
|
19
|
-
|
|
19
|
+
__models_raw_root = "https://raw.githubusercontent.com/Neotys-Labs/neoload-models/v3"
|
|
20
|
+
__compatibility_url = __models_raw_root + "/schemas/compatibility.json"
|
|
21
|
+
__default_schema_version = "3.0"
|
|
20
22
|
|
|
21
23
|
_MERGED_ARRAY_FIELDS = ['sla_profiles', 'variables', 'servers', 'user_paths', 'populations', 'scenarios', 'frameworks']
|
|
22
|
-
_MERGED_SPECIAL_FIELDS = set(_MERGED_ARRAY_FIELDS) | {'project_settings', 'name', 'includes'}
|
|
24
|
+
_MERGED_SPECIAL_FIELDS = set(_MERGED_ARRAY_FIELDS) | {'project_settings', 'name', 'includes', 'schemaVersion'}
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
def parse_yaml_file(file_path):
|
|
@@ -55,6 +57,10 @@ def merge_projects(projects):
|
|
|
55
57
|
if project.get('name'):
|
|
56
58
|
merged['name'] = project['name']
|
|
57
59
|
|
|
60
|
+
for project in projects:
|
|
61
|
+
if 'schemaVersion' in project and project.get('schemaVersion') is not None:
|
|
62
|
+
merged['schemaVersion'] = project['schemaVersion']
|
|
63
|
+
|
|
58
64
|
# Carry over any other/unrecognized top-level key too, so genuinely
|
|
59
65
|
# invalid content isn't silently dropped by the merge instead of being
|
|
60
66
|
# caught by the schema (e.g. root "additionalProperties: false").
|
|
@@ -112,8 +118,58 @@ def resolve_and_merge_project(entry_file_path):
|
|
|
112
118
|
return merge_projects(resolved)
|
|
113
119
|
|
|
114
120
|
|
|
121
|
+
def normalize_schema_version(value):
|
|
122
|
+
"""Return the schemaVersion contract as a string. Absent values default to 3.0."""
|
|
123
|
+
if value is None or value == '':
|
|
124
|
+
return __default_schema_version
|
|
125
|
+
if isinstance(value, bool):
|
|
126
|
+
raise cli_exception.CliException('Invalid schemaVersion: %s' % value)
|
|
127
|
+
if isinstance(value, int):
|
|
128
|
+
return '%s.0' % value
|
|
129
|
+
if isinstance(value, float):
|
|
130
|
+
if value == int(value):
|
|
131
|
+
return '%s.0' % int(value)
|
|
132
|
+
return str(value)
|
|
133
|
+
return str(value).strip()
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def schema_url_for_version(version):
|
|
137
|
+
return '%s/schemas/v%s/as-code.schema.json' % (__models_raw_root, version)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def load_supported_schema_versions(ssl_cert=''):
|
|
141
|
+
"""Supported versions are the keys of neoload-models schemas/compatibility.json (v3)."""
|
|
142
|
+
compatibility_json, _etag, _not_modified = get_network_schema_by_spec(__compatibility_url, ssl_cert)
|
|
143
|
+
if compatibility_json is None:
|
|
144
|
+
raise cli_exception.CliException(
|
|
145
|
+
'Could not load schema compatibility matrix from %s' % __compatibility_url)
|
|
146
|
+
try:
|
|
147
|
+
compatibility = json.loads(compatibility_json)
|
|
148
|
+
except JSONDecodeError as err:
|
|
149
|
+
raise cli_exception.CliException(
|
|
150
|
+
'Invalid schema compatibility matrix at %s:\n%s' % (__compatibility_url, err))
|
|
151
|
+
if not isinstance(compatibility, dict) or not compatibility:
|
|
152
|
+
raise cli_exception.CliException(
|
|
153
|
+
'Schema compatibility matrix at %s does not list any versions.' % __compatibility_url)
|
|
154
|
+
return compatibility
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def resolve_schema_spec(project_object, schema_spec=None, ssl_cert=''):
|
|
158
|
+
"""Pick the GitHub schema URL from schemaVersion, unless the caller overrode it."""
|
|
159
|
+
if schema_spec is not None:
|
|
160
|
+
return schema_spec, None
|
|
161
|
+
version = normalize_schema_version((project_object or {}).get('schemaVersion'))
|
|
162
|
+
compatibility = load_supported_schema_versions(ssl_cert)
|
|
163
|
+
if version not in compatibility:
|
|
164
|
+
supported = ', '.join(sorted(compatibility.keys()))
|
|
165
|
+
raise cli_exception.CliException(
|
|
166
|
+
'Unsupported schemaVersion "%s". Supported versions: %s' % (version, supported))
|
|
167
|
+
return schema_url_for_version(version), version
|
|
168
|
+
|
|
169
|
+
|
|
115
170
|
def validate_project_object(project_object, schema_spec, ssl_cert='', check_schema=True, label=None):
|
|
116
|
-
|
|
171
|
+
schema_spec, schema_key = resolve_schema_spec(project_object, schema_spec, ssl_cert)
|
|
172
|
+
json_schema = init_yaml_schema_with_checks(schema_spec, ssl_cert, check_schema, schema_key=schema_key)
|
|
117
173
|
try:
|
|
118
174
|
schema_as_object = json.loads(json_schema)
|
|
119
175
|
except JSONDecodeError as err:
|
|
@@ -207,10 +263,10 @@ def validate_yaml_dir(path, schema_spec, ssl_cert='',continue_on_error=True):
|
|
|
207
263
|
raise ValueError('One or more errors in files underneath this directory.')
|
|
208
264
|
|
|
209
265
|
|
|
210
|
-
def init_yaml_schema_with_checks(schema_spec, ssl_cert='', check_schema=True):
|
|
211
|
-
json_schema = get_yaml_schema(False)
|
|
266
|
+
def init_yaml_schema_with_checks(schema_spec, ssl_cert='', check_schema=True, schema_key=None):
|
|
267
|
+
json_schema = get_yaml_schema(False, schema_key=schema_key)
|
|
212
268
|
if json_schema is not None:
|
|
213
|
-
cached_etag = get_yaml_schema_etag()
|
|
269
|
+
cached_etag = get_yaml_schema_etag(schema_key=schema_key)
|
|
214
270
|
if cached_etag:
|
|
215
271
|
logging.info('Loaded schema and ETag from disk cache.')
|
|
216
272
|
else:
|
|
@@ -222,13 +278,11 @@ def init_yaml_schema_with_checks(schema_spec, ssl_cert='', check_schema=True):
|
|
|
222
278
|
if not check_schema:
|
|
223
279
|
return json_schema
|
|
224
280
|
|
|
225
|
-
schema_spec_remote = __default_schema_url
|
|
226
|
-
if schema_spec is None: schema_spec = schema_spec_remote
|
|
227
281
|
logging.debug("Checking schema source for changes %s" %schema_spec)
|
|
228
282
|
|
|
229
283
|
try:
|
|
230
284
|
if is_network_spec(schema_spec):
|
|
231
|
-
cached_etag = get_yaml_schema_etag() if json_schema is not None else None
|
|
285
|
+
cached_etag = get_yaml_schema_etag(schema_key=schema_key) if json_schema is not None else None
|
|
232
286
|
json_schema_spec, response_etag, not_modified = get_network_schema_by_spec(schema_spec, ssl_cert, cached_etag)
|
|
233
287
|
if not_modified:
|
|
234
288
|
logging.info('Remote schema unchanged since last download (ETag match) - using cached schema.')
|
|
@@ -239,7 +293,7 @@ def init_yaml_schema_with_checks(schema_spec, ssl_cert='', check_schema=True):
|
|
|
239
293
|
else:
|
|
240
294
|
logging.info('Cached schema updated from remote source (no ETag).')
|
|
241
295
|
json_schema = json_schema_spec
|
|
242
|
-
update_schema(json_schema_spec, response_etag)
|
|
296
|
+
update_schema(json_schema_spec, response_etag, schema_key=schema_key)
|
|
243
297
|
else:
|
|
244
298
|
json_schema = None
|
|
245
299
|
else:
|
|
@@ -253,7 +307,7 @@ def init_yaml_schema_with_checks(schema_spec, ssl_cert='', check_schema=True):
|
|
|
253
307
|
if hash_disk != hash_spec:
|
|
254
308
|
logging.info('Cached schema differs from source!')
|
|
255
309
|
json_schema = json_schema_spec
|
|
256
|
-
update_schema(json_schema_spec)
|
|
310
|
+
update_schema(json_schema_spec, schema_key=schema_key)
|
|
257
311
|
else:
|
|
258
312
|
logging.info('No differences between cached and remote schema.')
|
|
259
313
|
except Exception as err:
|
|
@@ -308,20 +362,3 @@ def get_json_schema_by_spec(schema_spec, ssl_cert):
|
|
|
308
362
|
|
|
309
363
|
return json_schema_spec
|
|
310
364
|
|
|
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))
|
|
@@ -18,6 +18,16 @@ CONFIG_FILE = __local_file if os.path.exists(__local_file) else os.path.join(__c
|
|
|
18
18
|
__yaml_schema_file = os.path.join(__config_dir, "yaml_schema.json")
|
|
19
19
|
__yaml_schema_etag_file = os.path.join(__config_dir, "yaml_schema.etag")
|
|
20
20
|
|
|
21
|
+
|
|
22
|
+
def __schema_cache_paths(schema_key=None):
|
|
23
|
+
if not schema_key:
|
|
24
|
+
return __yaml_schema_file, __yaml_schema_etag_file
|
|
25
|
+
safe_key = re.sub(r'[^0-9A-Za-z._-]', '_', str(schema_key))
|
|
26
|
+
return (
|
|
27
|
+
os.path.join(__config_dir, "yaml_schema-%s.json" % safe_key),
|
|
28
|
+
os.path.join(__config_dir, "yaml_schema-%s.etag" % safe_key),
|
|
29
|
+
)
|
|
30
|
+
|
|
21
31
|
__no_write = False
|
|
22
32
|
|
|
23
33
|
|
|
@@ -239,44 +249,64 @@ def get_meta_required(key):
|
|
|
239
249
|
return get_user_data().metadata.get(key)
|
|
240
250
|
|
|
241
251
|
|
|
242
|
-
def __load_yaml_schema():
|
|
243
|
-
|
|
244
|
-
|
|
252
|
+
def __load_yaml_schema(schema_key=None):
|
|
253
|
+
schema_file, _etag_file = __schema_cache_paths(schema_key)
|
|
254
|
+
if os.path.exists(schema_file):
|
|
255
|
+
with open(schema_file, "r") as stream:
|
|
245
256
|
return stream.read()
|
|
246
257
|
return None
|
|
247
258
|
|
|
248
259
|
|
|
249
|
-
def __load_yaml_schema_etag():
|
|
250
|
-
|
|
251
|
-
|
|
260
|
+
def __load_yaml_schema_etag(schema_key=None):
|
|
261
|
+
_schema_file, etag_file = __schema_cache_paths(schema_key)
|
|
262
|
+
if os.path.exists(etag_file):
|
|
263
|
+
with open(etag_file, "r") as stream:
|
|
252
264
|
return stream.read() or None
|
|
253
265
|
return None
|
|
254
266
|
|
|
255
267
|
|
|
256
268
|
__yaml_schema_singleton = __load_yaml_schema()
|
|
257
269
|
__yaml_schema_etag_singleton = __load_yaml_schema_etag()
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
270
|
+
__yaml_schema_by_key = {}
|
|
271
|
+
__yaml_schema_etag_by_key = {}
|
|
272
|
+
|
|
273
|
+
|
|
274
|
+
def get_yaml_schema(throw=True, schema_key=None):
|
|
275
|
+
if schema_key:
|
|
276
|
+
if schema_key not in __yaml_schema_by_key:
|
|
277
|
+
__yaml_schema_by_key[schema_key] = __load_yaml_schema(schema_key)
|
|
278
|
+
schema = __yaml_schema_by_key[schema_key]
|
|
279
|
+
if schema is None and throw:
|
|
280
|
+
raise cli_exception.CliException("No yaml schema found. Please add --refresh option to download it first")
|
|
281
|
+
return schema
|
|
261
282
|
if __yaml_schema_singleton is None and throw:
|
|
262
283
|
raise cli_exception.CliException("No yaml schema found. Please add --refresh option to download it first")
|
|
263
284
|
return __yaml_schema_singleton
|
|
264
285
|
|
|
265
286
|
|
|
266
|
-
def get_yaml_schema_etag():
|
|
287
|
+
def get_yaml_schema_etag(schema_key=None):
|
|
288
|
+
if schema_key:
|
|
289
|
+
if schema_key not in __yaml_schema_etag_by_key:
|
|
290
|
+
__yaml_schema_etag_by_key[schema_key] = __load_yaml_schema_etag(schema_key)
|
|
291
|
+
return __yaml_schema_etag_by_key[schema_key]
|
|
267
292
|
return __yaml_schema_etag_singleton
|
|
268
293
|
|
|
269
294
|
|
|
270
|
-
def update_schema(yaml_schema_as_json: str, etag: str = None):
|
|
295
|
+
def update_schema(yaml_schema_as_json: str, etag: str = None, schema_key=None):
|
|
271
296
|
global __yaml_schema_singleton, __yaml_schema_etag_singleton
|
|
272
|
-
|
|
273
|
-
__yaml_schema_etag_singleton = etag
|
|
297
|
+
schema_file, etag_file = __schema_cache_paths(schema_key)
|
|
274
298
|
os.makedirs(__config_dir, exist_ok=True)
|
|
275
|
-
with open(
|
|
276
|
-
stream.write(
|
|
299
|
+
with open(schema_file, "w") as stream:
|
|
300
|
+
stream.write(yaml_schema_as_json)
|
|
277
301
|
if etag:
|
|
278
|
-
with open(
|
|
302
|
+
with open(etag_file, "w") as stream:
|
|
279
303
|
stream.write(etag)
|
|
280
|
-
elif os.path.exists(
|
|
304
|
+
elif os.path.exists(etag_file):
|
|
281
305
|
# no etag for this schema source (e.g. a local file) - don't leave a stale one around
|
|
282
|
-
os.remove(
|
|
306
|
+
os.remove(etag_file)
|
|
307
|
+
if schema_key:
|
|
308
|
+
__yaml_schema_by_key[schema_key] = yaml_schema_as_json
|
|
309
|
+
__yaml_schema_etag_by_key[schema_key] = etag
|
|
310
|
+
return
|
|
311
|
+
__yaml_schema_singleton = yaml_schema_as_json
|
|
312
|
+
__yaml_schema_etag_singleton = etag
|
{neoload-1.3.19.dev2/examples/as-code-demo → neoload-1.4.0/neoload/resources/templates}/default.yaml
RENAMED
|
@@ -4,13 +4,11 @@
|
|
|
4
4
|
# Target : https://demowebshop.tricentis.com/ (nopCommerce demo)
|
|
5
5
|
# Scenario: add a product to the cart -> checkout as guest -> view details
|
|
6
6
|
#
|
|
7
|
-
# Out-of-the-box usage (
|
|
8
|
-
# Run CheckVU against the project:
|
|
9
|
-
# neoload checkvu examples/as-code-demo/default.yaml
|
|
7
|
+
# Out-of-the-box usage (via neoload-cli), from this project directory:
|
|
10
8
|
# Run the full test:
|
|
11
9
|
# neoload login $NLW_TOKEN \
|
|
12
10
|
# test-settings --zone defaultzone --lgs 1 createorpatch DemoWebShopTest \
|
|
13
|
-
# project --path
|
|
11
|
+
# project --path default.yaml upload DemoWebShopTest \
|
|
14
12
|
# run --scenario DemoWebShop
|
|
15
13
|
#
|
|
16
14
|
# =============================================================================
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "1.4.0"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: neoload
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
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
|
|
@@ -215,24 +215,6 @@ Pressing `Ctrl+C` causes the CLI to attempt to stop the test gracefully.
|
|
|
215
215
|
neoload stop # Sends the stop signal to the test and waits until it ends.
|
|
216
216
|
```
|
|
217
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
|
-
|
|
236
218
|
## Reporting
|
|
237
219
|
|
|
238
220
|
The NeoLoad CLI provides basic support for viewing and exporting test results.
|
|
@@ -418,9 +400,14 @@ The configuration lets you customize the CLI's behavior. For now, it is only use
|
|
|
418
400
|
|
|
419
401
|
### As-Code Demo Project
|
|
420
402
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
403
|
+
Create a starter NeoLoad As-Code YAML project with:
|
|
404
|
+
|
|
405
|
+
```
|
|
406
|
+
neoload project create DemoWebShop
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
This scaffolds `DemoWebShop/default.yaml` from the bundled Demo Web Shop template —
|
|
410
|
+
no NeoLoad Web project, no manual scenario setup.
|
|
424
411
|
|
|
425
412
|
Target: [Tricentis Demo Web Shop](https://demowebshop.tricentis.com/) (nopCommerce demo).
|
|
426
413
|
|
|
@@ -435,16 +422,12 @@ The `BuyAsGuest` user path walks through a typical guest purchase:
|
|
|
435
422
|
|
|
436
423
|
It uses two variables (`product_id`, `quantity`) and a single population (`GuestShoppers`)
|
|
437
424
|
|
|
438
|
-
Run CheckVU against the project:
|
|
439
|
-
```
|
|
440
|
-
neoload checkvu examples/as-code-demo/default.yaml
|
|
441
|
-
```
|
|
442
|
-
|
|
443
425
|
Run the full test:
|
|
444
426
|
```
|
|
427
|
+
neoload project create DemoWebShop
|
|
445
428
|
neoload login $NLW_TOKEN \
|
|
446
429
|
test-settings --zone defaultzone --lgs 1 createorpatch DemoWebShopTest \
|
|
447
|
-
project --path
|
|
430
|
+
project --path DemoWebShop/default.yaml upload DemoWebShopTest \
|
|
448
431
|
run --scenario DemoWebShop
|
|
449
432
|
```
|
|
450
433
|
|