aws_auditor 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0a8fb7ab9b3d04b41fb21c6640e2c4de2a469799
4
- data.tar.gz: b2ab26ed6fc4707deb07ae35d3f149d7e0340c7a
3
+ metadata.gz: 3aaac3737b9cf61e89d42dc0bb7d553a60190e79
4
+ data.tar.gz: e1b1852944cdf66ea8f4766ddcb297ad001e5ebe
5
5
  SHA512:
6
- metadata.gz: d8826b6b49c204399655aa81c10be4364ff898f52c9318434fe20165b943927d9afe0d93bdb773c0b6de9e4c366d688ebb9c3caac4ab982dbcd15a3cc9a69d6f
7
- data.tar.gz: eae728c9c0221dbc66d7d7559c588f5dfe15e79346ce77b77ed00dddbd6125b4ff5b98cf84833a4eef8ce77d62440cc381a46b0e30e2c93aae2dc7d08f2128af
6
+ metadata.gz: edb9b18f94fd362a32eefa44577cdb050985338bbcf93bed4c281103bb60578a42ebce033bbabf08187966a06971e72ab84b3b94bf1f87d77d1c338959d10711
7
+ data.tar.gz: 1d51d364acc3d5152a1da77e4e1d9ecfa5041ba0843d99a8ac437a814164143f165e9bbaddb186d98a5034f08da714728b34759b6e0d2f8444b67c0fe2f174b2
data/.gitignore CHANGED
@@ -14,4 +14,5 @@
14
14
  mkmf.log
15
15
 
16
16
  .aws.yml
17
+ .google.yml
17
18
  *.gem
data/README.md CHANGED
@@ -18,27 +18,45 @@ Or install it yourself as:
18
18
 
19
19
  $ gem install aws_auditor
20
20
 
21
- ## Usage
21
+ ## How-to
22
22
 
23
- Create a `.aws.yml` file in the root directory, with the following structure.
23
+ ### AWS Setup
24
+ Create a `.aws.yml` file in the root directory with the following structure.
24
25
 
25
26
  ```yaml
26
27
  ---
27
28
  account1:
28
29
  access_key_id: 'ACCESS_KEY_ID'
29
- secret_access_key: 'SECRET_ACCESS_KEY
30
+ secret_access_key: 'SECRET_ACCESS_KEY'
30
31
  account2:
31
32
  access_key_id: 'ACCESS_KEY_ID'
32
33
  secret_access_key: 'SECRET_ACCESS_KEY
33
34
  ```
34
35
 
36
+ ### Google Setup (optional)
37
+ You can export audit information to a Google Spreadsheet, but you must first create a `.google.yml` in the root directory with the following structure.
38
+
39
+ ```yaml
40
+ ---
41
+ login:
42
+ email: 'GOOGLE_EMAIL_ADDRESS'
43
+ password: 'GOOGLE_EMAIL_PASSWORD'
44
+ file:
45
+ path: 'DESIRED_PATH_TO_FILE' #optional, creates in root directory otherwise
46
+ name: 'NAME_OF_FILE'
47
+ ```
48
+
35
49
  To find discrepancies between number of running instances and purchased instances, run:
36
50
 
37
51
  $ aws_auditor audit account1
38
52
 
39
- To list instances for all stacks in your account, run:
53
+ To list running instances for all stacks in your account, run:
54
+
55
+ $ aws_auditor inspect account1
56
+
57
+ To export audit information to a Google Spreadsheet, make sure you added a `.google.yml` and run:
40
58
 
41
- $ aws_auditor stack-audit account1
59
+ $ aws_auditor export account1
42
60
 
43
61
  ## Contributing
44
62
 
data/aws_auditor.gemspec CHANGED
@@ -21,6 +21,8 @@ Gem::Specification.new do |spec|
21
21
  spec.add_dependency 'aws-sdk', '~>1'
22
22
  spec.add_dependency 'hashie', '~> 3.3'
23
23
  spec.add_dependency 'gli', '~> 2.10'
24
+ spec.add_dependency 'highline', '~> 1.6'
25
+ spec.add_dependency 'google_drive', '~> 0.3'
24
26
 
25
27
  spec.add_development_dependency "bundler", "~> 1.7"
