# Runit capistrano 3.x tasks # # Application config and tasks that apply to all services setup # with runit for the application # # Recommendation: # Everything that should run as either a service or deamon, # can and should use runit

require 'capistrano/dsl/base_paths' require 'capistrano/dsl/runit_paths' require 'capistrano/helpers/base' require 'capistrano/helpers/runit'

include Capistrano::DSL::BasePaths include Capistrano::DSL::RunitPaths include Capistrano::Helpers::Base include Capistrano::Helpers::Runit

namespace :load do

task :defaults do
  set :runit_dir,               proc { shared_path.join('runit') }
  set :runit_run_template,      File.join(File.expand_path(File.join(File.dirname(__FILE__), '../../../templates')), 'runit', 'run.erb') # rubocop:disable Metrics/LineLength:
  set :runit_finish_template,   File.join(File.expand_path(File.join(File.dirname(__FILE__), '../../../templates')), 'runit', 'finish.erb') # rubocop:disable Metrics/LineLength:
  set :runit_log_run_template,  File.join(File.expand_path(File.join(File.dirname(__FILE__), '../../../templates')), 'runit', 'log_run.erb') # rubocop:disable Metrics/LineLength:
  set :runit_log_user,          'syslog'
  set :runit_log_group,         'syslog'
  set :runit_restart_interval,  10
  set :runit_restart_count,     7
  set :runit_autorestart_clear_interval, 90
end

end

namespace :runit do

desc 'Setup runit for the application'
task :setup do
  on roles([:app, :worker]) do |host|
    info "RUNIT: Setting up initial runit configuration on #{host}"
    if test "[ ! -f #{fetch(:runit_dir)}/.env/HOME ]"
      if test "[ ! -d #{fetch(:runit_dir)}/.env ]"
        execute :mkdir, "-p '#{fetch(:runit_dir)}/.env'"
      end
      upload! StringIO.new('$HOME'), "#{File.join(fetch(:runit_dir), '.env', 'HOME')}"
    end
  end
end

namespace :setup do
  # '[INTERNAL] create /etc/sv folders and upload base templates needed'
  task :runit_create_app_services do
    on roles([:app, :worker]) do |host|
      within("#{runit_user_base_path}") do
        execute :mkdir, "-p #{app_env_folder}"
      end

      upload! template_to_s_io(fetch(:runit_run_template)), runit_run_file
      upload! template_to_s_io(fetch(:runit_finish_template)), runit_finish_file

      execute :chmod, "0775 '#{runit_run_file}'"
      execute :chmod, "0775 '#{runit_finish_file}'"
      info "RUNIT: Created inital runit services in #{runit_base_path} for #{fetch(:application)} on #{host}"
    end
  end

  # [Internal] create log service for app
  task :runit_create_app_log_services do
    on roles([:app, :worker]) do |host|
      within("#{runit_base_path}") do
        execute :mkdir, '-p log'
      end
      upload! template_to_s_io(fetch(:runit_log_run_template)), runit_log_run_file
      execute :mkdir, "-p #{runit_var_log_service_runit_path}" if test("[ ! -d #{runit_var_log_service_runit_path} ]")
      execute :chmod, "775 '#{runit_log_run_file}'"

      info "RUNIT: Created inital runit log services in #{runit_base_log_path} for #{fetch(:application)} on #{host}"
    end
  end
  # '[INTERNAL] create /etc/sv folders and upload base templates needed'
  task :runit_ensure_shared_sockets_and_pids_folders do
    on roles([:app, :worker]) do |host|
      execute :mkdir, fetch(:pids_path) if test("[ ! -d #{fetch(:pids_path)} ]")
      execute :mkdir, fetch(:sockets_path) if test("[ ! -d #{fetch(:sockets_path)} ]")
    end
  end
end

desc 'Disable runit services for application'
task :disable do
  on roles([:app, :worker]) do |host|
    if test "[ -h #{runit_etc_service_app_symlink_name} ]"
      execute :rm, "-rf '#{runit_etc_service_app_symlink_name}'"
      info "RUNIT disabling on '#{host}'"
    else
      info "RUNIT already disabled on '#{host}'"
    end
  end
end

desc 'Enable runit services for application'
task :enable do
  on roles([:app, :worker]) do |host|
    if test "[ ! -h #{runit_etc_service_app_symlink_name} ]"
      execute :ln, "-sf '#{runit_base_path}' '#{runit_etc_service_app_symlink_name}'"
      info "RUNIT enabling on '#{host}'"
    else
      info "RUNIT already enabled on '#{host}'"
    end
  end
end

desc 'Purge/remove all runit configurations for the application'
task :purge do
  on roles([:app, :worker]) do |host|
    execute :rm, "-rf #{runit_etc_service_app_symlink_name}"
    execute :rm, "-rf #{runit_base_path}"
    info "RUNIT purging config on '#{host}'"
  end
end

%w(stop start once restart).each do |single_cmd|
  desc "#{single_cmd} runit services for application"
  task single_cmd.to_sym do
    on roles([:app, :worker]) do |host|
      info "RUNIT: #{single_cmd} on #{host}"
      runit_app_services_control(single_cmd)
    end
  end
end

end

before 'runit:purge', 'runit:stop'

after 'deploy:updated', 'runit:enable' # after 'deploy:setup', 'runit:setup' after 'runit:setup', 'runit:setup:runit_create_app_services' after 'runit:setup:runit_create_app_services', 'runit:setup:runit_create_app_log_services' after 'runit:setup:runit_create_app_services', 'runit:setup:runit_ensure_shared_sockets_and_pids_folders'