lib/preserve-rds-snapshot/cli.rb in preserve-rds-snapshot-0.2.0 vs lib/preserve-rds-snapshot/cli.rb in preserve-rds-snapshot-0.3.0

- old
+ new

@@ -2,15 +2,23 @@ require 'thor/aws' module PreserveRdsSnapshot class CLI < Thor include Thor::Aws + PRESERVE_TAG_NAME = 'preserve-rds-snapshot' class_option :instance, aliases: [:i], type: :string, desc: 'target DB Instance' + class_option :aws_account_number, + aliases: [:n], + type: :string, + desc: 'AWS Account Number (ex: 012345678901)' + class_option :dry_run, + type: :boolean, + desc: "show only, don't modify" desc :list, 'Show list of RDS Snapshots' option :snapshot_type, aliases: [:t], type: :string, @@ -27,26 +35,60 @@ rescue ::Aws::Errors::ServiceError => e $stderr.puts e end end + desc :init, "initialize instance" + option :generations, + aliases: [:g], + type: :numeric, + desc: "preserved snapshot generations", + default: 10 + def init + begin + rds.db_instances.each do |instance| + if options[:dry_run] + puts "init(dry run)\t#{instance.db_instance_identifier}\t#{options[:generations]}" + else + if enable_preserve(instance.db_instance_identifier, options[:generations]) + puts "init\t#{instance.db_instance_identifier}\t#{options[:generations]}" + end + end + end + fix_tags + rescue ::Aws::Errors::ServiceError => e + $stderr.puts e + end + end + desc :preserve, 'copy automated snapshot to manual' def preserve begin instances = db_instances(options[:instance]) instances.each do |i| - latest = latest_auto_snapshot(i.db_instance_identifier) + instance = i.db_instance_identifier + latest = latest_auto_snapshot(instance) if latest - db_snapshot_identifier = latest.db_snapshot_identifier - resp = rds.client.copy_db_snapshot( - source_db_snapshot_identifier: db_snapshot_identifier, - target_db_snapshot_identifier: preserve_snapshot_name(db_snapshot_identifier), - tags: [key: 'type', value: 'preserve'] - ) - s = resp.db_snapshot - puts "#{s.db_snapshot_identifier}\t#{s.snapshot_create_time}" + if options[:dry_run] + puts "#{latest.db_snapshot_identifier}\t-\t-" + else + s = copy_snapshot(latest.db_snapshot_identifier) + puts "copy\t#{latest.db_snapshot_identifier}\t#{s.db_snapshot_identifier}\t#{s.snapshot_create_time}" if s + end end + + tag = preserve_tag(instance, 'db') + expireds = expired_snapshots(instance, tag[:value].to_i) + dry_run_msg = '(dry run)' if options[:dry_run] + expireds.each do |expired| + unless options[:dry_run] + rds.client.delete_db_snapshot( + db_snapshot_identifier: expired.db_snapshot_identifier + ) + end + puts "delete#{dry_run_msg}\t#{expired.db_snapshot_identifier}" + end end rescue ::Aws::Errors::ServiceError => e $stderr.puts e end end @@ -58,18 +100,24 @@ desc: 'source snapshot identifier', required: true option :target_db_snapshot_identifier, aliases: [:t], type: :string, - desc: 'target snapshot identifier', - required: true + desc: 'target snapshot identifier' def copy + if options[:target_db_snapshot_identifier] + target = options[:target_db_snapshot_identifier] + else + target = preserve_snapshot_name(options[:source_db_snapshot_identifier]) + end + source = options[:source_db_snapshot_identifier] + begin resp = rds.client.copy_db_snapshot( - source_db_snapshot_identifier: options[:source_db_snapshot_identifier], - target_db_snapshot_identifier: options[:target_db_snapshot_identifier], - tags: [key: 'type', value: 'preserve'] + source_db_snapshot_identifier: source, + target_db_snapshot_identifier: target, + tags: [key: PRESERVE_TAG_NAME, value: 'true'] ) s = resp.db_snapshot puts "#{s.db_snapshot_identifier}\t#{s.snapshot_create_time}" rescue ::Aws::Errors::ServiceError => e $stderr.puts e @@ -105,17 +153,122 @@ list = [] begin if db_instance_identifier list << rds.db_instance(db_instance_identifier) else - list = rds.db_instances.to_a + rds.db_instances.each do |i| + list << i if preserve_tag(i.db_instance_identifier, 'db') + end end rescue ::Aws::Errors::ServiceError => e $stderr.puts e end + list end def preserve_snapshot_name(db_snapshot_identifier) 'preserve-' + db_snapshot_identifier.gsub(/^rds:/, '') + end + + def aws_account_number + if options[:aws_account_number] + return options[:aws_account_number] + else + begin + return ec2.security_groups(group_names: ['default']).first.owner_id + rescue ::Aws::Errors::ServiceError => e + $stderr.puts e + end + end + end + + def rds_arn(resource_id, type) + "arn:aws:rds:#{options[:region]}:#{aws_account_number}:#{type}:#{resource_id}" + end + + def preserve_tag(resource_id, type) + tag = nil + begin + resp = rds.client.list_tags_for_resource( + resource_name: rds_arn(resource_id, type) + ) + tag = resp.tag_list.find {|t| t[:key] == PRESERVE_TAG_NAME} + rescue ::Aws::Errors::ServiceError => e + $stderr.puts e + end + tag + end + + def enable_preserve(resource_id, generations) + return false unless generations.kind_of? Integer + begin + tag = preserve_tag(resource_id, 'db') + unless tag + resp = rds.client.add_tags_to_resource( + resource_name: rds_arn(resource_id, 'db'), + tags: [{key: PRESERVE_TAG_NAME, value: generations.to_s}] + ) + return resp.successful? + end + rescue ::Aws::Errors::ServiceError => e + $stderr.puts e + end + end + + # fix v0.2.0 format tag to latest + def fix_tags + begin + rds.client.describe_db_snapshots( + snapshot_type: 'manual' + ).db_snapshots.each do |s| + arn = rds_arn(s.db_snapshot_identifier, 'snapshot') + resp = rds.client.list_tags_for_resource( + resource_name: arn + ) + tag = resp.tag_list.find {|t| t[:key] == 'type' && t[:value] == 'preserve'} + if tag + rds.client.add_tags_to_resource( + resource_name: arn, + tags: [{key: PRESERVE_TAG_NAME, value: 'true'}] + ) + rds.client.remove_tags_from_resource( + resource_name: arn, + tag_keys: ['type'] + ) + end + end + rescue ::Aws::Errors::ServiceError => e + $stderr.puts e + end + end + + def copy_snapshot(db_snapshot_identifier) + begin + resp = rds.client.copy_db_snapshot( + source_db_snapshot_identifier: db_snapshot_identifier, + target_db_snapshot_identifier: preserve_snapshot_name(db_snapshot_identifier), + tags: [key: PRESERVE_TAG_NAME, value: 'true'] + ) + return resp.db_snapshot + rescue ::Aws::Errors::ServiceError => e + $stderr.puts e + end + end + + def expired_snapshots(db_instance_identifier, generations) + expired_snapshots = [] + begin + resp = rds.client.describe_db_snapshots( + snapshot_type: 'manual', + db_instance_identifier: db_instance_identifier + ) + snapshots = resp.db_snapshots.select {|s| + preserve_tag(s.db_snapshot_identifier, 'snapshot') + }.sort_by(&:snapshot_create_time).reverse + expired_snapshots = snapshots[generations..-1] if snapshots.size > generations + rescue ::Aws::Errors::ServiceError => e + $stderr.puts e + end + expired_snapshots end end end