26
28
  spec.add_development_dependency "rake", "~> 10.0"
@@ -0,0 +1,38 @@
1
+ require_relative './instance_helper'
2
+
3
+ module AwsAuditor
4
+ class CacheInstance
5
+ extend InstanceHelper
6
+ extend CacheWrapper
7
+
8
+ attr_accessor :id, :name, :instance_type, :engine, :count
9
+ def initialize(cache_instance)
10
+ @id = cache_instance[:cache_cluster_id] || cache_instance[:reserved_cache_node_id]
11
+ @name = cache_instance[:cache_cluster_id] || cache_instance[:reserved_cache_node_id]
12
+ @instance_type = cache_instance[:cache_node_type]
13
+ @engine = cache_instance[:engine] || cache_instance[:product_description]
14
+ @count = cache_instance[:cache_node_count] || 1
15
+ end
16
+
17
+ def to_s
18
+ "#{engine} #{instance_type}"
19
+ end
20
+
21
+ def self.get_instances
22
+ instances = cache.describe_cache_clusters[:cache_clusters]
23
+ instances.map do |instance|
24
+ next unless instance[:cache_cluster_status].to_s == 'available'
25
+ new(instance)
26
+ end if instances
27
+ end
28
+
29
+ def self.get_reserved_instances
30
+ instances = cache.describe_reserved_cache_nodes[:reserved_db_instances]
31
+ instances.map do |instance|
32
+ next unless instance[:state].to_s == 'active'
33
+ new(instance)
34
+ end if instances
35
+ end
36
+
37
+ end
38
+ end
@@ -1,7 +1,14 @@
1
+ arg :aws_account
1
2
  desc 'Reviews Reserved Instances'
2
3
  command 'audit' do |c|
4
+ c.switch [:e, :ec2], :desc => "Only audit EC2 instances"
5
+ c.switch [:d, :rds], :desc => "Only audit RDS instances"
6
+ c.switch [:c, :cache], :desc => "Only audit ElastiCache instances"
7
+ c.switch [:r, :reserved], :desc => "Shows reserved instance counts"
8
+ c.switch [:i, :instances], :desc => "Shows current instance counts"
3
9
  c.action do |global_options, options, args|
4
10
  require_relative '../scripts/audit'
5
- AwsAuditor::Scripts::Audit.execute args.first
11
+ raise ArgumentError, 'You must specify an AWS account' unless args.first
12
+ AwsAuditor::Scripts::Audit.execute(args.first,options)
6
13
  end
7
14
  end
@@ -0,0 +1,9 @@
1
+ arg :aws_account
2
+ desc 'Reviews Reserved Instances'
3
+ command 'export' do |c|
4
+ c.action do |global_options, options, args|
5
+ require_relative '../scripts/export'
6
+ raise ArgumentError, 'You must specify an AWS account' unless args.first
7
+ AwsAuditor::Scripts::Export.execute(args.first, options)
8
+ end
9
+ end
@@ -0,0 +1,12 @@
1
+ arg :aws_account
2
+ desc 'Reviews Stack Instances'
3
+ command 'inspect' do |c|
4
+ c.switch [:e, :ec2], :desc => "Only audit EC2 instances"
5
+ c.switch [:d, :rds], :desc => "Only audit RDS instances"
6
+ c.switch [:c, :cache], :desc => "Only audit ElastiCache instances"
7
+ c.action do |global_options, options, args|
8
+ require_relative '../scripts/inspect'
9
+ raise ArgumentError, 'You must specify an AWS account' unless args.first
10
+ AwsAuditor::Scripts::Inspect.execute(args.first,options)
11
+ end
12
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative './aws'
2
+ require_relative './google'
2
3
 
3
4
  module AwsAuditor
4
5
  module AWSWrapper
@@ -13,7 +14,7 @@ module AwsAuditor
13
14
  attr_accessor :ec2
14
15
 
15
16
  def ec2
16
- @ec2 ||= AWS::EC2.new()
17
+ @ec2 ||= AWS::EC2.new
17
18
  end
18
19
  end
19
20
 
@@ -24,5 +25,29 @@ module AwsAuditor
24
25
  @opsworks ||= AWS::OpsWorks.new.client
25
26
  end
26
27
  end
