Make container name optional in console command

When omitted, tries: 1) same name as stack, 2) 'app'.
So 'portainer-cli console librarian' resolves to librarian-librarian-1,
and 'portainer-cli console myapp' falls back to myapp-app-1.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-22 14:06:56 +01:00
parent 948910fc87
commit 382ba15f15
2 changed files with 15 additions and 3 deletions
+1 -1
View File
@@ -30,7 +30,7 @@ module PortainerCli
portainer-cli list networks <endpoint-id> List networks
portainer-cli create stack --endpoint ID --name NAME --file FILE
portainer-cli create container --endpoint ID --image IMAGE [--name NAME] [--port h:c] [--env K=V]
portainer-cli console <stack> <container> Open interactive shell (resolves endpoint automatically)
portainer-cli console <stack> [container] Open interactive shell (resolves endpoint automatically)
--shell SHELL Shell to use (default: /bin/sh)
portainer-cli exec <endpoint-id> <container> Open interactive shell (manual endpoint)
--shell SHELL Shell to use (default: /bin/sh)
+14 -2
View File
@@ -25,8 +25,8 @@ module PortainerCli
o.on('--shell SHELL', 'Shell to use (default: /bin/sh)') { |v| opts[:shell] = v }
end.parse!(args)
stack_name = args.shift or error("Usage: portainer-cli console <stack> <container> [--shell /bin/bash]")
container_name = args.shift or error("Usage: portainer-cli console <stack> <container> [--shell /bin/bash]")
stack_name = args.shift or error("Usage: portainer-cli console <stack> [container] [--shell /bin/bash]")
container_name = args.shift || stack_name
stack = resolve_stack(stack_name)
endpoint_id = stack['EndpointId']
@@ -107,6 +107,18 @@ module PortainerCli
error("Ambiguous container '#{name_or_id}'. Did you mean one of:\n#{list}")
end
# 4. Try 'app' as a last resort when the implicit default didn't match
if name_or_id != 'app' && stack_name
app_candidates = containers.select do |c|
names_for.(c).any? { |n| n.match?(/\A#{Regexp.escape(stack_name)}-app-\d+\z/) }
end
if app_candidates.size == 1
matched_name = names_for.(app_candidates.first).first
$stderr.puts dim("Matched '#{name_or_id}' → #{matched_name} (fallback to 'app')")
return app_candidates.first['Id']
end
end
available = pool.map { |c| " #{c['Id'][0, 12]} #{names_for.(c).first}" }.join("\n")
error("Container '#{name_or_id}' not found. Available:\n#{available}")
end