# frozen_string_literal: true
require 'tempfile'
namespace :docker do
namespace :swarm do def docker_cmd fetch(:docker_swarm_docker_cmd) { fetch(:docker_cmd, 'docker') } end def docker_stack_name (fetch(:docker_stack_name) { fetch(:application) }) || raise('unable to discern docker_stack_name name; specify :application or :docker_stack_name') end def docker_stack_deploy_opts fetch(:docker_stack_deploy_opts, '--prune') end # Relative path to the docker-compose.yml for deployments def docker_compose_file fetch(:docker_compose_file, 'docker-compose.yml') end # Path for docker-compose remote deployments def docker_compose_path fetch(:docker_compose_path) { build_path } end task :check_docker_swarm_root do on roles(:docker_swarm) do |remote| # info "ON HOST #{remote}" # info "checking docker_compose_path: #{docker_compose_path}" # should really fix this to preserve typical capistrano dir-tree, but meh for now... unless test("[ -d #{docker_compose_path} ]") warn "docker_compose_path does not exist on host (#{remote}): #{docker_compose_path}" warn "creating docker_compose_path on host (#{remote}): #{docker_compose_path}" warn 'this can break future `cap stage deploy` execution on build hosts' execute :mkdir, '-p', docker_compose_path end end end task :local_source_warning do run_locally do warn 'Using docker-compose files directly from local workspace... (typically undesirable)' warn '>> assign :docker_build role to enable remote builds' end end desc 'copies a new docker_compose_file from the docker_build role to each docker_compose role' task :upload do if roles(:docker_swarm).empty? invoke 'docker:swarm:upload_local' else invoke 'docker:swarm:upload_remote' end end # copies a new docker-compose.yml file up to each docker_swarm host task :upload_local do run_locally do info 'Nothing to do here, docker swarm will run locally...' end end # copies a new docker-compose.yml file up to each docker_swarm host task :upload_remote => :check_docker_swarm_root do run_locally do info 'Copying docker_compose_file to docker_swarm hosts...' end tmp_file = Tempfile.new('upload_remote') tmp_file_path = tmp_file.path tmp_file.close(false) begin docker_build_role = roles(:docker_build).first upload_roles = roles(:docker_swarm) - [docker_build_role] unless upload_roles.empty? if docker_build_role on docker_build_role do |build_remote| info "fetching #{build_remote}:#{docker_compose_path.join(docker_compose_file)}" download! docker_compose_path.join(docker_compose_file), tmp_file_path end else invoke 'docker:swarm:local_source_warning' run_locally do warn "fetching #{docker_compose_file}" download! docker_compose_file, tmp_file_path end end on upload_roles do |upload_role| info "uploading to #{upload_role}:#{docker_compose_path.join(docker_compose_file)}" upload! tmp_file_path, docker_compose_path.join(docker_compose_file) end end ensure File.unlink(tmp_file_path) end end desc 'List the tasks in the stack' task :ps do if roles(:docker_swarm).empty? invoke 'docker:swarm:ps_local' else invoke 'docker:swarm:ps_remote' end end task :ps_local do current_build_dir = pwd run_locally do info "Current Working Directory: #{current_build_dir}" execute docker_cmd, :stack, :ps, docker_stack_name end end task :ps_remote do on roles(:docker_swarm) do |buildremote| info "ON HOST #{buildremote}" within build_path do execute docker_cmd, :stack, :ps, docker_stack_name end end end desc 'List the services in the stack' task :status do if roles(:docker_swarm).empty? invoke 'docker:swarm:status_local' else invoke 'docker:swarm:status_remote' end end task :status_local do current_build_dir = pwd run_locally do info "Current Working Directory: #{current_build_dir}" execute docker_cmd, :stack, :services, docker_stack_name end end task :status_remote do on roles(:docker_swarm) do |buildremote| info "ON HOST #{buildremote}" within build_path do execute docker_cmd, :stack, :services, docker_stack_name end end end desc 'starts/updates services' task :up do if roles(:docker_swarm).empty? invoke 'docker:swarm:up_local' else invoke 'docker:swarm:up_remote' end end task :up_local do current_build_dir = pwd run_locally do info "Current Working Directory: #{current_build_dir}" execute docker_cmd, :stack, :deploy, docker_stack_deploy_opts, "--compose-file=#{docker_compose_file}", docker_stack_name end end task :up_remote do on roles(:docker_swarm) do |buildremote| info "ON HOST #{buildremote}" within build_path do execute docker_cmd, :stack, :deploy, docker_stack_deploy_opts, "--compose-file=#{docker_compose_file}", docker_stack_name end end end desc 'stop and clean up all services' task :down do if roles(:docker_swarm).empty? invoke 'docker:swarm:down_local' else invoke 'docker:swarm:down_remote' end end task :down_local do current_build_dir = pwd run_locally do info "Current Working Directory: #{current_build_dir}" execute docker_cmd, :stack, :rm, docker_stack_name end end task :down_remote do on roles(:docker_swarm) do |buildremote| info "ON HOST #{buildremote}" within build_path do execute docker_cmd, :stack, :rm, docker_stack_name end end end desc 'Update all docker_swarm roles' task :update do invoke 'docker:swarm:upload' invoke 'docker:swarm:up' end desc '(alias for docker:swarm:update)' task :deploy => :update # Default `cap env deploy` flow hook task :capdeploy_hook do if fetch(:dockerswarm_deployhook, true) invoke 'docker:swarm:update' end end end # namespace :swarm do
end # namespace :docker do