28
+
29
+ module RDSWrapper
30
+ attr_accessor :rds
31
+
32
+ def rds
33
+ @rds ||= AWS::RDS.new.client
34
+ end
35
+ end
36
+
37
+ module CacheWrapper
38
+ attr_accessor :cache
39
+
40
+ def cache
41
+ @cache ||= AWS::ElastiCache.new.client
42
+ end
43
+ end
44
+
45
+ module GoogleWrapper
46
+ attr_accessor :google
47
+
48
+ def google
49
+ @google ||= AwsAuditor::Google.configuration
50
+ end
51
+ end
27
52
 
28
53
  end
@@ -1,13 +1,16 @@
1
+ require_relative './instance_helper'
2
+
1
3
  module AwsAuditor
2
- class Instance
4
+ class EC2Instance
5
+ extend InstanceHelper
3
6
  extend EC2Wrapper
4
7
 
5
8
  attr_accessor :id, :platform, :availability_zone, :instance_type, :count
6
- def initialize(aws_instance, count=1)
7
- @id = aws_instance.id
8
- @platform = platform_helper(aws_instance)
9
- @availability_zone = aws_instance.availability_zone
10
- @instance_type = aws_instance.instance_type
9
+ def initialize(ec2_instance, count=1)
10
+ @id = ec2_instance.id
11
+ @platform = platform_helper(ec2_instance)
12
+ @availability_zone = ec2_instance.availability_zone
13
+ @instance_type = ec2_instance.instance_type
11
14
  @count = count
12
15
  end
13
16
 
@@ -15,12 +18,12 @@ module AwsAuditor
15
18
  "#{@platform} #{@availability_zone} #{@instance_type}"
16
19
  end
17
20
 
18
- def platform_helper(aws_instance)
19
- if aws_instance.class.to_s == 'AWS::EC2::Instance'
20
- if aws_instance.vpc?
21
+ def platform_helper(ec2_instance)
22
+ if ec2_instance.class.to_s == 'AWS::EC2::Instance'
23
+ if ec2_instance.vpc?
21
24
  return 'VPC'
22
- elsif aws_instance.platform
23
- if aws_instance.platform.downcase.include? 'windows'
25
+ elsif ec2_instance.platform
26
+ if ec2_instance.platform.downcase.include? 'windows'
24
27
  return 'Windows'
25
28
  else
26
29
  return 'Linux'
@@ -28,10 +31,10 @@ module AwsAuditor
28
31
  else
29
32
  return 'Linux'
30
33
  end
31
- elsif aws_instance.class.to_s == 'AWS::EC2::ReservedInstances'
32
- if aws_instance.product_description.downcase.include? 'vpc'
34
+ elsif ec2_instance.class.to_s == 'AWS::EC2::ReservedInstances'
35
+ if ec2_instance.product_description.downcase.include? 'vpc'
33
36
  return 'VPC'
34
- elsif aws_instance.product_description.downcase.include? 'windows'
37
+ elsif ec2_instance.product_description.downcase.include? 'windows'
35
38
  return 'Windows'
36
39
  else
37
40
  return 'Linux'
@@ -43,7 +46,7 @@ module AwsAuditor
43
46
  instances = ec2.instances
44
47
  instances.map do |instance|
45
48
  next unless instance.status.to_s == 'running'
46
- Instance.new(instance)
49
+ new(instance)
47
50
  end if instances
48
51
  end
49
52
 
@@ -51,12 +54,9 @@ module AwsAuditor
51
54
  reserved_instances = ec2.reserved_instances
52
55
  reserved_instances.map do |ri|
53
56
  next unless ri.state == 'active'
54
- Instance.new(ri, ri.instance_count)
57
+ new(ri, ri.instance_count)
55
58
  end if reserved_instances
56
59
  end
57
60
 
58
- def self.instance_hash
59
- Hash[get_instances.map {|instance| [instance.id, instance]}]
60
- end
61
61
  end
62
62
  end
