module Jarl class Application attr_reader :group, :name, :hostname attr_reader :image, :volumes, :ports, :environment, :entrypoint, :command # Create Application object from application definition: # # app_name: # image: blabla # volumes: # - /host/path:/container/path # ports: # - 1234:5678 # command: blabla # def initialize(group, name, params) @group = group @name = name @image = params['image'] || fail("Application '#{self}' has no 'image' defined") unless @image.is_a?(String) fail "Application '#{self}' has invalid 'image' definition, String is expected" end @volumes = params['volumes'] || [] unless @volumes.is_a?(Array) fail "Application '#{self}' has invalid 'volumes' definition, Array is expected" end @ports = params['ports'] || [] unless @ports.is_a?(Array) fail "Application '#{self}' has invalid 'ports' definition, Array is expected" end @environment = params['environment'] || {} unless @environment.is_a?(Hash) fail "Application '#{self}' has invalid 'environment' definition, Hash is expected" end @entrypoint = params['entrypoint'] if @entrypoint && !@entrypoint.is_a?(String) fail "Application '#{self}' has invalid 'entrypoint' definition, String is expected" end @command = params['command'] if @command && !@command.is_a?(String) fail "Application '#{self}' has invalid 'command' definition, String is expected" end @serial = self.class.next_serial @hostname = @name end def full_name "#{group}.#{name}" end def image_is_a_path? image =~ /^[~\.\/]/ end def running? running_container end def running_container Docker.containers_running.find { |c| c.name == full_name } end def start running_container.stop! if running? Docker.start( name: full_name, hostname: hostname, image: image_name, volumes: volumes, ports: ports, environment: environment, command: command ) end def execute(execute_command, args) Docker.execute( name: full_name, hostname: hostname, image: image_name, volumes: volumes, ports: ports, environment: environment, command: (execute_command || command || '') + ' ' + args.join(' ') ) end def ssh fail 'Not a running application' unless running? running_container.open_ssh_session!(Jarl.config.params) end def build fail 'Not a file based image' unless image_is_a_path? Docker::Image.new(image_name, image_path).build! end def image_name image_is_a_path? ? File.basename(name) : image end def image_path image_is_a_path? ? image : nil end def show_log(*_args) color_code = Console::Colors::SEQUENCE[@serial % Console::Colors::SEQUENCE.size] return unless running? begin IO.popen "docker logs -f #{running_container.id}", 'r' do |p| str = '<<< STARTED >>>' while str str = p.gets str.split("\n").each do |s| puts "#{esc_color color_code, full_name}: #{s}" end end end rescue Interrupt # end end def to_s full_name end def self.next_serial @current_serial ||= 0 @current_serial += 1 @current_serial - 1 end end # class Application end # module Jarl