legate 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +345 -0
- data/bin/legate +13 -0
- data/examples/00_quickstart.rb +51 -0
- data/examples/01_simple_agent.rb +105 -0
- data/examples/02_multi_tool_agent.rb +140 -0
- data/examples/03_custom_tool.rb +93 -0
- data/examples/04_agent_instructions.rb +84 -0
- data/examples/05_state_and_sessions.rb +91 -0
- data/examples/06_callbacks.rb +186 -0
- data/examples/07_async_jobs.rb +112 -0
- data/examples/08_loop_agent.rb +197 -0
- data/examples/09_sequential_workflow.rb +40 -0
- data/examples/10_parallel_workflow.rb +34 -0
- data/examples/11_agent_delegation.rb +24 -0
- data/examples/12_http_client_tool.rb +156 -0
- data/examples/13_authentication.rb +220 -0
- data/examples/14_mcp_client.rb +154 -0
- data/examples/15_mcp_server.rb +79 -0
- data/examples/16_webhooks.rb +91 -0
- data/examples/README_sequential_agents.md +164 -0
- data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
- data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
- data/examples/advanced/auth/excon_middleware.rb +317 -0
- data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
- data/examples/advanced/auth/fiber_auth_example.rb +281 -0
- data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
- data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
- data/examples/advanced/auth/oauth2_auth.rb +419 -0
- data/examples/advanced/auth/oidc_auth.rb +514 -0
- data/examples/advanced/auth/openweather_api.rb +251 -0
- data/examples/advanced/auth/openweather_tool.rb +153 -0
- data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
- data/examples/advanced/auth/service_account.rb +135 -0
- data/examples/advanced/auth/test_with_httpbin.rb +202 -0
- data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
- data/examples/advanced/callback_monitoring.rb +679 -0
- data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
- data/examples/advanced/mas/loop_workflow.rb +28 -0
- data/examples/advanced/mas/mock_planner.rb +77 -0
- data/examples/advanced/mas/proper_delegation_example.rb +276 -0
- data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
- data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
- data/examples/advanced/mcp/mcp_server_async.rb +76 -0
- data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
- data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
- data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
- data/examples/advanced/random_calculator.rb +104 -0
- data/examples/advanced/sleep_agent.rb +153 -0
- data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
- data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
- data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
- data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
- data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
- data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
- data/examples/tools/oauth2_example.rb +136 -0
- data/examples/tools/sleepy_tool.rb +42 -0
- data/lib/legate/activity_log.rb +71 -0
- data/lib/legate/agent.rb +959 -0
- data/lib/legate/agent_code_generator.rb +185 -0
- data/lib/legate/agent_definition.rb +812 -0
- data/lib/legate/agentic/decision.rb +49 -0
- data/lib/legate/agentic/loop.rb +134 -0
- data/lib/legate/agentic.rb +5 -0
- data/lib/legate/agents/loop_agent.rb +248 -0
- data/lib/legate/agents/parallel_agent.rb +163 -0
- data/lib/legate/agents/sequential_agent.rb +190 -0
- data/lib/legate/agents.rb +14 -0
- data/lib/legate/auth/config.rb +148 -0
- data/lib/legate/auth/coordinator.rb +218 -0
- data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
- data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
- data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
- data/lib/legate/auth/credential.rb +157 -0
- data/lib/legate/auth/encryption.rb +108 -0
- data/lib/legate/auth/error.rb +94 -0
- data/lib/legate/auth/exchanged_credential.rb +180 -0
- data/lib/legate/auth/excon_middleware.rb +285 -0
- data/lib/legate/auth/http_client_utils.rb +364 -0
- data/lib/legate/auth/manager.rb +531 -0
- data/lib/legate/auth/manager_store.rb +394 -0
- data/lib/legate/auth/middleware_factory.rb +290 -0
- data/lib/legate/auth/runner.rb +279 -0
- data/lib/legate/auth/scheme.rb +125 -0
- data/lib/legate/auth/schemes/api_key.rb +212 -0
- data/lib/legate/auth/schemes/google_service_account.rb +108 -0
- data/lib/legate/auth/schemes/http_bearer.rb +98 -0
- data/lib/legate/auth/schemes/oauth2.rb +396 -0
- data/lib/legate/auth/schemes/openid_connect.rb +346 -0
- data/lib/legate/auth/schemes/service_account.rb +388 -0
- data/lib/legate/auth/schemes.rb +40 -0
- data/lib/legate/auth/token_manager.rb +362 -0
- data/lib/legate/auth/token_store.rb +86 -0
- data/lib/legate/auth/tool_context_extension.rb +97 -0
- data/lib/legate/auth/tool_integration.rb +188 -0
- data/lib/legate/auth/url_guard.rb +81 -0
- data/lib/legate/auth.rb +453 -0
- data/lib/legate/callbacks/callback_context.rb +71 -0
- data/lib/legate/cli/agent_commands.rb +950 -0
- data/lib/legate/cli/auth_commands.rb +520 -0
- data/lib/legate/cli/base_command.rb +24 -0
- data/lib/legate/cli/deployment_commands.rb +934 -0
- data/lib/legate/cli/output_helper.rb +108 -0
- data/lib/legate/cli/session_commands.rb +138 -0
- data/lib/legate/cli/skaffold_commands.rb +223 -0
- data/lib/legate/cli/tool_commands.rb +261 -0
- data/lib/legate/cli/web_commands.rb +182 -0
- data/lib/legate/cli.rb +40 -0
- data/lib/legate/configuration/webhooks.rb +113 -0
- data/lib/legate/configuration.rb +39 -0
- data/lib/legate/definition_store.rb +23 -0
- data/lib/legate/errors.rb +118 -0
- data/lib/legate/event.rb +161 -0
- data/lib/legate/gemini_ai_beta_patch.rb +39 -0
- data/lib/legate/generators/agent_generator.rb +412 -0
- data/lib/legate/generators/code_validator.rb +48 -0
- data/lib/legate/generators/legate/install_generator.rb +35 -0
- data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
- data/lib/legate/generators/legate/templates/initializer.rb +18 -0
- data/lib/legate/generators/runtime_tool_loader.rb +76 -0
- data/lib/legate/generators/tool_generator.rb +408 -0
- data/lib/legate/generators.rb +11 -0
- data/lib/legate/global_definition_registry.rb +506 -0
- data/lib/legate/global_tool_manager.rb +135 -0
- data/lib/legate/llm/adapter.rb +69 -0
- data/lib/legate/llm/gemini.rb +172 -0
- data/lib/legate/llm/ollama.rb +80 -0
- data/lib/legate/llm.rb +34 -0
- data/lib/legate/mcp/client.rb +320 -0
- data/lib/legate/mcp/connection/sse.rb +292 -0
- data/lib/legate/mcp/connection/stdio.rb +273 -0
- data/lib/legate/mcp/connection_manager.rb +103 -0
- data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
- data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
- data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
- data/lib/legate/mcp/tool_wrapper.rb +138 -0
- data/lib/legate/mcp/util/schema_converter.rb +134 -0
- data/lib/legate/mcp.rb +23 -0
- data/lib/legate/plan_executor.rb +375 -0
- data/lib/legate/planner.rb +839 -0
- data/lib/legate/rails/railtie.rb +43 -0
- data/lib/legate/rails.rb +9 -0
- data/lib/legate/redaction.rb +32 -0
- data/lib/legate/session.rb +299 -0
- data/lib/legate/session_service/active_record.rb +300 -0
- data/lib/legate/session_service/base.rb +68 -0
- data/lib/legate/session_service/event_broadcast.rb +74 -0
- data/lib/legate/session_service/in_memory.rb +188 -0
- data/lib/legate/tool/metadata_dsl.rb +122 -0
- data/lib/legate/tool.rb +276 -0
- data/lib/legate/tool_code_generator.rb +103 -0
- data/lib/legate/tool_context.rb +350 -0
- data/lib/legate/tool_loader.rb +39 -0
- data/lib/legate/tool_registry.rb +73 -0
- data/lib/legate/tool_result.rb +61 -0
- data/lib/legate/tools/agent_tool.rb +187 -0
- data/lib/legate/tools/base/http_client.rb +319 -0
- data/lib/legate/tools/base/safe_url.rb +56 -0
- data/lib/legate/tools/base_async_job_tool.rb +91 -0
- data/lib/legate/tools/calculator.rb +89 -0
- data/lib/legate/tools/cat_facts.rb +81 -0
- data/lib/legate/tools/check_job_status_tool.rb +48 -0
- data/lib/legate/tools/current_time_tool.rb +64 -0
- data/lib/legate/tools/echo.rb +43 -0
- data/lib/legate/tools/http_request_tool.rb +105 -0
- data/lib/legate/tools/random_number_tool.rb +64 -0
- data/lib/legate/tools/read_webpage_tool.rb +92 -0
- data/lib/legate/tools/sleepy_tool.rb +74 -0
- data/lib/legate/tools/webhook_tool.rb +146 -0
- data/lib/legate/version.rb +5 -0
- data/lib/legate/web/app.rb +984 -0
- data/lib/legate/web/public/css/main.css +4980 -0
- data/lib/legate/web/public/images/favicon-256.png +0 -0
- data/lib/legate/web/public/images/favicon-32.png +0 -0
- data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
- data/lib/legate/web/public/images/legate-logo-light.png +0 -0
- data/lib/legate/web/public/js/legate.js +616 -0
- data/lib/legate/web/public/styles/main.scss +4402 -0
- data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
- data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
- data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
- data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
- data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
- data/lib/legate/web/routes/api_routes.rb +56 -0
- data/lib/legate/web/routes/authentication_routes.rb +1541 -0
- data/lib/legate/web/routes/core_routes.rb +111 -0
- data/lib/legate/web/routes/documentation_routes.rb +220 -0
- data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
- data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
- data/lib/legate/web/sass_compiler.rb +73 -0
- data/lib/legate/web/views/_active_session_info.slim +25 -0
- data/lib/legate/web/views/_activity_list.slim +55 -0
- data/lib/legate/web/views/_agent_card.slim +56 -0
- data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
- data/lib/legate/web/views/_agent_status_controls.slim +71 -0
- data/lib/legate/web/views/_agent_tool_table.slim +74 -0
- data/lib/legate/web/views/_chat_message.slim +95 -0
- data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
- data/lib/legate/web/views/_display_agent_description.slim +11 -0
- data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
- data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
- data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
- data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
- data/lib/legate/web/views/_display_agent_model.slim +17 -0
- data/lib/legate/web/views/_display_agent_name.slim +42 -0
- data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
- data/lib/legate/web/views/_display_agent_type.slim +65 -0
- data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
- data/lib/legate/web/views/_edit_agent_description.slim +16 -0
- data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
- data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
- data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
- data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
- data/lib/legate/web/views/_edit_agent_model.slim +23 -0
- data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
- data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
- data/lib/legate/web/views/_edit_agent_type.slim +67 -0
- data/lib/legate/web/views/_session_error.slim +4 -0
- data/lib/legate/web/views/_skeleton.slim +69 -0
- data/lib/legate/web/views/_tool_card.slim +9 -0
- data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
- data/lib/legate/web/views/agent.slim +436 -0
- data/lib/legate/web/views/agent_auth.slim +562 -0
- data/lib/legate/web/views/agents.slim +369 -0
- data/lib/legate/web/views/auth.slim +112 -0
- data/lib/legate/web/views/auth_credential_detail.slim +327 -0
- data/lib/legate/web/views/auth_credentials.slim +261 -0
- data/lib/legate/web/views/auth_debug.slim +94 -0
- data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
- data/lib/legate/web/views/auth_mapping_new.slim +123 -0
- data/lib/legate/web/views/auth_mappings.slim +120 -0
- data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
- data/lib/legate/web/views/auth_schemes.slim +259 -0
- data/lib/legate/web/views/auth_test.slim +418 -0
- data/lib/legate/web/views/chat.slim +192 -0
- data/lib/legate/web/views/docs_index.slim +105 -0
- data/lib/legate/web/views/docs_show.slim +105 -0
- data/lib/legate/web/views/error_404.slim +5 -0
- data/lib/legate/web/views/index.slim +148 -0
- data/lib/legate/web/views/layout.slim +144 -0
- data/lib/legate/web/views/tool_detail.slim +87 -0
- data/lib/legate/web/views/tools.slim +50 -0
- data/lib/legate/web/webhook_listener.rb +367 -0
- data/lib/legate/web.rb +9 -0
- data/lib/legate.rb +220 -0
- data/public/docs/advanced/callbacks.md +828 -0
- data/public/docs/advanced/mcp_schema_conversion.md +59 -0
- data/public/docs/authentication/api_reference/config.md +210 -0
- data/public/docs/authentication/api_reference/credential.md +246 -0
- data/public/docs/authentication/api_reference/encryption.md +218 -0
- data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
- data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
- data/public/docs/authentication/api_reference/index.md +30 -0
- data/public/docs/authentication/api_reference/scheme.md +250 -0
- data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
- data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
- data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
- data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
- data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
- data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
- data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
- data/public/docs/authentication/api_reference/token_manager.md +221 -0
- data/public/docs/authentication/api_reference/token_store.md +146 -0
- data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
- data/public/docs/authentication/guides/api_key.md +190 -0
- data/public/docs/authentication/guides/bearer.md +172 -0
- data/public/docs/authentication/guides/configuration.md +255 -0
- data/public/docs/authentication/guides/custom_flow.md +523 -0
- data/public/docs/authentication/guides/index.md +24 -0
- data/public/docs/authentication/guides/migration.md +435 -0
- data/public/docs/authentication/guides/oauth2.md +252 -0
- data/public/docs/authentication/guides/oidc.md +241 -0
- data/public/docs/authentication/guides/overview.md +155 -0
- data/public/docs/authentication/guides/secure_storage.md +301 -0
- data/public/docs/authentication/guides/service_account.md +228 -0
- data/public/docs/authentication/guides/token_lifecycle.md +295 -0
- data/public/docs/authentication/guides/web_ui_integration.md +504 -0
- data/public/docs/authentication/index.md +58 -0
- data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
- data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
- data/public/docs/authentication/troubleshooting/index.md +11 -0
- data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
- data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
- data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
- data/public/docs/cli/legate_cli_usage.md +363 -0
- data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
- data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
- data/public/docs/core_concepts/legate_configuration.md +116 -0
- data/public/docs/core_concepts/legate_definition_store.md +102 -0
- data/public/docs/core_concepts/legate_planner.md +94 -0
- data/public/docs/core_concepts/legate_session_service.md +104 -0
- data/public/docs/error_handling/legate_error_handling.md +122 -0
- data/public/docs/examples.md +199 -0
- data/public/docs/getting_started.md +111 -0
- data/public/docs/guides/agentic_agents.md +137 -0
- data/public/docs/guides/ai_code_generators.md +437 -0
- data/public/docs/guides/auto_loading.md +326 -0
- data/public/docs/guides/configuring_agent_webhooks.md +219 -0
- data/public/docs/guides/http_client_usage.md +264 -0
- data/public/docs/guides/llm_providers.md +137 -0
- data/public/docs/guides/mcp_client_integration.md +232 -0
- data/public/docs/guides/mcp_server_exposure.md +206 -0
- data/public/docs/guides/rails_integration.md +128 -0
- data/public/docs/guides/sending_outbound_webhooks.md +227 -0
- data/public/docs/guides/streaming.md +112 -0
- data/public/docs/guides/webhooks.md +288 -0
- data/public/docs/introduction.md +51 -0
- data/public/docs/multi_agent_systems/advanced_features.md +57 -0
- data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
- data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
- data/public/docs/multi_agent_systems/state_management.md +47 -0
- data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
- data/public/docs/tools/legate_built_in_tools.md +332 -0
- data/public/docs/tools/legate_tools_and_registry.md +263 -0
- data/public/docs/web_ui/legate_web_ui.md +137 -0
- metadata +823 -0
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
# File: lib/legate/cli/auth_commands.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'thor'
|
|
5
|
+
require_relative 'base_command'
|
|
6
|
+
require 'cli/ui'
|
|
7
|
+
require_relative '../../legate'
|
|
8
|
+
|
|
9
|
+
module Legate
|
|
10
|
+
module CLI
|
|
11
|
+
# Helper module for auth command formatting
|
|
12
|
+
module AuthCommandHelpers
|
|
13
|
+
# Mask sensitive values for display
|
|
14
|
+
def mask_sensitive_value(value)
|
|
15
|
+
return '(not set)' if value.nil? || value.empty?
|
|
16
|
+
return value if value.start_with?('ENV:') # Show env var references as-is
|
|
17
|
+
|
|
18
|
+
if value.length <= 8
|
|
19
|
+
'********'
|
|
20
|
+
else
|
|
21
|
+
"#{value[0, 4]}********#{value[-4..]}"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Get scheme type description
|
|
26
|
+
def scheme_type_description(scheme_type)
|
|
27
|
+
case scheme_type.to_sym
|
|
28
|
+
when :api_key then 'API Key authentication'
|
|
29
|
+
when :http_bearer then 'HTTP Bearer token'
|
|
30
|
+
when :oauth2 then 'OAuth 2.0 flow'
|
|
31
|
+
when :oidc, :openid_connect then 'OpenID Connect'
|
|
32
|
+
when :service_account then 'Service Account'
|
|
33
|
+
when :google_service_account then 'Google Service Account'
|
|
34
|
+
else scheme_type.to_s
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Get credential type description
|
|
39
|
+
def credential_type_description(auth_type)
|
|
40
|
+
case auth_type.to_sym
|
|
41
|
+
when :api_key then 'API Key'
|
|
42
|
+
when :http_bearer then 'Bearer Token'
|
|
43
|
+
when :oauth2 then 'OAuth2 Client'
|
|
44
|
+
when :oidc then 'OIDC Client'
|
|
45
|
+
when :service_account then 'Service Account'
|
|
46
|
+
when :google_service_account then 'Google Service Account'
|
|
47
|
+
when :basic then 'Basic Auth'
|
|
48
|
+
else auth_type.to_s
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Sensitive field names
|
|
53
|
+
def sensitive_field?(name)
|
|
54
|
+
%i[api_key client_secret bearer_token password private_key service_account_key token].include?(name.to_sym)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# Print styled header
|
|
58
|
+
def print_header(text)
|
|
59
|
+
puts ::CLI::UI.fmt("{{bold:#{text}}}")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Print styled table row
|
|
63
|
+
def print_row(label, value, indent: 2)
|
|
64
|
+
padding = ' ' * indent
|
|
65
|
+
puts "#{padding}#{::CLI::UI.fmt("{{cyan:#{label}:}}")} #{value}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Ensure auth manager is ready
|
|
69
|
+
def auth_manager
|
|
70
|
+
@auth_manager ||= begin
|
|
71
|
+
manager = Legate::Auth::Manager.instance
|
|
72
|
+
manager.load_from_store
|
|
73
|
+
manager
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Scheme management subcommands
|
|
79
|
+
class AuthSchemeCommands < BaseCommand
|
|
80
|
+
include AuthCommandHelpers
|
|
81
|
+
|
|
82
|
+
namespace 'auth:schemes'
|
|
83
|
+
|
|
84
|
+
desc 'list', 'List all registered authentication schemes'
|
|
85
|
+
def list
|
|
86
|
+
schemes = auth_manager.instance_variable_get(:@schemes) || {}
|
|
87
|
+
|
|
88
|
+
if schemes.empty?
|
|
89
|
+
puts ::CLI::UI.fmt('{{yellow:No authentication schemes registered.}}')
|
|
90
|
+
return
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
print_header("Authentication Schemes (#{schemes.size})")
|
|
94
|
+
puts
|
|
95
|
+
|
|
96
|
+
schemes.each do |name, scheme|
|
|
97
|
+
puts ::CLI::UI.fmt(" {{bold:#{name}}} {{gray:(#{scheme.scheme_type})}}")
|
|
98
|
+
puts " #{scheme_type_description(scheme.scheme_type)}"
|
|
99
|
+
puts
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
desc 'show NAME', 'Show details for a specific scheme'
|
|
104
|
+
def show(name)
|
|
105
|
+
scheme = auth_manager.get_scheme(name.to_sym)
|
|
106
|
+
|
|
107
|
+
unless scheme
|
|
108
|
+
puts ::CLI::UI.fmt("{{red:Scheme not found:}} #{name}")
|
|
109
|
+
exit 1
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
print_header("Scheme: #{name}")
|
|
113
|
+
print_row('Type', scheme.scheme_type)
|
|
114
|
+
print_row('Class', scheme.class.name.split('::').last)
|
|
115
|
+
print_row('Description', scheme_type_description(scheme.scheme_type))
|
|
116
|
+
|
|
117
|
+
# Show scheme-specific config
|
|
118
|
+
config = scheme.to_h
|
|
119
|
+
config.each do |key, value|
|
|
120
|
+
next if key == :type
|
|
121
|
+
|
|
122
|
+
print_row(key.to_s.capitalize, value) if value
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
desc 'create NAME', 'Create a new authentication scheme'
|
|
127
|
+
method_option :type, type: :string, required: true,
|
|
128
|
+
desc: 'Scheme type (api_key, http_bearer, oauth2, oidc, service_account, google_service_account)'
|
|
129
|
+
method_option :authorization_url, type: :string, desc: 'OAuth2/OIDC authorization URL'
|
|
130
|
+
method_option :token_url, type: :string, desc: 'OAuth2/OIDC/Service Account token URL'
|
|
131
|
+
method_option :userinfo_url, type: :string, desc: 'OIDC userinfo URL'
|
|
132
|
+
method_option :scopes, type: :string, desc: 'Space-separated scopes'
|
|
133
|
+
method_option :use_pkce, type: :boolean, default: false, desc: 'Use PKCE for OAuth2/OIDC'
|
|
134
|
+
method_option :revocation_url, type: :string, desc: 'OAuth2 revocation URL'
|
|
135
|
+
def create(name)
|
|
136
|
+
scheme_name = name.to_sym
|
|
137
|
+
scheme_type = options[:type].to_sym
|
|
138
|
+
|
|
139
|
+
if auth_manager.get_scheme(scheme_name)
|
|
140
|
+
puts ::CLI::UI.fmt("{{red:Scheme already exists:}} #{name}")
|
|
141
|
+
exit 1
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
scheme = case scheme_type
|
|
145
|
+
when :api_key
|
|
146
|
+
Legate::Auth::Schemes::ApiKey.new
|
|
147
|
+
when :http_bearer
|
|
148
|
+
Legate::Auth::Schemes::HTTPBearer.new
|
|
149
|
+
when :oauth2
|
|
150
|
+
Legate::Auth::Schemes::OAuth2.new(
|
|
151
|
+
authorization_url: options[:authorization_url],
|
|
152
|
+
token_url: options[:token_url],
|
|
153
|
+
scopes: options[:scopes]&.split(/\s+/),
|
|
154
|
+
use_pkce: options[:use_pkce],
|
|
155
|
+
revocation_url: options[:revocation_url]
|
|
156
|
+
)
|
|
157
|
+
when :oidc, :openid_connect
|
|
158
|
+
Legate::Auth::Schemes::OpenIDConnect.new(
|
|
159
|
+
authorization_url: options[:authorization_url],
|
|
160
|
+
token_url: options[:token_url],
|
|
161
|
+
userinfo_url: options[:userinfo_url],
|
|
162
|
+
scopes: options[:scopes]&.split(/\s+/),
|
|
163
|
+
use_pkce: options[:use_pkce]
|
|
164
|
+
)
|
|
165
|
+
when :service_account
|
|
166
|
+
Legate::Auth::Schemes::ServiceAccount.new(
|
|
167
|
+
token_url: options[:token_url],
|
|
168
|
+
scopes: options[:scopes]&.split(/\s+/)
|
|
169
|
+
)
|
|
170
|
+
when :google_service_account
|
|
171
|
+
Legate::Auth::Schemes::GoogleServiceAccount.new(
|
|
172
|
+
scopes: options[:scopes]&.split(/\s+/)
|
|
173
|
+
)
|
|
174
|
+
else
|
|
175
|
+
puts ::CLI::UI.fmt("{{red:Unsupported scheme type:}} #{scheme_type}")
|
|
176
|
+
exit 1
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
auth_manager.register_scheme(scheme, scheme_name)
|
|
180
|
+
puts ::CLI::UI.fmt("{{green:✓}} Scheme '#{name}' created successfully")
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
desc 'delete NAME', 'Delete an authentication scheme'
|
|
184
|
+
method_option :force, type: :boolean, default: false, desc: 'Force delete even if in use'
|
|
185
|
+
def delete(name)
|
|
186
|
+
scheme_name = name.to_sym
|
|
187
|
+
|
|
188
|
+
unless auth_manager.get_scheme(scheme_name)
|
|
189
|
+
puts ::CLI::UI.fmt("{{red:Scheme not found:}} #{name}")
|
|
190
|
+
exit 1
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# Check for dependent mappings
|
|
194
|
+
url_mappings = auth_manager.instance_variable_get(:@url_mappings) || []
|
|
195
|
+
dependent = url_mappings.select { |m| m[:scheme_name] == scheme_name }
|
|
196
|
+
|
|
197
|
+
if dependent.any? && !options[:force]
|
|
198
|
+
puts ::CLI::UI.fmt("{{red:Cannot delete}} - scheme is used by #{dependent.size} URL mapping(s)")
|
|
199
|
+
puts 'Use --force to delete anyway'
|
|
200
|
+
exit 1
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
auth_manager.unregister_scheme(scheme_name)
|
|
204
|
+
puts ::CLI::UI.fmt("{{green:✓}} Scheme '#{name}' deleted")
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
# Credential management subcommands
|
|
209
|
+
class AuthCredentialCommands < BaseCommand
|
|
210
|
+
include AuthCommandHelpers
|
|
211
|
+
|
|
212
|
+
namespace 'auth:credentials'
|
|
213
|
+
|
|
214
|
+
desc 'list', 'List all registered credentials'
|
|
215
|
+
def list
|
|
216
|
+
credentials = auth_manager.instance_variable_get(:@credentials) || {}
|
|
217
|
+
|
|
218
|
+
if credentials.empty?
|
|
219
|
+
puts ::CLI::UI.fmt('{{yellow:No credentials registered.}}')
|
|
220
|
+
return
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
print_header("Credentials (#{credentials.size})")
|
|
224
|
+
puts
|
|
225
|
+
|
|
226
|
+
credentials.each do |name, cred|
|
|
227
|
+
puts ::CLI::UI.fmt(" {{bold:#{name}}} {{gray:(#{cred.auth_type})}}")
|
|
228
|
+
|
|
229
|
+
# Show masked key info
|
|
230
|
+
case cred.auth_type
|
|
231
|
+
when :api_key
|
|
232
|
+
puts " API Key: #{mask_sensitive_value(cred[:api_key, resolve_env: false])}"
|
|
233
|
+
when :http_bearer
|
|
234
|
+
puts " Token: #{mask_sensitive_value(cred[:bearer_token, resolve_env: false])}"
|
|
235
|
+
when :oauth2, :oidc
|
|
236
|
+
puts " Client ID: #{cred[:client_id, resolve_env: false]}"
|
|
237
|
+
when :service_account, :google_service_account
|
|
238
|
+
puts ' Service Account Key: ********'
|
|
239
|
+
end
|
|
240
|
+
puts
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
desc 'show NAME', 'Show details for a specific credential'
|
|
245
|
+
def show(name)
|
|
246
|
+
credential = auth_manager.get_credential(name.to_sym)
|
|
247
|
+
|
|
248
|
+
unless credential
|
|
249
|
+
puts ::CLI::UI.fmt("{{red:Credential not found:}} #{name}")
|
|
250
|
+
exit 1
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
print_header("Credential: #{name}")
|
|
254
|
+
print_row('Type', credential_type_description(credential.auth_type))
|
|
255
|
+
|
|
256
|
+
credential.to_h(resolve_env: false).each do |key, value|
|
|
257
|
+
next if key == :auth_type
|
|
258
|
+
|
|
259
|
+
display_value = sensitive_field?(key) ? mask_sensitive_value(value.to_s) : value
|
|
260
|
+
print_row(key.to_s, display_value)
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
desc 'create NAME', 'Create a new credential'
|
|
265
|
+
method_option :type, type: :string, required: true,
|
|
266
|
+
desc: 'Credential type (api_key, http_bearer, oauth2, oidc, service_account, google_service_account, basic)'
|
|
267
|
+
method_option :api_key, type: :string, desc: 'API key value (or ENV:VAR_NAME)'
|
|
268
|
+
method_option :bearer_token, type: :string, desc: 'Bearer token (or ENV:VAR_NAME)'
|
|
269
|
+
method_option :client_id, type: :string, desc: 'OAuth2/OIDC client ID'
|
|
270
|
+
method_option :client_secret, type: :string, desc: 'OAuth2/OIDC client secret (or ENV:VAR_NAME)'
|
|
271
|
+
method_option :redirect_uri, type: :string, desc: 'OAuth2/OIDC redirect URI'
|
|
272
|
+
method_option :username, type: :string, desc: 'Basic auth username'
|
|
273
|
+
method_option :password, type: :string, desc: 'Basic auth password (or ENV:VAR_NAME)'
|
|
274
|
+
method_option :service_account_key, type: :string, desc: 'Service account JSON key (or ENV:VAR_NAME)'
|
|
275
|
+
method_option :service_account_key_file, type: :string, desc: 'Path to service account key file'
|
|
276
|
+
def create(name)
|
|
277
|
+
cred_name = name.to_sym
|
|
278
|
+
auth_type = options[:type].to_sym
|
|
279
|
+
|
|
280
|
+
if auth_manager.get_credential(cred_name)
|
|
281
|
+
puts ::CLI::UI.fmt("{{red:Credential already exists:}} #{name}")
|
|
282
|
+
exit 1
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
attrs = { auth_type: auth_type }
|
|
286
|
+
|
|
287
|
+
case auth_type
|
|
288
|
+
when :api_key
|
|
289
|
+
attrs[:api_key] = options[:api_key] || prompt_for('API Key')
|
|
290
|
+
when :http_bearer
|
|
291
|
+
attrs[:bearer_token] = options[:bearer_token] || prompt_for('Bearer Token')
|
|
292
|
+
when :oauth2, :oidc
|
|
293
|
+
attrs[:client_id] = options[:client_id] || prompt_for('Client ID')
|
|
294
|
+
attrs[:client_secret] = options[:client_secret]
|
|
295
|
+
attrs[:redirect_uri] = options[:redirect_uri] if options[:redirect_uri]
|
|
296
|
+
when :service_account, :google_service_account
|
|
297
|
+
attrs[:service_account_key] = if options[:service_account_key_file]
|
|
298
|
+
File.read(options[:service_account_key_file])
|
|
299
|
+
else
|
|
300
|
+
options[:service_account_key] || prompt_for('Service Account Key JSON')
|
|
301
|
+
end
|
|
302
|
+
when :basic
|
|
303
|
+
attrs[:username] = options[:username] || prompt_for('Username')
|
|
304
|
+
attrs[:password] = options[:password] || prompt_for('Password')
|
|
305
|
+
else
|
|
306
|
+
puts ::CLI::UI.fmt("{{red:Unsupported credential type:}} #{auth_type}")
|
|
307
|
+
exit 1
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
credential = Legate::Auth::Credential.new(**attrs)
|
|
311
|
+
auth_manager.register_credential(credential, cred_name)
|
|
312
|
+
puts ::CLI::UI.fmt("{{green:✓}} Credential '#{name}' created successfully")
|
|
313
|
+
rescue Legate::Auth::CredentialError => e
|
|
314
|
+
puts ::CLI::UI.fmt("{{red:Invalid credential:}} #{e.message}")
|
|
315
|
+
exit 1
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
desc 'delete NAME', 'Delete a credential'
|
|
319
|
+
method_option :force, type: :boolean, default: false, desc: 'Force delete even if in use'
|
|
320
|
+
def delete(name)
|
|
321
|
+
cred_name = name.to_sym
|
|
322
|
+
|
|
323
|
+
unless auth_manager.get_credential(cred_name)
|
|
324
|
+
puts ::CLI::UI.fmt("{{red:Credential not found:}} #{name}")
|
|
325
|
+
exit 1
|
|
326
|
+
end
|
|
327
|
+
|
|
328
|
+
# Check for dependent mappings
|
|
329
|
+
url_mappings = auth_manager.instance_variable_get(:@url_mappings) || []
|
|
330
|
+
dependent = url_mappings.select { |m| m[:credential_name] == cred_name }
|
|
331
|
+
|
|
332
|
+
if dependent.any? && !options[:force]
|
|
333
|
+
puts ::CLI::UI.fmt("{{red:Cannot delete}} - credential is used by #{dependent.size} URL mapping(s)")
|
|
334
|
+
puts 'Use --force to delete anyway'
|
|
335
|
+
exit 1
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
auth_manager.unregister_credential(cred_name)
|
|
339
|
+
puts ::CLI::UI.fmt("{{green:✓}} Credential '#{name}' deleted")
|
|
340
|
+
end
|
|
341
|
+
|
|
342
|
+
desc 'test NAME', 'Test a credential'
|
|
343
|
+
method_option :url, type: :string, desc: 'URL to test the credential against'
|
|
344
|
+
def test(name)
|
|
345
|
+
credential = auth_manager.get_credential(name.to_sym)
|
|
346
|
+
|
|
347
|
+
unless credential
|
|
348
|
+
puts ::CLI::UI.fmt("{{red:Credential not found:}} #{name}")
|
|
349
|
+
exit 1
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
print_header("Testing credential: #{name}")
|
|
353
|
+
puts
|
|
354
|
+
|
|
355
|
+
# Basic validation
|
|
356
|
+
begin
|
|
357
|
+
credential.to_h(resolve_env: true)
|
|
358
|
+
puts ::CLI::UI.fmt(' {{green:✓}} Basic validation passed')
|
|
359
|
+
rescue Legate::Auth::EnvironmentVariableNotFoundError => e
|
|
360
|
+
puts ::CLI::UI.fmt(" {{red:✗}} Environment variable not found: #{e.message}")
|
|
361
|
+
exit 1
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
# Type-specific validation
|
|
365
|
+
case credential.auth_type
|
|
366
|
+
when :api_key
|
|
367
|
+
api_key = credential[:api_key]
|
|
368
|
+
if api_key && !api_key.empty?
|
|
369
|
+
puts ::CLI::UI.fmt(' {{green:✓}} API key is present')
|
|
370
|
+
else
|
|
371
|
+
puts ::CLI::UI.fmt(' {{red:✗}} API key is empty')
|
|
372
|
+
end
|
|
373
|
+
when :oauth2, :oidc
|
|
374
|
+
client_id = credential[:client_id]
|
|
375
|
+
client_secret = credential[:client_secret]
|
|
376
|
+
puts client_id ? ::CLI::UI.fmt(' {{green:✓}} Client ID is present') : ::CLI::UI.fmt(' {{red:✗}} Client ID missing')
|
|
377
|
+
puts client_secret ? ::CLI::UI.fmt(' {{green:✓}} Client secret is present') : ::CLI::UI.fmt(' {{yellow:⚠}} Client secret not set')
|
|
378
|
+
when :google_service_account
|
|
379
|
+
begin
|
|
380
|
+
key_data = credential[:service_account_key]
|
|
381
|
+
parsed = JSON.parse(key_data)
|
|
382
|
+
required = %w[type project_id private_key_id private_key client_email client_id]
|
|
383
|
+
missing = required.reject { |f| parsed.key?(f) }
|
|
384
|
+
if missing.empty?
|
|
385
|
+
puts ::CLI::UI.fmt(' {{green:✓}} Service account key is valid JSON with all required fields')
|
|
386
|
+
else
|
|
387
|
+
puts ::CLI::UI.fmt(" {{red:✗}} Missing fields: #{missing.join(', ')}")
|
|
388
|
+
end
|
|
389
|
+
rescue JSON::ParserError
|
|
390
|
+
puts ::CLI::UI.fmt(' {{red:✗}} Service account key is not valid JSON')
|
|
391
|
+
end
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
puts
|
|
395
|
+
puts ::CLI::UI.fmt('{{green:Test complete}}')
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
private
|
|
399
|
+
|
|
400
|
+
def prompt_for(field)
|
|
401
|
+
print "#{field}: "
|
|
402
|
+
$stdin.gets.chomp
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# URL mapping management subcommands
|
|
407
|
+
class AuthMappingCommands < BaseCommand
|
|
408
|
+
include AuthCommandHelpers
|
|
409
|
+
|
|
410
|
+
namespace 'auth:mappings'
|
|
411
|
+
|
|
412
|
+
desc 'list', 'List all URL-to-auth mappings'
|
|
413
|
+
def list
|
|
414
|
+
mappings = auth_manager.instance_variable_get(:@url_mappings) || []
|
|
415
|
+
|
|
416
|
+
if mappings.empty?
|
|
417
|
+
puts ::CLI::UI.fmt('{{yellow:No URL mappings registered.}}')
|
|
418
|
+
return
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
print_header("URL Mappings (#{mappings.size})")
|
|
422
|
+
puts
|
|
423
|
+
|
|
424
|
+
mappings.each_with_index do |mapping, idx|
|
|
425
|
+
pattern = mapping[:pattern].is_a?(Regexp) ? mapping[:pattern].source : mapping[:pattern].to_s
|
|
426
|
+
pattern_type = mapping[:pattern].is_a?(Regexp) ? 'regex' : 'string'
|
|
427
|
+
|
|
428
|
+
puts ::CLI::UI.fmt(" {{bold:[#{idx}]}} #{pattern} {{gray:(#{pattern_type})}}")
|
|
429
|
+
puts " Scheme: #{mapping[:scheme_name]}, Credential: #{mapping[:credential_name]}"
|
|
430
|
+
puts
|
|
431
|
+
end
|
|
432
|
+
end
|
|
433
|
+
|
|
434
|
+
desc 'create', 'Create a new URL mapping'
|
|
435
|
+
method_option :pattern, type: :string, required: true, desc: 'URL pattern (string or regex)'
|
|
436
|
+
method_option :scheme, type: :string, required: true, desc: 'Scheme name to use'
|
|
437
|
+
method_option :credential, type: :string, required: true, desc: 'Credential name to use'
|
|
438
|
+
method_option :regex, type: :boolean, default: false, desc: 'Treat pattern as regex'
|
|
439
|
+
def create
|
|
440
|
+
scheme_name = options[:scheme].to_sym
|
|
441
|
+
cred_name = options[:credential].to_sym
|
|
442
|
+
|
|
443
|
+
unless auth_manager.get_scheme(scheme_name)
|
|
444
|
+
puts ::CLI::UI.fmt("{{red:Scheme not found:}} #{options[:scheme]}")
|
|
445
|
+
exit 1
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
unless auth_manager.get_credential(cred_name)
|
|
449
|
+
puts ::CLI::UI.fmt("{{red:Credential not found:}} #{options[:credential]}")
|
|
450
|
+
exit 1
|
|
451
|
+
end
|
|
452
|
+
|
|
453
|
+
pattern = if options[:regex]
|
|
454
|
+
begin
|
|
455
|
+
Regexp.new(options[:pattern])
|
|
456
|
+
rescue RegexpError => e
|
|
457
|
+
puts ::CLI::UI.fmt("{{red:Invalid regex:}} #{e.message}")
|
|
458
|
+
exit 1
|
|
459
|
+
end
|
|
460
|
+
else
|
|
461
|
+
options[:pattern]
|
|
462
|
+
end
|
|
463
|
+
|
|
464
|
+
auth_manager.register_url_mapping(pattern, scheme_name, cred_name)
|
|
465
|
+
puts ::CLI::UI.fmt('{{green:✓}} URL mapping created successfully')
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
desc 'delete INDEX', 'Delete a URL mapping by index'
|
|
469
|
+
def delete(index)
|
|
470
|
+
idx = index.to_i
|
|
471
|
+
mappings = auth_manager.instance_variable_get(:@url_mappings) || []
|
|
472
|
+
|
|
473
|
+
if idx < 0 || idx >= mappings.size
|
|
474
|
+
puts ::CLI::UI.fmt("{{red:Invalid index:}} #{index} (valid range: 0-#{mappings.size - 1})")
|
|
475
|
+
exit 1
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
auth_manager.remove_url_mapping(idx)
|
|
479
|
+
puts ::CLI::UI.fmt("{{green:✓}} URL mapping [#{index}] deleted")
|
|
480
|
+
end
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
# Main auth commands class that registers subcommands
|
|
484
|
+
class AuthCommands < BaseCommand
|
|
485
|
+
namespace :auth
|
|
486
|
+
|
|
487
|
+
desc 'schemes SUBCOMMAND', 'Manage authentication schemes'
|
|
488
|
+
subcommand 'schemes', AuthSchemeCommands
|
|
489
|
+
|
|
490
|
+
desc 'credentials SUBCOMMAND', 'Manage authentication credentials'
|
|
491
|
+
subcommand 'credentials', AuthCredentialCommands
|
|
492
|
+
|
|
493
|
+
desc 'mappings SUBCOMMAND', 'Manage URL-to-auth mappings'
|
|
494
|
+
subcommand 'mappings', AuthMappingCommands
|
|
495
|
+
|
|
496
|
+
desc 'status', 'Show authentication system status'
|
|
497
|
+
def status
|
|
498
|
+
manager = Legate::Auth::Manager.instance
|
|
499
|
+
manager.load_from_store
|
|
500
|
+
|
|
501
|
+
schemes = manager.instance_variable_get(:@schemes) || {}
|
|
502
|
+
credentials = manager.instance_variable_get(:@credentials) || {}
|
|
503
|
+
mappings = manager.instance_variable_get(:@url_mappings) || []
|
|
504
|
+
|
|
505
|
+
puts ::CLI::UI.fmt('{{bold:Authentication System Status}}')
|
|
506
|
+
puts
|
|
507
|
+
puts ::CLI::UI.fmt(" Schemes: {{cyan:#{schemes.size}}}")
|
|
508
|
+
puts ::CLI::UI.fmt(" Credentials: {{cyan:#{credentials.size}}}")
|
|
509
|
+
puts ::CLI::UI.fmt(" Mappings: {{cyan:#{mappings.size}}}")
|
|
510
|
+
puts
|
|
511
|
+
|
|
512
|
+
puts ::CLI::UI.fmt(' {{gray:Scheme types:}} ' + schemes.values.map(&:scheme_type).uniq.join(', ')) if schemes.any?
|
|
513
|
+
|
|
514
|
+
return unless credentials.any?
|
|
515
|
+
|
|
516
|
+
puts ::CLI::UI.fmt(' {{gray:Credential types:}} ' + credentials.values.map(&:auth_type).uniq.join(', '))
|
|
517
|
+
end
|
|
518
|
+
end
|
|
519
|
+
end
|
|
520
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# File: lib/legate/cli/base_command.rb
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'thor'
|
|
5
|
+
|
|
6
|
+
module Legate
|
|
7
|
+
module CLI
|
|
8
|
+
# Base class for every Legate CLI command group.
|
|
9
|
+
#
|
|
10
|
+
# Thor 1.5 ships a built-in `tree` command on the base Thor class. Left
|
|
11
|
+
# alone it leaks into help output namespaced by the implementation class
|
|
12
|
+
# (e.g. `legate tool_commands tree`), which looks like a bug. We hide it
|
|
13
|
+
# here once so all command groups inherit clean help output.
|
|
14
|
+
class BaseCommand < Thor
|
|
15
|
+
# The method body is intentionally a bare `super`: redefining `tree` here
|
|
16
|
+
# is what lets the preceding `hide: true` take effect, suppressing Thor's
|
|
17
|
+
# inherited (visible) command without changing its behavior.
|
|
18
|
+
desc 'tree', 'Print a tree of all available commands', hide: true
|
|
19
|
+
def tree # rubocop:disable Lint/UselessMethodDefinition
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|