@@ -0,0 +1,40 @@
1
+ module AwsAuditor
2
+ class GoogleConfig < Hash
3
+ include Hashie::Extensions::IndifferentAccess
4
+ end
5
+
6
+ class Google
7
+ FILE_NAMES = %w[.google.yml]
8
+
9
+ def self.configuration
10
+ credentials = load_config[:login]
11
+ GoogleDrive.login(credentials[:email],credentials[:password])
12
+ end
13
+
14
+ def self.file
15
+ load_config[:file]
16
+ end
17
+
18
+ def self.load_config
19
+ return @config if @config
20
+ @config = GoogleConfig[YAML.load_file(config_path)]
21
+ end
22
+
23
+ def self.config_path
24
+ if filepath = FILE_NAMES.detect {|filename| File.exists?(filename)}
25
+ File.join(Dir.pwd, filepath)
26
+ else
27
+ old_dir = Dir.pwd
28
+ Dir.chdir('..')
29
+ if old_dir != Dir.pwd
30
+ config_path
31
+ else
32
+ puts "Could not find #{FILE_NAMES.join(' or ')}"
33
+ exit
34
+ end
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+
@@ -0,0 +1,80 @@
1
+ require 'google_drive'
2
+
3
+ module AwsAuditor
4
+ class GoogleSheet
5
+ extend GoogleWrapper
6
+
7
+ attr_accessor :sheet, :worksheet, :path
8
+ def initialize(title, path, environment)
9
+ @sheet = self.class.create_sheet(title, path)
10
+ @worksheet = self.class.worksheet(sheet, environment)
11
+ end
12
+
13
+ def write_header(header)
14
+ worksheet.list.keys = header.unshift('name')
15
+ worksheet.save
16
+ end
17
+
18
+ def write_row(value_hash)
19
+ worksheet.list.push(value_hash)
20
+ worksheet.save
21
+ end
22
+
23
+ def self.first_or_create(title)
24
+ spreadsheet = google.root_collection.files("title" => title, "title-exact" => true)[0]
25
+ spreadsheet ? spreadsheet : google.create_spreadsheet(title)
26
+ end
27
+
28
+ #returns a spreadsheet object
29
+ def self.create_sheet(title, path)
30
+ folder = go_to_collection(path) if path
31
+ if folder
32
+ spreadsheet = folder.files("title" => title, "title-exact" => true)[0]
33
+ if spreadsheet
34
+ return spreadsheet
35
+ else
36
+ file = first_or_create(title)
37
+ folder.add(file)
38
+ google.root_collection.remove(file)
39
+ return folder.files("title" => title, "title-exact" => true)[0]
40
+ end
41
+ else
42
+ first_or_create(title)
43
+ end
44
+ end
45
+
46
+ #returns a worksheet object
47
+ def self.worksheet(spreadsheet, title)
48
+ worksheet = spreadsheet.worksheet_by_title(title)
49
+ worksheet ? delete_all_rows(worksheet) : spreadsheet.add_worksheet(title)
50
+ end
51
+
52
+ #returns a collection object
53
+ def self.go_to_collection(directory)
54
+ if directory
55
+ path = directory.split('/')
56
+ go_to_subcollection(google.collection_by_title(path[0]),path[1..-1])
57
+ end
58
+ end
59
+
60
+ #returns a collection object
61
+ def self.go_to_subcollection(base, subs)
62
+ puts "Folder doesn't exist in specified path" and exit if base.nil?
63
+ if subs.empty?
64
+ return base
65
+ else
66
+ base = base.subcollection_by_title(subs[0])
67
+ go_to_subcollection(base,subs[1..-1])
68
+ end
69
+ end
70
+
71
+ def self.delete_all_rows(worksheet)
72
+ worksheet.list.each do |row|
73
+ row.clear
74
+ end
75
+ worksheet.save
76
+ worksheet
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,28 @@
1
+ module AwsAuditor
2
+ module InstanceHelper
3
+ def instance_hash
4
+ Hash[get_instances.map { |instance| instance.nil? ? next : [instance.id, instance]}.compact]
5
+ end
6
+
7
+ def instance_count_hash(instances)
8
+ instance_hash = Hash.new()
9
+ instances.each do |instance|
10
+ next if instance.nil?
11
+ instance_hash[instance.to_s] = instance_hash.has_key?(instance.to_s) ? instance_hash[instance.to_s] + instance.count : instance.count
12
+ end if instances
13
+ instance_hash
14
+ end
15
+
16
+ def compare
17
+ differences = Hash.new()
18
+ instances = instance_count_hash(get_instances)
19
+ ris = instance_count_hash(get_reserved_instances)
20
+ instances.keys.concat(ris.keys).uniq.each do |key|
21
+ instance_count = instances.has_key?(key) ? instances[key] : 0
22
+ ris_count = ris.has_key?(key) ? ris[key] : 0
23
+ differences[key] = ris_count - instance_count
24
+ end
25
+ differences
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,51 @@
1
+ require_relative './instance_helper'
2
+
3
+ module AwsAuditor
4
+ class RDSInstance
5
+ extend InstanceHelper
6
+ extend RDSWrapper
7
+
8
+ attr_accessor :id, :name, :multi_az, :instance_type, :engine, :count
9
+ def initialize(rds_instance)
10
+ @id = rds_instance[:db_instance_identifier] || rds_instance[:reserved_db_instances_offering_id]
11
+ @name = rds_instance[:db_instance_identifier] || rds_instance[:db_name]
12
+ @multi_az = rds_instance[:multi_az]
13
+ @instance_type = rds_instance[:db_instance_class]
14
+ @engine = rds_instance[:engine] || rds_instance[:product_description]
15
+ @count = rds_instance[:db_instance_count] || 1
16
+ end
17
+
18
+ def to_s
19
+ "#{engine_helper} #{multi_az?} #{instance_type}"
20
+ end
21
+
22
+ def multi_az?
23
+ multi_az ? "Multi-AZ" : "Single-AZ"
24
+ end
25
+
26
+ def engine_helper
27
+ if engine.downcase.include? "post"
28
+ return "PostgreSQL"
29
+ elsif engine.downcase.include? "mysql"
30
+ return "MySQL"
31
+ end
32
+ end
33
+
34
+ def self.get_instances
35
+ instances = rds.describe_db_instances[:db_instances]
36
+ instances.map do |instance|
37
+ next unless instance[:db_instance_status].to_s == 'available'
38
+ new(instance)
39
+ end
40
+ end
41
+
42
+ def self.get_reserved_instances
43
+ instances = rds.describe_reserved_db_instances[:reserved_db_instances]
44
+ instances.map do |instance|
45
+ next unless instance[:state].to_s == 'active'
46
+ new(instance)
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -1,36 +1,87 @@
1
+ require 'highline/import'
2
+
1
3
  module AwsAuditor
