fog_tracker 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -35,23 +35,27 @@ How is it [done]? (Usage)
35
35
 
36
36
  Here are the contents of a sample `accounts.yml`:
37
37
 
38
- AWS EC2 development account:
39
- :provider: AWS
40
- :service: Compute
38
+ AWS EC2 production account: # The account name - can be anything
39
+ :provider: AWS # This is the Fog provider Module
40
+ :service: Compute # The Fog service Module. So, Fog::Compute::AWS
41
41
  :credentials:
42
42
  :aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
43
43
  :aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
44
- :polling_time: 180
45
- :exclude_resources:
46
- - :flavors
47
- - :images
48
- Rackspace development account:
49
- :provider: Rackspace
50
- :service: Compute
44
+ :delay: 120 # Wait time between successive pollings (in seconds)
45
+ :exclude_resources:
46
+ - :account # No need to poll for accounts - those are listed here
47
+ - :flavors # You may or may not want EC2 server types
48
+ - :images # Takes a while to list all AMIs (works though)
49
+ AWS S3 development account:
50
+ :provider: AWS
51
+ :service: Storage
52
+ :exclude_resources:
53
+ #- :directories # The S3 buckets - fetch the list
54
+ - :files # "secondary" entity to buckets - does not work yet
51
55
  :credentials:
52
- :rackspace_api_key: XXXXXXXXXXXXXXXXXXXX
53
- :rackspace_username: XXXXXXXXX
54
- :polling_time: 180
56
+ :aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
57
+ :aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
58
+ :delay: 150
55
59
 
56
60
  2) Call `start` on the Tracker. It will run asynchronously, with one thread per account. At any time, you can call `start` or `stop` on it, and query the resulting collections of Fog Resource objects.
57
61
 
@@ -63,7 +67,7 @@ How is it [done]? (Usage)
63
67
  tracker.query("*::Compute::*::servers")
64
68
 
65
69
  # get all Amazon EC2 Resources, of all types, across all accounts
66
- tracker["*::Compute::AWS::*"] # the [] operator is the same as query()
70
+ tracker["*::Compute::AWS::*"] # the [] operator is aliased to query()
67
71
 
68
72
  # get all S3 buckets in a given account
69
73
  tracker["my production account::Storage::AWS::directories"]
@@ -75,7 +79,7 @@ How is it [done]? (Usage)
75
79
 
76
80
  tracker.query("*::*::*::*"){|r| puts "Found #{r.class} #{r.identity}"}
77
81
 
78
- * You can pass a callback Proc to the Tracker at initialization, which will be invoked whenever all an account's Resources have been updated. It should accept an Array containing the updated Resources as its first parameter:
82
+ * You can pass a callback Proc to the Tracker at initialization, which will be invoked whenever all an account's Resources have been updated. It should accept an Array as its first parameter, which will contain the all the account's Resources. Like this:
79
83
 
80
84
  FogTracker::Tracker.new(YAML::load(File.read 'accounts.yml'),
81
85
  :callback => Proc.new do |resources|
@@ -84,15 +88,27 @@ How is it [done]? (Usage)
84
88
  end
85
89
  ).start
86
90
 
87
- * The resources returned from a query are all Fog::Model objects, but they are "decorated" with some extra methods for fetching the account information, or for fetching more resources. This simplifies the code that consumes the query results, because it does not have to know anything about the tracker. Here are the methods added by {FogTracker::Extensions::FogModel}:
91
+ * The resources returned from a query are all Fog::Model objects, but they are "decorated" with some extra methods for fetching the account information, or for fetching more resources. This simplifies the code that consumes the query results, because it does not have to know anything about the tracker. Here are the some of the methods added by {FogTracker::Extensions::FogModel}:
88
92
  1. `tracker_account` returns a Hash of the Resource's account information _(:name is added; :credentials are removed)_.
89
- 2. `tracker_query(query_string)` queries the tracker for more resources.
90
- 3. `account_resources(collection_query)` also returns an Array of resources, but only from the same account. (This is essentially shorthand for `tracker_query("account::service::provider::#{collection_query}")`)
91
- 4. `tracker_description` returns a descriptive string that is short, but unique to this resource.
93
+ 2. `tracker_description` returns a descriptive identifier (a String) that is unique to this resource.
94
+ 3. `tracker_query(query_string)` queries the tracker for more resources.
95
+ 4. `account_resources(collection_query)` also returns an Array of resources, but only from the same account. (This is essentially shorthand for `tracker_query("account::service::provider::#{collection_query}")`)
92
96
 
93
97
  * Any Exceptions that occur in the Tracker's polling threads are rescued and logged. If you want to take further action, you can initialize the Tracker with an `:error_callback` Proc. This is similar to the Account update `:callback` above, except that the parameter for `:error_callback` should be an Exception instead of an Array of Resources.
