aws_tracker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (35) hide show
  1. data/.gitignore +12 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/README.md +111 -0
  5. data/Rakefile +9 -0
  6. data/aws_tracker.gemspec +33 -0
  7. data/bin/tracker +104 -0
  8. data/config/database.yml.example +4 -0
  9. data/db/migrate/20110331145142_create_aws_accounts.rb +16 -0
  10. data/db/migrate/20110331152735_create_instances.rb +38 -0
  11. data/db/migrate/20110403041402_create_security_groups.rb +16 -0
  12. data/db/migrate/20110403060000_create_instance_groups.rb +14 -0
  13. data/db/migrate/20110404014218_create_ebs_volumes.rb +23 -0
  14. data/db/migrate/20110408193824_create_tags.rb +17 -0
  15. data/lib/aws_tracker/models/aws_account.rb +69 -0
  16. data/lib/aws_tracker/models/ebs_volume.rb +55 -0
  17. data/lib/aws_tracker/models/instance.rb +71 -0
  18. data/lib/aws_tracker/models/security_group.rb +34 -0
  19. data/lib/aws_tracker/models/tag.rb +66 -0
  20. data/lib/aws_tracker/tracker.rb +64 -0
  21. data/lib/aws_tracker/version.rb +3 -0
  22. data/lib/aws_tracker.rb +17 -0
  23. data/lib/tasks/bundler.rake +1 -0
  24. data/lib/tasks/database.rake +21 -0
  25. data/lib/tasks/rspec.rake +6 -0
  26. data/spec/lib/aws_tracker/models/aws_account_spec.rb +103 -0
  27. data/spec/lib/aws_tracker/models/ebs_volume_spec.rb +97 -0
  28. data/spec/lib/aws_tracker/models/instance_spec.rb +96 -0
  29. data/spec/lib/aws_tracker/models/security_group_spec.rb +71 -0
  30. data/spec/lib/aws_tracker/models/tag_spec.rb +76 -0
  31. data/spec/lib/aws_tracker/tracker_spec.rb +50 -0
  32. data/spec/spec_helper.rb +17 -0
  33. data/spec/support/_configure_logging.rb +8 -0
  34. data/spec/support/create_testing_objects.rb +30 -0
  35. metadata +178 -0
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *~
6
+ .DS_Store
7
+ *.tmproj
8
+ config/database.yml
9
+ config/tracker_db.yml
10
+ db/*.sqlite3
11
+ log/*.log
12
+ tmp/**/*
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in aws_tracker.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,111 @@
1
+ AWS Tracker
2
+ ================
3
+ Models the state of one or more Amazon Web Services accounts in an ActiveRecord object graph.
4
+
5
+ *ALPHA VERSION - not yet fully functional*
6
+
7
+
8
+ ----------------
9
+ What is it?
10
+ ----------------
11
+ The AWS Tracker monitors one or more AWS accounts and the current state of their associated "resources" -- Instances, EBS volumes, RDS servers, and so on. The Tracker periodically polls the Amazon Web Services API for the latest information on each account's resources, and then maintains the corresponding rows in an ActiveRecord-compatible database. Users of the library can thereafter run multiple complex queries on the state of their AWS assets, with no network overhead.
12
+
13
+
14
+ ----------------
15
+ Why is it?
16
+ ----------------
17
+ The AWS Tracker is intended to be a foundation library, on top of which more complex AWS applications can be built. It decouples the process of downloading AWS state information from the process of displaying and/or acting on that information. Although an executable 'tracker' command-line program is included, the library is primarily intended for use from within Rails, or some other ActiveRecord context. An ActiveRecord database connection must be initialized before the aws_tracker library is loaded from within Ruby.
18
+
19
+
20
+ ----------------
21
+ Installation
22
+ ----------------
23
+ 1) Install the AWS Tracker gem (use _sudo_ as necessary).
24
+
25
+ gem install aws_tracker
26
+
27
+ 2) Install your database adaptor of choice. Sqlite3 is installed with AWS Tracker, so this step may be optional.
28
+
29
+
30
+ ----------------
31
+ Usage [from the command line]
32
+ ----------------
33
+ 1) First, generate an ActiveRecord-style configuration file.
34
+
35
+ Here are the sample contents of `tracker_db.yml`:
36
+
37
+ adapter: sqlite3
38
+ database: aws_tracker.sqlite3
39
+ pool: 5
40
+ timeout: 5000
41
+
42
+ 2) Create the database to contain the data. This is not necessary if using sqlite.
43
+
44
+ 3) To store your AWS account information in the database, export the credentials as environment variables. This is only needed the first time you run.
45
+
46
+ export AWS_ACCOUNT_NUMBER=[your AWS account number]
47
+ export AWS_ACCESS_KEY_ID=[your EC2 access key ID]
48
+ export AWS_ACCESS_KEY_SECRET=[your EC2 access key secret]
49
+
50
+ 4) Run the tracker, and point it at the database config file
51
+
52
+ tracker tracker_db.yml --migrate --create-account
53
+
54
+ * The `--migrate` argument updates the database to the latest version of the schema, and is only necessary for new databases, or when upgrading to a new version of the Tracker gem.
55
+ * The `--create-account` argument stores the above environment values as an AWSAccount object in the tracker database.
56
+
57
+
58
+ ----------------
59
+ Usage [from within Ruby]
60
+ ----------------
61
+ 1) Insert the necessary tables into your database.
62
+ First, `require 'AWSTracker/tasks'` from your Rakefile, then run
63
+
64
+ rake db:migrate:tracker
65
+
66
+ 2) In your Ruby app, first set up an ActiveRecord connection. In Rails, this is done for you automatically, but here's an example for a non-Rails app:
67
+
68
+ require 'active_record'
69
+ ActiveRecord::Base.establish_connection({
70
+ :adapter => 'sqlite3', :database => 'aws_tracker.sqlite3'
71
+ })
72
+
73
+ 3) Now `require 'aws_tracker'`. This will load the models and allow you to perform queries on the following AWS resources and their relationships:
74
+
75
+ * AWSTracker::AWSAccount
76
+ * AWSTracker::SecurityGroup
77
+ * AWSTracker::Instance
78
+ * AWSTracker::EBSVolume
79
+
80
+ But first, you need to create an AWSAccount, and use a Tracker object to fetch its status from AWS:
81
+
82
+ include AWSTracker # Load model class names into namespace
83
+ a = AWSAccount.from_memory # Create an account (see command-line usage)
84
+ a.save! # Save it in the database
85
+ t = Tracker.new # A Tracker updates all accounts in the DB
86
+ t.delay = 15 # Update every 15 seconds
87
+ t.start # Runs in the background. Call 'stop' later
88
+
89
+
90
+ ----------------
91
+ Development
92
+ ----------------
93
+ This project is still in its early stages, but most of the framework is in place. More AWS resources need to be modeled, but the patterns for the code to do so are now laid out. Helping hands are appreciated!
94
+
95
+ 1) Fetch the project code and bundle up...
96
+
97
+ git clone https://github.com/benton/aws_tracker.git
98
+ cd aws_tracker
99
+ bundle install
100
+
101
+ 2) Create a database config and the necessary tables
102
+
103
+ cp config/database.yml.example config/database.yml
104
+ rake db:migrate:tracker
105
+
106
+ 3) To run the tests, first export the credentials as environment variables, then `rake spec`.
107
+
108
+ export AWS_ACCOUNT_NUMBER=[your AWS account number]
109
+ export AWS_ACCESS_KEY_ID=[your EC2 access key ID]
110
+ export AWS_ACCESS_KEY_SECRET=[your EC2 access key secret]
111
+ rake spec
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require "rubygems"
2
+ require 'bundler'
3
+ Bundler.setup(:default, :test, :development)
4
+
5
+ # Load all tasks from 'lib/tasks'
6
+ Dir["#{File.dirname(__FILE__)}/lib/tasks/*.rake"].sort.each {|ext| load ext}
7
+
8
+ desc 'Default: run specs.'
9
+ task :default => :spec
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "aws_tracker/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "aws_tracker"
7
+ s.version = AwsTracker::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Benton Roberts"]
10
+ s.email = ["benton@bentonroberts.com"]
11
+ s.homepage = "http://github.com/benton/aws_tracker"
12
+ s.summary = %q{Models the state of Amazon Web Services accounts in ActiveRecord}
13
+ s.description = %q{This gem peridically queries AWS for information about }+
14
+ %q{Instances, SecurityGroups, EBSVolumes, etc., and saves }+
15
+ %q{the data as interconnected ActiveRecord objects.}+
16
+
17
+ s.rubyforge_project = "aws_tracker"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ # Runtime dependencies
25
+ s.add_dependency "activerecord"
26
+ s.add_dependency "right_aws"
27
+ s.add_dependency "sqlite3"
28
+
29
+ # Development / Test dependencies
30
+ s.add_development_dependency "rake"
31
+ s.add_development_dependency "rspec"
32
+
33
+ end
data/bin/tracker ADDED
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # == Synopsis
4
+ # Monitors one or more AWS accounts and pushes their status into a database.
5
+ #
6
+ # == Usage
7
+ # tracker.rb [options] DB_CONFIG_FILE.YML
8
+ #
9
+ # == Options (all options can be put into the config file)
10
+ # -d, --delay [INTEGER] Seconds between status updates. default = 180
11
+ # -l, --log-level [LEVEL] Sets Log4r level for console output. default = INFO
12
+ # -m, --migrate Update database schema
13
+ # -c, --create-account Create a new Account from environment variables
14
+ # -h, --help Displays help message
15
+ #
16
+ # == Author
17
+ # Benton Roberts
18
+
19
+ require 'logger'
20
+ require 'optparse'
21
+ require 'yaml'
22
+ LOG_LVLS = {
23
+ "DEBUG" => ::Logger::DEBUG,
24
+ "INFO" => ::Logger::INFO,
25
+ "WARN" => ::Logger::WARN,
26
+ "ERROR" => ::Logger::ERROR,
27
+ "FATAL" => ::Logger::FATAL
28
+ }
29
+
30
+ class AWSTrackerConsoleApp
31
+
32
+ def initialize
33
+ @log = ::Logger.new(STDOUT)
34
+ @log.formatter = proc {|lvl, time, prog, msg|
35
+ "#{lvl} #{time.strftime '%Y-%m-%d %H:%M:%S %Z'}: #{msg}\n"
36
+ }
37
+ parse_options
38
+ (@log.error "A database config file must be specified" ; exit) if ARGV.empty?
39
+ db_config_file = ARGV.first
40
+ @log.info "Loading database configuration from #{db_config_file}"
41
+ db_config = YAML::load(File.open(db_config_file))
42
+ connect_to_database(db_config)
43
+ create_account if @opts[:create_account]
44
+ go
45
+ end
46
+
47
+ def connect_to_database(db_config)
48
+ @log.info "Connecting to database #{db_config['database']}"
49
+ require 'active_record'
50
+ ::ActiveRecord::Base.establish_connection(db_config)
51
+ migrate if @opts[:migrate]
52
+ require 'aws_tracker'
53
+ end
54
+
55
+ def go
56
+ @tracker = AWSTracker::Tracker.new(:logger => @log)
57
+ @tracker.delay = @opts[:delay]
58
+ @tracker.start
59
+ while true do
60
+ sleep @opts[:delay] # Loop forever
61
+ end
62
+ end
63
+
64
+ def parse_options
65
+ @opts = { :delay => 180, :log_level => 'INFO' }
66
+ optparse = OptionParser.new do |opts|
67
+ opts.on('-d', '--delay SECONDS', Integer,
68
+ 'Number of seconds between status updates') do |delay|
69
+ @opts[:delay] = delay
70
+ end
71
+ opts.on('-l', '--log-level LEVEL', 'Set logging level') do |log_level|
72
+ @opts[:log_level] = log_level.upcase
73
+ end
74
+ opts.on('-m', '--migrate', 'Update database schema') do
75
+ @opts[:migrate] = true
76
+ end
77
+ acct_help = "Create a new AWSAccount object from ENV varaibles"
78
+ opts.on('-c', '--create-account', acct_help) do
79
+ @opts[:create_account] = true
80
+ end
81
+ opts.on('-h', '--help', 'Display this help message') do
82
+ puts opts and exit
83
+ end
84
+ end
85
+ optparse.parse!
86
+ @log.level = LOG_LVLS[@opts[:log_level]] if LOG_LVLS[@opts[:log_level]]
87
+ end
88
+
89
+ def migrate
90
+ @log.info "Updating database schema..."
91
+ migration_dir = File.expand_path('../../db/migrate', __FILE__)
92
+ ActiveRecord::Migrator.migrate migration_dir
93
+ end
94
+
95
+ def create_account
96
+ @log.info "Creating account from environment..."
97
+ a = AWSTracker::AWSAccount.from_memory
98
+ a.log.info "Loaded account #'#{a.account_id}' from memory"
99
+ a.save!
100
+ end
101
+
102
+ end
103
+
104
+ myApp = AWSTrackerConsoleApp.new
@@ -0,0 +1,4 @@
1
+ adapter: sqlite3
2
+ database: db/aws_tracker.sqlite3
3
+ pool: 5
4
+ timeout: 5000
@@ -0,0 +1,16 @@
1
+ class CreateAwsAccounts < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :aws_accounts do |t|
4
+ t.string :name
5
+ t.string :account_id
6
+ t.string :access_key_id
7
+ t.string :secret_access_key
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :aws_accounts
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ class CreateInstances < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :instances do |t|
4
+ t.integer :aws_account_id
5
+ t.string :instance_id
6
+ t.string :image_id
7
+ t.string :instance_state
8
+ t.integer :state_code
9
+ t.string :private_dns_name
10
+ t.string :dns_name
11
+ t.string :key_name
12
+ t.integer :ami_launch_index
13
+ t.string :instance_type
14
+ t.datetime :launch_time
15
+ t.datetime :termination_time
16
+ t.string :availability_zone
17
+ t.string :kernel_id
18
+ t.string :ramdisk_id
19
+ t.string :private_ip_address
20
+ t.string :ip_address
21
+ t.string :architecture
22
+ t.string :root_device_type
23
+ t.string :root_device_name
24
+ t.string :instance_life_cycle
25
+ t.string :spot_instance_request_id
26
+ t.string :virtualization_type
27
+ t.string :reason
28
+ t.string :state_reason_message
29
+ t.string :vpc_id
30
+
31
+ t.timestamps
32
+ end
33
+ end
34
+
35
+ def self.down
36
+ drop_table :instances
37
+ end
38
+ end
@@ -0,0 +1,16 @@
1
+ class CreateSecurityGroups < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :security_groups do |t|
4
+ t.integer :aws_account_id
5
+ t.string :name
6
+ t.string :description
7
+ t.string :owner
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :security_groups
15
+ end
16
+ end
@@ -0,0 +1,14 @@
1
+ class CreateInstanceGroups < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :instances_security_groups, :id => false do |t|
4
+ t.integer :instance_id
5
+ t.integer :security_group_id
6
+
7
+ # t.timestamps
8
+ end
9
+ end
10
+
11
+ def self.down
12
+ drop_table :instances_security_groups
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ class CreateEbsVolumes < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :ebs_volumes do |t|
4
+ t.integer :aws_account_id
5
+ t.string :volume_id
6
+ t.integer :size
7
+ t.string :status
8
+ t.string :availability_zone
9
+ t.string :snapshot_id
10
+ t.datetime :create_time
11
+ t.datetime :attach_time
12
+ t.string :attachment_status
13
+ t.string :device
14
+ t.integer :instance_id
15
+
16
+ t.timestamps
17
+ end
18
+ end
19
+
20
+ def self.down
21
+ drop_table :ebs_volumes
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ class CreateTags < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :tags do |t|
4
+ t.integer :aws_account_id
5
+ t.string :key
6
+ t.string :value
7
+ t.string :resource_type
8
+ t.integer :resource_id
9
+
10
+ t.timestamps
11
+ end
12
+ end
13
+
14
+ def self.down
15
+ drop_table :tags
16
+ end
17
+ end
@@ -0,0 +1,69 @@
1
+ require 'right_aws'
2
+
3
+ module AWSTracker
4
+ class AWSAccount < ActiveRecord::Base
5
+
6
+ # Relationships
7
+ has_many :instances, :dependent => :destroy
8
+ has_many :security_groups, :dependent => :destroy
9
+ has_many :ebs_volumes, {:dependent => :destroy, :class_name => 'EBSVolume'}
10
+ has_many :tags, :dependent => :destroy
11
+ # Validations
12
+ validates_presence_of :account_id, :access_key_id, :secret_access_key
13
+ validates_uniqueness_of :name, :account_id
14
+
15
+ # Configure logging
16
+ attr_accessor :log
17
+ after_initialize :setup_default_logger
18
+ def setup_default_logger
19
+ @log ||= AWSTracker.default_logger
20
+ end
21
+
22
+ def update_status
23
+ update_security_groups
24
+ update_instances
25
+ update_ebs_volumes
26
+ update_tags
27
+ end
28
+
29
+ # Fetches Security Group data and saves to database
30
+ def update_security_groups
31
+ SecurityGroup.refresh_from_account self
32
+ end
33
+
34
+ # Fetches Instance data and saves to database
35
+ def update_instances
36
+ Instance.refresh_from_account self
37
+ end
38
+
39
+ # Fetches EBS Volume data and saves to database
40
+ def update_ebs_volumes
41
+ EBSVolume.refresh_from_account self
42
+ end
43
+
44
+ # Fetches Tags and saves to database
45
+ def update_tags
46
+ Tag.refresh_from_account self
47
+ end
48
+
49
+ # Returns a right_aws connection to EC2, creating it on demand
50
+ attr_accessor :ec2 # Allow replacement of the connection for efficiency
51
+ def ec2
52
+ @ec2 ||= RightAws::Ec2.new(
53
+ access_key_id, secret_access_key, {:logger => @log}
54
+ )
55
+ end
56
+
57
+ # Creates and returns an account based on the environment variables:
58
+ # AWS_ACCOUNT_NUMBER, AWS_ACCESS_KEY_ID, AWS_ACCESS_KEY_SECRET
59
+ def self.from_memory
60
+ account_id = ENV['AWS_ACCOUNT_NUMBER']
61
+ AWSAccount.find_or_initialize_by_account_id(account_id) do |acc|
62
+ acc.name = "M-R #{account_id}"
63
+ acc.access_key_id = ENV['AWS_ACCESS_KEY_ID']
64
+ acc.secret_access_key = ENV['AWS_ACCESS_KEY_SECRET']
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,55 @@
1
+ module AWSTracker
2
+ class EBSVolume < ActiveRecord::Base
3
+
4
+ belongs_to :account,
5
+ :class_name => 'AWSAccount',
6
+ :foreign_key => "aws_account_id"
7
+ belongs_to :instance
8
+ has_many :tags, :as => :resource, :dependent => :destroy
9
+
10
+ validates_presence_of :account, :volume_id, :size, :status
11
+ validates_uniqueness_of :volume_id
12
+
13
+ def self.refresh_from_account(acc)
14
+ acc.log.info "Updating EBS volumes for account '#{acc.name}'"
15
+ right_aws_array = acc.ec2.describe_volumes
16
+ right_aws_array.each do |right_aws_hash|
17
+ aws_id = right_aws_hash[:aws_id]
18
+ volume = EBSVolume.find_or_initialize_by_volume_id(aws_id) do |vol|
19
+ acc.ebs_volumes << vol
20
+ vol.account = acc
21
+ end
22
+ volume.update_from_right_hash(right_aws_hash)
23
+ if not volume.save
24
+ acc.log.error "Failed to save volume #{aws_id}: #{volume.errors}"
25
+ end
26
+ end
27
+ acc.log.info "Account '#{acc.name}' reports "+
28
+ "#{right_aws_array.count} EBS volumes"
29
+ end
30
+
31
+ def update_from_right_hash(right_hash)
32
+ self.volume_id = right_hash[:aws_id]
33
+ self.size = right_hash[:aws_size]
34
+ self.status = right_hash[:aws_status]
35
+ self.availability_zone = right_hash[:zone]
36
+ self.snapshot_id = right_hash[:snapshot_id]
37
+ self.create_time = right_hash[:aws_created_at]
38
+ self.attach_time = right_hash[:aws_attached_at]
39
+ self.attachment_status = right_hash[:aws_attachment_status]
40
+ self.device = right_hash[:aws_device]
41
+ self.update_instance right_hash[:aws_instance_id]
42
+ end
43
+
44
+ # Resets the instance attribute given an AWS instance ID
45
+ def update_instance(instance_id)
46
+ if instance_id == nil
47
+ self.instance = nil
48
+ else
49
+ self.instance = self.account.instances.find(:first,
50
+ :conditions => {:instance_id => instance_id})
51
+ end
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,71 @@
1
+ module AWSTracker
2
+ class Instance < ActiveRecord::Base
3
+
4
+ belongs_to :account,
5
+ :class_name => 'AWSAccount',
6
+ :foreign_key => "aws_account_id"
7
+ has_and_belongs_to_many :security_groups
8
+ has_many :ebs_volumes, :class_name => 'EBSVolume'
9
+ has_many :tags, :as => :resource, :dependent => :destroy
10
+
11
+ validates_presence_of :account, :instance_id, :image_id, :instance_state
12
+ validates_uniqueness_of :instance_id
13
+
14
+ def self.refresh_from_account(acc)
15
+ acc.log.info "Updating instances for account '#{acc.name}'"
16
+ right_aws_array = acc.ec2.describe_instances
17
+ right_aws_array.each do |right_aws_hash|
18
+ aws_id = right_aws_hash[:aws_instance_id]
19
+ instance = Instance.find_or_initialize_by_instance_id(aws_id) do |inst|
20
+ acc.instances << inst
21
+ inst.account = acc
22
+ end
23
+ instance.update_from_right_hash(right_aws_hash)
24
+ instance.save
25
+ end
26
+ acc.log.info "Account '#{acc.name}' reports #{right_aws_array.count} instances"
27
+ end
28
+
29
+ def update_from_right_hash(rs_instance)
30
+ self.instance_id = rs_instance[:aws_instance_id]
31
+ self.image_id = rs_instance[:aws_image_id]
32
+ self.instance_state = rs_instance[:aws_state]
33
+ self.state_code = rs_instance[:aws_state_code]
34
+ self.instance_type = rs_instance[:aws_instance_type]
35
+ self.private_dns_name = rs_instance[:private_dns_name]
36
+ self.dns_name = rs_instance[:dns_name]
37
+ self.key_name = rs_instance[:ssh_key_name]
38
+ self.ami_launch_index = rs_instance[:ami_launch_index]
39
+ self.launch_time = rs_instance[:aws_launch_time]
40
+ self.termination_time = rs_instance[:aws_termination_time]
41
+ self.availability_zone = rs_instance[:aws_availability_zone]
42
+ self.kernel_id = rs_instance[:aws_kernel_id]
43
+ self.ramdisk_id = rs_instance[:aws_ramdisk_id]
44
+ self.private_ip_address = rs_instance[:private_ip_address]
45
+ self.ip_address = rs_instance[:ip_address]
46
+ self.architecture = rs_instance[:architecture]
47
+ self.root_device_type = rs_instance[:root_device_type]
48
+ self.root_device_name = rs_instance[:root_device_name]
49
+ self.virtualization_type = rs_instance[:virtualization_type]
50
+ self.reason = rs_instance[:aws_reason]
51
+ self.state_reason_message = rs_instance[:state_reason_message]
52
+ self.vpc_id = rs_instance[:vpc_id]
53
+ #:instance_life_cycle = rs_instance[:XXXXXXXXX]
54
+ #:spot_instance_request_id = rs_instance[:XXXXXXXXX]
55
+ update_security_groups(rs_instance[:aws_groups])
56
+ end
57
+
58
+ # Updates this Instance's ActiveRecord relationship security_groups
59
+ # based on group_names, an array of strings
60
+ def update_security_groups(group_names)
61
+ new_groups = []
62
+ group_names.each do |name|
63
+ new_group = self.account.security_groups.find(:first,
64
+ :conditions => {:name => name})
65
+ new_groups.push(new_group) if new_group
66
+ end
67
+ self.security_groups = new_groups
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,34 @@
1
+ module AWSTracker
2
+ class SecurityGroup < ActiveRecord::Base
3
+
4
+ belongs_to :account,
5
+ :class_name => 'AWSAccount',
6
+ :foreign_key => "aws_account_id"
7
+ has_and_belongs_to_many :instances
8
+
9
+ validates_presence_of :account, :name, :description, :owner
10
+ validates_uniqueness_of :name, :scope => "aws_account_id"
11
+
12
+ def self.refresh_from_account(acc)
13
+ acc.log.info "Updating security groups for account '#{acc.name}'"
14
+ right_aws_array = acc.ec2.describe_security_groups
15
+ right_aws_array.each do |rs_group|
16
+ group_to_update = (acc.security_groups.select() do |grp|
17
+ grp.name == rs_group[:aws_group_name]
18
+ end).first
19
+ group_to_update ||= SecurityGroup.new(:account => acc)
20
+ acc.security_groups << group_to_update
21
+ group_to_update.update_from_right_hash(rs_group)
22
+ group_to_update.save
23
+ end
24
+ acc.log.info "Account '#{acc.name}' reports #{right_aws_array.count} groups"
25
+ end
26
+
27
+ def update_from_right_hash(rs_group)
28
+ self.name = rs_group[:aws_group_name]
29
+ self.description = rs_group[:aws_description]
30
+ self.owner = rs_group[:aws_owner]
31
+ end
32
+
33
+ end
34
+ end