2
4
  module Scripts
3
5
  class Audit
4
6
  extend AWSWrapper
5
- extend EC2Wrapper
6
7
 
7
- def self.execute(environment)
8
+ def self.execute(environment, options=nil)
8
9
  aws(environment)
9
- compare.each do |key,value|
10
- puts "#{key}: #{value}"
10
+ if options[:ec2]
11
+ audit_ec2(options)
12
+ elsif options[:rds]
13
+ audit_rds(options)
14
+ elsif options[:cache]
15
+ audit_cache(options)
16
+ else
17
+ audit_ec2(options)
18
+ audit_rds(options)
19
+ audit_cache(options)
20
+ end
21
+
22
+ end
23
+
24
+ def self.audit_rds(options)
25
+ puts "=============== RDS ==============="
26
+ if options[:instances]
27
+ RDSInstance.instance_count_hash(RDSInstance.get_instances).each do |key,value|
28
+ say "<%= color('#{key}: #{value}', :white) %>"
29
+ end
30
+ elsif options[:reserved]
31
+ RDSInstance.instance_count_hash(RDSInstance.get_reserved_instances).each do |key,value|
32
+ say "<%= color('#{key}: #{value}', :white) %>"
33
+ end
34
+ else
35
+ RDSInstance.compare.each do |key, value|
36
+ colorize(key,value)
37
+ end
11
38
  end
12
39
  end
13
40
 
14
- def self.create_instance_hash(instance_type)
15
- instance_hash = Hash.new()
16
- instance_type.each do |instance|
17
- next if instance.nil?
18
- instance_hash[instance.to_s] = instance_hash.has_key?(instance.to_s) ? instance_hash[instance.to_s] + instance.count : instance.count
41
+ def self.audit_ec2(options)
42
+ puts "=============== EC2 ==============="
43
+ if options[:instances]
44
+ EC2Instance.instance_count_hash(EC2Instance.get_instances).each do |key,value|
45
+ say "<%= color('#{key}: #{value}', :white) %>"
46
+ end
47
+ elsif options[:reserved]
48
+ EC2Instance.instance_count_hash(EC2Instance.get_reserved_instances).each do |key,value|
49
+ say "<%= color('#{key}: #{value}', :white) %>"
50
+ end
51
+ else
52
+ EC2Instance.compare.each do |key,value|
53
+ colorize(key,value)
54
+ end
19
55
  end