94
98
 
95
- * The Tracker can also be used synchronously. Its `update` method polls all accounts immediately, and waits for the result (the updated Array of resource objects) in the current thread.
99
+ * The Tracker can also be used synchronously. Its `update` method polls all accounts immediately, one at a time, and waits for the result (the updated Array of resource objects) in the current thread. In this mode, any exceptions are raised immediately.
100
+
101
+ ----------------
102
+ *Known Limitations / Bugs*
103
+
104
+ * Some Fog resources are not currently supported, because polling them depends on making multiple calls to the service provider, once for each primary key of some other resource. These "secondary resources" include:
105
+ * S3 Objects (Fog::Storage[:aws].files) - each is dependent
106
+ on its bucket (Fog::Storage[:aws].directories)
107
+ * Route 53 addresses (Fog::DNS[:aws].addresses) - each is dependent
108
+ on its DNS zone (Fog::DNS[:aws].zones)
109
+
110
+ Supporting these would involve hard-coding these dependencies into this gem. Currently, all Fog resource information is introspected, which allows this gem to track new Fog functionality with no update. If you really want to get information on these resources, you can traverse the Fog resource graph in your Account update `:callback`.
111
+
96
112
 
97
113
  ----------------
98
114
  Who is it? (Contribution)
@@ -1,25 +1,29 @@
1
- AWS EC2 production account:
2
- :provider: AWS
3
- :service: Compute
4
- :credentials:
1
+ AWS EC2 production account: # The account name - can be anything
2
+ :provider: AWS # This is the Fog provider Module
3
+ :service: Compute # The Fog service Module. So, Fog::Compute::AWS
4
+ :credentials:
5
5
  :aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
6
6
  :aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
7
- :polling_time: 120
7
+ :delay: 120 # Wait time between successive pollings (in seconds)
8
8
  :exclude_resources:
9
- AWS EC2 development account:
9
+ - :account # No need to poll for accounts - those are listed here
10
+ - :flavors # You may or may not want EC2 server types
11
+ - :images # Takes a while to list all AMIs (works though)
12
+ AWS S3 development account:
10
13
  :provider: AWS
11
- :service: Compute
12
- :credentials:
14
+ :service: Storage
15
+ :credentials:
13
16
  :aws_access_key_id: XXXXXXXXXXXXXXXXXXXX
14
17
  :aws_secret_access_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
15
- :polling_time: 180
18
+ :delay: 150
16
19
  :exclude_resources:
17
- - :flavors
18
- - :images
19
- Rackspace development account:
20
+ #- :directories # The S3 buckets - fetch the list
21
+ - :files # "secondary" entity to buckets - does not work yet
22
+ Rackspace development account:
20
23
  :provider: Rackspace
21
24
  :service: Compute
22
- :credentials:
25
+ :credentials:
23
26
  :rackspace_api_key: XXXXXXXXXXXXXXXXXXXX
24
27
  :rackspace_username: XXXXXXXXX
25
- :polling_time: 180
28
+ :delay: 180
29
+ :exclude_resources: # Don't know which of these work yet...
@@ -12,6 +12,8 @@ module FogTracker
12
12
  attr_reader :log
13
13
  # How long to wait between successive polling of this account (Integer)
14
14
  attr_reader :delay
15
+ # The time that the *second-to-last* successful poll finished
16
+ attr_reader :preceeding_update_time
15
17
 
16
18
  # Creates an object for tracking all collections in a single Fog account
17
19
  # @param [String] account_name a human-readable name for the account
@@ -28,9 +30,9 @@ module FogTracker
28
30
  @account = account
29
31
  @callback = options[:callback]
30
32
  @log = options[:logger] || FogTracker.default_logger
31
- @delay = options[:delay] || account[:polling_time] ||
33
+ @delay = options[:delay] || account[:delay] ||
32
34
  FogTracker::DEFAULT_POLLING_TIME
33
- @account[:polling_time] = @delay
35
+ @account[:delay] = @delay
34
36
  @error_proc = options[:error_callback]
35
37
  @log.debug "Creating tracker for account #{@name}."
36
38
  create_collection_trackers
@@ -58,7 +60,7 @@ module FogTracker
58
60
  # Stops polling this tracker's account
59
61
  def stop
60
62
  if running?
61
- @log.info "Stopping tracker for #{name}..."
63
+ @log.info "Stopping tracker for #{@name}..."
62
64
  @timer.kill
63
65
  @timer = nil
64
66
  else
@@ -71,6 +73,9 @@ module FogTracker
71
73
  begin
72
74
  @log.info "Polling account #{@name}..."
73
75
  @collection_trackers.each {|tracker| tracker.update}
