class Moonshot::Plugins::Backup

Moonshot plugin class for deflating and uploading files on given hooks

Attributes

app_name[RW]
bucket[RW]
buckets[RW]
files[RW]
hooks[RW]
stack_name[RW]
target_bucket[RW]
target_name[RW]

Public Class Methods

new() { |self| ... } click to toggle source
# File lib/plugins/backup.rb, line 17
def initialize
  yield self if block_given?
  raise ArgumentError \
    if @files.nil? || @files.empty? || @hooks.nil? || !(@bucket.nil? ^ @buckets.nil?)

  @target_name ||= '%{app_name}_%{timestamp}_%{user}.tar.gz'
end
to_bucket(bucket) click to toggle source

Factory method to create preconfigured Backup plugins. Uploads current template and parameter files. @param backup [String] target bucket name @return [Backup] configured backup object

# File lib/plugins/backup.rb, line 29
def self.to_bucket(bucket)
  raise ArgumentError if bucket.nil? || bucket.empty?
  Moonshot::Plugins::Backup.new do |b|
    b.bucket = bucket
    b.files = [
      'cloud_formation/%{app_name}.json',
      'cloud_formation/parameters/%{stack_name}.yml'
    ]
    b.hooks = [:post_create, :post_update]
  end
end

Public Instance Methods

backup(resources) click to toggle source

Main worker method, creates a tarball of the given files, and uploads to an S3 bucket.

@param resources [Resources] injected Moonshot resources

# File lib/plugins/backup.rb, line 45
def backup(resources)
  raise ArgumentError if resources.nil?

  @app_name = resources.stack.app_name
  @stack_name = resources.stack.name
  @target_name = render(@target_name)
  @target_bucket = define_bucket

  return if @target_bucket.nil?

  resources.ilog.start("#{log_message} in progress.") do |s|
    begin
      tar_out = tar(@files)
      zip_out = zip(tar_out)
      upload(zip_out)

      s.success("#{log_message} succeeded.")
    rescue StandardError => e
      s.failure("#{log_message} failed: #{e}")
    ensure
      tar_out.close unless tar_out.nil?
      zip_out.close unless zip_out.nil?
    end
  end
end
method_missing(method_name, *args, &block) click to toggle source

Dynamically responding to hooks supplied in the constructor

Calls superclass method
# File lib/plugins/backup.rb, line 72
def method_missing(method_name, *args, &block)
  @hooks.include?(method_name) ? backup(*args) : super
end
respond_to?(method_name, include_private = false) click to toggle source
Calls superclass method
# File lib/plugins/backup.rb, line 76
def respond_to?(method_name, include_private = false)
  @hooks.include?(method_name) || super
end

Private Instance Methods

bucket_by_account(account) click to toggle source
# File lib/plugins/backup.rb, line 169
def bucket_by_account(account)
  @buckets[account]
end
define_bucket() click to toggle source
# File lib/plugins/backup.rb, line 155
def define_bucket
  case
  # returning already calculated bucket name
  when @target_bucket
    @target_bucket
  # single bucket for all accounts
  when @bucket
    @bucket
  # calculating bucket based on account name
  when @buckets
    bucket_by_account(iam_account)
  end
end
iam_account() click to toggle source
# File lib/plugins/backup.rb, line 151
def iam_account
  iam_client.list_account_aliases.account_aliases.first
end
log_message() click to toggle source
# File lib/plugins/backup.rb, line 147
def log_message
  "Uploading '#{@target_name}' to '#{@target_bucket}'"
end
render(placeholder) click to toggle source

Renders string with the specified placeholders

@param io_zip [String] raw string with placeholders @return [String] rendered string

# File lib/plugins/backup.rb, line 137
def render(placeholder)
  format(
    placeholder,
    app_name: @app_name,
    stack_name: @stack_name,
    timestamp: Time.now.to_i.to_s,
    user: ENV['USER']
  )
end
tar(target_files) click to toggle source

Create a tar archive in memory, returning the IO object pointing at the beginning of the archive.

@param target_files [Array<String>] @return tar_stream [IO]

# File lib/plugins/backup.rb, line 91
def tar(target_files)
  tar_stream = StringIO.new
  Gem::Package::TarWriter.new(tar_stream) do |writer|
    target_files.each do |file|
      file = render(file)

      writer.add_file(File.basename(file), 0644) do |io|
        File.open(file, 'r') { |f| io.write(f.read) }
      end
    end
  end
  tar_stream.seek(0)
  tar_stream
end
upload(io_zip) click to toggle source

Uploads an object from the passed IO stream to the specified bucket

@param io_zip [IO] tar stream

# File lib/plugins/backup.rb, line 124
def upload(io_zip)
  s3_client.put_object(
    acl: 'private',
    bucket: @target_bucket,
    key: @target_name,
    body: io_zip
  )
end
zip(io_tar) click to toggle source

Create a zip archive in memory, returning the IO object pointing at the beginning of the zipfile.

@param io_tar [IO] tar stream @return zip_stream [IO] IO stream of zipped file

# File lib/plugins/backup.rb, line 111
def zip(io_tar)
  zip_stream = StringIO.new
  Zlib::GzipWriter.wrap(zip_stream) do |gz|
    gz.write(io_tar.read)
    gz.finish
  end
  zip_stream.seek(0)
  zip_stream
end