snakemake-executor-plugin-aws-batch-flex 0.1.0__tar.gz → 0.1.1__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.
- snakemake_executor_plugin_aws_batch_flex-0.1.1/.release-please-manifest.json +3 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/CHANGELOG.md +10 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/PKG-INFO +1 -1
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/reference.md +1 -1
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/setup.md +3 -2
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/pyproject.toml +1 -1
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/bootstrap.py +21 -12
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/executor.py +12 -6
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/transfer.py +7 -3
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/usage.py +3 -1
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_integration.py +2 -2
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_prereqs.py +8 -2
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_smkflex.py +7 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_units.py +21 -2
- snakemake_executor_plugin_aws_batch_flex-0.1.0/.release-please-manifest.json +0 -3
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/.github/workflows/release.yml +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/.github/workflows/tests.yml +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/.gitignore +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/LICENSE +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/README.md +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/further.md +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/guide.md +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/docs/intro.md +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/environment.yml +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/auto.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/benchmark.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/checkpoint.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/conda.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/conda_named.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/config/pdsheet.tsv +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/directory.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/disk.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/ecr.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/entrypoint.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/envs/tiny.yaml +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/fanout.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/fargate.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/find-profile.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/group.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/mixed.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/oom.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/orphan-test.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/orphans.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pdsheet.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pipeline.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pyimage.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/pyrule.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/retries.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/rscript.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/run.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/script.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/pandas_script.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/py_script.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/r_script.R +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/sh_script.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/scripts/which_python.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/shadow.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/shm.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/tempdir.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/conformance/wrapper.smk +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/smoke-test/README.md +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/examples/smoke-test/Snakefile +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/release-please-config.json +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/bake-ami.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/cleanup-ami.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/cleanup-jobdefs.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/setup.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/scripts/update-ami.sh +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/__init__.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/bundle.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/check.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/condacache.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/headjob.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/hints.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/hostenv.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/imageinfo.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/jobdefs.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/jobfixes.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/jobmonitor.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/naming.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/orphans.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/patches.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/preflight.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/profiles.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/remote.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/settings.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/sizing.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/sources.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/src/snakemake_executor_plugin_aws_batch_flex/tags.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/.terraform.lock.hcl +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/README.md +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/fargate.tf +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/main.tf +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/outputs.tf +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/spot.tf +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/terraform.tfvars.example +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/userdata.snakemake.txt +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/variables.tf +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/terraform/versions.tf +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/conftest.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/fakeaws/sitecustomize.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/fixtures/existing_userdata.txt +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_bake_script.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_cleanup_ami.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_cleanup_jobdefs.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_conda_mount.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_condacache.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_conformance.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_host_env.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_imageinfo.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_script_python.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_setup.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_tags.py +0 -0
- {snakemake_executor_plugin_aws_batch_flex-0.1.0 → snakemake_executor_plugin_aws_batch_flex-0.1.1}/tests/test_userdata.py +0 -0
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.1](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/compare/v0.1.0...v0.1.1) (2026-10-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* big runs read peak memory from jobs across the whole run, not only the last ones ([147a054](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/147a054053c7e7dbfee38029c95d9fa92dd44f00))
|
|
9
|
+
* cancelling a run stops every job, also those Snakemake is checking on ([9edb388](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/9edb3880575bb8d3c4fb2aceb469f7a120bfb3a4))
|
|
10
|
+
* non-root images without curl get uv from their own conda at job start ([374cc30](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/374cc303e6d1d42b17255dc36fe05c76ec84beff))
|
|
11
|
+
* smkflex push gives the .gitignore note only when it uploaded, and no rate for tiny transfers ([6be28ad](https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex/commit/6be28ad2efe30a30f13c4c9bd077969f573024fb))
|
|
12
|
+
|
|
3
13
|
## 0.1.0 (2026-10-28)
|
|
4
14
|
|
|
5
15
|
First release. Needs Snakemake 9 (9.5 or newer) and Python 3.11 to 3.13. Tested on Linux; macOS
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: snakemake-executor-plugin-aws-batch-flex
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.1
|
|
4
4
|
Summary: Snakemake executor plugin for AWS Batch that runs every rule in its own container image
|
|
5
5
|
Project-URL: Homepage, https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex
|
|
6
6
|
Project-URL: Documentation, https://github.com/SSmith-NUIG/snakemake-executor-plugin-aws-batch-flex#getting-started
|
|
@@ -51,7 +51,7 @@ from the machine image (`host`); otherwise it's installed when each job starts,
|
|
|
51
51
|
| `host-env-wait-seconds` | `120` | How long a job waits for that Snakemake if its machine is still setting it up when the job starts. A machine image made by `setup.sh` has it from the start, so 0 is fine there. |
|
|
52
52
|
| `extra-packages` | *none* | Extra pip packages to install along with Snakemake when a job starts (e.g. `[pandas]`, or other Snakemake plugins). |
|
|
53
53
|
| `python-version` | *the one you run Snakemake with* | The Python version to install Snakemake with when a job starts. |
|
|
54
|
-
| `install-prereqs` | `false` | When installing at start
|
|
54
|
+
| `install-prereqs` | `false` | When installing at start, for images that have none of `curl`, `wget` or `pip`: get uv with the image's conda, mamba or micromamba (any user), or else install `curl` with its package manager (images that run as root). |
|
|
55
55
|
| `script-python` | `image` | Which Python runs Python `script:` rules. `image`: the image's own, if it's 3.10 or newer, so the script can use the image's packages. `host`: always Snakemake's own. |
|
|
56
56
|
|
|
57
57
|
**Memory, disk and Spot**
|
|
@@ -149,8 +149,9 @@ lines like `executor: aws-batch-flex` and `aws-batch-flex-queue: smkflex-queue`.
|
|
|
149
149
|
To try the plugin on an existing Batch queue without building an AMI, set
|
|
150
150
|
`aws-batch-flex-bootstrap: auto` in the profile instead of `host`. Snakemake is then installed into
|
|
151
151
|
each container when its job starts (about 10-15 s per job), which needs internet access and
|
|
152
|
-
`curl`, `wget` or `pip` in the image
|
|
153
|
-
|
|
152
|
+
`curl`, `wget` or `pip` in the image. Without them, `--aws-batch-flex-install-prereqs` gets uv
|
|
153
|
+
with the image's own conda, mamba or micromamba if it has one (as any user), or else installs
|
|
154
|
+
`curl` with its package manager, which needs an image that runs as root.
|
|
154
155
|
|
|
155
156
|
Or install the Snakemake env on each instance as it boots, with the stock ECS image and no AMI of
|
|
156
157
|
your own: every new instance then spends about a minute on it before its first job (not yet
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "snakemake-executor-plugin-aws-batch-flex"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.1"
|
|
8
8
|
description = "Snakemake executor plugin for AWS Batch that runs every rule in its own container image"
|
|
9
9
|
dynamic = ["readme"]
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -70,20 +70,29 @@ else
|
|
|
70
70
|
fi"""
|
|
71
71
|
|
|
72
72
|
|
|
73
|
-
#
|
|
73
|
+
# For an image without curl, wget or pip (only with install_prereqs): uv from the image's own
|
|
74
|
+
# conda, mamba or micromamba into $SMK_BOOT, which works as any user and leaves the image's
|
|
75
|
+
# environments alone; else curl from its package manager, which needs root
|
|
74
76
|
_PREREQS = r'''
|
|
75
77
|
if ! command -v curl >/dev/null 2>&1 && ! command -v wget >/dev/null 2>&1 \
|
|
76
78
|
&& ! { command -v python3 >/dev/null 2>&1 && python3 -m pip --version >/dev/null 2>&1; }; then
|
|
77
|
-
|
|
78
|
-
if [ "$
|
|
79
|
-
echo "[snakemake-batch]
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
elif
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
79
|
+
SMK_CONDA=$(command -v micromamba || command -v mamba || command -v conda || true)
|
|
80
|
+
if [ -n "$SMK_CONDA" ]; then
|
|
81
|
+
echo "[snakemake-batch] no curl/wget/pip in the image: getting uv with its $SMK_CONDA" >&2
|
|
82
|
+
CONDA_PKGS_DIRS="$SMK_BOOT/pkgs" "$SMK_CONDA" create -y -q -p "$SMK_BOOT/uvenv" -c conda-forge "uv=@@UVVER@@" >&2 \
|
|
83
|
+
&& mkdir -p "$SMK_BOOT/bin" && ln -sf "$SMK_BOOT/uvenv/bin/uv" "$SMK_BOOT/bin/uv" || true
|
|
84
|
+
elif [ "$(id -u)" != 0 ]; then
|
|
85
|
+
echo "[snakemake-batch] no curl/wget/pip/conda in the image, and it runs as a non-root user, so none can be installed. Add curl to the image (or USER root), or run the rule on EC2 (batch_queue), where Snakemake comes from the AMI" >&2
|
|
86
|
+
else
|
|
87
|
+
echo "[snakemake-batch] no curl/wget/pip in the image: installing curl, ca-certificates and bash" >&2
|
|
88
|
+
if command -v apt-get >/dev/null 2>&1; then
|
|
89
|
+
apt-get update -qq >&2 && DEBIAN_FRONTEND=noninteractive apt-get install -y -qq --no-install-recommends curl ca-certificates bash >&2 || true
|
|
90
|
+
elif command -v apk >/dev/null 2>&1; then apk add -q --no-cache curl ca-certificates bash >&2 || true
|
|
91
|
+
elif command -v dnf >/dev/null 2>&1; then dnf install -y -q curl ca-certificates bash >&2 || true
|
|
92
|
+
elif command -v microdnf >/dev/null 2>&1; then microdnf install -y curl ca-certificates bash >&2 || true
|
|
93
|
+
elif command -v yum >/dev/null 2>&1; then yum install -y -q curl ca-certificates bash >&2 || true
|
|
94
|
+
else echo "[snakemake-batch] no known package manager in the image" >&2
|
|
95
|
+
fi
|
|
87
96
|
fi
|
|
88
97
|
fi
|
|
89
98
|
'''
|
|
@@ -277,7 +286,7 @@ def build_prelude(
|
|
|
277
286
|
_TEMPLATE.replace("@@WORKDIR@@", WORKDIR)
|
|
278
287
|
.replace("@@CHECK@@", check)
|
|
279
288
|
.replace("@@PYVER@@", shlex.quote(python_version))
|
|
280
|
-
.replace("@@PREREQS@@", _PREREQS if install_prereqs else "")
|
|
289
|
+
.replace("@@PREREQS@@", _PREREQS.replace("@@UVVER@@", UV_VERSION) if install_prereqs else "")
|
|
281
290
|
.replace("@@REQS@@", reqs)
|
|
282
291
|
.replace("@@NEWER@@", f"--exclude-newer {shlex.quote(resolved_at)} " if resolved_at else "")
|
|
283
292
|
.replace("@@UV@@", uv_snippet("$SMK_BOOT/bin", "$SMK_BOOT/uvlib"))
|
|
@@ -156,6 +156,9 @@ class Executor(RemoteExecutor):
|
|
|
156
156
|
self._warned_fargate_shm = False
|
|
157
157
|
self._said_resolved = False
|
|
158
158
|
self._warned_tags: set = set()
|
|
159
|
+
# Batch jobs submitted and not seen to end. Cancelling stops these too: while Snakemake
|
|
160
|
+
# checks on its running jobs, it takes them out of the list it would hand cancel_jobs.
|
|
161
|
+
self._unfinished: set = set()
|
|
159
162
|
self._warned_disk: set = set()
|
|
160
163
|
self._existing_defs: dict = {} # ref -> ExistingJobDefinition
|
|
161
164
|
self._fair_share: dict = {} # queue -> has a scheduling policy
|
|
@@ -578,6 +581,7 @@ class Executor(RemoteExecutor):
|
|
|
578
581
|
f"Submitted {job.name} as AWS Batch job {resp['jobId']} "
|
|
579
582
|
f"({image}, {req.vcpu} vCPU, {req.memory_mib} MiB, queue {queue}, {platform})"
|
|
580
583
|
)
|
|
584
|
+
self._unfinished.add(resp["jobId"])
|
|
581
585
|
self.report_job_submission(
|
|
582
586
|
SubmittedJobInfo(
|
|
583
587
|
job,
|
|
@@ -608,6 +612,8 @@ class Executor(RemoteExecutor):
|
|
|
608
612
|
|
|
609
613
|
for jid, info in by_id.items():
|
|
610
614
|
d = described.get(jid)
|
|
615
|
+
if d is None or d["status"] in ("SUCCEEDED", "FAILED"):
|
|
616
|
+
self._unfinished.discard(jid)
|
|
611
617
|
if d is None:
|
|
612
618
|
self.report_job_error(
|
|
613
619
|
info, msg=f"AWS Batch no longer knows job {jid} (expired?)."
|
|
@@ -658,16 +664,16 @@ class Executor(RemoteExecutor):
|
|
|
658
664
|
def cancel_jobs(self, active_jobs: List[SubmittedJobInfo]):
|
|
659
665
|
# In parallel: a head job that is stopped has little time (ECS_CONTAINER_STOP_TIMEOUT)
|
|
660
666
|
# to cancel every job and save its state.
|
|
661
|
-
def cancel(
|
|
667
|
+
def cancel(jid):
|
|
662
668
|
try:
|
|
663
|
-
self.batch.terminate_job(
|
|
664
|
-
jobId=info.external_jobid, reason="Cancelled by Snakemake"
|
|
665
|
-
)
|
|
669
|
+
self.batch.terminate_job(jobId=jid, reason="Cancelled by Snakemake")
|
|
666
670
|
except (ClientError, BotoCoreError) as e:
|
|
667
|
-
self.logger.warning(f"Could not terminate {
|
|
671
|
+
self.logger.warning(f"Could not terminate {jid}: {e}")
|
|
668
672
|
|
|
673
|
+
# set() copies at once, so the status checks can't change it meanwhile
|
|
674
|
+
ids = {i.external_jobid for i in active_jobs} | set(self._unfinished)
|
|
669
675
|
with ThreadPoolExecutor(CANCEL_THREADS) as pool:
|
|
670
|
-
list(pool.map(cancel,
|
|
676
|
+
list(pool.map(cancel, sorted(ids)))
|
|
671
677
|
|
|
672
678
|
def _warn_if_stuck(self, d: dict, info: SubmittedJobInfo):
|
|
673
679
|
sub = _sub(info)
|
|
@@ -78,8 +78,11 @@ def _transfer(jobs, work, verb):
|
|
|
78
78
|
return done, total, secs
|
|
79
79
|
|
|
80
80
|
def _rate(total, secs):
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
"""How much was sent, and how fast when that means something (1 MB or more, over a second)."""
|
|
82
|
+
if not total:
|
|
83
|
+
return ""
|
|
84
|
+
size = f"{total / 1e6:.1f} MB" if total >= 1e5 else f"{total / 1e3:.1f} kB" if total >= 1e3 else f"{total} bytes"
|
|
85
|
+
return f"{size} in {secs:.0f} s ({total / 1e6 / secs:.1f} MB/s)" if total >= 1e6 and secs >= 1 else size
|
|
83
86
|
|
|
84
87
|
def cmd_pull(a):
|
|
85
88
|
_dir, profile = _load_profile(a.profile)
|
|
@@ -176,7 +179,8 @@ def cmd_push(a):
|
|
|
176
179
|
rate = _rate(total, secs)
|
|
177
180
|
print(f"{sent} uploaded to {prefix}" + (f" ({rate})" if rate else "")
|
|
178
181
|
+ (f", {skipped} already there (unchanged; --force sends them again)" if skipped else ""))
|
|
179
|
-
|
|
182
|
+
if sent: # not again on every push that had nothing new
|
|
183
|
+
_hint_gitignore([p for p in a.paths if not os.path.isabs(p)])
|
|
180
184
|
return 0
|
|
181
185
|
|
|
182
186
|
def _hint_gitignore(paths):
|
|
@@ -83,8 +83,10 @@ class Usage:
|
|
|
83
83
|
todo = []
|
|
84
84
|
for rule, streams in self.logs.items():
|
|
85
85
|
if total > ALL_PEAKS and len(streams) > PEAK_SAMPLE:
|
|
86
|
+
# spread over the run: a rule's biggest inputs aren't always its last jobs
|
|
86
87
|
self.sampled = True
|
|
87
|
-
|
|
88
|
+
step = len(streams) / PEAK_SAMPLE
|
|
89
|
+
streams = [streams[int(i * step)] for i in range(PEAK_SAMPLE)]
|
|
88
90
|
todo += [(rule, g, st) for g, st in streams]
|
|
89
91
|
|
|
90
92
|
def one(item):
|
|
@@ -469,8 +469,8 @@ def test_workdir_directive_stops_before_submitting(tmp_path):
|
|
|
469
469
|
|
|
470
470
|
|
|
471
471
|
def test_job_commands_fit_what_ecs_allows(tmp_path):
|
|
472
|
-
# installing Snakemake at job start makes the longest commands
|
|
473
|
-
r, calls = run(tmp_path, SNAKEFILE, "--aws-batch-flex-bootstrap", "always")
|
|
472
|
+
# installing Snakemake at job start, with the prerequisites, makes the longest commands
|
|
473
|
+
r, calls = run(tmp_path, SNAKEFILE, "--aws-batch-flex-bootstrap", "always", "--aws-batch-flex-install-prereqs")
|
|
474
474
|
assert r.returncode == 0, r.stdout + r.stderr
|
|
475
475
|
sizes = [c["overrides_chars"] for c in calls if c["call"] == "submit_job"]
|
|
476
476
|
assert sizes and max(sizes) < 8192 - 500, sizes # room for a longer storage prefix and the like
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""The curl
|
|
1
|
+
"""The fallbacks for images without curl, wget or pip, run in a stripped PATH with stub tools."""
|
|
2
2
|
import os, stat, subprocess
|
|
3
3
|
from snakemake_executor_plugin_aws_batch_flex.bootstrap import build_prelude
|
|
4
4
|
|
|
@@ -42,7 +42,13 @@ def test_off_by_default_installs_nothing_and_fails_clearly(tmp_path):
|
|
|
42
42
|
|
|
43
43
|
def test_non_root_is_reported_not_attempted(tmp_path):
|
|
44
44
|
r, calls = _run(tmp_path, True, ["apt-get"], uid="1000")
|
|
45
|
-
assert calls == "" and "non-root" in r.stderr
|
|
45
|
+
assert calls == "" and "non-root" in r.stderr and "batch_queue" in r.stderr
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def test_uv_from_the_images_conda_as_any_user(tmp_path):
|
|
49
|
+
# mambaorg/micromamba: non-root, no curl; its micromamba fetches uv into the job's folder
|
|
50
|
+
r, calls = _run(tmp_path, True, ["apt-get", "micromamba"], uid="1000")
|
|
51
|
+
assert "micromamba create -y -q -p" in calls and "-c conda-forge uv=" in calls and "apt-get" not in calls
|
|
46
52
|
|
|
47
53
|
|
|
48
54
|
def test_skipped_when_curl_already_present(tmp_path):
|
|
@@ -336,6 +336,13 @@ def test_push(tmp_path):
|
|
|
336
336
|
assert (tmp_path / "store" / "data" / "a.fq").read_text() == "CCC"
|
|
337
337
|
r, _ = smkflex(wf, "push", "../x")
|
|
338
338
|
assert r.returncode == 2 and "outside the workflow folder" in r.stderr
|
|
339
|
+
# a folder smkflex run would send too: said once, not on every push with nothing new
|
|
340
|
+
(wf / "refs").mkdir()
|
|
341
|
+
(wf / "refs" / "g.fa").write_text(">g\n")
|
|
342
|
+
r, _ = smkflex(wf, "push", "refs")
|
|
343
|
+
assert "add to .gitignore:\nrefs/" in r.stdout and "uploaded to" in r.stdout and "MB/s" not in r.stdout
|
|
344
|
+
r, _ = smkflex(wf, "push", "refs")
|
|
345
|
+
assert "0 uploaded" in r.stdout and ".gitignore" not in r.stdout
|
|
339
346
|
|
|
340
347
|
|
|
341
348
|
def test_push_absolute_paths_and_many_files(tmp_path):
|
|
@@ -221,6 +221,7 @@ def test_sources_patch_leaves_other_executors_alone(tmp_path, monkeypatch):
|
|
|
221
221
|
|
|
222
222
|
|
|
223
223
|
def test_cancel_terminates_jobs_in_parallel_and_goes_on_after_errors():
|
|
224
|
+
# also j20, which Snakemake leaves out of the list while it checks on it
|
|
224
225
|
import threading, time, types
|
|
225
226
|
from botocore.exceptions import ClientError
|
|
226
227
|
from snakemake_executor_plugin_aws_batch_flex.executor import Executor
|
|
@@ -235,12 +236,12 @@ def test_cancel_terminates_jobs_in_parallel_and_goes_on_after_errors():
|
|
|
235
236
|
done.append(jobId)
|
|
236
237
|
|
|
237
238
|
me = types.SimpleNamespace(batch=types.SimpleNamespace(terminate_job=terminate_job),
|
|
238
|
-
logger=types.SimpleNamespace(warning=warnings.append))
|
|
239
|
+
logger=types.SimpleNamespace(warning=warnings.append), _unfinished={"j1", "j20"})
|
|
239
240
|
jobs = [types.SimpleNamespace(external_jobid=f"j{i}") for i in range(20)]
|
|
240
241
|
start = time.time()
|
|
241
242
|
Executor.cancel_jobs(me, jobs)
|
|
242
243
|
assert time.time() - start < 2 # one at a time would take 4 s
|
|
243
|
-
assert sorted(done) == sorted(f"j{i}" for i in range(
|
|
244
|
+
assert sorted(done) == sorted(f"j{i}" for i in range(21) if i != 3) # j1 once
|
|
244
245
|
assert len(warnings) == 1 and "j3" in warnings[0]
|
|
245
246
|
|
|
246
247
|
|
|
@@ -316,6 +317,24 @@ def test_rules_whose_jobs_ran_out_get_no_memory_suggestion(tmp_path, monkeypatch
|
|
|
316
317
|
assert "Hint: in killed's jobs, Linux killed 2 process(es) for lack of memory" in u.table(256)
|
|
317
318
|
|
|
318
319
|
|
|
320
|
+
def test_big_runs_sample_jobs_from_the_whole_run():
|
|
321
|
+
from snakemake_executor_plugin_aws_batch_flex import usage
|
|
322
|
+
u = usage.Usage()
|
|
323
|
+
for i in range(usage.ALL_PEAKS + 100): # the first jobs took the most memory
|
|
324
|
+
u.add("align", {"startedAt": 0, "stoppedAt": 1000}, 1, 4352, "ec2")
|
|
325
|
+
u.add_log("align", "g", str(i))
|
|
326
|
+
client = types.SimpleNamespace(get_log_events=lambda logGroupName, logStreamName, **kw: {
|
|
327
|
+
"events": [{"message": f"[snakemake-batch] peak-memory-bytes={(4000 - int(logStreamName)) << 20}"}]})
|
|
328
|
+
u.fetch_peaks(client)
|
|
329
|
+
assert len(u.peaks["align"]) == usage.PEAK_SAMPLE and max(u.peaks["align"]) == 4000
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def test_transfer_sizes():
|
|
333
|
+
from snakemake_executor_plugin_aws_batch_flex.transfer import _rate
|
|
334
|
+
assert (_rate(0, 1), _rate(12, 0.01), _rate(4300, 0.01)) == ("", "12 bytes", "4.3 kB")
|
|
335
|
+
assert _rate(250_000_000, 10) == "250.0 MB in 10 s (25.0 MB/s)"
|
|
336
|
+
|
|
337
|
+
|
|
319
338
|
def test_hint_for_a_script_that_wasnt_sent():
|
|
320
339
|
from snakemake_executor_plugin_aws_batch_flex.hints import known_problem_hints as hints
|
|
321
340
|
py = ["python: can't open file '/tmp/snakemake-job-7/scripts/synthetic/gen.py': [Errno 2] No such file or directory"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|