20
- instance_hash
21
56
  end
22
57
 
23
- def self.compare
24
- differences = Hash.new()
25
- instances = create_instance_hash(Instance.get_instances)
26
- ris = create_instance_hash(Instance.get_reserved_instances)
27
- instances.keys.concat(ris.keys).uniq.each do |key|
28
- instance_count = instances.has_key?(key) ? instances[key] : 0
29
- ris_count = ris.has_key?(key) ? ris[key] : 0
30
- differences[key] = ris_count - instance_count
58
+ def self.audit_cache(options)
59
+ puts "============== CACHE =============="
60
+ if options[:instances]
61
+ CacheInstance.instance_count_hash(CacheInstance.get_instances).each do |key,value|
62
+ say "<%= color('#{key}: #{value}', :white) %>"
63
+ end
64
+ elsif options[:reserved]
65
+ CacheInstance.instance_count_hash(CacheInstance.get_reserved_instances).each do |key,value|
66
+ say "<%= color('#{key}: #{value}', :white) %>"
67
+ end
68
+ else
69
+ CacheInstance.compare.each do |key,value|
70
+ colorize(key,value)
71
+ end
31
72
  end
32
- differences
33
73
  end
74
+
75
+ def self.colorize(key,value)
76
+ if value < 0
77
+ say "<%= color('#{key}: #{value}', :yellow) %>"
78
+ elsif value == 0
79
+ say "<%= color('#{key}: #{value}', :green) %>"
80
+ elsif value > 0
81
+ say "<%= color('#{key}: #{value}', :red) %>"
82
+ end
83
+ end
84
+
34
85
  end
35
86
  end
36
87
  end
