d3cb4fdebd
Ruby CLI tool for interacting with the Portainer API. Supports listing endpoints/stacks/containers/volumes/networks, creating stacks and containers, and opening an interactive exec session in a container via WebSocket. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
111 lines
3.1 KiB
Ruby
111 lines
3.1 KiB
Ruby
# 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
|