ellf-cli 4.0.26__tar.gz → 4.0.28__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-4.0.26/ellf_cli.egg-info → ellf_cli-4.0.28}/PKG-INFO +1 -1
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/about.json +1 -1
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/auth.py +17 -2
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/register.py +39 -8
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf.json +1 -1
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/url.py +26 -7
- {ellf_cli-4.0.26 → ellf_cli-4.0.28/ellf_cli.egg-info}/PKG-INFO +1 -1
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/LICENSE +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/MANIFEST.in +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/README.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/__main__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/about.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/appdirs.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/cli.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/cloud/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/cloud/gcp.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/cluster_config.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/_recipe_file.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/_recipe_subcommand.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/_state.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/actions.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/agents.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/assets.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/clusters.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/config.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/datasets.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/files/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/files/cp.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/files/ls.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/files/rm.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/files/rsync.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/files/stats.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/general.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/import_export.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/_helpers.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/deploy.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/init_values.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/provision.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/setup.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/start.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/terraform.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/infra/tls.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/jobs.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/packages.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/paths.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/plans.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/projects.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/publish_code.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/publish_data.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/recipes.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/secrets.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/support.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/tasks.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/commands/todos.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/config.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/.claude-plugin/plugin.json +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/.gitignore +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/bin/write-current-session.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/hooks/hooks.json +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skill_variants.json +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/references/annotation_audit.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/references/builtin_ellf_annotation_recipes.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.coding/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.coding/references/annotation_audit.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.coding/references/builtin_ellf_annotation_recipes.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.coding/references/builtin_prodigy_recipes.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-ask/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-handoff/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.assistant/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.assistant/references/annotation_metrics.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.assistant/references/training_monitoring.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.coding/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.coding/references/annotation_metrics.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.coding/references/training_monitoring.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.coding/scripts/check_training.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-ops.assistant/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-ops.coding/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-ops.coding/scripts/run_job.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-patterns/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-patterns/references/pattern_strategies.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_action_recipe.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_agent_recipe.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_blocks_ui.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_correct.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_custom_ui.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_manual.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_pages_ui.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_routing.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_task_recipe.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/assets/templates/template_teach.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/builtin_recipes.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/ellf_recipe_sdk.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/lint_recipe.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/prodigy_recipe_api.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-prodigy/references/template_index.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.assistant/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.assistant/references/consulting_patterns.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.assistant/references/explosion_strategy.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.assistant/references/prodigy_llm_bot.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.coding/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.coding/references/consulting_patterns.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.coding/references/explosion_strategy.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.coding/references/prodigy_llm_bot.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-support.assistant/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-support.coding/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-todo/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.assistant/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.assistant/references/diagnostics.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.assistant/references/evaluation_guide.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.assistant/references/model_selection.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.assistant/references/training_paradigms.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.assistant/references/workflow.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/SKILL.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/config_advanced.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/config_architectures.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/config_training.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/diagnostics.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/evaluation_guide.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/experiment_patterns.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/model_selection.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/training_paradigms.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/training_troubleshooting.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/references/workflow.md +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.coding/scripts/ellf_logger.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/errors.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/helm.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/key_pair.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/main.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/messages.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/query.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/cookiecutter.json +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/.gitignore +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/README.md.tmpl +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements-dev.in +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/requirements.in +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/setup.py.tmpl +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/about.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/recipes_cookiecutter/{{cookiecutter.package_dir}}/{{cookiecutter.package_name}}/recipes/example_task.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/testing/__init__.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ty.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ui.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/util.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli.egg-info/SOURCES.txt +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli.egg-info/dependency_links.txt +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli.egg-info/entry_points.txt +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli.egg-info/not-zip-safe +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli.egg-info/requires.txt +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli.egg-info/top_level.txt +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/pyproject.toml +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/setup.cfg +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/setup.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_appdirs.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_auth.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_config.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_errors.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_files_cp.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_files_cp_helpers.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_info.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_invalid_secrets.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_key_pair.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_login.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_main.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_projects.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_query.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_recipe_file.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_recipes.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_state.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_support.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_ty.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_ui.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_ui_extras.py +0 -0
- {ellf_cli-4.0.26 → ellf_cli-4.0.28}/tests/test_util.py +0 -0
|
@@ -193,7 +193,10 @@ class AuthStateImpl:
|
|
|
193
193
|
self._secrets = None
|
|
194
194
|
self._broker_url = URL.parse(broker_host) if broker_host is not None else None
|
|
195
195
|
self._pam_url = URL.parse(pam_host)
|
|
196
|
-
|
|
196
|
+
# Seed from saved-defaults so we don't make an unnecessary (and brittle)
|
|
197
|
+
# PAM lookup-by-address every time the user runs an ellf command.
|
|
198
|
+
# `auth.broker_id` falls back to the address lookup only if this is None.
|
|
199
|
+
self._broker_id = settings.broker_id
|
|
197
200
|
self._org_id = None
|
|
198
201
|
self._secrets_path = ctx.secrets_path
|
|
199
202
|
self._saved_settings_path = ctx.saved_settings_path
|
|
@@ -407,10 +410,22 @@ class AuthStateImpl:
|
|
|
407
410
|
):
|
|
408
411
|
self._broker_client = None
|
|
409
412
|
api_token = self.get_api_token().access_token
|
|
413
|
+
# Prefer looking up the broker by id when we have it. Address
|
|
414
|
+
# lookup is brittle: the registered broker.address (e.g.
|
|
415
|
+
# 'cluster.example.com' or 'localhost') often doesn't textually
|
|
416
|
+
# match broker_host (e.g. 'https://localhost:8443'), and even
|
|
417
|
+
# canonicalized forms differ when the user includes a port to
|
|
418
|
+
# reach the cluster via tunnel that the broker.address doesn't
|
|
419
|
+
# carry. broker_id is unambiguous.
|
|
420
|
+
body: dict[str, str] = {}
|
|
421
|
+
if self._broker_id is not None:
|
|
422
|
+
body["id"] = str(self._broker_id)
|
|
423
|
+
else:
|
|
424
|
+
body["address"] = str(URL.parse(broker_host))
|
|
410
425
|
res = httpx.post(
|
|
411
426
|
str(self.pam_url / "api/v1/broker/token"),
|
|
412
427
|
headers={"authorization": f"Bearer {api_token}"},
|
|
413
|
-
json=
|
|
428
|
+
json=body,
|
|
414
429
|
)
|
|
415
430
|
if res.status_code != 200:
|
|
416
431
|
err = _format_http_error(res)
|
|
@@ -7,7 +7,6 @@ import srsly
|
|
|
7
7
|
from radicli import Arg
|
|
8
8
|
from wasabi import msg
|
|
9
9
|
|
|
10
|
-
from ellf_pam_sdk.errors import BrokerNotFound
|
|
11
10
|
from ellf_pam_sdk.models import BrokerCreating, BrokerUpdating
|
|
12
11
|
|
|
13
12
|
from ...cli import cli
|
|
@@ -36,7 +35,7 @@ def register(
|
|
|
36
35
|
as_json: bool = False,
|
|
37
36
|
) -> None:
|
|
38
37
|
"""Register a new cluster with PAM and write credentials to cluster-creds.json."""
|
|
39
|
-
from .._state import get_auth_state
|
|
38
|
+
from .._state import get_auth_state, get_root_cfg, get_saved_settings
|
|
40
39
|
|
|
41
40
|
if cloud_provider not in CLOUD_PROVIDERS:
|
|
42
41
|
msg.fail(
|
|
@@ -47,9 +46,23 @@ def register(
|
|
|
47
46
|
auth = get_auth_state()
|
|
48
47
|
client = auth.client
|
|
49
48
|
org_id = auth.org_id
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
# Idempotent on (org_id, name): list and filter client-side rather than
|
|
50
|
+
# `broker.read(name=...)`, which has historically returned the wrong record
|
|
51
|
+
# when the name doesn't disambiguate (no LIMIT 1 / ORDER BY guarantees in
|
|
52
|
+
# the PAM-side query). Address-based lookup also doesn't work as a
|
|
53
|
+
# disambiguator because two clusters with the same human-readable domain
|
|
54
|
+
# are valid (e.g. two `localhost`-served dev clusters in the same org).
|
|
55
|
+
# page_size is capped at 100 server-side; iterate pages so this still
|
|
56
|
+
# works in larger orgs.
|
|
57
|
+
existing = next(
|
|
58
|
+
(
|
|
59
|
+
b
|
|
60
|
+
for b in client.broker.all(page_size=100)
|
|
61
|
+
if b.name == name and b.org_id == org_id
|
|
62
|
+
),
|
|
63
|
+
None,
|
|
64
|
+
)
|
|
65
|
+
if existing is None:
|
|
53
66
|
body = BrokerCreating(
|
|
54
67
|
name=name,
|
|
55
68
|
org_id=org_id,
|
|
@@ -62,14 +75,14 @@ def register(
|
|
|
62
75
|
broker = client.broker.create(body)
|
|
63
76
|
else:
|
|
64
77
|
update_body = BrokerUpdating(
|
|
65
|
-
id=
|
|
78
|
+
id=existing.id,
|
|
66
79
|
name=name,
|
|
67
80
|
address=domain,
|
|
68
81
|
cloud_provider=cloud_provider,
|
|
69
82
|
state="creating",
|
|
70
83
|
cloud={},
|
|
71
84
|
)
|
|
72
|
-
|
|
85
|
+
broker = client.broker.update(update_body)
|
|
73
86
|
creds = client.broker.credentials(broker_id=broker.id)
|
|
74
87
|
creds_data = {
|
|
75
88
|
"broker_id": str(creds.broker_id),
|
|
@@ -81,9 +94,27 @@ def register(
|
|
|
81
94
|
}
|
|
82
95
|
creds_path = Path("cluster-creds.json")
|
|
83
96
|
srsly.write_json(creds_path, creds_data)
|
|
97
|
+
# Persist the broker id locally so subsequent `ellf` commands resolve the
|
|
98
|
+
# cluster identity from saved-defaults instead of looking it up by address
|
|
99
|
+
# (which is brittle when the user later sets `broker_host` to a tunnel URL
|
|
100
|
+
# like `https://localhost:8443` that doesn't match the registered domain).
|
|
101
|
+
settings = get_saved_settings()
|
|
102
|
+
prior_broker_id = settings.broker_id
|
|
103
|
+
settings.broker_id = broker.id
|
|
104
|
+
settings.save(get_root_cfg().saved_settings_path)
|
|
105
|
+
# Any cached broker access token from a previous broker_id is now stale.
|
|
106
|
+
# The cache is keyed by broker_host; if the broker behind that host has
|
|
107
|
+
# changed identity (re-registered cluster, name reused, tear-down + redeploy),
|
|
108
|
+
# the cached token will be rejected with 401 by the new broker.
|
|
109
|
+
if prior_broker_id is not None and prior_broker_id != broker.id:
|
|
110
|
+
secrets = auth.secrets
|
|
111
|
+
secrets.broker_tokens.clear()
|
|
112
|
+
secrets.save(get_root_cfg().secrets_path)
|
|
113
|
+
msg.info(" Cleared stale broker token cache (broker_id changed)")
|
|
84
114
|
if as_json:
|
|
85
115
|
print(json.dumps(creds_data, indent=2))
|
|
86
116
|
else:
|
|
87
|
-
|
|
117
|
+
action = "updated existing" if existing else "registered new"
|
|
118
|
+
msg.good(f"Cluster {action} with PAM")
|
|
88
119
|
msg.info(f" Broker ID: {creds.broker_id}")
|
|
89
120
|
msg.info(f" Wrote credentials to {creds_path}")
|
|
@@ -31,13 +31,22 @@ class URL:
|
|
|
31
31
|
'http://broker.internal:8080'
|
|
32
32
|
"""
|
|
33
33
|
|
|
34
|
-
__slots__ = ("url", "netloc", "port", "scheme")
|
|
35
|
-
|
|
36
|
-
def __init__(
|
|
34
|
+
__slots__ = ("url", "netloc", "port", "scheme", "hostname")
|
|
35
|
+
|
|
36
|
+
def __init__(
|
|
37
|
+
self,
|
|
38
|
+
*,
|
|
39
|
+
url: str,
|
|
40
|
+
netloc: str,
|
|
41
|
+
port: int,
|
|
42
|
+
scheme: str,
|
|
43
|
+
hostname: str,
|
|
44
|
+
) -> None:
|
|
37
45
|
object.__setattr__(self, "url", url)
|
|
38
46
|
object.__setattr__(self, "netloc", netloc)
|
|
39
47
|
object.__setattr__(self, "port", port)
|
|
40
48
|
object.__setattr__(self, "scheme", scheme)
|
|
49
|
+
object.__setattr__(self, "hostname", hostname)
|
|
41
50
|
|
|
42
51
|
def __setattr__(self, name: str, value: Any) -> None:
|
|
43
52
|
raise AttributeError("URL instances are immutable")
|
|
@@ -48,20 +57,22 @@ class URL:
|
|
|
48
57
|
def __eq__(self, other: object) -> bool:
|
|
49
58
|
if not isinstance(other, URL):
|
|
50
59
|
return NotImplemented
|
|
51
|
-
return (self.url, self.netloc, self.port, self.scheme) == (
|
|
60
|
+
return (self.url, self.netloc, self.port, self.scheme, self.hostname) == (
|
|
52
61
|
other.url,
|
|
53
62
|
other.netloc,
|
|
54
63
|
other.port,
|
|
55
64
|
other.scheme,
|
|
65
|
+
other.hostname,
|
|
56
66
|
)
|
|
57
67
|
|
|
58
68
|
def __hash__(self) -> int:
|
|
59
|
-
return hash((self.url, self.netloc, self.port, self.scheme))
|
|
69
|
+
return hash((self.url, self.netloc, self.port, self.scheme, self.hostname))
|
|
60
70
|
|
|
61
71
|
def __repr__(self) -> str:
|
|
62
72
|
return (
|
|
63
73
|
f"URL(url={self.url!r}, netloc={self.netloc!r},"
|
|
64
|
-
f" port={self.port!r}, scheme={self.scheme!r}
|
|
74
|
+
f" port={self.port!r}, scheme={self.scheme!r},"
|
|
75
|
+
f" hostname={self.hostname!r})"
|
|
65
76
|
)
|
|
66
77
|
|
|
67
78
|
@classmethod
|
|
@@ -128,6 +139,7 @@ class URL:
|
|
|
128
139
|
netloc=parsed.netloc,
|
|
129
140
|
port=resolved_port,
|
|
130
141
|
scheme=parsed.scheme,
|
|
142
|
+
hostname=parsed.hostname or "",
|
|
131
143
|
)
|
|
132
144
|
|
|
133
145
|
@classmethod
|
|
@@ -151,6 +163,7 @@ class URL:
|
|
|
151
163
|
netloc=self.netloc,
|
|
152
164
|
port=self.port,
|
|
153
165
|
scheme=self.scheme,
|
|
166
|
+
hostname=self.hostname,
|
|
154
167
|
)
|
|
155
168
|
|
|
156
169
|
def with_userinfo(self, username: str, password: str = "") -> URL:
|
|
@@ -164,4 +177,10 @@ class URL:
|
|
|
164
177
|
if parsed.port:
|
|
165
178
|
netloc = f"{netloc}:{parsed.port}"
|
|
166
179
|
new_url = parsed._replace(netloc=netloc).geturl()
|
|
167
|
-
return URL(
|
|
180
|
+
return URL(
|
|
181
|
+
url=new_url,
|
|
182
|
+
netloc=self.netloc,
|
|
183
|
+
port=self.port,
|
|
184
|
+
scheme=self.scheme,
|
|
185
|
+
hostname=self.hostname,
|
|
186
|
+
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.assistant/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-annotate.coding/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.assistant/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-monitor.coding/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-ops.coding/scripts/run_job.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.assistant/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-project.coding/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-support.assistant/SKILL.md
RENAMED
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-support.coding/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
{ellf_cli-4.0.26 → ellf_cli-4.0.28}/ellf_cli/ellf_skills/skills/ellf-train.assistant/SKILL.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|