#!/usr/bin/env ruby require_relative "../lib/harbr" class HarbrCLI < Thor no_commands do def display_containers_table(containers) return puts "No containers available." if containers.empty? # Define headers based on Container attributes headers = ["Name", "Host Header", "IP", "Port"] rows = containers.map do |container| [container.name, container.host_header, container.ip.nil? ? "127.0.0.1" : container.ip, container.port] end table = ::Terminal::Table.new(headings: headers, rows: rows) puts "" puts "Harbr Containers" puts "" puts table puts "" end def check_and_create_directory(path) unless Dir.exist?(path) puts "Creating directory: #{path}" FileUtils.mkdir_p(path) end end def command_exists?(command) system("command -v #{command} > /dev/null 2>&1") end def write_to_file(path, contents) dirname = File.dirname(path) FileUtils.mkdir_p(dirname) unless File.directory?(dirname) File.write(path, contents) end def install_with_snap(package) puts "Installing #{package} using Snap..." system("sudo snap install #{package}") or raise "Failed to install #{package}" end def install_with_apt(package) puts "Installing #{package} using apt..." system("sudo apt install #{package}") or raise "Failed to install #{package}" end end desc "destroy", "Destroy a container and remove all traces" def destroy(name) puts "Destroying container: #{name}" container_repo = Harbr::Container::Repository.new ["live.#{name}", "next.#{name}", name].each do |container_name| container_repo.get_by_name(container_name).each do |container| `port release #{container.port}` puts "released port #{container.port} successfully." container_repo.delete(container) end `rm -rf /etc/service/#{container_name}` `rm -rf /etc/sv/harbr/#{container_name}` puts "Container #{container_name} destroyed successfully." end `rm -rf /var/harbr/containers/#{name}` `rm -rf /var/log/harbr/#{name}` create_traefik_config(container_repo.all) end desc "logs", "Show logs" def logs exec "tail -f /var/log/harbr/current" end desc "peek CONTAINER", "Peek in a given container" method_option :live, type: :boolean, aliases: "-l", desc: "Process in live mode" method_option :next, type: :boolean, default: true, aliases: "-n", desc: "Process in next mode" def peek(container) container_repo = Harbr::Container::Repository.new container = container_repo.find_by_name(container) if container exec "tail -f /var/log/harbr/#{container.name}/live/current" if options[:live] exec "tail -f /var/log/harbr/#{container.name}/next/current" if options[:next] else puts "Container not recognized" end end desc "setup", "Set up Harbr environment" def setup # Check and create /var/harbr directory check_and_create_directory("/var/harbr/containers") check_and_create_directory("/var/dddr") # Check for Ruby, Traefik, and runit, and install if necessary install_with_snap("ruby") unless command_exists?("ruby") install_with_snap("traefik") unless command_exists?("traefik") install_with_apt("runit") unless command_exists?("runit") puts "Setup completed successfully." end desc "containers", "show all containers" def containers container_repo = Harbr::Container::Repository.new display_containers_table(container_repo.all) end desc "deploy", "deploy a container to production" method_option :live, type: :boolean, default: false, aliases: "-l", desc: "deploy to live environment" method_option :next, type: :boolean, default: false, aliases: "-n", desc: "deploy to next environment" def deploy(name,version=nil) if options[:live] /versions\/(?\d*)/ =~ `ls -l /var/harbr/containers/#{name}/next` version = $1 raise "Ooops! next version not found!" if version.nil? Harbr::Job.perform_async(name, version, "live") /versions\/(?\d*)/ =~ `ls -l /var/harbr/containers/#{name}/live` `ln -sf /var/harbr/containers/#{name}/version/#{$1} /var/harbr/containers/#{name}/rollback` puts "deploy version #{version} of #{name} to live environment" end if options[:next] `ln -sf /var/harbr/containers/#{name}/version/#{version} /var/harbr/containers/#{name}/next` Harbr::Job.perform_async(name, version, "next") puts "deploy version #{version} of #{name} to next environment" end end desc "rollback", "rollback last deploy" def rollback(name) Dir.chdir("/var/harbr/containers/#{name}") do if File.exist?("rollback") Dir.chdir("/var/harbr/containers/#{name}/") do /(?:. * -> (?:.*))/ =~ `ls -l /var/harbr/containers/#{name}/rollback` `rm -r live` `ln -sf #{$2} live` `sv restart live.#{name}` end puts "rollback successful" end end end desc "update", "update to the latest version of harbr" def update system "gem update harbr" end end HarbrCLI.start(ARGV)