dash 4.1.2 → 4.2.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 +4 -4
- data/lib/dash/autoscale/connections/builder.rb +51 -0
- data/lib/dash/autoscale/connections.rb +102 -0
- data/lib/dash/autoscale/controller.rb +296 -0
- data/lib/dash/autoscale/cron.rb +75 -0
- data/lib/dash/autoscale/decision.rb +89 -0
- data/lib/dash/autoscale/duration.rb +19 -0
- data/lib/dash/autoscale/evaluation.rb +52 -0
- data/lib/dash/autoscale/guard.rb +48 -0
- data/lib/dash/autoscale/lease.rb +55 -0
- data/lib/dash/autoscale/lease_held.rb +2 -0
- data/lib/dash/autoscale/lease_lost.rb +2 -0
- data/lib/dash/autoscale/member.rb +28 -0
- data/lib/dash/autoscale/metrics.rb +70 -0
- data/lib/dash/autoscale/metrics_server.rb +71 -0
- data/lib/dash/autoscale/observation.rb +41 -0
- data/lib/dash/autoscale/pause.rb +34 -0
- data/lib/dash/autoscale/policy.rb +198 -0
- data/lib/dash/autoscale/pool.rb +103 -0
- data/lib/dash/autoscale/prometheus_client.rb +76 -0
- data/lib/dash/autoscale/provider/base.rb +43 -0
- data/lib/dash/autoscale/provider/exec.rb +94 -0
- data/lib/dash/autoscale/provider/upcloud.rb +140 -0
- data/lib/dash/autoscale/provider.rb +9 -0
- data/lib/dash/autoscale/provider_error.rb +4 -0
- data/lib/dash/autoscale/read_only_query.rb +38 -0
- data/lib/dash/autoscale/reader.rb +17 -0
- data/lib/dash/autoscale/recorder.rb +13 -0
- data/lib/dash/autoscale/role_state.rb +110 -0
- data/lib/dash/autoscale/sample.rb +13 -0
- data/lib/dash/autoscale/signal/pgbus.rb +19 -0
- data/lib/dash/autoscale/signal/prometheus.rb +8 -0
- data/lib/dash/autoscale/signal/sidekiq.rb +49 -0
- data/lib/dash/autoscale/signal.rb +31 -0
- data/lib/dash/autoscale/simulation.rb +200 -0
- data/lib/dash/autoscale/state_store.rb +132 -0
- data/lib/dash/autoscale/timestamp.rb +15 -0
- data/lib/dash/autoscale/tunnel.rb +48 -0
- data/lib/dash/cli/accessory.rb +16 -0
- data/lib/dash/cli/app/boot.rb +69 -44
- data/lib/dash/cli/app/boot_state.rb +70 -0
- data/lib/dash/cli/app/rollout_boot.rb +28 -9
- data/lib/dash/cli/app/running_targets.rb +39 -0
- data/lib/dash/cli/app/slot_version.rb +29 -0
- data/lib/dash/cli/app.rb +89 -32
- data/lib/dash/cli/autoscale.rb +312 -0
- data/lib/dash/cli/base.rb +15 -3
- data/lib/dash/cli/lock.rb +6 -1
- data/lib/dash/cli/main.rb +77 -8
- data/lib/dash/cli/proxy/inspection.rb +52 -0
- data/lib/dash/cli/proxy/loadbalancer_deploy.rb +20 -0
- data/lib/dash/cli/proxy/loadbalancer_reboot.rb +1 -1
- data/lib/dash/cli/proxy/reboot.rb +4 -9
- data/lib/dash/cli/proxy.rb +12 -7
- data/lib/dash/cli/prune.rb +5 -3
- data/lib/dash/cli/report.rb +4 -1
- data/lib/dash/cli/scale/host_plan.rb +63 -0
- data/lib/dash/cli/scale/join.rb +128 -0
- data/lib/dash/cli/scale/leave.rb +58 -0
- data/lib/dash/cli/scale/placement.rb +54 -0
- data/lib/dash/cli/scale/power_off.rb +26 -0
- data/lib/dash/cli/scale/replica_join.rb +74 -0
- data/lib/dash/cli/scale/replica_leave.rb +121 -0
- data/lib/dash/cli/scale.rb +276 -0
- data/lib/dash/cli/server.rb +41 -0
- data/lib/dash/cli/stats_table.rb +34 -0
- data/lib/dash/cli/templates/sample_hooks/post-scale-in.sample +3 -0
- data/lib/dash/cli/templates/sample_hooks/post-scale-out.sample +3 -0
- data/lib/dash/cli/templates/sample_hooks/pre-scale-in.sample +6 -0
- data/lib/dash/cli/templates/sample_hooks/pre-scale-out.sample +6 -0
- data/lib/dash/commander.rb +17 -3
- data/lib/dash/commands/accessory/proxy.rb +1 -1
- data/lib/dash/commands/accessory.rb +21 -2
- data/lib/dash/commands/app/containers.rb +28 -3
- data/lib/dash/commands/app/logging.rb +13 -2
- data/lib/dash/commands/app/proxy.rb +4 -4
- data/lib/dash/commands/app.rb +90 -10
- data/lib/dash/commands/auditor.rb +2 -2
- data/lib/dash/commands/autoscale.rb +133 -0
- data/lib/dash/commands/base.rb +4 -0
- data/lib/dash/commands/proxy/services.rb +10 -0
- data/lib/dash/commands/prune.rb +10 -2
- data/lib/dash/commands/server.rb +16 -0
- data/lib/dash/configuration/accessory.rb +2 -2
- data/lib/dash/configuration/autoscale.rb +123 -0
- data/lib/dash/configuration/docs/autoscale.yml +141 -0
- data/lib/dash/configuration/docs/configuration.yml +8 -2
- data/lib/dash/configuration/docs/proxy.yml +12 -9
- data/lib/dash/configuration/docs/role.yml +203 -0
- data/lib/dash/configuration/loadbalancer.rb +3 -2
- data/lib/dash/configuration/proxy/run.rb +1 -1
- data/lib/dash/configuration/proxy.rb +19 -7
- data/lib/dash/configuration/role/drain.rb +49 -0
- data/lib/dash/configuration/role/replicas.rb +72 -0
- data/lib/dash/configuration/role/scale/guard.rb +40 -0
- data/lib/dash/configuration/role/scale/signal.rb +93 -0
- data/lib/dash/configuration/role/scale/window.rb +37 -0
- data/lib/dash/configuration/role/scale.rb +199 -0
- data/lib/dash/configuration/role.rb +123 -6
- data/lib/dash/configuration/validator/autoscale.rb +126 -0
- data/lib/dash/configuration/validator/proxy.rb +13 -0
- data/lib/dash/configuration/validator/role.rb +26 -5
- data/lib/dash/configuration.rb +126 -15
- data/lib/dash/diagnostics/audit.rb +28 -0
- data/lib/dash/diagnostics/autoscale_decisions.rb +18 -0
- data/lib/dash/diagnostics/autoscale_explain.rb +30 -0
- data/lib/dash/diagnostics/autoscale_signal.rb +82 -0
- data/lib/dash/diagnostics/base.rb +53 -0
- data/lib/dash/diagnostics/config.rb +32 -0
- data/lib/dash/diagnostics/container_stats.rb +67 -0
- data/lib/dash/diagnostics/containers.rb +20 -0
- data/lib/dash/diagnostics/controller_status.rb +44 -0
- data/lib/dash/diagnostics/docker_ps.rb +40 -0
- data/lib/dash/{cli → diagnostics}/doctor/config_checks.rb +3 -3
- data/lib/dash/diagnostics/doctor/controller_checks.rb +46 -0
- data/lib/dash/{cli → diagnostics}/doctor/endpoint_checks.rb +12 -4
- data/lib/dash/{cli → diagnostics}/doctor/host_checks.rb +5 -4
- data/lib/dash/diagnostics/doctor/pool_checks.rb +65 -0
- data/lib/dash/diagnostics/doctor/signal_checks.rb +54 -0
- data/lib/dash/diagnostics/doctor.rb +182 -0
- data/lib/dash/diagnostics/drift.rb +168 -0
- data/lib/dash/diagnostics/host_stats.rb +59 -0
- data/lib/dash/diagnostics/lines.rb +14 -0
- data/lib/dash/diagnostics/lock.rb +27 -0
- data/lib/dash/diagnostics/logs.rb +76 -0
- data/lib/dash/diagnostics/pool.rb +41 -0
- data/lib/dash/diagnostics/proxy_services.rb +36 -0
- data/lib/dash/diagnostics/redactor.rb +48 -0
- data/lib/dash/diagnostics/reports.rb +17 -0
- data/lib/dash/diagnostics/scale.rb +51 -0
- data/lib/dash/diagnostics/units.rb +31 -0
- data/lib/dash/mcp/base_tool.rb +43 -0
- data/lib/dash/mcp/runner.rb +28 -0
- data/lib/dash/mcp/server.rb +40 -0
- data/lib/dash/mcp/session.rb +51 -0
- data/lib/dash/mcp/tools/audit_tool.rb +11 -0
- data/lib/dash/mcp/tools/autoscale_decisions_tool.rb +22 -0
- data/lib/dash/mcp/tools/autoscale_explain_tool.rb +56 -0
- data/lib/dash/mcp/tools/config_tool.rb +10 -0
- data/lib/dash/mcp/tools/container_stats_tool.rb +15 -0
- data/lib/dash/mcp/tools/containers_tool.rb +10 -0
- data/lib/dash/mcp/tools/controller_status_tool.rb +18 -0
- data/lib/dash/mcp/tools/deploy_reports_tool.rb +10 -0
- data/lib/dash/mcp/tools/doctor_tool.rb +13 -0
- data/lib/dash/mcp/tools/drift_tool.rb +16 -0
- data/lib/dash/mcp/tools/host_stats_tool.rb +14 -0
- data/lib/dash/mcp/tools/lock_status_tool.rb +15 -0
- data/lib/dash/mcp/tools/logs_tool.rb +41 -0
- data/lib/dash/mcp/tools/pool_members_tool.rb +15 -0
- data/lib/dash/mcp/tools/proxy_services_tool.rb +10 -0
- data/lib/dash/mcp/tools/scale_status_tool.rb +10 -0
- data/lib/dash/mcp/tools/signal_sample_tool.rb +19 -0
- data/lib/dash/mcp/transport.rb +14 -0
- data/lib/dash/mcp.rb +56 -0
- data/lib/dash/sshkit_with_ext.rb +4 -4
- data/lib/dash/utils.rb +7 -0
- data/lib/dash/version.rb +1 -1
- data/lib/dash.rb +2 -0
- metadata +119 -5
- data/lib/dash/cli/doctor.rb +0 -113
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::AutoscaleExplainTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "autoscale_explain"
|
|
3
|
+
title "Autoscale explain"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
One live evaluation of a scaled role by the autoscale policy, as the controller's next tick would make it, without acting:
|
|
6
|
+
the action (scale_out, scale_in, replace_member, hold), the container counts from and to, the reason codes (schedule_floor,
|
|
7
|
+
at_min, at_max, at_target, cooldown, warming_up, paused, lock_busy, member_unreachable, host_unreachable, pool_unreadable,
|
|
8
|
+
action_failed, above_threshold, below_threshold, held_by_guard, missing_data), when a hold can next change (eligible_at),
|
|
9
|
+
and every input: running count, floor, min/max bounds, step, active schedule windows, cooldowns, warmup and boot timeout,
|
|
10
|
+
last scale times, warming and unreachable members, unreadable baseline hosts, pause, and for a role with a signal its
|
|
11
|
+
sample, its guards' samples, since when it has been above or below its band, and the band itself. controlled is false
|
|
12
|
+
for a role without a schedule or a signal, which the controller leaves alone.
|
|
13
|
+
DESC
|
|
14
|
+
input_schema properties: { role: { type: "string", description: "The scaled role" } }, required: [ "role" ], additionalProperties: false
|
|
15
|
+
|
|
16
|
+
def self.call(server_context:, role:)
|
|
17
|
+
answer(server_context) do
|
|
18
|
+
ensure_state_host_in_scope
|
|
19
|
+
Dash::Diagnostics::AutoscaleExplain.new(role: scoped_role(role)).to_h
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.scoped_role(name)
|
|
24
|
+
role = DASH.config.role(name) || raise(ArgumentError, "No role named #{name} (#{DASH.config.roles.map(&:name).join(",")})")
|
|
25
|
+
raise ArgumentError, "#{name} is outside this server's --roles and --hosts" unless roles_in_scope.include?(role)
|
|
26
|
+
|
|
27
|
+
role
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The roles within --roles, and with a baseline host within --hosts - from deploy.yml,
|
|
31
|
+
# never DASH.roles: that would ask the provider for the pool, and a pool that does not
|
|
32
|
+
# answer is an answer explain should give.
|
|
33
|
+
def self.roles_in_scope
|
|
34
|
+
roles = DASH.specific_roles || DASH.config.roles
|
|
35
|
+
DASH.specific_hosts ? roles.select { |role| (role.baseline_hosts & DASH.specific_hosts).any? } : roles
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# nil when nothing narrows the server: every role's decisions.
|
|
39
|
+
def self.role_names_in_scope
|
|
40
|
+
roles_in_scope.map(&:name) if DASH.specific_roles || DASH.specific_hosts
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# The controller's state host (Dash::Autoscale::StateStore.host) must be within the
|
|
44
|
+
# server's --hosts, or the hosts of its --roles (as lock_status asks) - when it is one of
|
|
45
|
+
# the app's hosts. The ceiling is over those: an `autoscale.controller` ops host that is
|
|
46
|
+
# none of them is outside its reach, and always answers. Baseline hosts only, never the
|
|
47
|
+
# pool, which a scope check must not ask.
|
|
48
|
+
def self.ensure_state_host_in_scope
|
|
49
|
+
host = Dash::Autoscale::StateStore.host
|
|
50
|
+
return unless (DASH.config.roles.flat_map(&:baseline_hosts) + DASH.config.accessories.flat_map(&:hosts)).include?(host)
|
|
51
|
+
|
|
52
|
+
hosts = DASH.specific_hosts || DASH.specific_roles&.flat_map(&:baseline_hosts)
|
|
53
|
+
|
|
54
|
+
raise ArgumentError, "The autoscale state lives on #{host}, outside this server's --hosts and --roles" if hosts && !hosts.include?(host)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::ConfigTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "config"
|
|
3
|
+
title "Configuration"
|
|
4
|
+
description "The effective deploy configuration (redacted) and its topology: which hosts each role runs on, which roles are proxied, the proxy hosts and the load balancer. Local, no SSH."
|
|
5
|
+
input_schema properties: {}, additionalProperties: false
|
|
6
|
+
|
|
7
|
+
def self.call(server_context:)
|
|
8
|
+
answer(server_context) { Dash::Diagnostics::Config.new.to_h }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::ContainerStatsTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "container_stats"
|
|
3
|
+
title "Container resource usage"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
CPU %, memory and its limit, network and block I/O, and PIDs of every running container of this service per app host,
|
|
6
|
+
with role, replica slot and version - and under `accessories`, the same for each accessory's container on its own hosts.
|
|
7
|
+
A point-in-time sample: docker stats measures over about a second per host.
|
|
8
|
+
No argument reaches the command; hosts and roles only choose which configured hosts are asked.
|
|
9
|
+
DESC
|
|
10
|
+
input_schema properties: SCOPE, additionalProperties: false
|
|
11
|
+
|
|
12
|
+
def self.call(server_context:, hosts: nil, roles: nil)
|
|
13
|
+
answer(server_context, hosts: hosts, roles: roles) { Dash::Diagnostics::ContainerStats.new.to_h }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::ContainersTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "containers"
|
|
3
|
+
title "Containers"
|
|
4
|
+
description "Every container of this service per app host: role, replica slot, version, state, health, image and creation time."
|
|
5
|
+
input_schema properties: SCOPE, additionalProperties: false
|
|
6
|
+
|
|
7
|
+
def self.call(server_context:, hosts: nil, roles: nil)
|
|
8
|
+
answer(server_context, hosts: hosts, roles: roles) { Dash::Diagnostics::Containers.new.to_h }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::ControllerStatusTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "controller_status"
|
|
3
|
+
title "Autoscale controller"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
Whether the autoscale controller (dash autoscale run) is running: its heartbeat - controller id, host, pid, dash version,
|
|
6
|
+
mode, interval, last tick and its age - read as running, stale (no tick for three intervals) or stopped; null when none ever ran.
|
|
7
|
+
Also the roles with a schedule or signal it controls, and the pauses in force (role, until, by whom).
|
|
8
|
+
DESC
|
|
9
|
+
input_schema properties: {}, additionalProperties: false
|
|
10
|
+
|
|
11
|
+
def self.call(server_context:)
|
|
12
|
+
answer(server_context) do
|
|
13
|
+
Dash::Mcp::Tools::AutoscaleExplainTool.ensure_state_host_in_scope
|
|
14
|
+
|
|
15
|
+
Dash::Diagnostics::ControllerStatus.new.to_h
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::DeployReportsTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "deploy_reports"
|
|
3
|
+
title "Deploy reports"
|
|
4
|
+
description "The saved deploy reports for this destination, most recent first: command, status, runtime, per-phase timings and advice. Local, no SSH."
|
|
5
|
+
input_schema properties: { last: { type: "integer", minimum: 1, maximum: Dash::Diagnostics::Reports::MAX, description: "How many reports (default 1)" } }, additionalProperties: false
|
|
6
|
+
|
|
7
|
+
def self.call(server_context:, last: 1)
|
|
8
|
+
answer(server_context) { Dash::Diagnostics::Reports.new(last: last).to_h }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::DoctorTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "doctor"
|
|
3
|
+
title "Doctor"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
dash doctor's readiness checks as {check, target, status, detail}: SSH, Docker, proxy image and version, ports, DNS,
|
|
6
|
+
certificates, readiness gates and drift. The registry check is skipped: it runs docker login on each host.
|
|
7
|
+
DESC
|
|
8
|
+
input_schema properties: SCOPE, additionalProperties: false
|
|
9
|
+
|
|
10
|
+
def self.call(server_context:, hosts: nil, roles: nil)
|
|
11
|
+
answer(server_context, hosts: hosts, roles: roles) { Dash::Diagnostics::Doctor.new(registry: false).to_h }
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::DriftTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "drift"
|
|
3
|
+
title "Drift"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
Whether the proxy pool is consistent with what runs: compares containers with dash-proxy and load balancer targets.
|
|
6
|
+
Each mismatch has a code: proxy_target_not_running, running_not_targeted, loadbalancer_target_missing,
|
|
7
|
+
loadbalancer_target_extra, version_mismatch, multiple_running_versions, member_not_targeted (a started pool member
|
|
8
|
+
the load balancer does not forward to), member_orphan (a started pool member running nothing of its role).
|
|
9
|
+
Version codes are skipped while the deploy lock is held.
|
|
10
|
+
DESC
|
|
11
|
+
input_schema properties: SCOPE, additionalProperties: false
|
|
12
|
+
|
|
13
|
+
def self.call(server_context:, hosts: nil, roles: nil)
|
|
14
|
+
answer(server_context, hosts: hosts, roles: roles) { Dash::Diagnostics::Drift.take.to_h }
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::HostStatsTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "host_stats"
|
|
3
|
+
title "Host resource usage"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
Per host: load average (1/5/15 minutes, and per CPU), CPU count, memory and swap, disk for / and for Docker's data root,
|
|
6
|
+
and uptime. A point-in-time read of /proc and df. No argument reaches the command; hosts and roles only choose which
|
|
7
|
+
configured hosts are asked.
|
|
8
|
+
DESC
|
|
9
|
+
input_schema properties: SCOPE, additionalProperties: false
|
|
10
|
+
|
|
11
|
+
def self.call(server_context:, hosts: nil, roles: nil)
|
|
12
|
+
answer(server_context, hosts: hosts, roles: roles) { Dash::Diagnostics::HostStats.new.to_h }
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::LockStatusTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "lock_status"
|
|
3
|
+
title "Deploy lock"
|
|
4
|
+
description "Whether this destination's deploy lock is held, by whom, since when, at which version and with what message."
|
|
5
|
+
input_schema properties: {}, additionalProperties: false
|
|
6
|
+
|
|
7
|
+
def self.call(server_context:)
|
|
8
|
+
answer(server_context) do
|
|
9
|
+
primary = DASH.config.primary_host
|
|
10
|
+
raise ArgumentError, "The deploy lock lives on the primary host #{primary}, outside this server's --hosts" unless DASH.hosts.include?(primary)
|
|
11
|
+
|
|
12
|
+
Dash::Diagnostics::Lock.new(host: primary).to_h
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::LogsTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "logs"
|
|
3
|
+
title "Container logs"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
The tail of a role's containers on its hosts (every replica slot), or of an accessory's. Off unless the server was started with --allow-logs
|
|
6
|
+
(or DASH_MCP_ALLOW_LOGS=true): logs can carry personal data. grep is a plain substring match.
|
|
7
|
+
DESC
|
|
8
|
+
input_schema properties: {
|
|
9
|
+
role: { type: "string", description: "The role (default: the primary role)" },
|
|
10
|
+
accessory: { type: "string", description: "An accessory instead of a role (e.g. the database)" },
|
|
11
|
+
hosts: SCOPE[:hosts],
|
|
12
|
+
lines: { type: "integer", minimum: 1, maximum: Dash::Diagnostics::Lines::MAX, description: "Lines per container (default 100)" },
|
|
13
|
+
since: { type: "string", description: "A duration like 15m or 1h30m, or a timestamp like 2026-10-05T10:00:00Z" },
|
|
14
|
+
grep: { type: "string", maxLength: Dash::Diagnostics::Logs::MAX_GREP_LENGTH, description: "Only lines containing this text" }
|
|
15
|
+
}, additionalProperties: false
|
|
16
|
+
|
|
17
|
+
REFUSED = "The logs tool is off: container logs can carry personal data. Restart `dash mcp` with --allow-logs (or DASH_MCP_ALLOW_LOGS=true) to enable it."
|
|
18
|
+
|
|
19
|
+
def self.call(server_context:, role: nil, accessory: nil, hosts: nil, lines: 100, since: nil, grep: nil)
|
|
20
|
+
return error_response(REFUSED) unless server_context.fetch(:session).allow_logs?
|
|
21
|
+
return error_response("Pass a role or an accessory, not both") if role && accessory
|
|
22
|
+
|
|
23
|
+
answer(server_context, hosts: hosts) do
|
|
24
|
+
source = accessory ? { accessory: scoped_accessory(accessory) } : { role: scoped_role(role) }
|
|
25
|
+
Dash::Diagnostics::Logs.new(**source, lines: lines, since: since, grep: grep, redactor: server_context.fetch(:session).redactor).to_h
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.scoped_accessory(name)
|
|
30
|
+
accessory = DASH.config.accessory(name) || raise(ArgumentError, "No accessory #{name} (#{DASH.accessory_names.join(",")})")
|
|
31
|
+
raise ArgumentError, "Accessory #{name} runs on no host within this server's scope" if (accessory.hosts & DASH.accessory_hosts).empty?
|
|
32
|
+
|
|
33
|
+
accessory
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.scoped_role(name)
|
|
37
|
+
return DASH.primary_role unless name
|
|
38
|
+
|
|
39
|
+
DASH.roles.find { |role| role.name == name } || raise(ArgumentError, "No role #{name} within this server's scope (#{DASH.roles.map(&:name).join(",")})")
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::PoolMembersTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "pool_members"
|
|
3
|
+
title "Pool members"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
The autoscale pool of every scaled role: its provider, members mode (power or create), host bounds and baseline
|
|
6
|
+
hosts, and per member its provider id, host, state (started, stopped, maintenance, error), labels, whether the
|
|
7
|
+
provider vouched for it (verified false: taken from --hosts while the provider was down), the versions a started
|
|
8
|
+
member runs, and orphan (started but running nothing of the role). A provider that does not answer is the role's error.
|
|
9
|
+
DESC
|
|
10
|
+
input_schema properties: SCOPE, additionalProperties: false
|
|
11
|
+
|
|
12
|
+
def self.call(server_context:, hosts: nil, roles: nil)
|
|
13
|
+
answer(server_context, hosts: hosts, roles: roles) { Dash::Diagnostics::Pool.new.to_h }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::ProxyServicesTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "proxy_services"
|
|
3
|
+
title "Proxy services"
|
|
4
|
+
description "What dash-proxy routes for this deploy on each proxy host (domains, targets, state), and the load balancer's routes when load balancing is on."
|
|
5
|
+
input_schema properties: SCOPE.slice(:hosts), additionalProperties: false
|
|
6
|
+
|
|
7
|
+
def self.call(server_context:, hosts: nil)
|
|
8
|
+
answer(server_context, hosts: hosts) { Dash::Diagnostics::ProxyServices.new.to_h }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::ScaleStatusTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "scale_status"
|
|
3
|
+
title "Scale status"
|
|
4
|
+
description "Per role: its replicas bounds (min, max per host), how many containers run in total, and each host's replica slots with version and docker status. Hosts that could not be read are listed under unread. A role with scale also has its host bounds and its pool members (orphan: started but running nothing of the role)."
|
|
5
|
+
input_schema properties: SCOPE, additionalProperties: false
|
|
6
|
+
|
|
7
|
+
def self.call(server_context:, hosts: nil, roles: nil)
|
|
8
|
+
answer(server_context, hosts: hosts, roles: roles) { Dash::Diagnostics::Scale.new.to_h }
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
class Dash::Mcp::Tools::SignalSampleTool < Dash::Mcp::BaseTool
|
|
2
|
+
tool_name "signal_sample"
|
|
3
|
+
title "Signal sample"
|
|
4
|
+
description <<~DESC
|
|
5
|
+
One live sample of a scaled role's autoscale signal (scale.signal: sidekiq or pgbus queue age in seconds, or a Prometheus
|
|
6
|
+
query) and of each of its saturation guards (scale.hold_when), read from the machine dash mcp runs on, each with its latency:
|
|
7
|
+
the source, value, time and error of the signal, where it sits against the role's band (above, inside, below) and the band
|
|
8
|
+
itself (up.above, up.for, down.below, down.for); per guard its index, source, bound, value, error and whether it is holding
|
|
9
|
+
a scale-out. The fields match the signal and guards inputs of the controller's decisions, so a sample compares directly
|
|
10
|
+
with autoscale_explain and autoscale_decisions. Reads only. configured is false for a role without a signal.
|
|
11
|
+
DESC
|
|
12
|
+
input_schema properties: { role: { type: "string", description: "The scaled role" } }, required: [ "role" ], additionalProperties: false
|
|
13
|
+
|
|
14
|
+
def self.call(server_context:, role:)
|
|
15
|
+
answer(server_context) do
|
|
16
|
+
Dash::Diagnostics::AutoscaleSignal.new(role: Dash::Mcp::Tools::AutoscaleExplainTool.scoped_role(role)).to_h
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# stdio, with the protocol on an IO of its own. dash prints from everywhere - SSHKit's
|
|
2
|
+
# formatter, `say`, hooks, warnings - and over stdio any line on stdout is a protocol
|
|
3
|
+
# frame, so the Runner points $stdout at $stderr and hands the real stdout here.
|
|
4
|
+
class Dash::Mcp::Transport < ::MCP::Server::Transports::StdioTransport
|
|
5
|
+
def initialize(server, output:)
|
|
6
|
+
super(server)
|
|
7
|
+
@output = output
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def send_response(message)
|
|
11
|
+
@output.puts(message.is_a?(String) ? message : JSON.generate(message))
|
|
12
|
+
@output.flush
|
|
13
|
+
end
|
|
14
|
+
end
|
data/lib/dash/mcp.rb
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# `dash mcp`: read-only diagnostics for an AI agent over the Model Context Protocol.
|
|
2
|
+
#
|
|
3
|
+
# Kept out of Zeitwerk (lib/dash.rb ignores lib/dash/mcp/) because the tools subclass
|
|
4
|
+
# `MCP::Tool` from the optional `mcp` gem, which a deploy should never need. This file
|
|
5
|
+
# stays autoloadable so `dash mcp` can say what to install; `load!` pulls in the rest.
|
|
6
|
+
module Dash::Mcp
|
|
7
|
+
module Tools; end
|
|
8
|
+
|
|
9
|
+
REQUIRES = %w[
|
|
10
|
+
dash/mcp/session
|
|
11
|
+
dash/mcp/base_tool
|
|
12
|
+
dash/mcp/tools/config_tool
|
|
13
|
+
dash/mcp/tools/containers_tool
|
|
14
|
+
dash/mcp/tools/proxy_services_tool
|
|
15
|
+
dash/mcp/tools/drift_tool
|
|
16
|
+
dash/mcp/tools/deploy_reports_tool
|
|
17
|
+
dash/mcp/tools/audit_tool
|
|
18
|
+
dash/mcp/tools/lock_status_tool
|
|
19
|
+
dash/mcp/tools/doctor_tool
|
|
20
|
+
dash/mcp/tools/logs_tool
|
|
21
|
+
dash/mcp/tools/scale_status_tool
|
|
22
|
+
dash/mcp/tools/pool_members_tool
|
|
23
|
+
dash/mcp/tools/autoscale_explain_tool
|
|
24
|
+
dash/mcp/tools/autoscale_decisions_tool
|
|
25
|
+
dash/mcp/tools/controller_status_tool
|
|
26
|
+
dash/mcp/tools/signal_sample_tool
|
|
27
|
+
dash/mcp/tools/container_stats_tool
|
|
28
|
+
dash/mcp/tools/host_stats_tool
|
|
29
|
+
dash/mcp/server
|
|
30
|
+
dash/mcp/transport
|
|
31
|
+
dash/mcp/runner
|
|
32
|
+
].freeze
|
|
33
|
+
|
|
34
|
+
# Everything that prints after this lands on stderr; the returned IO carries only the
|
|
35
|
+
# protocol. `dash mcp` calls it first, before even the gem loads, so nothing - not the
|
|
36
|
+
# "add the gem" error either - can print onto the protocol stream.
|
|
37
|
+
def self.reserve_stdout!
|
|
38
|
+
protocol = $stdout
|
|
39
|
+
protocol.set_encoding("UTF-8")
|
|
40
|
+
$stdout = $stderr
|
|
41
|
+
SSHKit.config.output = SSHKit::Formatter::Pretty.new($stderr)
|
|
42
|
+
protocol
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Only the gem's own require is rescued, so a broken dash/mcp/* require shows up as
|
|
46
|
+
# itself instead of as "add the gem".
|
|
47
|
+
def self.load!
|
|
48
|
+
begin
|
|
49
|
+
require "mcp"
|
|
50
|
+
rescue LoadError
|
|
51
|
+
raise Dash::ConfigurationError, "dash mcp needs the `mcp` gem: add `gem \"mcp\", \"~> 1.6\"` to your Gemfile and run `bundle install`"
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
REQUIRES.each { |path| require path }
|
|
55
|
+
end
|
|
56
|
+
end
|
data/lib/dash/sshkit_with_ext.rb
CHANGED
|
@@ -45,10 +45,10 @@ class SSHKit::Backend::Abstract
|
|
|
45
45
|
$stdout.binmode
|
|
46
46
|
$stdout.write(output)
|
|
47
47
|
else
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
puts "#{output}\n\n"
|
|
48
|
+
# One write: hosts print from parallel threads onto an unbuffered stdout, so a header
|
|
49
|
+
# written on its own can end up above another host's output.
|
|
50
|
+
header = "#{type} Host: #{host}\n" unless quiet
|
|
51
|
+
puts "#{header}#{output}\n\n"
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
data/lib/dash/utils.rb
CHANGED
|
@@ -93,6 +93,13 @@ module Dash::Utils
|
|
|
93
93
|
.join
|
|
94
94
|
end
|
|
95
95
|
|
|
96
|
+
# Wraps a value in single quotes, closing and reopening them around any quote the value
|
|
97
|
+
# carries, so the shell reads it as one literal word: no expansion, no command
|
|
98
|
+
# substitution, no way out of the quotes. `grep 'my-id'` stays `grep 'my-id'`.
|
|
99
|
+
def single_quote(value)
|
|
100
|
+
"'#{value.to_s.gsub("'") { %q('\\'') }}'"
|
|
101
|
+
end
|
|
102
|
+
|
|
96
103
|
def escape_ascii_shell_value(value)
|
|
97
104
|
value.to_s.dump
|
|
98
105
|
.gsub(/`/, '\\\\`')
|
data/lib/dash/version.rb
CHANGED
data/lib/dash.rb
CHANGED
|
@@ -26,5 +26,7 @@ require "digest/sha2"
|
|
|
26
26
|
|
|
27
27
|
loader = Zeitwerk::Loader.for_gem
|
|
28
28
|
loader.ignore(File.join(__dir__, "dash", "sshkit_with_ext.rb"))
|
|
29
|
+
# The MCP tools subclass MCP::Tool from the optional `mcp` gem; Dash::Mcp.load! requires them.
|
|
30
|
+
loader.ignore(File.join(__dir__, "dash", "mcp"))
|
|
29
31
|
loader.setup
|
|
30
32
|
loader.eager_load_namespace(Dash::Cli) # We need all commands loaded.
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: dash
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 4.
|
|
4
|
+
version: 4.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mikael Henriksson
|
|
@@ -177,6 +177,43 @@ files:
|
|
|
177
177
|
- README.md
|
|
178
178
|
- bin/dash
|
|
179
179
|
- lib/dash.rb
|
|
180
|
+
- lib/dash/autoscale/connections.rb
|
|
181
|
+
- lib/dash/autoscale/connections/builder.rb
|
|
182
|
+
- lib/dash/autoscale/controller.rb
|
|
183
|
+
- lib/dash/autoscale/cron.rb
|
|
184
|
+
- lib/dash/autoscale/decision.rb
|
|
185
|
+
- lib/dash/autoscale/duration.rb
|
|
186
|
+
- lib/dash/autoscale/evaluation.rb
|
|
187
|
+
- lib/dash/autoscale/guard.rb
|
|
188
|
+
- lib/dash/autoscale/lease.rb
|
|
189
|
+
- lib/dash/autoscale/lease_held.rb
|
|
190
|
+
- lib/dash/autoscale/lease_lost.rb
|
|
191
|
+
- lib/dash/autoscale/member.rb
|
|
192
|
+
- lib/dash/autoscale/metrics.rb
|
|
193
|
+
- lib/dash/autoscale/metrics_server.rb
|
|
194
|
+
- lib/dash/autoscale/observation.rb
|
|
195
|
+
- lib/dash/autoscale/pause.rb
|
|
196
|
+
- lib/dash/autoscale/policy.rb
|
|
197
|
+
- lib/dash/autoscale/pool.rb
|
|
198
|
+
- lib/dash/autoscale/prometheus_client.rb
|
|
199
|
+
- lib/dash/autoscale/provider.rb
|
|
200
|
+
- lib/dash/autoscale/provider/base.rb
|
|
201
|
+
- lib/dash/autoscale/provider/exec.rb
|
|
202
|
+
- lib/dash/autoscale/provider/upcloud.rb
|
|
203
|
+
- lib/dash/autoscale/provider_error.rb
|
|
204
|
+
- lib/dash/autoscale/read_only_query.rb
|
|
205
|
+
- lib/dash/autoscale/reader.rb
|
|
206
|
+
- lib/dash/autoscale/recorder.rb
|
|
207
|
+
- lib/dash/autoscale/role_state.rb
|
|
208
|
+
- lib/dash/autoscale/sample.rb
|
|
209
|
+
- lib/dash/autoscale/signal.rb
|
|
210
|
+
- lib/dash/autoscale/signal/pgbus.rb
|
|
211
|
+
- lib/dash/autoscale/signal/prometheus.rb
|
|
212
|
+
- lib/dash/autoscale/signal/sidekiq.rb
|
|
213
|
+
- lib/dash/autoscale/simulation.rb
|
|
214
|
+
- lib/dash/autoscale/state_store.rb
|
|
215
|
+
- lib/dash/autoscale/timestamp.rb
|
|
216
|
+
- lib/dash/autoscale/tunnel.rb
|
|
180
217
|
- lib/dash/build/progress_parser.rb
|
|
181
218
|
- lib/dash/build/report.rb
|
|
182
219
|
- lib/dash/build/step.rb
|
|
@@ -186,17 +223,17 @@ files:
|
|
|
186
223
|
- lib/dash/cli/app.rb
|
|
187
224
|
- lib/dash/cli/app/assets.rb
|
|
188
225
|
- lib/dash/cli/app/boot.rb
|
|
226
|
+
- lib/dash/cli/app/boot_state.rb
|
|
189
227
|
- lib/dash/cli/app/error_pages.rb
|
|
190
228
|
- lib/dash/cli/app/rollout_boot.rb
|
|
229
|
+
- lib/dash/cli/app/running_targets.rb
|
|
230
|
+
- lib/dash/cli/app/slot_version.rb
|
|
191
231
|
- lib/dash/cli/app/ssl_certificates.rb
|
|
232
|
+
- lib/dash/cli/autoscale.rb
|
|
192
233
|
- lib/dash/cli/base.rb
|
|
193
234
|
- lib/dash/cli/build.rb
|
|
194
235
|
- lib/dash/cli/build/clone.rb
|
|
195
236
|
- lib/dash/cli/build/port_forwarding.rb
|
|
196
|
-
- lib/dash/cli/doctor.rb
|
|
197
|
-
- lib/dash/cli/doctor/config_checks.rb
|
|
198
|
-
- lib/dash/cli/doctor/endpoint_checks.rb
|
|
199
|
-
- lib/dash/cli/doctor/host_checks.rb
|
|
200
237
|
- lib/dash/cli/healthcheck/barrier.rb
|
|
201
238
|
- lib/dash/cli/healthcheck/drift_error.rb
|
|
202
239
|
- lib/dash/cli/healthcheck/error.rb
|
|
@@ -207,15 +244,26 @@ files:
|
|
|
207
244
|
- lib/dash/cli/main/migrate.rb
|
|
208
245
|
- lib/dash/cli/proxy.rb
|
|
209
246
|
- lib/dash/cli/proxy/drift.rb
|
|
247
|
+
- lib/dash/cli/proxy/inspection.rb
|
|
210
248
|
- lib/dash/cli/proxy/legacy_rename.rb
|
|
211
249
|
- lib/dash/cli/proxy/loadbalancer_claim.rb
|
|
250
|
+
- lib/dash/cli/proxy/loadbalancer_deploy.rb
|
|
212
251
|
- lib/dash/cli/proxy/loadbalancer_reboot.rb
|
|
213
252
|
- lib/dash/cli/proxy/reboot.rb
|
|
214
253
|
- lib/dash/cli/prune.rb
|
|
215
254
|
- lib/dash/cli/registry.rb
|
|
216
255
|
- lib/dash/cli/report.rb
|
|
256
|
+
- lib/dash/cli/scale.rb
|
|
257
|
+
- lib/dash/cli/scale/host_plan.rb
|
|
258
|
+
- lib/dash/cli/scale/join.rb
|
|
259
|
+
- lib/dash/cli/scale/leave.rb
|
|
260
|
+
- lib/dash/cli/scale/placement.rb
|
|
261
|
+
- lib/dash/cli/scale/power_off.rb
|
|
262
|
+
- lib/dash/cli/scale/replica_join.rb
|
|
263
|
+
- lib/dash/cli/scale/replica_leave.rb
|
|
217
264
|
- lib/dash/cli/secrets.rb
|
|
218
265
|
- lib/dash/cli/server.rb
|
|
266
|
+
- lib/dash/cli/stats_table.rb
|
|
219
267
|
- lib/dash/cli/templates/deploy.yml
|
|
220
268
|
- lib/dash/cli/templates/sample_hooks/docker-setup.sample
|
|
221
269
|
- lib/dash/cli/templates/sample_hooks/post-app-boot.sample
|
|
@@ -223,6 +271,8 @@ files:
|
|
|
223
271
|
- lib/dash/cli/templates/sample_hooks/post-deploy.sample
|
|
224
272
|
- lib/dash/cli/templates/sample_hooks/post-proxy-deploy.sample
|
|
225
273
|
- lib/dash/cli/templates/sample_hooks/post-proxy-reboot.sample
|
|
274
|
+
- lib/dash/cli/templates/sample_hooks/post-scale-in.sample
|
|
275
|
+
- lib/dash/cli/templates/sample_hooks/post-scale-out.sample
|
|
226
276
|
- lib/dash/cli/templates/sample_hooks/pre-app-boot.sample
|
|
227
277
|
- lib/dash/cli/templates/sample_hooks/pre-app-stop.sample
|
|
228
278
|
- lib/dash/cli/templates/sample_hooks/pre-build.sample
|
|
@@ -230,6 +280,8 @@ files:
|
|
|
230
280
|
- lib/dash/cli/templates/sample_hooks/pre-deploy.sample
|
|
231
281
|
- lib/dash/cli/templates/sample_hooks/pre-proxy-deploy.sample
|
|
232
282
|
- lib/dash/cli/templates/sample_hooks/pre-proxy-reboot.sample
|
|
283
|
+
- lib/dash/cli/templates/sample_hooks/pre-scale-in.sample
|
|
284
|
+
- lib/dash/cli/templates/sample_hooks/pre-scale-out.sample
|
|
233
285
|
- lib/dash/cli/templates/secrets
|
|
234
286
|
- lib/dash/commander.rb
|
|
235
287
|
- lib/dash/commander/specifics.rb
|
|
@@ -245,6 +297,7 @@ files:
|
|
|
245
297
|
- lib/dash/commands/app/logging.rb
|
|
246
298
|
- lib/dash/commands/app/proxy.rb
|
|
247
299
|
- lib/dash/commands/auditor.rb
|
|
300
|
+
- lib/dash/commands/autoscale.rb
|
|
248
301
|
- lib/dash/commands/base.rb
|
|
249
302
|
- lib/dash/commands/builder.rb
|
|
250
303
|
- lib/dash/commands/builder/base.rb
|
|
@@ -260,6 +313,7 @@ files:
|
|
|
260
313
|
- lib/dash/commands/lock.rb
|
|
261
314
|
- lib/dash/commands/proxy.rb
|
|
262
315
|
- lib/dash/commands/proxy/cert_transfer.rb
|
|
316
|
+
- lib/dash/commands/proxy/services.rb
|
|
263
317
|
- lib/dash/commands/proxy/state.rb
|
|
264
318
|
- lib/dash/commands/prune.rb
|
|
265
319
|
- lib/dash/commands/registry.rb
|
|
@@ -267,10 +321,12 @@ files:
|
|
|
267
321
|
- lib/dash/configuration.rb
|
|
268
322
|
- lib/dash/configuration/accessory.rb
|
|
269
323
|
- lib/dash/configuration/alias.rb
|
|
324
|
+
- lib/dash/configuration/autoscale.rb
|
|
270
325
|
- lib/dash/configuration/boot.rb
|
|
271
326
|
- lib/dash/configuration/builder.rb
|
|
272
327
|
- lib/dash/configuration/docs/accessory.yml
|
|
273
328
|
- lib/dash/configuration/docs/alias.yml
|
|
329
|
+
- lib/dash/configuration/docs/autoscale.yml
|
|
274
330
|
- lib/dash/configuration/docs/boot.yml
|
|
275
331
|
- lib/dash/configuration/docs/builder.yml
|
|
276
332
|
- lib/dash/configuration/docs/configuration.yml
|
|
@@ -296,7 +352,13 @@ files:
|
|
|
296
352
|
- lib/dash/configuration/registry.rb
|
|
297
353
|
- lib/dash/configuration/report.rb
|
|
298
354
|
- lib/dash/configuration/role.rb
|
|
355
|
+
- lib/dash/configuration/role/drain.rb
|
|
299
356
|
- lib/dash/configuration/role/healthcheck.rb
|
|
357
|
+
- lib/dash/configuration/role/replicas.rb
|
|
358
|
+
- lib/dash/configuration/role/scale.rb
|
|
359
|
+
- lib/dash/configuration/role/scale/guard.rb
|
|
360
|
+
- lib/dash/configuration/role/scale/signal.rb
|
|
361
|
+
- lib/dash/configuration/role/scale/window.rb
|
|
300
362
|
- lib/dash/configuration/servers.rb
|
|
301
363
|
- lib/dash/configuration/ssh.rb
|
|
302
364
|
- lib/dash/configuration/sshkit.rb
|
|
@@ -304,6 +366,7 @@ files:
|
|
|
304
366
|
- lib/dash/configuration/validator.rb
|
|
305
367
|
- lib/dash/configuration/validator/accessory.rb
|
|
306
368
|
- lib/dash/configuration/validator/alias.rb
|
|
369
|
+
- lib/dash/configuration/validator/autoscale.rb
|
|
307
370
|
- lib/dash/configuration/validator/builder.rb
|
|
308
371
|
- lib/dash/configuration/validator/configuration.rb
|
|
309
372
|
- lib/dash/configuration/validator/env.rb
|
|
@@ -312,6 +375,34 @@ files:
|
|
|
312
375
|
- lib/dash/configuration/validator/role.rb
|
|
313
376
|
- lib/dash/configuration/validator/servers.rb
|
|
314
377
|
- lib/dash/configuration/volume.rb
|
|
378
|
+
- lib/dash/diagnostics/audit.rb
|
|
379
|
+
- lib/dash/diagnostics/autoscale_decisions.rb
|
|
380
|
+
- lib/dash/diagnostics/autoscale_explain.rb
|
|
381
|
+
- lib/dash/diagnostics/autoscale_signal.rb
|
|
382
|
+
- lib/dash/diagnostics/base.rb
|
|
383
|
+
- lib/dash/diagnostics/config.rb
|
|
384
|
+
- lib/dash/diagnostics/container_stats.rb
|
|
385
|
+
- lib/dash/diagnostics/containers.rb
|
|
386
|
+
- lib/dash/diagnostics/controller_status.rb
|
|
387
|
+
- lib/dash/diagnostics/docker_ps.rb
|
|
388
|
+
- lib/dash/diagnostics/doctor.rb
|
|
389
|
+
- lib/dash/diagnostics/doctor/config_checks.rb
|
|
390
|
+
- lib/dash/diagnostics/doctor/controller_checks.rb
|
|
391
|
+
- lib/dash/diagnostics/doctor/endpoint_checks.rb
|
|
392
|
+
- lib/dash/diagnostics/doctor/host_checks.rb
|
|
393
|
+
- lib/dash/diagnostics/doctor/pool_checks.rb
|
|
394
|
+
- lib/dash/diagnostics/doctor/signal_checks.rb
|
|
395
|
+
- lib/dash/diagnostics/drift.rb
|
|
396
|
+
- lib/dash/diagnostics/host_stats.rb
|
|
397
|
+
- lib/dash/diagnostics/lines.rb
|
|
398
|
+
- lib/dash/diagnostics/lock.rb
|
|
399
|
+
- lib/dash/diagnostics/logs.rb
|
|
400
|
+
- lib/dash/diagnostics/pool.rb
|
|
401
|
+
- lib/dash/diagnostics/proxy_services.rb
|
|
402
|
+
- lib/dash/diagnostics/redactor.rb
|
|
403
|
+
- lib/dash/diagnostics/reports.rb
|
|
404
|
+
- lib/dash/diagnostics/scale.rb
|
|
405
|
+
- lib/dash/diagnostics/units.rb
|
|
315
406
|
- lib/dash/docker.rb
|
|
316
407
|
- lib/dash/dockerfile/analyzer.rb
|
|
317
408
|
- lib/dash/dockerfile/context.rb
|
|
@@ -340,6 +431,29 @@ files:
|
|
|
340
431
|
- lib/dash/dockerfile/stage.rb
|
|
341
432
|
- lib/dash/env_file.rb
|
|
342
433
|
- lib/dash/git.rb
|
|
434
|
+
- lib/dash/mcp.rb
|
|
435
|
+
- lib/dash/mcp/base_tool.rb
|
|
436
|
+
- lib/dash/mcp/runner.rb
|
|
437
|
+
- lib/dash/mcp/server.rb
|
|
438
|
+
- lib/dash/mcp/session.rb
|
|
439
|
+
- lib/dash/mcp/tools/audit_tool.rb
|
|
440
|
+
- lib/dash/mcp/tools/autoscale_decisions_tool.rb
|
|
441
|
+
- lib/dash/mcp/tools/autoscale_explain_tool.rb
|
|
442
|
+
- lib/dash/mcp/tools/config_tool.rb
|
|
443
|
+
- lib/dash/mcp/tools/container_stats_tool.rb
|
|
444
|
+
- lib/dash/mcp/tools/containers_tool.rb
|
|
445
|
+
- lib/dash/mcp/tools/controller_status_tool.rb
|
|
446
|
+
- lib/dash/mcp/tools/deploy_reports_tool.rb
|
|
447
|
+
- lib/dash/mcp/tools/doctor_tool.rb
|
|
448
|
+
- lib/dash/mcp/tools/drift_tool.rb
|
|
449
|
+
- lib/dash/mcp/tools/host_stats_tool.rb
|
|
450
|
+
- lib/dash/mcp/tools/lock_status_tool.rb
|
|
451
|
+
- lib/dash/mcp/tools/logs_tool.rb
|
|
452
|
+
- lib/dash/mcp/tools/pool_members_tool.rb
|
|
453
|
+
- lib/dash/mcp/tools/proxy_services_tool.rb
|
|
454
|
+
- lib/dash/mcp/tools/scale_status_tool.rb
|
|
455
|
+
- lib/dash/mcp/tools/signal_sample_tool.rb
|
|
456
|
+
- lib/dash/mcp/transport.rb
|
|
343
457
|
- lib/dash/otel_shipper.rb
|
|
344
458
|
- lib/dash/output/base_logger.rb
|
|
345
459
|
- lib/dash/output/file_logger.rb
|