ellf-cli 21.0.10__tar.gz → 22.0.2__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.10/ellf_cli.egg-info → ellf_cli-22.0.2}/PKG-INFO +1 -1
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/README.md +3 -34
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/__main__.py +4 -5
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/auth.py +2 -3
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/cli.py +0 -1
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/__init__.py +0 -2
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/__init__.py +0 -1
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/_helpers.py +30 -1
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/init.py +19 -7
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/register.py +22 -4
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/start.py +2 -22
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/terraform.py +53 -2
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf.json +5 -158
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/interactivity.py +1 -1
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/messages.py +5 -3
- ellf_cli-22.0.2/ellf_cli/version/21.0.10_2026-10-30-14-29-34_major_4fd535f6-6e41-4f34-b29c-543e1a9bac51 +3 -0
- ellf_cli-22.0.2/ellf_cli/version/22.0.0_2026-10-30-15-25-42_patch_1f39caf4-aadc-4d26-9124-a854d945b32a +3 -0
- ellf_cli-22.0.2/ellf_cli/version/22.0.1_2026-10-30-17-30-37_patch_4a6e6cfb-d86e-4f1e-84c5-02d4c071f75b +3 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2/ellf_cli.egg-info}/PKG-INFO +1 -1
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli.egg-info/SOURCES.txt +4 -2
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_destroy.py +42 -1
- ellf_cli-22.0.2/tests/test_infra_register.py +67 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_start_validation.py +1 -1
- ellf_cli-21.0.10/ellf_cli/commands/auth.py +0 -122
- ellf_cli-21.0.10/ellf_cli/commands/infra/tls.py +0 -453
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/LICENSE +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/MANIFEST.in +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/__init__.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/about.json +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/about.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/agents.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/appdirs.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/cloud/__init__.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/cloud/gcp.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/cluster_config.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/_cluster_select.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/_org_select.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/_project_scope.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/_recipe_file.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/_recipe_subcommand.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/_state.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/_usage.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/actions.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/agents.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/assets.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/clusters.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/config.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/datasets.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/files/__init__.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/files/cp.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/files/ls.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/files/rm.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/files/rsync.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/files/stats.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/general.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/import_export.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/_config_io.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/configure.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/deploy.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/hibernate.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/init_values.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/pause.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/provision.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/infra/setup.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/jobs.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/mcp.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/packages.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/paths.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/plans.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/projects.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/publish_code.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/publish_data.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/recipes.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/secrets.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/services.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/sessions.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/support.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/tasks.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/todos.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/commands/users.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/config.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/.gitignore +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/render.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/references/annotation_audit.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/references/annotation_audit.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_ellf_annotation_recipes.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_ellf_annotation_recipes.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/references/builtin_prodigy_recipes.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/references/label_schemes.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-annotate/references/label_schemes.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-ask/SKILL.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-handoff/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-monitor/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-monitor/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-monitor/references/annotation_metrics.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-monitor/references/annotation_metrics.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-monitor/references/training_monitoring.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-monitor/references/training_monitoring.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-monitor/scripts.coding/check_training.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-ops/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-ops/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-ops/references.coding/data_infra_cli.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-ops/scripts.coding/run_job.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-patterns/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-patterns/references/pattern_strategies.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_action_recipe.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_agent_recipe.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_blocks_ui.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_correct.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_custom_ui.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_manual.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_pages_ui.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_routing.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_service_recipe.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_task_recipe.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_teach.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/builtin_recipes.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/ellf_recipe_sdk.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/lint_recipe.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/prodigy_recipe_api.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/template_index.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/references/annotation_agents.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/references/consulting_patterns.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/references/explosion_strategy.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/references/jev.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/references/label_schemes.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-project/references/label_schemes.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-support/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-support/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-template/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-template/references/template_format.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-template/scripts/placeholders.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-todo/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/SKILL.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/SKILL.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/config_advanced.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/config_architectures.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/config_training.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/diagnostics.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/evaluation_guide.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/experiment_patterns.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/model_selection.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/training_paradigms.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/training_troubleshooting.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/workflow.assistant.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/references/workflow.coding.md +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ellf_skills/skills/ellf-train/scripts.coding/ellf_logger.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/errors.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/helm.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/key_pair.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/main.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/mcp_proxy.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/pypi_auth.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/query.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/cookiecutter.json +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/.gitignore +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/README.md.tmpl +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements-dev.in +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements.in +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/setup.py.tmpl +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/__init__.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/about.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/__init__.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/example_task.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/testing/__init__.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ty.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/ui.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/url.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/util.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.114_2026-08-19-08-36-57__1a4e37c1-471e-4a81-b4d5-1ffe7dec3a61 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.114_2026-08-19-09-25-21_patch_33ff1e26-0e5e-46d8-8052-ab1d032e8b6c +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.115_2026-08-19-09-27-13_patch_4ac728c3-0342-4a36-adbc-e28d2d99b1ba +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.116_2026-08-19-09-30-47_patch_c706fef6-6813-4183-b268-12e7b00d7d0b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.117_2026-08-19-09-39-14_patch_c6b0495f-2f88-4aa8-9ebf-0a235b4c407e +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.118_2026-08-19-09-52-00_patch_b395655a-8d78-4344-9266-6901c20f6517 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.119_2026-08-19-10-22-38_patch_8f95c49d-aedc-41b8-816d-ccb95f048831 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.120_2026-08-19-10-26-58_patch_7fbf35e6-cc01-4b75-8c9a-f5d054bcaf93 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.121_2026-08-19-10-42-02_patch_31a81b02-a886-4dea-84e0-67cc6ca412d5 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.122_2026-08-19-11-16-49_patch_1c4d7307-48d4-493e-936d-80af799d644b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.123_2026-08-19-11-47-32_patch_d3d78d04-9989-45b1-91b1-93b571d8814a +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.124_2026-08-20-08-03-17_patch_57f4c389-2d19-41ce-aca4-13b61c62f387 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.125_2026-08-20-08-25-05_patch_7f368148-0d1c-4525-bbdf-c6d257ad861a +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.126_2026-08-20-14-51-36_patch_a99abcc8-3371-4c63-a759-bb7ea5b32432 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.127_2026-08-21-05-48-58_patch_34b4ccee-7596-4f57-93e9-774973cca58e +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.128_2026-08-21-10-47-20_patch_693112b9-927c-4a8f-8553-b06eef86079d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.129_2026-08-21-11-16-54_patch_7a981666-01d9-4d1b-9ba3-2129744e3bd5 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.130_2026-08-21-13-09-36_patch_b7ad1a76-ce70-4d70-9d1a-7c414eba5bb4 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.131_2026-08-21-14-31-10_patch_9128ef66-193e-4caf-8710-afd86128e638 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.132_2026-08-24-08-59-34_patch_c600fc14-86a5-460f-9c4e-f0177056f756 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.133_2026-08-24-10-28-29_patch_b6ce3e32-9d7b-48ac-981a-270c22c180dd +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.134_2026-08-24-11-00-51_patch_a4fc0484-4a64-46a2-94f8-aa805254c7b0 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.135_2026-08-24-12-12-41_patch_a870a56f-9a65-49eb-92da-f572b26667d8 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.136_2026-08-24-12-42-46_patch_9b399356-6482-4291-8da7-e748a99c4b53 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.137_2026-08-24-12-53-57_patch_f7979348-1910-40cd-a535-90299eca84ee +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.138_2026-08-24-14-36-30_patch_ed0f8750-f663-498b-85e7-0d3f2213fcfe +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.139_2026-08-25-08-37-26_patch_3ba87e19-902b-4f76-b64c-90e5c0ca1fc6 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.140_2026-08-25-09-52-45_patch_abc830f2-df15-4385-b797-cdaf72c10752 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.141_2026-08-25-11-37-20_patch_1d9ec01e-06f6-4c8e-b095-af17d5b62b00 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.142_2026-08-26-07-38-49_patch_3dd23e36-e7df-494c-986f-a412861a8d40 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.143_2026-08-26-09-32-32_patch_7b7ebd34-de27-4b73-98a7-3e1501e16cd5 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.144_2026-08-26-10-56-43_patch_166064f2-2208-4c9b-9e25-25dc4cd32084 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.145_2026-08-26-11-37-29_patch_b997f3ee-d7d3-4408-9f2f-c8b6d08bdb3b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.146_2026-08-26-12-15-20_patch_afbbb893-25db-468c-81db-2663ca373068 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.147_2026-08-26-14-10-50_patch_fd753b1f-2fa1-4ddb-a9e7-de690da85254 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.148_2026-08-27-09-08-35_patch_23814c0b-7f77-489c-b4a8-ceadd18146e3 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.149_2026-08-27-09-40-17_patch_8879d72e-a3d8-4abc-a16a-d9dcf75f0fa1 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.150_2026-08-27-10-57-25_patch_afbe60ed-3e23-4d88-be3c-f800d7002a7d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.151_2026-08-28-09-02-46_patch_1d4ca23b-aeae-4ea8-96b1-8cf57371f29d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.152_2026-08-28-15-37-24_patch_c9d0bdc1-a7e1-432b-92b9-92dc76fe0c78 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.153_2026-08-29-09-03-27_patch_7531573a-1b33-4092-aa9c-0e65f47b201f +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.154_2026-08-29-11-56-35_patch_919f5787-39c8-4dc1-ae6a-f27c28380f21 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.155_2026-08-29-15-15-59_patch_822f9ed8-c366-4e5f-9791-dee8467cf3ce +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.156_2026-08-29-16-19-01_patch_3ac2bf36-20f7-4c9f-9fdb-295d4466d59e +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.157_2026-08-30-17-32-17_patch_4302354c-c9c5-4be7-acd3-542872a748d8 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.158_2026-08-31-09-28-33_patch_3523774f-c25d-4102-8c1a-92fff046a48d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.159_2026-08-31-10-31-01_patch_fe3e6290-2553-4154-a0a0-8b8a418280ed +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.160_2026-08-31-11-23-39_patch_e701a085-3d23-4212-b0af-73b1d419a4c1 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.161_2026-08-31-12-41-01_patch_074d7bde-c493-44db-bc15-e81fd91e2921 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.162_2026-08-31-13-58-06_patch_84db1d60-4280-433b-bd3a-22e5611cd315 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.163_2026-08-31-15-25-54_patch_1931c5ba-73df-48cb-8dcb-555ace0af267 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.163_2026-08-31-15-44-37_patch_3962e805-2a92-494a-a87b-b6e6d66c40a0 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.165_2026-08-31-19-48-59_patch_86e5b923-2b99-4b86-b542-469b197614be +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.166_2026-09-01-07-39-57_patch_c344892f-d542-4e7b-8f27-02365a411e15 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.167_2026-09-01-08-21-53_patch_e199d419-282a-4dbb-8756-cf98b7037e2b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.168_2026-09-01-09-12-31_patch_235c9fe0-da15-431d-bb56-01e2b9b15f4b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.169_2026-09-01-11-54-19_patch_98b617ab-d130-42b5-93f2-19cae56d4c4c +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.170_2026-09-02-09-27-28_patch_e448d2e6-b7ec-4235-96bf-0173b3623c87 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.171_2026-09-02-12-52-44_patch_e6a241c2-1d62-482c-a9eb-9e3373395c50 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.172_2026-09-04-08-47-04_patch_daae079f-c104-4fcd-bb57-7bff68e80ad9 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.173_2026-09-04-12-34-42_patch_399c4cbd-0c28-4dfd-a4ec-e569420a36e4 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.174_2026-09-04-13-08-48_patch_f5cfe3d5-808e-45e4-bafc-00d0554838ee +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.175_2026-09-04-17-20-46_patch_1ef542fa-5d8e-4d90-aa15-9fc4cea3dfec +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.176_2026-09-05-08-25-05_patch_ced5521f-f9da-4640-a921-95fcb5cd2e6d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.177_2026-09-05-09-00-16_patch_803c1ad4-a9af-4953-92c5-d882dec03ea2 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.178_2026-09-05-09-30-34_patch_012f6259-2e3f-4591-9806-1920fd06cb1f +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.179_2026-09-05-09-33-43_patch_f4bdf28c-d584-47a5-b699-8c883330162c +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.180_2026-09-05-12-02-21_patch_34a14b01-d22d-44a8-ac63-be0370a61422 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.181_2026-09-05-12-47-46_patch_56b18867-99f6-4d5c-8215-7b9d60d34010 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.182_2026-09-05-13-35-18_patch_61b7d4d1-73c8-4603-9b0c-593e7405587f +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.183_2026-09-06-07-27-09_patch_d76331b2-e3a3-4c0b-8412-ecd131b6ac02 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.184_2026-09-06-10-21-47_patch_7680b7a1-49f0-4eef-b12e-4c854407448c +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.185_2026-09-06-10-30-40_patch_e56c2183-77f8-44ef-a92e-7377ea6ce8c1 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.186_2026-09-07-10-00-51_patch_67de5683-d208-4bc0-8fb6-7677377908e7 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.187_2026-09-07-10-18-13_patch_2086cee2-276b-48f7-80ce-6a17397b9541 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.188_2026-09-07-12-51-28_patch_d6590822-068f-4a19-814d-34bbf204ba6e +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.189_2026-09-07-12-55-23_patch_7e0fb04b-4d40-4490-974f-c74ba2ae55a1 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.190_2026-09-08-08-58-03_patch_15e3ac1e-4475-4272-bdd8-d00bb0db8f17 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.191_2026-09-08-09-55-58_patch_3d350e50-ee53-4282-bc75-d2251142c46e +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.192_2026-09-08-11-12-21_patch_0733223b-1ae2-4b5b-897f-dfc57574ff83 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.193_2026-09-08-21-48-17_patch_8d07d4e6-3555-4720-85c9-9452570fae2d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.194_2026-09-09-07-53-43_patch_69559429-aa42-4b62-9bd7-cdfded1c00d0 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.195_2026-09-09-09-55-40_patch_bbf67f1d-3b9a-43a2-b1bc-22df3fed8a34 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.196_2026-09-09-09-59-47_patch_70d76812-7b3c-4192-ad49-fcaccc29b0da +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.197_2026-09-09-13-06-06_patch_d455be0b-5421-492a-b952-fab0fd8110f8 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.198_2026-09-09-13-14-34_patch_267f54e5-311e-435e-882f-8e19191325ea +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.199_2026-09-09-22-24-18_patch_81e3e453-ca0e-42fa-9c21-8f94d43c05f2 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.200_2026-09-10-07-19-50_patch_911714fa-1fa3-4165-bfe6-d10c650bf5bf +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.201_2026-09-10-10-14-19_patch_864015f2-b0b0-4563-a1c8-155629cb9126 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.202_2026-09-10-11-00-05_patch_18270ecf-e770-4e69-8bcf-e5143c39929b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.203_2026-09-10-11-10-41_patch_ff273ab1-44f3-4bc0-b184-3396e943df04 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.204_2026-09-10-13-02-02_patch_d4ee41e2-d13c-4941-8605-3f1a42b56b22 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.205_2026-09-10-13-57-50_patch_284df67e-5957-4b0c-bc64-5581db6ddecc +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.206_2026-09-11-10-18-50_patch_1ac7e410-0e62-4eef-bbe4-ebf93c9d0869 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/17.0.207_2026-09-11-15-26-02_major_3f1b3ed7-eaac-41f5-b740-0af3331595d9 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.0_2026-09-12-10-01-10_patch_8995783a-a9fa-4c4e-90b3-6386a4c481eb +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.10_2026-09-14-16-09-38_patch_9403d562-eed0-4125-a8b3-09cd92a13298 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.11_2026-09-15-09-05-57_patch_8b22dba2-d931-4c4d-ae60-db3238d5e73d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.12_2026-09-15-11-18-52_patch_81314afa-e70d-4ad8-b45b-3f8d62b983e7 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.13_2026-09-16-08-00-55_patch_bfa30fc0-3281-4de6-bb56-d7290c98d1c3 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.14_2026-09-16-14-38-26_patch_aae6e9b0-88f4-4bcf-b611-3308c7fcd6eb +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.15_2026-09-17-07-58-54_patch_43d40582-effd-4925-a8bd-e70fecf1faab +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.16_2026-09-17-08-12-37_patch_b4db2d23-88f1-45c1-82d9-78d38014fcb6 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.17_2026-09-18-09-38-19_patch_25697fc3-e9a8-4980-962b-e6cb0a4760c5 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.18_2026-09-18-09-54-33_patch_d37d9c71-c469-4d94-90d7-4898915ee991 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.19_2026-09-18-10-47-33_patch_47607b3c-d1b6-4864-b9b0-00a2a8d2ac32 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.1_2026-09-12-17-33-30_patch_f6ea2c99-a715-4c4d-876a-23ed8c62a83d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.20_2026-09-18-11-07-21_patch_5a336f91-63a6-4877-97ed-da89395cc8f5 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.21_2026-09-18-13-34-52_patch_c56462e1-63d9-498f-a912-c80c5f0171d1 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.22_2026-09-20-08-10-45_patch_6afa2c20-bcef-4b7d-8685-2c9815d8683f +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.23_2026-09-20-08-38-35_patch_a7f169e5-37ab-4ec0-bf89-d14770181303 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.24_2026-09-20-15-49-27_patch_c1222081-ff44-4f20-aea2-5840b6d76efd +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.25_2026-09-21-06-11-40_patch_6df46dd9-e7d3-4e71-bec4-e5c93b4ac863 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.26_2026-09-21-07-54-11_patch_cc52dd36-5eba-4094-a1b0-d6f79f103441 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.27_2026-09-21-08-36-49_patch_a25fa125-9bcd-4317-8da5-851c1c329631 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.28_2026-09-21-09-44-01_patch_4430a721-0b3c-4f6a-b9bc-a53e667161bb +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.29_2026-09-21-10-58-07_patch_83b2b942-60a4-4bef-afd1-99690ba52b69 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.2_2026-09-13-06-36-33_patch_176bb944-1c49-4dd3-a001-8fce908825a0 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.30_2026-09-21-12-51-16_patch_519b9a65-d400-4234-b113-36b46e315507 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.31_2026-09-22-06-53-35_patch_5c45a235-81b6-4d05-801a-07dc7db61400 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.32_2026-09-22-07-42-04_patch_f12c6415-8166-4063-9e5d-26601b929d63 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.33_2026-09-22-08-12-32_patch_cec31bb0-a6cb-43e6-8407-25aba322b54c +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.34_2026-09-23-07-09-16_patch_659fccbb-c0a0-4f6f-bc87-e6abaa8815a7 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.35_2026-09-23-09-38-52_patch_023f904d-807a-4833-8a40-570365e8ec06 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.36_2026-09-23-10-05-33_patch_846fb491-2b1b-47ed-ac1f-ba40e744e199 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.37_2026-09-23-13-08-30_patch_8e4b1d24-156e-4ffe-8e4a-b8740ec18588 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.38_2026-09-24-06-41-37_patch_67adb1d6-3f49-4357-a67f-b1d48f23a972 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.39_2026-09-24-15-24-32_patch_e5dd375d-5643-4514-9b65-8d877c4a2bb2 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.3_2026-09-13-12-32-46_patch_58e5ce3a-f2a7-4789-b2cd-5cc75c72b6ec +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.40_2026-09-24-19-58-14_patch_ff18824b-be51-4a3d-a621-e96279e53c3e +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.41_2026-09-26-09-24-52_patch_b9979267-30f9-440a-a4ce-c611991d4886 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.42_2026-09-28-12-39-34_patch_dda535d9-8922-4eb9-ab51-6ecff0650c10 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.43_2026-09-28-13-35-27_minor_aca1168a-1286-4326-9d0c-2f2587c9fe92 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.4_2026-09-13-12-45-14_patch_b6c79d55-8f85-4f47-a304-df52b122c38c +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.5_2026-09-13-14-11-18_patch_9b111116-5e62-472a-b72c-d1bbafa22c97 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.5_2026-09-13-17-01-11_patch_d4bf61c0-83ac-4dd3-b512-a65805d298c8 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.6_2026-09-14-11-31-04_patch_fd2ebda6-22cb-4e7d-9452-2f6f2640e828 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.7_2026-09-13-17-06-08_patch_428af161-0b27-43c2-8751-e5f7874df120 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.0.9_2026-09-14-12-37-42_patch_b2ca0529-4b67-4fa4-8fdc-5f5e9f5d5166 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.1.0_2026-09-28-14-27-54_patch_324444f7-d24e-4189-b21f-1188894a3109 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/18.1.1_2026-09-28-21-03-07_major_e266a14a-7d96-4ece-92a3-8f34e64438a5 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.0_2026-09-29-11-05-31_patch_77d6f9f8-ead3-4d79-a4b2-b084b2dffc98 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.10_2026-10-02-12-56-52_patch_14e97576-73ca-44b8-82c9-7dad6f1789ab +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.11_2026-10-04-10-31-19_patch_088eb371-1799-4949-a119-286cf1cd55d1 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.12_2026-10-06-18-00-25_patch_36554bed-49c5-41cb-9fd4-48cc6af74c09 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.13_2026-10-07-12-24-08_patch_a540a364-3a0d-4960-b278-06ba2c7cc258 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.14_2026-10-07-12-52-39_patch_e3a6fc5c-2ee4-414c-a2dd-4910a655a7dd +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.15_2026-10-09-04-15-56_patch_bd7a9b06-867b-4fea-9678-973a05e3022d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.16_2026-10-09-16-11-56_patch_a1135435-7dea-4f00-8c98-203ba3974382 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.17_2026-10-09-17-44-55_patch_faeacad8-541a-40f2-ab9c-abcd66fcd00e +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.18_2026-10-10-07-29-38_major_02601a1e-9bdb-45bf-ad67-a07b7dcd0002 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.1_2026-09-29-11-59-38_patch_bbf4753c-d641-4c2f-ac7c-02be6bd8e7c2 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.2_2026-09-29-12-44-07_patch_19fdaa94-60dc-464b-93b8-c17607ebc7b6 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.3_2026-09-29-14-16-00_patch_3cb60272-95cf-4311-8897-721e1b5c2c88 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.4_2026-09-29-16-24-53_patch_9fe8ad2b-e3ec-4558-a5fc-9c44c5c266dc +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.5_2026-09-29-17-13-16_patch_e48d2dd2-f41a-402e-a441-756b23c01dcb +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.6_2026-09-29-17-22-11_patch_3b1c79e9-9002-4e96-ba78-10668c33be6a +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.7_2026-09-30-07-50-58_patch_e8b1f046-d819-499c-9cd5-3e1a20fc9acf +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.8_2026-10-01-13-41-44_patch_7d63af18-e0af-4127-ab58-aede2407490f +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/19.0.9_2026-10-01-15-57-35_patch_143863cb-8f63-4ef7-bd78-c1114fc93a2d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.0_2026-10-10-09-36-17_patch_d2618f39-cdc9-4d3a-ba40-1a0ad6265f3b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.1_2026-10-11-10-24-33_patch_e29a8713-eecb-4eb1-9641-789d3cfab21a +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.2_2026-10-12-07-22-24_patch_f4053ad1-8fcd-4591-a68d-bf1e23485ba7 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.3_2026-10-14-14-29-16_patch_070af1c4-f9d9-4f97-8112-058de90d3ea8 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.4_2026-10-14-16-20-24_patch_c6672844-8227-4e0a-9fb5-36af7e7141dc +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.5_2026-10-15-08-53-28_patch_10154146-8afd-4632-b250-9b4b9f5bf67c +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.6_2026-10-15-14-17-40_patch_df3a5d3c-f0e0-46cb-aeaf-15b51c8a0f13 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/20.0.7_2026-10-16-07-09-40_major_3e5dfba3-2810-47b4-85a9-938bfff72a04 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.0_2026-10-16-10-44-29_patch_1058e453-613f-492b-a3c7-f3ca2abe8c2d +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.1_2026-10-16-16-06-10_patch_e20b4ad2-b87f-478e-b4f4-323c8bcc5ea9 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.2_2026-10-19-13-54-31_patch_bf091df4-00bb-43c8-9117-51047944e305 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.3_2026-10-19-14-58-29_patch_9b985381-1b1d-4531-b242-b02cea2484c5 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.4_2026-10-20-17-08-51_patch_38d02583-cb5c-4adc-b5d7-614b483acf19 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.5_2026-10-21-09-28-47_patch_fabd5cfe-2d04-4215-abf1-58fba226acb7 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.6_2026-10-22-16-07-37_patch_d2bb27d7-6304-4c99-abbc-46d3dd7e363b +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.7_2026-10-27-11-41-55_patch_6b50567f-209d-42c9-a2cd-d251a2bc8fbf +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.8_2026-10-29-13-48-18_patch_bdab3ee6-fba8-4625-9243-c4cbe839ba32 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/21.0.9_2026-10-29-17-51-00_patch_803a4c70-2e2b-4024-8598-c7d91c9db0d2 +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/__init__.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli/version/read_version.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli.egg-info/dependency_links.txt +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli.egg-info/entry_points.txt +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli.egg-info/not-zip-safe +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli.egg-info/requires.txt +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/ellf_cli.egg-info/top_level.txt +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/pyproject.toml +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/setup.cfg +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/setup.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_agents.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_agents_info_stats.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_appdirs.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_auth.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_clusters_info_stats.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_config.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_datasets_export.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_errors.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_files_cp.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_files_cp_helpers.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_helm.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_import_export.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_info.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_config_io.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_configure.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_deploy_node_labels.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_deploy_preflight.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_deploy_registry_key.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_get_terraform.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_hibernate.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_init.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_pause.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_provision.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_start_fixes.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_state_bucket.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_infra_terraform_init.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_invalid_secrets.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_job_list_project_filter.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_jobs_info_hides_creator.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_jobs_list_unmatched.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_key_pair.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_login.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_logout.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_main.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_mcp_proxy.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_org_select.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_plans.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_projects.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_projects_delete_confirm.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_publish_build_poll.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_publish_data.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_publish_import_root.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_publish_requirements.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_publish_versions.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_pypi_auth.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_query.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_recipe_file.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_recipe_help.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_recipe_required_args.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_recipes.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_recipes_init.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_sessions.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_state.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_support.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_todos.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_ty.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_ui.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_ui_extras.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_usage_counts.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_users_assign.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_users_info_stats.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/tests/test_users_list.py +0 -0
- {ellf_cli-21.0.10 → ellf_cli-22.0.2}/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
|
|
|
@@ -169,13 +169,25 @@ 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
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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")
|
|
186
|
+
msg.info("Local (k3s) cluster registered. Continue with the local flow:")
|
|
187
|
+
# Plain prints: wasabi re-wraps its messages, which ran the steps
|
|
188
|
+
# together into one paragraph.
|
|
189
|
+
for step in steps:
|
|
190
|
+
print(f" {step}")
|
|
179
191
|
return
|
|
180
192
|
|
|
181
193
|
# --- 2. Terraform files -------------------------------------------------
|
|
@@ -13,6 +13,7 @@ from ellf_pam_sdk.models import ClusterCreating, ClusterUpdating
|
|
|
13
13
|
|
|
14
14
|
from ...cli import cli
|
|
15
15
|
from ...messages import Messages
|
|
16
|
+
from ...util import URL
|
|
16
17
|
from ._helpers import ClusterCredsFile
|
|
17
18
|
|
|
18
19
|
CLOUD_PROVIDERS = ("gcp", "k3s", "aws", "azure")
|
|
@@ -23,6 +24,11 @@ CLOUD_PROVIDERS = ("gcp", "k3s", "aws", "azure")
|
|
|
23
24
|
PENDING_ADDRESS = "pending.invalid"
|
|
24
25
|
|
|
25
26
|
|
|
27
|
+
def _org_is_solo(client, org_id) -> bool:
|
|
28
|
+
"""Whether the org is on the free Solo plan, as PAM judges it."""
|
|
29
|
+
return client.org.read(id=org_id).billing_state == "solo"
|
|
30
|
+
|
|
31
|
+
|
|
26
32
|
class Registration(NamedTuple):
|
|
27
33
|
"""Outcome of ensure_registered, consumed by register and infra init."""
|
|
28
34
|
|
|
@@ -43,7 +49,8 @@ class Registration(NamedTuple):
|
|
|
43
49
|
help=(
|
|
44
50
|
"Public address the cluster is reached on, host or host:port "
|
|
45
51
|
"(e.g. 'cluster.example.com' for a hosted cluster on port 443, "
|
|
46
|
-
"or 'localhost
|
|
52
|
+
"or 'http://localhost' for a cluster on this machine, which needs "
|
|
53
|
+
"no certificate and is what the free Solo plan uses). "
|
|
47
54
|
"Stored verbatim as the cluster address; the chart derives the "
|
|
48
55
|
"bare hostname for K8s ingress / cert SAN where a port isn't allowed. "
|
|
49
56
|
"Omit to get a managed subdomain under an Explosion-controlled zone."
|
|
@@ -101,7 +108,8 @@ def register(
|
|
|
101
108
|
|
|
102
109
|
Pass --domain to use your own DNS, or omit it to be allocated a managed
|
|
103
110
|
subdomain (with base + wildcard A records) under an Explosion-controlled
|
|
104
|
-
zone.
|
|
111
|
+
zone. An org on the free Solo plan has no managed subdomain: omitting
|
|
112
|
+
--domain registers it at http://localhost.
|
|
105
113
|
"""
|
|
106
114
|
from .._state import get_auth_state
|
|
107
115
|
|
|
@@ -175,6 +183,12 @@ def ensure_registered(
|
|
|
175
183
|
),
|
|
176
184
|
None,
|
|
177
185
|
)
|
|
186
|
+
# Solo's one cluster is on localhost, and PAM refuses it anything else.
|
|
187
|
+
if domain is None and _org_is_solo(client, org_id):
|
|
188
|
+
msg.info(Messages.T074)
|
|
189
|
+
# Plain http: browsers treat localhost as a secure context, so
|
|
190
|
+
# the cluster needs no certificate.
|
|
191
|
+
domain = "http://localhost"
|
|
178
192
|
# With no --domain, register under a placeholder first; the managed
|
|
179
193
|
# subdomain allocation below replaces it with the real FQDN. On
|
|
180
194
|
# re-registration keep whatever address the cluster already has so an
|
|
@@ -255,11 +269,15 @@ def ensure_registered(
|
|
|
255
269
|
srsly.write_json(creds_path, creds_data)
|
|
256
270
|
# Persist the cluster id locally so subsequent `ellf` commands resolve the
|
|
257
271
|
# cluster identity from saved-defaults instead of looking it up by address
|
|
258
|
-
# (which is brittle when
|
|
259
|
-
#
|
|
272
|
+
# (which is brittle when `broker_host` is spelled differently from the
|
|
273
|
+
# registered domain, e.g. `https://localhost:8443` against `localhost`).
|
|
274
|
+
# The broker host goes with it, as `clusters use` saves them: a host left
|
|
275
|
+
# over from another cluster would send this cluster's token exchange to
|
|
276
|
+
# that one, which refuses it.
|
|
260
277
|
settings = get_saved_settings()
|
|
261
278
|
prior_cluster_id = settings.cluster_id
|
|
262
279
|
settings.cluster_id = cluster.id
|
|
280
|
+
settings.broker_host = str(URL.parse(allocated_fqdn or address))
|
|
263
281
|
settings.save(get_root_cfg().saved_settings_path)
|
|
264
282
|
# Any cached cluster access token from a previous cluster_id is now stale.
|
|
265
283
|
# The cache is keyed by broker_host; if the cluster behind that host has
|
|
@@ -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.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"prog": "ellf",
|
|
3
3
|
"help": "Ellf Command Line Interface.",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "22.0.2",
|
|
5
5
|
"extra_key": "_extra",
|
|
6
6
|
"commands": {
|
|
7
7
|
"actions": {
|
|
@@ -36,14 +36,6 @@
|
|
|
36
36
|
"parent": null,
|
|
37
37
|
"is_placeholder": true
|
|
38
38
|
},
|
|
39
|
-
"auth": {
|
|
40
|
-
"name": "auth",
|
|
41
|
-
"args": [],
|
|
42
|
-
"description": "Manage authentication artifacts (import/push device-flow tokens)",
|
|
43
|
-
"allow_extra": false,
|
|
44
|
-
"parent": null,
|
|
45
|
-
"is_placeholder": true
|
|
46
|
-
},
|
|
47
39
|
"clusters": {
|
|
48
40
|
"name": "clusters",
|
|
49
41
|
"args": [],
|
|
@@ -1968,51 +1960,6 @@
|
|
|
1968
1960
|
"is_placeholder": false
|
|
1969
1961
|
}
|
|
1970
1962
|
},
|
|
1971
|
-
"auth": {
|
|
1972
|
-
"import": {
|
|
1973
|
-
"name": "import",
|
|
1974
|
-
"args": [],
|
|
1975
|
-
"description": "Read a serialised FileSecrets blob from stdin and write it to\nthe local secrets file.\n\nCounterpart to ``ellf auth push``. Existing local auth state is\noverwritten; the file is written 0600 by FileSecrets.save.\n",
|
|
1976
|
-
"allow_extra": false,
|
|
1977
|
-
"parent": "auth",
|
|
1978
|
-
"is_placeholder": false
|
|
1979
|
-
},
|
|
1980
|
-
"push": {
|
|
1981
|
-
"name": "push",
|
|
1982
|
-
"args": [
|
|
1983
|
-
{
|
|
1984
|
-
"id": "host",
|
|
1985
|
-
"option": null,
|
|
1986
|
-
"short": null,
|
|
1987
|
-
"orig_help": "SSH host to push the token to",
|
|
1988
|
-
"default": "==SUPPRESS==",
|
|
1989
|
-
"help": "SSH host to push the token to (str)",
|
|
1990
|
-
"action": null,
|
|
1991
|
-
"choices": null,
|
|
1992
|
-
"has_converter": false,
|
|
1993
|
-
"type": "str",
|
|
1994
|
-
"orig_type": "str"
|
|
1995
|
-
},
|
|
1996
|
-
{
|
|
1997
|
-
"id": "remote_ellf",
|
|
1998
|
-
"option": "--remote-ellf",
|
|
1999
|
-
"short": null,
|
|
2000
|
-
"orig_help": "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'.",
|
|
2001
|
-
"default": null,
|
|
2002
|
-
"help": "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'. (str)",
|
|
2003
|
-
"action": null,
|
|
2004
|
-
"choices": null,
|
|
2005
|
-
"has_converter": false,
|
|
2006
|
-
"type": "str",
|
|
2007
|
-
"orig_type": "str"
|
|
2008
|
-
}
|
|
2009
|
-
],
|
|
2010
|
-
"description": "Push local auth state to a remote machine via SSH.\n\nReads the local FileSecrets, JSON-serialises it, and pipes it to\n``<remote_ellf> auth import`` over an SSH connection to *host*.\nAuthentication is delegated to ssh \u2014 anything in your ssh config\n(host aliases, ProxyJump, key-based auth) just works.\n\nThe pushed blob includes id_token, api_token, and any cached\nbroker_tokens. id_token expiry is dictated by the issuer (typically\n~1h), so this is a \"give the remote a usable session\" operation,\nnot a permanent provisioning. Re-run when the token expires.\n",
|
|
2011
|
-
"allow_extra": false,
|
|
2012
|
-
"parent": "auth",
|
|
2013
|
-
"is_placeholder": false
|
|
2014
|
-
}
|
|
2015
|
-
},
|
|
2016
1963
|
"clusters": {
|
|
2017
1964
|
"list": {
|
|
2018
1965
|
"name": "list",
|
|
@@ -3616,9 +3563,9 @@
|
|
|
3616
3563
|
"id": "domain",
|
|
3617
3564
|
"option": "--domain",
|
|
3618
3565
|
"short": null,
|
|
3619
|
-
"orig_help": "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
|
|
3566
|
+
"orig_help": "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.",
|
|
3620
3567
|
"default": null,
|
|
3621
|
-
"help": "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
|
|
3568
|
+
"help": "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. (str)",
|
|
3622
3569
|
"action": null,
|
|
3623
3570
|
"choices": null,
|
|
3624
3571
|
"has_converter": false,
|
|
@@ -3704,7 +3651,7 @@
|
|
|
3704
3651
|
"orig_type": "bool"
|
|
3705
3652
|
}
|
|
3706
3653
|
],
|
|
3707
|
-
"description": "Register a new cluster with PAM and write credentials to cluster-creds.json.\n\nPass --domain to use your own DNS, or omit it to be allocated a managed\nsubdomain (with base + wildcard A records) under an Explosion-controlled\nzone.\n",
|
|
3654
|
+
"description": "Register a new cluster with PAM and write credentials to cluster-creds.json.\n\nPass --domain to use your own DNS, or omit it to be allocated a managed\nsubdomain (with base + wildcard A records) under an Explosion-controlled\nzone. An org on the free Solo plan has no managed subdomain: omitting\n--domain registers it at http://localhost.\n",
|
|
3708
3655
|
"allow_extra": false,
|
|
3709
3656
|
"parent": "infra",
|
|
3710
3657
|
"is_placeholder": false
|
|
@@ -4000,7 +3947,7 @@
|
|
|
4000
3947
|
"orig_type": "bool"
|
|
4001
3948
|
}
|
|
4002
3949
|
],
|
|
4003
|
-
"description": "Destroy the cluster infrastructure created by 'infra terraform',\nincluding every annotation, file and dataset stored on it.\n\nThe database, data bucket and shared volume are deletion-protected, so\nthis refuses to run without --delete-data. To stop paying for compute\nwhile keeping the data, use 'ellf infra pause' instead. With\n--delete-data, a first apply lifts the protection, then the destroy runs.\nOn AWS the database still leaves a final snapshot behind.\n\nNote this never touches the terraform state bucket: the bucket is managed\noutside the terraform (see 'infra init --state-bucket') and outlives the\ncluster so the destroy itself has state to work against.\n",
|
|
3950
|
+
"description": "Destroy the cluster infrastructure created by 'infra terraform',\nincluding every annotation, file and dataset stored on it.\n\nThe database, data bucket and shared volume are deletion-protected, so\nthis refuses to run without --delete-data. To stop paying for compute\nwhile keeping the data, use 'ellf infra pause' instead. With\n--delete-data, a first apply lifts the protection, then the destroy runs,\nonce the broker, its jobs and traefik are removed from the cluster.\nOn AWS the database still leaves a final snapshot behind.\n\nNote this never touches the terraform state bucket: the bucket is managed\noutside the terraform (see 'infra init --state-bucket') and outlives the\ncluster so the destroy itself has state to work against.\n",
|
|
4004
3951
|
"allow_extra": false,
|
|
4005
3952
|
"parent": "infra",
|
|
4006
3953
|
"is_placeholder": false
|
|
@@ -5130,106 +5077,6 @@
|
|
|
5130
5077
|
"allow_extra": false,
|
|
5131
5078
|
"parent": "infra",
|
|
5132
5079
|
"is_placeholder": false
|
|
5133
|
-
},
|
|
5134
|
-
"tls": {
|
|
5135
|
-
"name": "tls",
|
|
5136
|
-
"args": [
|
|
5137
|
-
{
|
|
5138
|
-
"id": "self_signed",
|
|
5139
|
-
"option": "--self-signed",
|
|
5140
|
-
"short": null,
|
|
5141
|
-
"orig_help": "Create a self-signed CA and certificate",
|
|
5142
|
-
"default": false,
|
|
5143
|
-
"help": "Create a self-signed CA and certificate (bool)",
|
|
5144
|
-
"action": "store_true",
|
|
5145
|
-
"choices": null,
|
|
5146
|
-
"has_converter": false,
|
|
5147
|
-
"type": null,
|
|
5148
|
-
"orig_type": "bool"
|
|
5149
|
-
},
|
|
5150
|
-
{
|
|
5151
|
-
"id": "trust",
|
|
5152
|
-
"option": "--trust",
|
|
5153
|
-
"short": null,
|
|
5154
|
-
"orig_help": "SSH host to fetch CA from and install into local trust store",
|
|
5155
|
-
"default": null,
|
|
5156
|
-
"help": "SSH host to fetch CA from and install into local trust store (str)",
|
|
5157
|
-
"action": null,
|
|
5158
|
-
"choices": null,
|
|
5159
|
-
"has_converter": false,
|
|
5160
|
-
"type": "str",
|
|
5161
|
-
"orig_type": "str"
|
|
5162
|
-
},
|
|
5163
|
-
{
|
|
5164
|
-
"id": "setup",
|
|
5165
|
-
"option": "--setup",
|
|
5166
|
-
"short": null,
|
|
5167
|
-
"orig_help": "SSH host: create certs remotely, then fetch and trust the CA locally",
|
|
5168
|
-
"default": null,
|
|
5169
|
-
"help": "SSH host: create certs remotely, then fetch and trust the CA locally (str)",
|
|
5170
|
-
"action": null,
|
|
5171
|
-
"choices": null,
|
|
5172
|
-
"has_converter": false,
|
|
5173
|
-
"type": "str",
|
|
5174
|
-
"orig_type": "str"
|
|
5175
|
-
},
|
|
5176
|
-
{
|
|
5177
|
-
"id": "status",
|
|
5178
|
-
"option": "--status",
|
|
5179
|
-
"short": null,
|
|
5180
|
-
"orig_help": "Show current TLS configuration",
|
|
5181
|
-
"default": false,
|
|
5182
|
-
"help": "Show current TLS configuration (bool)",
|
|
5183
|
-
"action": "store_true",
|
|
5184
|
-
"choices": null,
|
|
5185
|
-
"has_converter": false,
|
|
5186
|
-
"type": null,
|
|
5187
|
-
"orig_type": "bool"
|
|
5188
|
-
},
|
|
5189
|
-
{
|
|
5190
|
-
"id": "fqdn",
|
|
5191
|
-
"option": "--fqdn",
|
|
5192
|
-
"short": null,
|
|
5193
|
-
"orig_help": "Certificate FQDN (default: localhost)",
|
|
5194
|
-
"default": "localhost",
|
|
5195
|
-
"help": "Certificate FQDN (default: localhost) (str)",
|
|
5196
|
-
"action": null,
|
|
5197
|
-
"choices": null,
|
|
5198
|
-
"has_converter": false,
|
|
5199
|
-
"type": "str",
|
|
5200
|
-
"orig_type": "str"
|
|
5201
|
-
},
|
|
5202
|
-
{
|
|
5203
|
-
"id": "namespace",
|
|
5204
|
-
"option": "--namespace",
|
|
5205
|
-
"short": null,
|
|
5206
|
-
"orig_help": "Kubernetes namespace",
|
|
5207
|
-
"default": "ellf",
|
|
5208
|
-
"help": "Kubernetes namespace (str)",
|
|
5209
|
-
"action": null,
|
|
5210
|
-
"choices": null,
|
|
5211
|
-
"has_converter": false,
|
|
5212
|
-
"type": "str",
|
|
5213
|
-
"orig_type": "str"
|
|
5214
|
-
},
|
|
5215
|
-
{
|
|
5216
|
-
"id": "output",
|
|
5217
|
-
"option": "--output",
|
|
5218
|
-
"short": null,
|
|
5219
|
-
"orig_help": "Output format for trust commands: human, json, shell",
|
|
5220
|
-
"default": "human",
|
|
5221
|
-
"help": "Output format for trust commands: human, json, shell (str)",
|
|
5222
|
-
"action": null,
|
|
5223
|
-
"choices": null,
|
|
5224
|
-
"has_converter": false,
|
|
5225
|
-
"type": "str",
|
|
5226
|
-
"orig_type": "str"
|
|
5227
|
-
}
|
|
5228
|
-
],
|
|
5229
|
-
"description": "Manage TLS certificates for local cluster access.\n\nUse --self-signed when you have direct kubectl access to the cluster.\nUse --setup HOST to do everything from your laptop over SSH.\nUse --trust HOST to fetch and install an existing CA from a remote cluster.\n",
|
|
5230
|
-
"allow_extra": false,
|
|
5231
|
-
"parent": "infra",
|
|
5232
|
-
"is_placeholder": false
|
|
5233
5080
|
}
|
|
5234
5081
|
},
|
|
5235
5082
|
"jobs": {
|