Fuzzy container name matching in console command
Falls back to substring match when exact name isn't found. Auto-selects if unambiguous (e.g. "librarian" → "librarian-librarian-1"), errors with a disambiguation list if multiple containers match. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -67,17 +67,35 @@ module PortainerCli
|
|||||||
|
|
||||||
def resolve_container(endpoint_id, name_or_id)
|
def resolve_container(endpoint_id, name_or_id)
|
||||||
containers = @client.get("/api/endpoints/#{endpoint_id}/docker/containers/json", all: 1)
|
containers = @client.get("/api/endpoints/#{endpoint_id}/docker/containers/json", all: 1)
|
||||||
match = containers.find do |c|
|
|
||||||
|
# 1. Exact match: full name or ID prefix
|
||||||
|
exact = containers.find do |c|
|
||||||
c['Id'].start_with?(name_or_id) ||
|
c['Id'].start_with?(name_or_id) ||
|
||||||
Array(c['Names']).any? { |n| n.delete_prefix('/') == name_or_id }
|
Array(c['Names']).any? { |n| n.delete_prefix('/') == name_or_id }
|
||||||
end
|
end
|
||||||
unless match
|
return exact['Id'] if exact
|
||||||
available = containers.map do |c|
|
|
||||||
" #{c['Id'][0, 12]} #{Array(c['Names']).first&.delete_prefix('/')}"
|
# 2. Fuzzy: container name contains the search term as a word segment
|
||||||
end.join("\n")
|
# Prefers "<stack>-<name>-<n>" pattern, falls back to any substring match
|
||||||
error("Container '#{name_or_id}' not found on endpoint #{endpoint_id}. Available:\n#{available}")
|
names_for = ->(c) { Array(c['Names']).map { |n| n.delete_prefix('/') } }
|
||||||
|
|
||||||
|
fuzzy = containers.select do |c|
|
||||||
|
names_for.(c).any? { |n| n.include?(name_or_id) }
|
||||||
end
|
end
|
||||||
match['Id']
|
|
||||||
|
if fuzzy.size == 1
|
||||||
|
matched_name = names_for.(fuzzy.first).first
|
||||||
|
$stderr.puts dim("Matched '#{name_or_id}' → #{matched_name}")
|
||||||
|
return fuzzy.first['Id']
|
||||||
|
end
|
||||||
|
|
||||||
|
if fuzzy.size > 1
|
||||||
|
list = fuzzy.map { |c| " #{c['Id'][0, 12]} #{names_for.(c).first}" }.join("\n")
|
||||||
|
error("Ambiguous container '#{name_or_id}'. Did you mean one of:\n#{list}")
|
||||||
|
end
|
||||||
|
|
||||||
|
available = containers.map { |c| " #{c['Id'][0, 12]} #{names_for.(c).first}" }.join("\n")
|
||||||
|
error("Container '#{name_or_id}' not found on endpoint #{endpoint_id}. Available:\n#{available}")
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_exec(endpoint_id, container_id, shell)
|
def create_exec(endpoint_id, container_id, shell)
|
||||||
|
|||||||
Reference in New Issue
Block a user