@@ -0,0 +1,98 @@
1
+ require_relative "../google"
2
+
3
+ module AwsAuditor
4
+ module Scripts
5
+ class Export
6
+ extend GoogleWrapper
7
+ extend AWSWrapper
8
+
9
+ def self.execute(environment, options = nil)
10
+ aws(environment)
11
+ file = GoogleSheet.new(Google.file[:name], Google.file[:path], environment)
12
+ file.write_header(get_all_keys)
13
+ write_opsworks_stacks(file)
14
+ write_rds(file)
15
+ write_cache(file)
16
+ write_totals(file)
17
+ `open #{file.sheet.human_url}`
18
+ end
19
+
20
+ def self.write_opsworks_stacks(file)
21
+ file.write_row({name: "EC2"})
22
+ opsworks_stacks.each do |stack|
23
+ next if stack.instances.empty?
24
+ value_hash = EC2Instance.instance_count_hash(stack.instances)
25
+ value_hash[:name] = stack.name
26
+ file.write_row(value_hash)
27
+ end
28
+ end
29
+
30
+ def self.write_rds(file)
31
+ file.write_row({name: "RDS"})
32
+ rds_instances.each do |db|
33
+ value_hash = Hash({:name => db.name, :"#{db.to_s}" => '1'})
34
+ file.write_row(value_hash)
35
+ end
36
+ end
37
+
38
+ def self.write_cache(file)
39
+ file.write_row({name: "CACHE"})
40
+ cache_instances.each do |cache|
41
+ value_hash = Hash({:name => cache.name, :"#{cache.to_s}" => '1'})
42
+ file.write_row(value_hash)
43
+ end
44
+ end
45
+
46
+ def self.write_totals(file)
47
+ file.write_row({name: "TOTALS"})
48
+ instance_counts = get_all_instance_counts.merge({name: "Running Instances"})
49
+ file.write_row(instance_counts)
50
+ reserved_counts = get_all_reserved_counts.merge({name: "Reserved Instances"})
51
+ file.write_row(reserved_counts)
52
+ differences = get_difference_counts.merge({name: "Differences"})
53
+ file.write_row(differences)
54
+ end
55
+
56
+ def self.get_all_keys
57
+ ec2 = EC2Instance.instance_hash.values.map{ |x| x.to_s }.uniq.sort! { |a,b| a.downcase <=> b.downcase }
58
+ rds = RDSInstance.instance_hash.values.map{ |x| x.to_s }.uniq.sort! { |a,b| a.downcase <=> b.downcase }
59
+ cache = CacheInstance.instance_hash.values.map{ |x| x.to_s }.uniq.sort! { |a,b| a.downcase <=> b.downcase }
60
+ ec2.concat(rds).concat(cache).compact
61
+ end
62
+
63
+ def self.get_all_instance_counts
64
+ ec2 = EC2Instance.instance_count_hash(EC2Instance.get_instances)
65
+ rds = RDSInstance.instance_count_hash(RDSInstance.get_instances)
66
+ cache = CacheInstance.instance_count_hash(CacheInstance.get_instances)
67
+ ec2.merge(rds).merge(cache)
68
+ end
69
+
70
+ def self.get_all_reserved_counts
71
+ ec2 = EC2Instance.instance_count_hash(EC2Instance.get_reserved_instances)
72
+ rds = RDSInstance.instance_count_hash(RDSInstance.get_reserved_instances)
73
+ cache = CacheInstance.instance_count_hash(CacheInstance.get_reserved_instances)
74
+ ec2.merge(rds).merge(cache)
75
+ end
76
+
77
+ def self.get_difference_counts
78
+ ec2 = EC2Instance.compare
79
+ rds = RDSInstance.compare
80
+ cache = CacheInstance.compare
81
+ ec2.merge(rds).merge(cache)
82
+ end
83
+
84
+ def self.opsworks_stacks
85
+ @opsworks_stacks ||= Stack.all
86
+ end
87
+
88
+ def self.rds_instances
89
+ @rds_instances ||= RDSInstance.get_instances
90
+ end
91
+
92
+ def self.cache_instances
93
+ @cache_instances ||= CacheInstance.get_instances
94
+ end
95
+
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,48 @@
1
+ module AwsAuditor
2
+ module Scripts
3
+ class Inspect
4
+ extend AWSWrapper
5
+ extend OpsWorksWrapper
6
+
7
+ def self.execute(environment, options=nil)
8
+ aws(environment)
9
+ if options[:ec2]
10
+ inspect_stacks
11
+ elsif options[:rds]
12
+ inspect_dbs
13
+ elsif options[:cache]
14
+ inspect_caches
15
+ else
16
+ puts "You must use a switch. See `aws-auditor inspect --help` for more info."
17
+ end
18
+ end
19
+
20
+ def self.inspect_stacks
21
+ Stack.all.each do |stack|
22
+ stack.pretty_print
23
+ end
24
+ end
25
+
26
+ def self.inspect_dbs
27
+ RDSInstance.get_instances.each do |db|
28
+ puts "========================"
29
+ puts "#{db.name}"
30
+ puts "========================"
31
+ puts db.to_s
32
+ puts "\n"
33
+ end
34
+ end
35
+
36
+ def self.inspect_caches
37
+ CacheInstance.get_instances.each do |cache|
38
+ puts "========================"
39
+ puts "#{cache.name}"
40
+ puts "========================"
41
+ puts cache.to_s
42
+ puts "\n"
43
+ end
44
+ end
45
+
46
+ end
47
+ end
48
+ end
@@ -1,3 +1,5 @@
1
+ require 'highline/import'
2
+
1
3
  module AwsAuditor
2
4
  class Stack
3
5
  extend OpsWorksWrapper
@@ -14,7 +16,13 @@ module AwsAuditor
14
16
  instances = self.class.opsworks.describe_instances({stack_id: id})[:instances]
15
17
  instances.map do |instance|
16
18
  next unless instance[:status].to_s == 'online'
17
- all_instances[instance[:ec2_instance_id]].to_s
19
+ self.class.all_instances[instance[:ec2_instance_id]]
20
+ end
21
+ end
22
+
23
+ def print_instances
24
+ EC2Instance.instance_count_hash(self.instances).each do |key,value|
25
+ say "<%= color('#{key}: #{value}', :white) %>"
18
26
  end