76
+ @preceeding_update_time = @most_recent_update
77
+ @most_recent_update = Time.now
78
+ @log.info "Polled account #{@name}"
74
79
  @callback.call(all_resources) if @callback
75
80
  rescue Exception => e
76
81
  @log.error "Exception polling account #{name}: #{e.message}"
@@ -24,26 +24,28 @@ module FogTracker
24
24
  # Polls the {AccountTracker}'s connection for updated info on all existing
25
25
  # instances of this tracker's resource_type
26
26
  def update
27
- @log.info "Polling #{@type} on #{@account_name}..."
27
+ new_collection = Array.new
28
28
  fog_collection = @account_tracker.connection.send(@type) || Array.new
29
29
  @log.info "Fetching #{fog_collection.count} #{@type} on #{@account_name}."
30
- new_collection = Array.new
31
30
  # Here's where most of the network overhead is actually incurred
32
31
  fog_collection.each do |resource|
33
32
  @log.debug "Fetching resource: #{resource.class} #{resource.identity}"
34
33
  resource._fog_collection_tracker = self
35
34
  new_collection << resource
36
- @log.debug "Got resource: #{resource.inspect}"
35
+ #@log.debug "Got resource: #{resource.inspect}"
37
36
  end
37
+ @log.info "Fetched #{new_collection.count} #{@type} on #{@account_name}."
38
38
  @collection = new_collection
39
39
  end
40
40
 
41
41
  # @return [Hash] a Hash of account information, slighly modified:
42
42
  # a :name parameter is added, and the :credentials are removed
43
+ # :preceeding_update_time is also added
43
44
  def clean_account_data
44
45
  @clean_data ||= @account # generate this data only once per res
45
46
  @clean_data[:name] = @account_name
46
47
  @clean_data[:credentials] = Hash.new
48
+ @clean_data[:preceeding_update_time] = @account_tracker.preceeding_update_time
47
49
  @clean_data
48
50
  end
49
51
 
@@ -52,8 +52,8 @@ module FogTracker
52
52
  results
53
53
  end
54
54
 
55
- # Returns a short description of this resource
56
- # @return [String] a short description of this resource
55
+ # returns a descriptive identifier unique to this resource
56
+ # @return [String] the type, identity, and account name of the resource
57
57
  def tracker_description
58
58
  type = (self.class.name.match(/::([^:]+)$/))[1]
59
59
  "#{type} #{self.identity} in account #{tracker_account[:name]}"
@@ -1,7 +1,7 @@
1
1
  module FogTracker
2
2
  module Query
3
- # A class for gathering all Fog resources for a set of {AccountTracker}s,
4
- # and filtering them based on a regular-expression-based query
3
+ # A class for filtering the Fog resources for a set of {AccountTracker}s,
4
+ # based on a regular-expression-based query
5
5
  class QueryProcessor
6
6
 
7
7
  # The Regular Expression which all resource queries must match
@@ -16,7 +16,7 @@ module FogTracker
16
16
  @log = options[:logger] || FogTracker.default_logger
17
17
  end
18
18
 
19
- # Uses the query string to filter this account's resources
19
+ # Uses the query string to filter all polled resources
20
20
  # for a desired subset
21
21
  # @param [String] query a string used to filter for matching resources
22
22
  # @return [Array <Fog::Model>] an Array of Resources, filtered by query
@@ -36,7 +36,7 @@ module FogTracker
36
36
  # Returns an Array of 4 RegEx objeccts based on the +query_string+
37
37
  # for matching [account name, service, provider, collection]
38
38
  def parse_query(query_string)
39
- @log.debug "Parsing Query #{query_string}"
39
+ #@log.debug "Parsing Query #{query_string}"
40
40
  tokenize(query_string).map {|token| regex_from_token(token)}
41
41
  end
42
42
 
@@ -92,6 +92,13 @@ module FogTracker
92
92
  results
93
93
  end
94
94
 
95
+ # Returns the time of given account's most recent successful update
96
+ # @param [String] account_name the name of the account that was polled
97
+ # @return [Time] the time the account finished updating
98
+ def preceeding_update_time(account_name)
99
+ @trackers[account_name].preceeding_update_time
100
+ end
101
+
95
102
  # Returns this tracker's logger, for changing logging dynamically
96
103
  def logger ; @log end
97
104
 
@@ -1,3 +1,3 @@
1
1
  module FogTracker
2
- VERSION = "0.2.2"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -27,8 +27,8 @@ module FogTracker
27
27
  it "exposes its logger" do
28
28
  @tracker.log.should_not == nil
29
29
  end
30
- it "always sets a polling time" do
31
- @tracker.account[:polling_time].should be_an_instance_of(Fixnum)
30
+ it "always has a delay" do
31
+ @tracker.account[:delay].should be_an_instance_of(Fixnum)
32
32
  end
