require 'thor' module Jarl class CLI < Thor # global options # class_option :config, aliases: '-c', type: :string, desc: 'Use specified config file (defaul: ~/.jarl)' class_option :debug # desc 'config', 'Show current configuration' def config Jarl.load(options) puts esc_yellow('config:') + " #{Jarl.config.path}" Jarl.config.params.each do |key, value| puts " #{key}: #{value.inspect}" end puts esc_yellow('jarl files:') Jarl.jarl_files.each do |jarl_file| puts " #{jarl_file.path}" jarl_file.applications.each do |app| puts " #{app.name}" end end # show_jarl_applications_status(apps) end # desc 'status [NAME]', '(default) Show applications statuses' def status(name = nil) Jarl.load(options) apps = name ? Jarl.find_applications_by(name) : Jarl.applications show_jarl_applications_status(apps) end default_task :status # desc 'up [NAME]', 'Start or restart applications' def up(name = nil) Jarl.load(options) apps = name ? Jarl.find_applications_by(name) : Jarl.applications apps.each do |app| puts esc_green(app.running? ? "Restarting '#{app}'..." : "Starting '#{app}'...") app.start end # show_jarl_applications_status(apps) end # desc 'down [NAME]', 'Stop applications' def down(name = nil) Jarl.load(options) apps = name ? Jarl.find_applications_by(name) : Jarl.applications apps.each do |app| next unless app.running? puts esc_yellow "Stopping '#{app}'..." app.running_container.stop! end end desc 'execute NAME [COMMAND ...]', 'Run a single command against application image' def execute(name, command = nil, *args) Jarl.load(options) app = Jarl.find_applications_by(name).first abort "Failed to find application by name: '#{name}'" unless app app.execute(command, args) end # desc 'ssh NAME', 'Open SSH session to a running application' def ssh(name) Jarl.load(options) app = Jarl.find_applications_by(name).first abort "Failed to find application by name: '#{name}'" unless app abort "Application is not running: '#{app.full_name}'" unless app.running? app.ssh end # option :ip, type: :boolean, desc: 'Show only IPs' desc 'inspect [NAME]', 'Inspect applications' def inspect(name = nil) Jarl.load(options) apps = name ? Jarl.find_applications_by(name) : Jarl.applications apps.each do |app| if options[:ip] puts app.running_container.ip if app.running? else show_jarl_application_inspect(app) end end end desc 'build [NAME]', 'Rebuild docker images for Dockerfile based applications' def build(name = nil) Jarl.load(options) apps = name ? Jarl.find_applications_by(name) : Jarl.applications apps.select(&:image_is_a_path?).each do |app| puts esc_yellow "Building image for '#{app}'..." app.build end end desc 'logs [NAME]', 'Show log output for applications' def logs(name = nil) Jarl.load(options) apps = name ? Jarl.find_applications_by(name) : Jarl.applications threads = [] apps.select(&:running?).each do |app| threads << Thread.new { app.show_log } end begin threads.each(&:join) rescue Interrupt # end puts end desc 'version', 'Show Jarl version' def version puts app_name_version end private def app_name_version "Jarl v#{Jarl::VERSION}" end def show_jarl_applications_status(apps) if apps.size == 0 puts esc_yellow 'No applications found' return end max_full_name_len = [apps.map(&:full_name).map(&:size).max, 12].max puts esc_format( ['APPLICATION', max_full_name_len], ['RUNNING', 12], ['UPTIME', 12], ['IP', 12], ['PORTS'] ) apps.each do |app| container = app.running_container puts esc_format( [app.full_name, max_full_name_len, :yellow], (app.running? ? [container.id, 12, :green] : ['no', 12]), (app.running? ? [seconds_to_human(container.uptime), 12, :yellow] : ['', 12]), (app.running? ? [container.ip, 12, :yellow] : ['', 12]), (app.running? ? [container.ports.map { |p| "#{p[:from]}"}.join(', ')] : ['']) ) end end def show_jarl_application_inspect(app) unless app.running? puts esc_yellow("#{app.full_name}: ") + 'down' return end container = app.running_container puts esc_yellow "#{app.full_name}: " + esc_green(container.id) puts " name: #{esc_yellow container.name}" puts " image: #{esc_yellow container.image}" puts " full ID: #{esc_yellow container.long_id}" puts " uptime: #{esc_yellow seconds_to_human container.uptime}" puts " IP: #{esc_yellow container.ip}" puts " ports: #{esc_yellow container.ports.map { |p| "#{p[:from]}->#{p[:to]}"}.join(', ')}" puts " volumes: #{esc_yellow container.params['Volumes']}" end end # class CLI end # module Jarl