19
27
  end
20
28
 
@@ -22,14 +30,19 @@ module AwsAuditor
22
30
  puts "----------------------------------"
23
31
  puts "#{@name}"
24
32
  puts "----------------------------------"
25
- instances.each do |instance|
26
- puts instance.to_s
27
- end
33
+ print_instances
28
34
  puts "\n"
29
35
  end
36
+
37
+ def self.all
38
+ stacks = opsworks.describe_stacks
39
+ stacks.data[:stacks].map do |stack|
40
+ new(stack)
41
+ end.sort! { |a,b| a.name.downcase <=> b.name.downcase } if stacks
42
+ end
30
43
 
31
- def all_instances
32
- @all_instances ||= Instance.instance_hash
44
+ def self.all_instances
45
+ @all_instances ||= EC2Instance.instance_hash
33
46
  end
34
47
 
35
48
  end
@@ -1,3 +1,3 @@
1
1
  module AwsAuditor
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/aws_auditor.rb CHANGED
@@ -1,7 +1,10 @@
1
1
  require 'aws_auditor/version'
2
2
  require_relative 'aws_auditor/convenience_wrappers'
3
- require_relative 'aws_auditor/instance'
3
+ require_relative 'aws_auditor/ec2_instance'
4
+ require_relative 'aws_auditor/rds_instance'
5
+ require_relative 'aws_auditor/cache_instance'
4
6
  require_relative 'aws_auditor/stack'
7
+ require_relative 'aws_auditor/google_sheet'
5
8
 
6
9
  module AwsAuditor
7
10
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: aws_auditor
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Elliot Hursh
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-27 00:00:00.000000000 Z
11
+ date: 2014-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -52,6 +52,34 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '2.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: highline
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: google_drive
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.3'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.3'
55
83
  - !ruby/object:Gem::Dependency
56
84
  name: bundler
57
85
  requirement: !ruby/object:Gem::Requirement
@@ -99,12 +127,19 @@ files:
99
127
  - bin/aws-auditor
100
128
  - lib/aws_auditor.rb
101
129
  - lib/aws_auditor/aws.rb
130
+ - lib/aws_auditor/cache_instance.rb
102
131
  - lib/aws_auditor/commands/audit.rb
103
- - lib/aws_auditor/commands/stack-audit.rb
132
+ - lib/aws_auditor/commands/export.rb
133
+ - lib/aws_auditor/commands/inspect.rb
104
134
  - lib/aws_auditor/convenience_wrappers.rb
105
- - lib/aws_auditor/instance.rb
135
+ - lib/aws_auditor/ec2_instance.rb
136
+ - lib/aws_auditor/google.rb
137
+ - lib/aws_auditor/google_sheet.rb
138
+ - lib/aws_auditor/instance_helper.rb
139
+ - lib/aws_auditor/rds_instance.rb
106
140
  - lib/aws_auditor/scripts/audit.rb
107
- - lib/aws_auditor/scripts/stack-audit.rb
141
+ - lib/aws_auditor/scripts/export.rb
142
+ - lib/aws_auditor/scripts/inspect.rb
108
143
  - lib/aws_auditor/stack.rb
109
144
  - lib/aws_auditor/version.rb
110
145
  homepage: https://github.com/elliothursh/aws_auditor
@@ -1,8 +0,0 @@
1
- arg :environment
2
- desc 'Reviews Stack Instances'
3
- command 'stack-audit' do |c|
4
- c.action do |global_options, options, args|
5
- require_relative '../scripts/stack-audit'
6
- AwsAuditor::Scripts::StackAudit.execute args.first
7
- end
8
- end
@@ -1,24 +0,0 @@
1
- module AwsAuditor
2
- module Scripts
3
- class StackAudit
4
- extend AWSWrapper
5
- extend EC2Wrapper
6
- extend OpsWorksWrapper
7
-
8
- def self.execute(environment)
9
- aws(environment)
10
- get_stacks
11
- end
12
-
13
- def self.get_stacks
14
- stacks = opsworks.describe_stacks
15
- stacks.data[:stacks].map do |stack|
16
- stck = Stack.new(stack)
17
- stck.pretty_print
18
- stck
19
- end if stacks
20
- end
21
-
22
- end
23
- end
24
- end