33
33
 
34
34
  describe '#connection' do
@@ -76,6 +76,12 @@ module FogTracker
76
76
  (Proc.new { @tracker.update }).should raise_error
77
77
  end
78
78
  end
79
+ it "saves the time of it's next-to-last update as @preceeding_update_time" do
80
+ @tracker.update
81
+ @tracker.preceeding_update_time.should == nil
82
+ @tracker.update
83
+ @tracker.preceeding_update_time.should_not == nil
84
+ end
79
85
  end
80
86
 
81
87
  describe '#start' do
@@ -22,10 +22,17 @@ module FogTracker
22
22
  @tracker.update
23
23
  end
24
24
  it "attaches account information to all resources" do
25
+ fake_connection = double('mock fog connection')
26
+ fake_connection.stub(:servers).and_return(
27
+ [Fog::Compute[:aws].servers.new])
28
+ now = Time.now
29
+ @account_tracker.stub(:connection).and_return fake_connection
30
+ @account_tracker.stub(:preceeding_update_time).and_return now
25
31
  @tracker.update
26
32
  @tracker.collection.each do |resource|
27
33
  resource.tracker_account[:name].should == FAKE_ACCOUNT_NAME
28
34
  resource.tracker_account[:credentials].should == {}
35
+ resource.tracker_account[:preceeding_update_time].should == now
29
36
  end
30
37
  end
31
38
  end
@@ -66,6 +66,17 @@ module FogTracker
66
66
  end
67
67
  end
68
68
 
69
+ describe '#preceeding_update_time' do
70
+ context "when given an account name" do
71
+ it "returns time of the account's next-most-recent succesful update" do
72
+ @tracker.update
73
+ @tracker.preceeding_update_time(ACCOUNTS.keys.first).should == nil
74
+ @tracker.update
75
+ @tracker.preceeding_update_time(ACCOUNTS.keys.first).should_not == nil
76
+ end
77
+ end
78
+ end
79
+
69
80
  describe '#all' do
70
81
  WILDCARD_QUERY = '*::*::*::*'
71
82
  before(:each) do
@@ -8,7 +8,7 @@ module FogTracker
8
8
  FAKE_ACCOUNT = {
9
9
  :provider => 'AWS',
10
10
  :service => 'Compute',
11
- :polling_time => 10,
11
+ :delay => 10,
12
12
  :credentials => {
13
13
  :aws_access_key_id => "fake user",
14
14
  :aws_secret_access_key => 'fake password'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fog_tracker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-02-09 00:00:00.000000000Z
12
+ date: 2012-02-18 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: fog
16
- requirement: &70268295001560 !ruby/object:Gem::Requirement
16
+ requirement: &70238491411280 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70268295001560
24
+ version_requirements: *70238491411280
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rake
27
- requirement: &70268295000400 !ruby/object:Gem::Requirement
27
+ requirement: &70238491410860 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70268295000400
35
+ version_requirements: *70238491410860
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: rspec
38
- requirement: &70268294999500 !ruby/object:Gem::Requirement
38
+ requirement: &70238491410440 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70268294999500
46
+ version_requirements: *70238491410440
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: yard
49
- requirement: &70268294998340 !ruby/object:Gem::Requirement
49
+ requirement: &70238491410020 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70268294998340
57
+ version_requirements: *70238491410020
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: guard
60
- requirement: &70268294997600 !ruby/object:Gem::Requirement
60
+ requirement: &70238491409600 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70268294997600
68
+ version_requirements: *70238491409600
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: guard-rspec
71
- requirement: &70268294996740 !ruby/object:Gem::Requirement
71
+ requirement: &70238491409180 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70268294996740
79
+ version_requirements: *70238491409180
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: ruby_gntp
82
- requirement: &70268294995920 !ruby/object:Gem::Requirement
82
+ requirement: &70238491408740 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,7 +87,7 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70268294995920
90
+ version_requirements: *70238491408740
91
91
  description: This gem peridically polls mutiple cloud computing services using the
92
92
  fog gem, asynchronously updating the state of the resulting collections of Fog Resources.
93
93
  email:
@@ -138,7 +138,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
138
138
  version: '0'
139
139
  segments:
140
140
  - 0
141
- hash: -2942181140589294968
141
+ hash: -64177952162432192
142
142
  required_rubygems_version: !ruby/object:Gem::Requirement
143
143
  none: false
144
144
  requirements:
@@ -147,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
147
147
  version: '0'
148
148
  segments:
149
149
  - 0
150
- hash: -2942181140589294968
150
+ hash: -64177952162432192
151
151
  requirements: []
152
152
  rubyforge_project: fog_tracker
153
153
  rubygems_version: 1.8.10