# frozen_string_literal: true require_relative 'base' module PortainerCli module Commands class List include Base SUBCOMMANDS = %w[endpoints stacks containers volumes networks].freeze def initialize(config, client) @config = config @client = client end def run(args) require_config!(@config) sub = args.shift&.downcase case sub when 'endpoints', 'envs', 'env' list_endpoints when 'stacks', 'stack' list_stacks when 'containers', 'container', 'ps' endpoint_id = resolve_endpoint_id(args) list_containers(endpoint_id) when 'volumes', 'volume' endpoint_id = resolve_endpoint_id(args) list_volumes(endpoint_id) when 'networks', 'network' endpoint_id = resolve_endpoint_id(args) list_networks(endpoint_id) else puts "Usage: portainer-cli list <#{SUBCOMMANDS.join('|')}> [endpoint-id]" exit 1 end end private def list_endpoints data = @client.get('/api/endpoints') rows = data.map do |e| [e['Id'], e['Name'], e['URL'] || e['PublicURL'] || '-', endpoint_status(e['Status'])] end print_table(%w[ID Name URL Status], rows) end def list_stacks data = @client.get('/api/stacks') rows = data.map do |s| [s['Id'], s['Name'], s['EndpointId'], stack_status(s['Status'])] end print_table(%w[ID Name Endpoint Status], rows) end def list_containers(endpoint_id) data = @client.get("/api/endpoints/#{endpoint_id}/docker/containers/json", all: 1) rows = data.map do |c| name = Array(c['Names']).first&.delete_prefix('/') || '-' image = c['Image'] status = c['Status'] id = c['Id'][0, 12] [id, name, image, status] end print_table(%w[ID Name Image Status], rows) end def list_volumes(endpoint_id) data = @client.get("/api/endpoints/#{endpoint_id}/docker/volumes") vols = data.is_a?(Hash) ? (data['Volumes'] || []) : data rows = vols.map { |v| [v['Name'], v['Driver'], v['Mountpoint']] } print_table(%w[Name Driver Mountpoint], rows) end def list_networks(endpoint_id) data = @client.get("/api/endpoints/#{endpoint_id}/docker/networks") rows = data.map { |n| [n['Id'][0, 12], n['Name'], n['Driver'], n['Scope']] } print_table(%w[ID Name Driver Scope], rows) end def resolve_endpoint_id(args) id = args.shift unless id puts "Endpoint ID required. Run 'portainer-cli list endpoints' to see IDs." exit 1 end id end def endpoint_status(code) case code when 1 then green('active') when 2 then red('inactive') else dim(code.to_s) end end def stack_status(code) case code when 1 then green('active') when 2 then yellow('inactive') else dim(code.to_s) end end end end end