Skip to content

Instantly share code, notes, and snippets.

@isubas
Created November 1, 2019 12:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save isubas/063d00ccd617de424687ee6c1e929571 to your computer and use it in GitHub Desktop.
Save isubas/063d00ccd617de424687ee6c1e929571 to your computer and use it in GitHub Desktop.
s3.rb
# frozen_string_literal: true
require 'aws-sdk-s3'
require 'fileutils'
require 'open3'
require 'singleton'
# Adapted from https://github.com/omu/zoo/blob/master/git-import/git-import
module Shell
Result = Struct.new :args, :out, :err, :exit_code do
def outline
out.first
end
# :reek:NilCheck
def ok?
exit_code&.zero?
end
def notok?
!ok?
end
def command
args.join ' '
end
end
# Adapted to popen3 from github.com/mina-deploy/mina
class Runner
def initialize
@coathooks = 0
end
def run(*args)
return dummy_result if args.empty?
out, err, status =
Open3.popen3(*args) do |_, stdout, stderr, wait_thread|
block(stdout, stderr, wait_thread)
end
Result.new args, out, err, status.exitstatus
end
private
attr_reader :coathooks
def block(stdout, stderr, wait_thread)
# Handle `^C`
trap('INT') { handle_sigint(wait_thread.pid) }
out = stdout.readlines.map(&:chomp)
err = stderr.readlines.map(&:chomp)
[out, err, wait_thread.value]
end
def handle_sigint(pid)
message, signal = message_and_signal
warn "\n" + message
::Process.kill signal, pid
@coathooks += 1
rescue Errno::ESRCH
warn 'No process to kill.'
end
def message_and_signal
if coathooks > 1
['SIGINT received again. Force quitting...', 'KILL']
else
['SIGINT received.', 'TERM']
end
end
end
module_function
def run(args, msg = nil)
warn msg if msg
Runner.new.run(*args)
end
def run_or_die(args, msg = nil)
result = run(args, msg)
result.ok? || abort("Command failed with exit code #{result.exit_code}: #{result.command}")
result
end
end
class S3
include Singleton
TOPLEVEL = %w[git rev-parse --show-toplevel].freeze
BUCKET = 'test'
def initialize(config = Tenant.credentials.config[:s3])
@client = Aws::S3::Client.new(config)
end
def pull(file, bucket: BUCKET)
Dir.chdir(Shell.run_or_die(TOPLEVEL).outline) do
dest = File.join(Dir.pwd, file)
FileUtils.mkdir_p File.dirname(dest)
client.get_object bucket: bucket, key: File.basename(dest), response_target: dest
end
rescue Errno::EEXIST
warn "#{target} already exist."
end
def push(file, bucket: BUCKET)
Dir.chdir(Shell.run_or_die(TOPLEVEL).outline) do
dest = File.join(Dir.pwd, file)
client.put_object bucket: bucket, body: IO.read(dest), key: File.basename(dest)
end
rescue Errno::ENOENT
warn "#{source} does not exist."
end
protected
attr_reader :client
end
namespace :s3 do
FILES = %w[
db/encrypted_data/sample_data.sql.enc.gz
db/encrypted_data/static_data.sql.enc.gz
lib/templates/ldap/openldap-2.4-bcyrpt-module.tar.gz
].freeze
desc 'Pull S3 objects from remote'
task pull: :environment do
FILES.each do |file|
puts "#{file} pulling..."
S3.instance.pull(file)
end
rescue StandardError => e
warn "An error occured for #{file}: #{e}"
end
desc 'Push S3 objects to remote'
task push: :environment do
FILES.each do |file|
puts "#{file} pushing..."
S3.instance.push(file)
end
rescue StandardError => e
warn "An error occured for #{file}: #{e}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment