ellf-cli 21.0.9__tar.gz → 22.0.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.
- {ellf_cli-21.0.9/ellf_cli.egg-info → ellf_cli-22.0.1}/PKG-INFO +1 -1
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/README.md +3 -34
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/__main__.py +4 -5
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/auth.py +2 -3
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/cli.py +0 -1
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/__init__.py +0 -2
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/__init__.py +0 -1
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/_helpers.py +30 -1
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/deploy.py +6 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/init.py +15 -4
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/init_values.py +4 -4
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/register.py +17 -4
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/start.py +2 -22
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/terraform.py +53 -2
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf.json +5 -158
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/interactivity.py +1 -1
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/messages.py +5 -3
- ellf_cli-22.0.1/ellf_cli/version/21.0.10_2026-10-30-14-29-34_major_4fd535f6-6e41-4f34-b29c-543e1a9bac51 +3 -0
- ellf_cli-22.0.1/ellf_cli/version/21.0.9_2026-10-29-17-51-00_patch_803a4c70-2e2b-4024-8598-c7d91c9db0d2 +3 -0
- ellf_cli-22.0.1/ellf_cli/version/22.0.0_2026-10-30-15-25-42_patch_1f39caf4-aadc-4d26-9124-a854d945b32a +3 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1/ellf_cli.egg-info}/PKG-INFO +1 -1
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli.egg-info/SOURCES.txt +4 -2
- ellf_cli-22.0.1/tests/test_infra_deploy_registry_key.py +46 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_destroy.py +42 -1
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_start_validation.py +1 -1
- ellf_cli-21.0.9/ellf_cli/commands/auth.py +0 -122
- ellf_cli-21.0.9/ellf_cli/commands/infra/tls.py +0 -453
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/LICENSE +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/MANIFEST.in +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/__init__.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/about.json +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/about.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/agents.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/appdirs.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/cloud/__init__.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/cloud/gcp.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/cluster_config.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/_cluster_select.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/_org_select.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/_project_scope.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/_recipe_file.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/_recipe_subcommand.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/_state.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/_usage.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/actions.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/agents.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/assets.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/clusters.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/config.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/datasets.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/files/__init__.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/files/cp.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/files/ls.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/files/rm.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/files/rsync.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/files/stats.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/general.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/import_export.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/_config_io.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/configure.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/hibernate.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/pause.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/provision.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/infra/setup.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/jobs.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/mcp.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/packages.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/paths.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/plans.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/projects.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/publish_code.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/publish_data.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/recipes.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/secrets.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/services.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/sessions.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/support.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/tasks.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/todos.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/commands/users.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/config.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/.gitignore +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/render.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/references/annotation_audit.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/references/annotation_audit.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_ellf_annotation_recipes.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_ellf_annotation_recipes.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_prodigy_recipes.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/references/label_schemes.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-annotate/references/label_schemes.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-ask/SKILL.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-handoff/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-monitor/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-monitor/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-monitor/references/annotation_metrics.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-monitor/references/annotation_metrics.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-monitor/references/training_monitoring.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-monitor/references/training_monitoring.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-monitor/scripts.coding/check_training.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-ops/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-ops/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-ops/references.coding/data_infra_cli.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-ops/scripts.coding/run_job.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-patterns/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-patterns/references/pattern_strategies.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_action_recipe.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_agent_recipe.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_blocks_ui.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_correct.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_custom_ui.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_manual.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_pages_ui.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_routing.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_service_recipe.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_task_recipe.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_teach.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/builtin_recipes.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/ellf_recipe_sdk.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/lint_recipe.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/prodigy_recipe_api.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/template_index.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/references/annotation_agents.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/references/consulting_patterns.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/references/explosion_strategy.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/references/jev.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/references/label_schemes.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-project/references/label_schemes.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-support/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-support/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-template/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-template/references/template_format.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-template/scripts/placeholders.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-todo/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/SKILL.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/config_advanced.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/config_architectures.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/config_training.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/diagnostics.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/evaluation_guide.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/experiment_patterns.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/model_selection.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/training_paradigms.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/training_troubleshooting.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/workflow.assistant.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/references/workflow.coding.md +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ellf_skills/skills/ellf-train/scripts.coding/ellf_logger.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/errors.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/helm.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/key_pair.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/main.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/mcp_proxy.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/pypi_auth.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/query.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/cookiecutter.json +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/.gitignore +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/README.md.tmpl +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements-dev.in +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements.in +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/setup.py.tmpl +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/__init__.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/about.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/__init__.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/example_task.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/testing/__init__.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ty.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/ui.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/url.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/util.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.114_2026-08-19-08-36-57__1a4e37c1-471e-4a81-b4d5-1ffe7dec3a61 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.114_2026-08-19-09-25-21_patch_33ff1e26-0e5e-46d8-8052-ab1d032e8b6c +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.115_2026-08-19-09-27-13_patch_4ac728c3-0342-4a36-adbc-e28d2d99b1ba +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.116_2026-08-19-09-30-47_patch_c706fef6-6813-4183-b268-12e7b00d7d0b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.117_2026-08-19-09-39-14_patch_c6b0495f-2f88-4aa8-9ebf-0a235b4c407e +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.118_2026-08-19-09-52-00_patch_b395655a-8d78-4344-9266-6901c20f6517 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.119_2026-08-19-10-22-38_patch_8f95c49d-aedc-41b8-816d-ccb95f048831 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.120_2026-08-19-10-26-58_patch_7fbf35e6-cc01-4b75-8c9a-f5d054bcaf93 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.121_2026-08-19-10-42-02_patch_31a81b02-a886-4dea-84e0-67cc6ca412d5 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.122_2026-08-19-11-16-49_patch_1c4d7307-48d4-493e-936d-80af799d644b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.123_2026-08-19-11-47-32_patch_d3d78d04-9989-45b1-91b1-93b571d8814a +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.124_2026-08-20-08-03-17_patch_57f4c389-2d19-41ce-aca4-13b61c62f387 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.125_2026-08-20-08-25-05_patch_7f368148-0d1c-4525-bbdf-c6d257ad861a +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.126_2026-08-20-14-51-36_patch_a99abcc8-3371-4c63-a759-bb7ea5b32432 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.127_2026-08-21-05-48-58_patch_34b4ccee-7596-4f57-93e9-774973cca58e +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.128_2026-08-21-10-47-20_patch_693112b9-927c-4a8f-8553-b06eef86079d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.129_2026-08-21-11-16-54_patch_7a981666-01d9-4d1b-9ba3-2129744e3bd5 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.130_2026-08-21-13-09-36_patch_b7ad1a76-ce70-4d70-9d1a-7c414eba5bb4 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.131_2026-08-21-14-31-10_patch_9128ef66-193e-4caf-8710-afd86128e638 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.132_2026-08-24-08-59-34_patch_c600fc14-86a5-460f-9c4e-f0177056f756 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.133_2026-08-24-10-28-29_patch_b6ce3e32-9d7b-48ac-981a-270c22c180dd +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.134_2026-08-24-11-00-51_patch_a4fc0484-4a64-46a2-94f8-aa805254c7b0 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.135_2026-08-24-12-12-41_patch_a870a56f-9a65-49eb-92da-f572b26667d8 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.136_2026-08-24-12-42-46_patch_9b399356-6482-4291-8da7-e748a99c4b53 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.137_2026-08-24-12-53-57_patch_f7979348-1910-40cd-a535-90299eca84ee +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.138_2026-08-24-14-36-30_patch_ed0f8750-f663-498b-85e7-0d3f2213fcfe +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.139_2026-08-25-08-37-26_patch_3ba87e19-902b-4f76-b64c-90e5c0ca1fc6 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.140_2026-08-25-09-52-45_patch_abc830f2-df15-4385-b797-cdaf72c10752 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.141_2026-08-25-11-37-20_patch_1d9ec01e-06f6-4c8e-b095-af17d5b62b00 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.142_2026-08-26-07-38-49_patch_3dd23e36-e7df-494c-986f-a412861a8d40 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.143_2026-08-26-09-32-32_patch_7b7ebd34-de27-4b73-98a7-3e1501e16cd5 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.144_2026-08-26-10-56-43_patch_166064f2-2208-4c9b-9e25-25dc4cd32084 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.145_2026-08-26-11-37-29_patch_b997f3ee-d7d3-4408-9f2f-c8b6d08bdb3b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.146_2026-08-26-12-15-20_patch_afbbb893-25db-468c-81db-2663ca373068 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.147_2026-08-26-14-10-50_patch_fd753b1f-2fa1-4ddb-a9e7-de690da85254 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.148_2026-08-27-09-08-35_patch_23814c0b-7f77-489c-b4a8-ceadd18146e3 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.149_2026-08-27-09-40-17_patch_8879d72e-a3d8-4abc-a16a-d9dcf75f0fa1 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.150_2026-08-27-10-57-25_patch_afbe60ed-3e23-4d88-be3c-f800d7002a7d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.151_2026-08-28-09-02-46_patch_1d4ca23b-aeae-4ea8-96b1-8cf57371f29d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.152_2026-08-28-15-37-24_patch_c9d0bdc1-a7e1-432b-92b9-92dc76fe0c78 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.153_2026-08-29-09-03-27_patch_7531573a-1b33-4092-aa9c-0e65f47b201f +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.154_2026-08-29-11-56-35_patch_919f5787-39c8-4dc1-ae6a-f27c28380f21 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.155_2026-08-29-15-15-59_patch_822f9ed8-c366-4e5f-9791-dee8467cf3ce +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.156_2026-08-29-16-19-01_patch_3ac2bf36-20f7-4c9f-9fdb-295d4466d59e +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.157_2026-08-30-17-32-17_patch_4302354c-c9c5-4be7-acd3-542872a748d8 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.158_2026-08-31-09-28-33_patch_3523774f-c25d-4102-8c1a-92fff046a48d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.159_2026-08-31-10-31-01_patch_fe3e6290-2553-4154-a0a0-8b8a418280ed +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.160_2026-08-31-11-23-39_patch_e701a085-3d23-4212-b0af-73b1d419a4c1 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.161_2026-08-31-12-41-01_patch_074d7bde-c493-44db-bc15-e81fd91e2921 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.162_2026-08-31-13-58-06_patch_84db1d60-4280-433b-bd3a-22e5611cd315 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.163_2026-08-31-15-25-54_patch_1931c5ba-73df-48cb-8dcb-555ace0af267 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.163_2026-08-31-15-44-37_patch_3962e805-2a92-494a-a87b-b6e6d66c40a0 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.165_2026-08-31-19-48-59_patch_86e5b923-2b99-4b86-b542-469b197614be +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.166_2026-09-01-07-39-57_patch_c344892f-d542-4e7b-8f27-02365a411e15 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.167_2026-09-01-08-21-53_patch_e199d419-282a-4dbb-8756-cf98b7037e2b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.168_2026-09-01-09-12-31_patch_235c9fe0-da15-431d-bb56-01e2b9b15f4b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.169_2026-09-01-11-54-19_patch_98b617ab-d130-42b5-93f2-19cae56d4c4c +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.170_2026-09-02-09-27-28_patch_e448d2e6-b7ec-4235-96bf-0173b3623c87 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.171_2026-09-02-12-52-44_patch_e6a241c2-1d62-482c-a9eb-9e3373395c50 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.172_2026-09-04-08-47-04_patch_daae079f-c104-4fcd-bb57-7bff68e80ad9 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.173_2026-09-04-12-34-42_patch_399c4cbd-0c28-4dfd-a4ec-e569420a36e4 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.174_2026-09-04-13-08-48_patch_f5cfe3d5-808e-45e4-bafc-00d0554838ee +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.175_2026-09-04-17-20-46_patch_1ef542fa-5d8e-4d90-aa15-9fc4cea3dfec +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.176_2026-09-05-08-25-05_patch_ced5521f-f9da-4640-a921-95fcb5cd2e6d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.177_2026-09-05-09-00-16_patch_803c1ad4-a9af-4953-92c5-d882dec03ea2 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.178_2026-09-05-09-30-34_patch_012f6259-2e3f-4591-9806-1920fd06cb1f +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.179_2026-09-05-09-33-43_patch_f4bdf28c-d584-47a5-b699-8c883330162c +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.180_2026-09-05-12-02-21_patch_34a14b01-d22d-44a8-ac63-be0370a61422 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.181_2026-09-05-12-47-46_patch_56b18867-99f6-4d5c-8215-7b9d60d34010 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.182_2026-09-05-13-35-18_patch_61b7d4d1-73c8-4603-9b0c-593e7405587f +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.183_2026-09-06-07-27-09_patch_d76331b2-e3a3-4c0b-8412-ecd131b6ac02 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.184_2026-09-06-10-21-47_patch_7680b7a1-49f0-4eef-b12e-4c854407448c +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.185_2026-09-06-10-30-40_patch_e56c2183-77f8-44ef-a92e-7377ea6ce8c1 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.186_2026-09-07-10-00-51_patch_67de5683-d208-4bc0-8fb6-7677377908e7 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.187_2026-09-07-10-18-13_patch_2086cee2-276b-48f7-80ce-6a17397b9541 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.188_2026-09-07-12-51-28_patch_d6590822-068f-4a19-814d-34bbf204ba6e +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.189_2026-09-07-12-55-23_patch_7e0fb04b-4d40-4490-974f-c74ba2ae55a1 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.190_2026-09-08-08-58-03_patch_15e3ac1e-4475-4272-bdd8-d00bb0db8f17 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.191_2026-09-08-09-55-58_patch_3d350e50-ee53-4282-bc75-d2251142c46e +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.192_2026-09-08-11-12-21_patch_0733223b-1ae2-4b5b-897f-dfc57574ff83 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.193_2026-09-08-21-48-17_patch_8d07d4e6-3555-4720-85c9-9452570fae2d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.194_2026-09-09-07-53-43_patch_69559429-aa42-4b62-9bd7-cdfded1c00d0 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.195_2026-09-09-09-55-40_patch_bbf67f1d-3b9a-43a2-b1bc-22df3fed8a34 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.196_2026-09-09-09-59-47_patch_70d76812-7b3c-4192-ad49-fcaccc29b0da +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.197_2026-09-09-13-06-06_patch_d455be0b-5421-492a-b952-fab0fd8110f8 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.198_2026-09-09-13-14-34_patch_267f54e5-311e-435e-882f-8e19191325ea +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.199_2026-09-09-22-24-18_patch_81e3e453-ca0e-42fa-9c21-8f94d43c05f2 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.200_2026-09-10-07-19-50_patch_911714fa-1fa3-4165-bfe6-d10c650bf5bf +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.201_2026-09-10-10-14-19_patch_864015f2-b0b0-4563-a1c8-155629cb9126 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.202_2026-09-10-11-00-05_patch_18270ecf-e770-4e69-8bcf-e5143c39929b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.203_2026-09-10-11-10-41_patch_ff273ab1-44f3-4bc0-b184-3396e943df04 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.204_2026-09-10-13-02-02_patch_d4ee41e2-d13c-4941-8605-3f1a42b56b22 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.205_2026-09-10-13-57-50_patch_284df67e-5957-4b0c-bc64-5581db6ddecc +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.206_2026-09-11-10-18-50_patch_1ac7e410-0e62-4eef-bbe4-ebf93c9d0869 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/17.0.207_2026-09-11-15-26-02_major_3f1b3ed7-eaac-41f5-b740-0af3331595d9 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.0_2026-09-12-10-01-10_patch_8995783a-a9fa-4c4e-90b3-6386a4c481eb +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.10_2026-09-14-16-09-38_patch_9403d562-eed0-4125-a8b3-09cd92a13298 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.11_2026-09-15-09-05-57_patch_8b22dba2-d931-4c4d-ae60-db3238d5e73d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.12_2026-09-15-11-18-52_patch_81314afa-e70d-4ad8-b45b-3f8d62b983e7 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.13_2026-09-16-08-00-55_patch_bfa30fc0-3281-4de6-bb56-d7290c98d1c3 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.14_2026-09-16-14-38-26_patch_aae6e9b0-88f4-4bcf-b611-3308c7fcd6eb +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.15_2026-09-17-07-58-54_patch_43d40582-effd-4925-a8bd-e70fecf1faab +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.16_2026-09-17-08-12-37_patch_b4db2d23-88f1-45c1-82d9-78d38014fcb6 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.17_2026-09-18-09-38-19_patch_25697fc3-e9a8-4980-962b-e6cb0a4760c5 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.18_2026-09-18-09-54-33_patch_d37d9c71-c469-4d94-90d7-4898915ee991 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.19_2026-09-18-10-47-33_patch_47607b3c-d1b6-4864-b9b0-00a2a8d2ac32 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.1_2026-09-12-17-33-30_patch_f6ea2c99-a715-4c4d-876a-23ed8c62a83d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.20_2026-09-18-11-07-21_patch_5a336f91-63a6-4877-97ed-da89395cc8f5 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.21_2026-09-18-13-34-52_patch_c56462e1-63d9-498f-a912-c80c5f0171d1 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.22_2026-09-20-08-10-45_patch_6afa2c20-bcef-4b7d-8685-2c9815d8683f +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.23_2026-09-20-08-38-35_patch_a7f169e5-37ab-4ec0-bf89-d14770181303 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.24_2026-09-20-15-49-27_patch_c1222081-ff44-4f20-aea2-5840b6d76efd +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.25_2026-09-21-06-11-40_patch_6df46dd9-e7d3-4e71-bec4-e5c93b4ac863 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.26_2026-09-21-07-54-11_patch_cc52dd36-5eba-4094-a1b0-d6f79f103441 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.27_2026-09-21-08-36-49_patch_a25fa125-9bcd-4317-8da5-851c1c329631 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.28_2026-09-21-09-44-01_patch_4430a721-0b3c-4f6a-b9bc-a53e667161bb +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.29_2026-09-21-10-58-07_patch_83b2b942-60a4-4bef-afd1-99690ba52b69 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.2_2026-09-13-06-36-33_patch_176bb944-1c49-4dd3-a001-8fce908825a0 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.30_2026-09-21-12-51-16_patch_519b9a65-d400-4234-b113-36b46e315507 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.31_2026-09-22-06-53-35_patch_5c45a235-81b6-4d05-801a-07dc7db61400 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.32_2026-09-22-07-42-04_patch_f12c6415-8166-4063-9e5d-26601b929d63 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.33_2026-09-22-08-12-32_patch_cec31bb0-a6cb-43e6-8407-25aba322b54c +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.34_2026-09-23-07-09-16_patch_659fccbb-c0a0-4f6f-bc87-e6abaa8815a7 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.35_2026-09-23-09-38-52_patch_023f904d-807a-4833-8a40-570365e8ec06 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.36_2026-09-23-10-05-33_patch_846fb491-2b1b-47ed-ac1f-ba40e744e199 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.37_2026-09-23-13-08-30_patch_8e4b1d24-156e-4ffe-8e4a-b8740ec18588 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.38_2026-09-24-06-41-37_patch_67adb1d6-3f49-4357-a67f-b1d48f23a972 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.39_2026-09-24-15-24-32_patch_e5dd375d-5643-4514-9b65-8d877c4a2bb2 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.3_2026-09-13-12-32-46_patch_58e5ce3a-f2a7-4789-b2cd-5cc75c72b6ec +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.40_2026-09-24-19-58-14_patch_ff18824b-be51-4a3d-a621-e96279e53c3e +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.41_2026-09-26-09-24-52_patch_b9979267-30f9-440a-a4ce-c611991d4886 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.42_2026-09-28-12-39-34_patch_dda535d9-8922-4eb9-ab51-6ecff0650c10 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.43_2026-09-28-13-35-27_minor_aca1168a-1286-4326-9d0c-2f2587c9fe92 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.4_2026-09-13-12-45-14_patch_b6c79d55-8f85-4f47-a304-df52b122c38c +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.5_2026-09-13-14-11-18_patch_9b111116-5e62-472a-b72c-d1bbafa22c97 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.5_2026-09-13-17-01-11_patch_d4bf61c0-83ac-4dd3-b512-a65805d298c8 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.6_2026-09-14-11-31-04_patch_fd2ebda6-22cb-4e7d-9452-2f6f2640e828 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.7_2026-09-13-17-06-08_patch_428af161-0b27-43c2-8751-e5f7874df120 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.0.9_2026-09-14-12-37-42_patch_b2ca0529-4b67-4fa4-8fdc-5f5e9f5d5166 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.1.0_2026-09-28-14-27-54_patch_324444f7-d24e-4189-b21f-1188894a3109 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/18.1.1_2026-09-28-21-03-07_major_e266a14a-7d96-4ece-92a3-8f34e64438a5 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.0_2026-09-29-11-05-31_patch_77d6f9f8-ead3-4d79-a4b2-b084b2dffc98 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.10_2026-10-02-12-56-52_patch_14e97576-73ca-44b8-82c9-7dad6f1789ab +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.11_2026-10-04-10-31-19_patch_088eb371-1799-4949-a119-286cf1cd55d1 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.12_2026-10-06-18-00-25_patch_36554bed-49c5-41cb-9fd4-48cc6af74c09 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.13_2026-10-07-12-24-08_patch_a540a364-3a0d-4960-b278-06ba2c7cc258 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.14_2026-10-07-12-52-39_patch_e3a6fc5c-2ee4-414c-a2dd-4910a655a7dd +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.15_2026-10-09-04-15-56_patch_bd7a9b06-867b-4fea-9678-973a05e3022d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.16_2026-10-09-16-11-56_patch_a1135435-7dea-4f00-8c98-203ba3974382 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.17_2026-10-09-17-44-55_patch_faeacad8-541a-40f2-ab9c-abcd66fcd00e +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.18_2026-10-10-07-29-38_major_02601a1e-9bdb-45bf-ad67-a07b7dcd0002 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.1_2026-09-29-11-59-38_patch_bbf4753c-d641-4c2f-ac7c-02be6bd8e7c2 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.2_2026-09-29-12-44-07_patch_19fdaa94-60dc-464b-93b8-c17607ebc7b6 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.3_2026-09-29-14-16-00_patch_3cb60272-95cf-4311-8897-721e1b5c2c88 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.4_2026-09-29-16-24-53_patch_9fe8ad2b-e3ec-4558-a5fc-9c44c5c266dc +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.5_2026-09-29-17-13-16_patch_e48d2dd2-f41a-402e-a441-756b23c01dcb +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.6_2026-09-29-17-22-11_patch_3b1c79e9-9002-4e96-ba78-10668c33be6a +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.7_2026-09-30-07-50-58_patch_e8b1f046-d819-499c-9cd5-3e1a20fc9acf +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.8_2026-10-01-13-41-44_patch_7d63af18-e0af-4127-ab58-aede2407490f +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/19.0.9_2026-10-01-15-57-35_patch_143863cb-8f63-4ef7-bd78-c1114fc93a2d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.0_2026-10-10-09-36-17_patch_d2618f39-cdc9-4d3a-ba40-1a0ad6265f3b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.1_2026-10-11-10-24-33_patch_e29a8713-eecb-4eb1-9641-789d3cfab21a +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.2_2026-10-12-07-22-24_patch_f4053ad1-8fcd-4591-a68d-bf1e23485ba7 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.3_2026-10-14-14-29-16_patch_070af1c4-f9d9-4f97-8112-058de90d3ea8 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.4_2026-10-14-16-20-24_patch_c6672844-8227-4e0a-9fb5-36af7e7141dc +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.5_2026-10-15-08-53-28_patch_10154146-8afd-4632-b250-9b4b9f5bf67c +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.6_2026-10-15-14-17-40_patch_df3a5d3c-f0e0-46cb-aeaf-15b51c8a0f13 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/20.0.7_2026-10-16-07-09-40_major_3e5dfba3-2810-47b4-85a9-938bfff72a04 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.0_2026-10-16-10-44-29_patch_1058e453-613f-492b-a3c7-f3ca2abe8c2d +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.1_2026-10-16-16-06-10_patch_e20b4ad2-b87f-478e-b4f4-323c8bcc5ea9 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.2_2026-10-19-13-54-31_patch_bf091df4-00bb-43c8-9117-51047944e305 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.3_2026-10-19-14-58-29_patch_9b985381-1b1d-4531-b242-b02cea2484c5 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.4_2026-10-20-17-08-51_patch_38d02583-cb5c-4adc-b5d7-614b483acf19 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.5_2026-10-21-09-28-47_patch_fabd5cfe-2d04-4215-abf1-58fba226acb7 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.6_2026-10-22-16-07-37_patch_d2bb27d7-6304-4c99-abbc-46d3dd7e363b +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.7_2026-10-27-11-41-55_patch_6b50567f-209d-42c9-a2cd-d251a2bc8fbf +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/21.0.8_2026-10-29-13-48-18_patch_bdab3ee6-fba8-4625-9243-c4cbe839ba32 +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/__init__.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli/version/read_version.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli.egg-info/dependency_links.txt +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli.egg-info/entry_points.txt +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli.egg-info/not-zip-safe +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli.egg-info/requires.txt +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/ellf_cli.egg-info/top_level.txt +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/pyproject.toml +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/setup.cfg +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/setup.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_agents.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_agents_info_stats.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_appdirs.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_auth.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_clusters_info_stats.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_config.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_datasets_export.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_errors.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_files_cp.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_files_cp_helpers.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_helm.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_import_export.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_info.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_config_io.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_configure.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_deploy_node_labels.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_deploy_preflight.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_get_terraform.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_hibernate.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_init.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_pause.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_provision.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_start_fixes.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_state_bucket.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_infra_terraform_init.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_invalid_secrets.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_job_list_project_filter.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_jobs_info_hides_creator.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_jobs_list_unmatched.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_key_pair.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_login.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_logout.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_main.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_mcp_proxy.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_org_select.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_plans.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_projects.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_projects_delete_confirm.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_publish_build_poll.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_publish_data.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_publish_import_root.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_publish_requirements.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_publish_versions.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_pypi_auth.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_query.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_recipe_file.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_recipe_help.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_recipe_required_args.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_recipes.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_recipes_init.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_sessions.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_state.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_support.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_todos.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_ty.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_ui.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_ui_extras.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_usage_counts.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_users_assign.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_users_info_stats.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_users_list.py +0 -0
- {ellf_cli-21.0.9 → ellf_cli-22.0.1}/tests/test_util.py +0 -0
|
@@ -329,23 +329,6 @@ Delete an asset registered with Ellf
|
|
|
329
329
|
| `--cluster` | `str` | Name, slug, or ID of the cluster to search for asset name (or the last cluster if not set) | `None` |
|
|
330
330
|
| `--json` | `bool` | Output the result as JSON | `False` |
|
|
331
331
|
|
|
332
|
-
### `ellf auth`
|
|
333
|
-
|
|
334
|
-
Manage authentication artifacts (import/push device-flow tokens)
|
|
335
|
-
|
|
336
|
-
#### `ellf auth import`
|
|
337
|
-
|
|
338
|
-
Read a serialised FileSecrets blob from stdin and write it to the local secrets file. Counterpart to ``ellf auth push``. Existing local auth state is overwritten; the file is written 0600 by FileSecrets.save.
|
|
339
|
-
|
|
340
|
-
#### `ellf auth push`
|
|
341
|
-
|
|
342
|
-
Push local auth state to a remote machine via SSH. Reads the local FileSecrets, JSON-serialises it, and pipes it to ``<remote_ellf> auth import`` over an SSH connection to *host*. Authentication is delegated to ssh — anything in your ssh config (host aliases, ProxyJump, key-based auth) just works. The pushed blob includes id_token, api_token, and any cached broker_tokens. id_token expiry is dictated by the issuer (typically ~1h), so this is a "give the remote a usable session" operation, not a permanent provisioning. Re-run when the token expires.
|
|
343
|
-
|
|
344
|
-
| Argument | Type | Description | Default |
|
|
345
|
-
| --- | --- | --- | --- |
|
|
346
|
-
| `host` | `str` | SSH host to push the token to | |
|
|
347
|
-
| `--remote-ellf` | `str` | Command to run on the remote (default: 'ellf' from PATH). Pass an absolute path or shell-expanded form when ellf isn't on the remote login shell's PATH, e.g. '$HOME/ellf-test/venv/bin/ellf'. | `None` |
|
|
348
|
-
|
|
349
332
|
### `ellf clusters`
|
|
350
333
|
|
|
351
334
|
Interact with clusters
|
|
@@ -676,12 +659,12 @@ Deploy and manage cluster infrastructure (Kubernetes, TLS, Terraform)
|
|
|
676
659
|
|
|
677
660
|
#### `ellf infra register`
|
|
678
661
|
|
|
679
|
-
Register a new cluster with PAM and write credentials to cluster-creds.json. Pass --domain to use your own DNS, or omit it to be allocated a managed subdomain (with base + wildcard A records) under an Explosion-controlled zone.
|
|
662
|
+
Register a new cluster with PAM and write credentials to cluster-creds.json. Pass --domain to use your own DNS, or omit it to be allocated a managed subdomain (with base + wildcard A records) under an Explosion-controlled zone. An org on the free Solo plan has no managed subdomain: omitting --domain registers it at http://localhost.
|
|
680
663
|
|
|
681
664
|
| Argument | Type | Description | Default |
|
|
682
665
|
| --- | --- | --- | --- |
|
|
683
666
|
| `--name` | `str` | Human-readable name for the cluster | |
|
|
684
|
-
| `--domain` | `str` | Public address the cluster is reached on, host or host:port (e.g. 'cluster.example.com' for a hosted cluster on port 443, or 'localhost
|
|
667
|
+
| `--domain` | `str` | Public address the cluster is reached on, host or host:port (e.g. 'cluster.example.com' for a hosted cluster on port 443, or 'http://localhost' for a cluster on this machine, which needs no certificate and is what the free Solo plan uses). Stored verbatim as the cluster address; the chart derives the bare hostname for K8s ingress / cert SAN where a port isn't allowed. Omit to get a managed subdomain under an Explosion-controlled zone. | `None` |
|
|
685
668
|
| `--subdomain` | `str` | Requested label for a managed subdomain (e.g. 'acme' for acme.<zone>). Only valid without --domain; defaults to a slug derived from your org/cluster name. | `None` |
|
|
686
669
|
| `--public-ip` | `str` | Cluster ingress IP to point the managed subdomain at. Omit to reserve the name now and re-run with --public-ip once the load balancer IP is known. | `None` |
|
|
687
670
|
| `--cloud-provider` | `str` | Cloud provider: gcp, k3s, aws, azure | |
|
|
@@ -727,7 +710,7 @@ Apply terraform to create or update cluster infrastructure. Returns True when an
|
|
|
727
710
|
|
|
728
711
|
#### `ellf infra destroy`
|
|
729
712
|
|
|
730
|
-
Destroy the cluster infrastructure created by 'infra terraform', including every annotation, file and dataset stored on it. The database, data bucket and shared volume are deletion-protected, so this refuses to run without --delete-data. To stop paying for compute while keeping the data, use 'ellf infra pause' instead. With --delete-data, a first apply lifts the protection, then the destroy runs. On AWS the database still leaves a final snapshot behind. Note this never touches the terraform state bucket: the bucket is managed outside the terraform (see 'infra init --state-bucket') and outlives the cluster so the destroy itself has state to work against.
|
|
713
|
+
Destroy the cluster infrastructure created by 'infra terraform', including every annotation, file and dataset stored on it. The database, data bucket and shared volume are deletion-protected, so this refuses to run without --delete-data. To stop paying for compute while keeping the data, use 'ellf infra pause' instead. With --delete-data, a first apply lifts the protection, then the destroy runs, once the broker, its jobs and traefik are removed from the cluster. On AWS the database still leaves a final snapshot behind. Note this never touches the terraform state bucket: the bucket is managed outside the terraform (see 'infra init --state-bucket') and outlives the cluster so the destroy itself has state to work against.
|
|
731
714
|
|
|
732
715
|
| Argument | Type | Description | Default |
|
|
733
716
|
| --- | --- | --- | --- |
|
|
@@ -893,20 +876,6 @@ Start a cluster on infrastructure configured under your own cloud account.
|
|
|
893
876
|
| `--config-key` | `str` | Top-level key for the cluster config. | `None` |
|
|
894
877
|
| `--offline` | `Path` | Path to a credentials JSON file. Deploys without connecting to PAM. | `None` |
|
|
895
878
|
|
|
896
|
-
#### `ellf infra tls`
|
|
897
|
-
|
|
898
|
-
Manage TLS certificates for local cluster access. Use --self-signed when you have direct kubectl access to the cluster. Use --setup HOST to do everything from your laptop over SSH. Use --trust HOST to fetch and install an existing CA from a remote cluster.
|
|
899
|
-
|
|
900
|
-
| Argument | Type | Description | Default |
|
|
901
|
-
| --- | --- | --- | --- |
|
|
902
|
-
| `--self-signed` | `bool` | Create a self-signed CA and certificate | `False` |
|
|
903
|
-
| `--trust` | `str` | SSH host to fetch CA from and install into local trust store | `None` |
|
|
904
|
-
| `--setup` | `str` | SSH host: create certs remotely, then fetch and trust the CA locally | `None` |
|
|
905
|
-
| `--status` | `bool` | Show current TLS configuration | `False` |
|
|
906
|
-
| `--fqdn` | `str` | Certificate FQDN (default: localhost) | `'localhost'` |
|
|
907
|
-
| `--namespace` | `str` | Kubernetes namespace | `'ellf'` |
|
|
908
|
-
| `--output` | `str` | Output format for trust commands: human, json, shell | `'human'` |
|
|
909
|
-
|
|
910
879
|
### `ellf jobs`
|
|
911
880
|
|
|
912
881
|
Run jobs directly on the cluster
|
|
@@ -6,11 +6,10 @@ import truststore
|
|
|
6
6
|
|
|
7
7
|
# Use the OS native trust store (macOS Keychain, /etc/ssl/certs on Linux,
|
|
8
8
|
# Windows certificate store) for every httpx/urllib/requests call this
|
|
9
|
-
# CLI makes — instead of httpx's default certifi bundle
|
|
10
|
-
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# install. No SSL_CERT_FILE, no combined ca.pem, no per-cluster bundle.
|
|
9
|
+
# CLI makes — instead of httpx's default certifi bundle — so a CA the
|
|
10
|
+
# machine already trusts (a corporate proxy's, or a dev stack's) is
|
|
11
|
+
# trusted by the browser, curl and the CLI alike, with no SSL_CERT_FILE
|
|
12
|
+
# or separate bundle to maintain.
|
|
14
13
|
# Must run before any code constructs an ssl.SSLContext, so it sits at
|
|
15
14
|
# module top.
|
|
16
15
|
truststore.inject_into_ssl()
|
|
@@ -560,9 +560,8 @@ class AuthStateImpl:
|
|
|
560
560
|
# lookup is brittle: the registered cluster.address (e.g.
|
|
561
561
|
# 'cluster.example.com' or 'localhost') often doesn't textually
|
|
562
562
|
# match broker_host (e.g. 'https://localhost:8443'), and even
|
|
563
|
-
# canonicalized forms differ when
|
|
564
|
-
#
|
|
565
|
-
# carry. cluster_id is unambiguous.
|
|
563
|
+
# canonicalized forms differ when broker_host carries a port the
|
|
564
|
+
# cluster.address doesn't. cluster_id is unambiguous.
|
|
566
565
|
body: dict[str, str] = {}
|
|
567
566
|
if self._cluster_id is not None:
|
|
568
567
|
body["id"] = str(self._cluster_id)
|
|
@@ -106,7 +106,6 @@ cli.placeholder("actions", description=Messages.doc_actions)
|
|
|
106
106
|
cli.placeholder("todo", description=Messages.doc_todos)
|
|
107
107
|
cli.placeholder("agents", description=Messages.doc_agents)
|
|
108
108
|
cli.placeholder("assets", description=Messages.doc_assets)
|
|
109
|
-
cli.placeholder("auth", description=Messages.doc_auth)
|
|
110
109
|
cli.placeholder("clusters", description=Messages.doc_clusters)
|
|
111
110
|
cli.placeholder("config", description=Messages.doc_config)
|
|
112
111
|
cli.placeholder("datasets", description=Messages.doc_datasets)
|
|
@@ -5,7 +5,7 @@ import json
|
|
|
5
5
|
import subprocess
|
|
6
6
|
import tempfile
|
|
7
7
|
from pathlib import Path
|
|
8
|
-
from typing import Annotated
|
|
8
|
+
from typing import TYPE_CHECKING, Annotated
|
|
9
9
|
from uuid import UUID
|
|
10
10
|
|
|
11
11
|
from pydantic import AliasChoices, BaseModel, Field, StringConstraints
|
|
@@ -14,6 +14,9 @@ from wasabi import msg
|
|
|
14
14
|
from ellf_pam_sdk import Client
|
|
15
15
|
from ellf_pam_sdk.models import ClusterCredentials, ClusterDetail
|
|
16
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from ...cluster_config import ClusterConfig
|
|
19
|
+
|
|
17
20
|
# Matches pam/ellf_pam/config.py's NonEmptyStr convention.
|
|
18
21
|
NonEmptyStr = Annotated[str, StringConstraints(min_length=1)]
|
|
19
22
|
|
|
@@ -146,6 +149,32 @@ def get_cluster_credentials(
|
|
|
146
149
|
)
|
|
147
150
|
|
|
148
151
|
|
|
152
|
+
def use_cluster_credentials(config: "ClusterConfig") -> None:
|
|
153
|
+
"""Point kubectl at the cluster *config* describes."""
|
|
154
|
+
cluster_name = config.deployment.cluster_name
|
|
155
|
+
cloud_provider = config.deployment.cloud_provider
|
|
156
|
+
if cloud_provider == "aws":
|
|
157
|
+
assert config.deployment.aws
|
|
158
|
+
get_cluster_credentials(
|
|
159
|
+
"aws", cluster_name, region=config.deployment.aws.region
|
|
160
|
+
)
|
|
161
|
+
elif cloud_provider == "azure":
|
|
162
|
+
assert config.deployment.azure
|
|
163
|
+
get_cluster_credentials(
|
|
164
|
+
"azure",
|
|
165
|
+
cluster_name,
|
|
166
|
+
resource_group=config.deployment.azure.resource_group,
|
|
167
|
+
)
|
|
168
|
+
else:
|
|
169
|
+
assert config.deployment.gcp
|
|
170
|
+
get_cluster_credentials(
|
|
171
|
+
"gcp",
|
|
172
|
+
cluster_name,
|
|
173
|
+
project=config.deployment.gcp.project,
|
|
174
|
+
zone=config.deployment.gcp.zone,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
149
178
|
def ensure_cluster_keypair(infra_secret_name: str, namespace: str = "ellf") -> str:
|
|
150
179
|
"""Ensure the infra K8s secret has a cluster RSA keypair, return the public PEM.
|
|
151
180
|
|
|
@@ -100,6 +100,12 @@ def deploy(
|
|
|
100
100
|
)
|
|
101
101
|
overrides.image.broker_version = creds.image.broker_version
|
|
102
102
|
overrides.image.cpl_version = creds.image.cpl_version
|
|
103
|
+
# The registry key is PAM's too: each org has its own, which PAM may
|
|
104
|
+
# replace (a leaked key is deleted and the org given a fresh one). The
|
|
105
|
+
# copy init-values saved in values.yaml goes stale when that happens,
|
|
106
|
+
# so always deploy the key PAM hands out now.
|
|
107
|
+
if overrides.secrets is not None:
|
|
108
|
+
overrides.secrets.container_sa_key = creds.secrets.container_sa_key
|
|
103
109
|
# 1. Create namespace
|
|
104
110
|
msg.info(f"Ensuring namespace {namespace}...")
|
|
105
111
|
subprocess.run(
|
|
@@ -169,12 +169,23 @@ def init(
|
|
|
169
169
|
# Stage 1 covers the cloud path; the k3s deployment isn't
|
|
170
170
|
# representable in ClusterConfig yet, so hand over to the documented
|
|
171
171
|
# local flow after registration.
|
|
172
|
+
# A cluster on http://localhost needs no certificate; one on a
|
|
173
|
+
# public domain gets Let's Encrypt through cert-manager.
|
|
174
|
+
if address.startswith("http://"):
|
|
175
|
+
steps = [
|
|
176
|
+
"ellf infra init-values --creds cluster-creds.json "
|
|
177
|
+
f"--cloud-provider k3s --domain {address}",
|
|
178
|
+
]
|
|
179
|
+
else:
|
|
180
|
+
steps = [
|
|
181
|
+
"ellf infra setup --cert-manager",
|
|
182
|
+
"ellf infra init-values --creds cluster-creds.json "
|
|
183
|
+
f"--cloud-provider k3s --domain {address} --acme-email <email>",
|
|
184
|
+
]
|
|
185
|
+
steps.append("ellf infra deploy --values values.yaml --wait")
|
|
172
186
|
msg.info(
|
|
173
187
|
"Local (k3s) cluster registered. Continue with the local flow:\n"
|
|
174
|
-
"
|
|
175
|
-
" ellf infra init-values --creds cluster-creds.json "
|
|
176
|
-
"--cloud-provider k3s --domain <domain>\n"
|
|
177
|
-
" ellf infra deploy --values values.yaml --wait"
|
|
188
|
+
+ "\n".join(f" {step}" for step in steps)
|
|
178
189
|
)
|
|
179
190
|
return
|
|
180
191
|
|
|
@@ -139,10 +139,10 @@ def init_values(
|
|
|
139
139
|
# release registry — but that's a cross-project IAM grant only
|
|
140
140
|
# Explosion can make, so it can't be the general mechanism for a
|
|
141
141
|
# customer-run (BYOC) cluster in their own GCP project. Use the
|
|
142
|
-
# same
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
# registry (
|
|
142
|
+
# same pull secret k3s/aws/azure already rely on instead:
|
|
143
|
+
# container_sa_key below is the org's own registry key from PAM,
|
|
144
|
+
# whose service account carries a reader grant on the release
|
|
145
|
+
# registry (see pam/ellf_pam/registry_keys.py).
|
|
146
146
|
values["imagePullSecrets"] = [{"name": IMAGE_PULL_SECRET_NAME}]
|
|
147
147
|
values["secrets"] = {
|
|
148
148
|
"infraSecretName": "ellf-infra",
|
|
@@ -23,6 +23,11 @@ CLOUD_PROVIDERS = ("gcp", "k3s", "aws", "azure")
|
|
|
23
23
|
PENDING_ADDRESS = "pending.invalid"
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def _org_is_solo(client, org_id) -> bool:
|
|
27
|
+
"""Whether the org is on the free Solo plan, as PAM judges it."""
|
|
28
|
+
return client.org.read(id=org_id).billing_state == "solo"
|
|
29
|
+
|
|
30
|
+
|
|
26
31
|
class Registration(NamedTuple):
|
|
27
32
|
"""Outcome of ensure_registered, consumed by register and infra init."""
|
|
28
33
|
|
|
@@ -43,7 +48,8 @@ class Registration(NamedTuple):
|
|
|
43
48
|
help=(
|
|
44
49
|
"Public address the cluster is reached on, host or host:port "
|
|
45
50
|
"(e.g. 'cluster.example.com' for a hosted cluster on port 443, "
|
|
46
|
-
"or 'localhost
|
|
51
|
+
"or 'http://localhost' for a cluster on this machine, which needs "
|
|
52
|
+
"no certificate and is what the free Solo plan uses). "
|
|
47
53
|
"Stored verbatim as the cluster address; the chart derives the "
|
|
48
54
|
"bare hostname for K8s ingress / cert SAN where a port isn't allowed. "
|
|
49
55
|
"Omit to get a managed subdomain under an Explosion-controlled zone."
|
|
@@ -101,7 +107,8 @@ def register(
|
|
|
101
107
|
|
|
102
108
|
Pass --domain to use your own DNS, or omit it to be allocated a managed
|
|
103
109
|
subdomain (with base + wildcard A records) under an Explosion-controlled
|
|
104
|
-
zone.
|
|
110
|
+
zone. An org on the free Solo plan has no managed subdomain: omitting
|
|
111
|
+
--domain registers it at http://localhost.
|
|
105
112
|
"""
|
|
106
113
|
from .._state import get_auth_state
|
|
107
114
|
|
|
@@ -175,6 +182,12 @@ def ensure_registered(
|
|
|
175
182
|
),
|
|
176
183
|
None,
|
|
177
184
|
)
|
|
185
|
+
# Solo's one cluster is on localhost, and PAM refuses it anything else.
|
|
186
|
+
if domain is None and _org_is_solo(client, org_id):
|
|
187
|
+
msg.info(Messages.T074)
|
|
188
|
+
# Plain http: browsers treat localhost as a secure context, so
|
|
189
|
+
# the cluster needs no certificate.
|
|
190
|
+
domain = "http://localhost"
|
|
178
191
|
# With no --domain, register under a placeholder first; the managed
|
|
179
192
|
# subdomain allocation below replaces it with the real FQDN. On
|
|
180
193
|
# re-registration keep whatever address the cluster already has so an
|
|
@@ -255,8 +268,8 @@ def ensure_registered(
|
|
|
255
268
|
srsly.write_json(creds_path, creds_data)
|
|
256
269
|
# Persist the cluster id locally so subsequent `ellf` commands resolve the
|
|
257
270
|
# cluster identity from saved-defaults instead of looking it up by address
|
|
258
|
-
# (which is brittle when
|
|
259
|
-
#
|
|
271
|
+
# (which is brittle when `broker_host` is spelled differently from the
|
|
272
|
+
# registered domain, e.g. `https://localhost:8443` against `localhost`).
|
|
260
273
|
settings = get_saved_settings()
|
|
261
274
|
prior_cluster_id = settings.cluster_id
|
|
262
275
|
settings.cluster_id = cluster.id
|
|
@@ -24,10 +24,10 @@ from ._helpers import (
|
|
|
24
24
|
ensure_cluster_record,
|
|
25
25
|
ensure_traefik,
|
|
26
26
|
get_cluster_auth,
|
|
27
|
-
get_cluster_credentials,
|
|
28
27
|
get_traefik_lb_address,
|
|
29
28
|
helm_registry_login,
|
|
30
29
|
point_managed_dns,
|
|
30
|
+
use_cluster_credentials,
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
DEFAULT_NAMESPACE = "ellf"
|
|
@@ -62,28 +62,8 @@ def start(
|
|
|
62
62
|
src = Path(src)
|
|
63
63
|
config = load_cluster_config(src, config_path, config_key)
|
|
64
64
|
check_deploy_ready(config)
|
|
65
|
-
cluster_name = config.deployment.cluster_name
|
|
66
65
|
cloud_provider = config.deployment.cloud_provider
|
|
67
|
-
|
|
68
|
-
assert config.deployment.aws
|
|
69
|
-
get_cluster_credentials(
|
|
70
|
-
"aws", cluster_name, region=config.deployment.aws.region
|
|
71
|
-
)
|
|
72
|
-
elif cloud_provider == "azure":
|
|
73
|
-
assert config.deployment.azure
|
|
74
|
-
get_cluster_credentials(
|
|
75
|
-
"azure",
|
|
76
|
-
cluster_name,
|
|
77
|
-
resource_group=config.deployment.azure.resource_group,
|
|
78
|
-
)
|
|
79
|
-
else:
|
|
80
|
-
assert config.deployment.gcp
|
|
81
|
-
get_cluster_credentials(
|
|
82
|
-
"gcp",
|
|
83
|
-
cluster_name,
|
|
84
|
-
project=config.deployment.gcp.project,
|
|
85
|
-
zone=config.deployment.gcp.zone,
|
|
86
|
-
)
|
|
66
|
+
use_cluster_credentials(config)
|
|
87
67
|
public_key = ensure_cluster_keypair(config.deployment.infra_secret_name)
|
|
88
68
|
cluster_detail = None
|
|
89
69
|
dns_client = None
|
|
@@ -7,7 +7,7 @@ import subprocess
|
|
|
7
7
|
import sys
|
|
8
8
|
import tarfile
|
|
9
9
|
from pathlib import Path
|
|
10
|
-
from typing import Optional, Union
|
|
10
|
+
from typing import Callable, Optional, Union
|
|
11
11
|
|
|
12
12
|
from radicli import Arg
|
|
13
13
|
from wasabi import msg
|
|
@@ -495,7 +495,8 @@ def destroy_terraform(
|
|
|
495
495
|
The database, data bucket and shared volume are deletion-protected, so
|
|
496
496
|
this refuses to run without --delete-data. To stop paying for compute
|
|
497
497
|
while keeping the data, use 'ellf infra pause' instead. With
|
|
498
|
-
--delete-data, a first apply lifts the protection, then the destroy runs
|
|
498
|
+
--delete-data, a first apply lifts the protection, then the destroy runs,
|
|
499
|
+
once the broker, its jobs and traefik are removed from the cluster.
|
|
499
500
|
On AWS the database still leaves a final snapshot behind.
|
|
500
501
|
|
|
501
502
|
Note this never touches the terraform state bucket: the bucket is managed
|
|
@@ -537,6 +538,7 @@ def destroy_terraform(
|
|
|
537
538
|
destroy=True,
|
|
538
539
|
prompt="Destroy all listed resources? 'yes' to accept\n",
|
|
539
540
|
auto_accept=yes_tf_auto_accept,
|
|
541
|
+
before_apply=lambda: _clear_cluster_workloads(config),
|
|
540
542
|
):
|
|
541
543
|
msg.warn(
|
|
542
544
|
"Destroy declined, but the deletion protection is lifted. Re-run "
|
|
@@ -555,6 +557,7 @@ def _plan_and_apply(
|
|
|
555
557
|
destroy: bool,
|
|
556
558
|
prompt: str,
|
|
557
559
|
auto_accept: bool,
|
|
560
|
+
before_apply: Optional[Callable[[], None]] = None,
|
|
558
561
|
) -> bool:
|
|
559
562
|
"""Plan, confirm, apply. Returns False when the plan was declined."""
|
|
560
563
|
cmd = ["terraform", "plan"]
|
|
@@ -574,11 +577,59 @@ def _plan_and_apply(
|
|
|
574
577
|
)
|
|
575
578
|
if input(prompt).strip() != "yes":
|
|
576
579
|
return False
|
|
580
|
+
if before_apply is not None:
|
|
581
|
+
before_apply()
|
|
577
582
|
cmd = ["terraform", "apply", "-auto-approve", plan_file]
|
|
578
583
|
_ = subprocess.run(cmd, check=True, text=True, cwd=tf_dir)
|
|
579
584
|
return True
|
|
580
585
|
|
|
581
586
|
|
|
587
|
+
def _clear_cluster_workloads(config: ClusterConfig) -> None:
|
|
588
|
+
"""Remove what 'infra start' and the broker put in the cluster, which
|
|
589
|
+
terraform doesn't manage but its destroy depends on.
|
|
590
|
+
|
|
591
|
+
Every pod in the ellf namespace -- the broker's, and the jobs it runs
|
|
592
|
+
-- mounts the shared volume, and Kubernetes won't delete a PVC that a
|
|
593
|
+
pod still uses, so terraform's destroy of it hangs until it times out.
|
|
594
|
+
Traefik's LoadBalancer Service, deleted along with the cluster, can
|
|
595
|
+
leave its cloud load balancer behind, still billing.
|
|
596
|
+
"""
|
|
597
|
+
from ._helpers import use_cluster_credentials
|
|
598
|
+
from .hibernate import _release_load_balancer
|
|
599
|
+
from .pause import _run
|
|
600
|
+
|
|
601
|
+
if config.deployment.hibernated:
|
|
602
|
+
return
|
|
603
|
+
try:
|
|
604
|
+
use_cluster_credentials(config)
|
|
605
|
+
except subprocess.CalledProcessError as err:
|
|
606
|
+
msg.warn(f"Couldn't reach the cluster ({err}); destroying it as it is.")
|
|
607
|
+
return
|
|
608
|
+
if _helm_release_installed("ellf", "ellf"):
|
|
609
|
+
msg.info("Uninstalling the ellf release")
|
|
610
|
+
_run(["helm", "uninstall", "ellf", "-n", "ellf", "--wait"])
|
|
611
|
+
# Jobs the broker started aren't part of the release, and helm's --wait
|
|
612
|
+
# returns before the pods of the workloads it deleted are gone.
|
|
613
|
+
_run(
|
|
614
|
+
["kubectl", "delete", "deployments,statefulsets,jobs,pods", "--all"]
|
|
615
|
+
+ ["-n", "ellf", "--ignore-not-found", "--wait", "--timeout=10m"]
|
|
616
|
+
)
|
|
617
|
+
if config.deployment.cloud_provider == "gcp":
|
|
618
|
+
_release_load_balancer(config)
|
|
619
|
+
elif _helm_release_installed("traefik", "traefik"):
|
|
620
|
+
msg.info("Uninstalling traefik to release the load balancer")
|
|
621
|
+
_run(["helm", "uninstall", "traefik", "-n", "traefik", "--wait"])
|
|
622
|
+
|
|
623
|
+
|
|
624
|
+
def _helm_release_installed(release: str, namespace: str) -> bool:
|
|
625
|
+
status = subprocess.run(
|
|
626
|
+
["helm", "status", release, "-n", namespace],
|
|
627
|
+
capture_output=True,
|
|
628
|
+
text=True,
|
|
629
|
+
)
|
|
630
|
+
return status.returncode == 0
|
|
631
|
+
|
|
632
|
+
|
|
582
633
|
def _find_csi_filestore(config: ClusterConfig) -> "tuple[str, str] | None":
|
|
583
634
|
"""The (zone, instance) of the GKE shared volume's CSI-provisioned
|
|
584
635
|
Filestore, or None when the cluster has none.
|