staugaard-cloudmaster 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +4 -0
- data/bin/cloudmaster +45 -0
- data/lib/AWS/AWS.rb +3 -0
- data/lib/AWS/EC2.rb +14 -0
- data/lib/AWS/S3.rb +14 -0
- data/lib/AWS/SQS.rb +14 -0
- data/lib/AWS/SimpleDB.rb +14 -0
- data/lib/MockAWS/EC2.rb +119 -0
- data/lib/MockAWS/S3.rb +39 -0
- data/lib/MockAWS/SQS.rb +82 -0
- data/lib/MockAWS/SimpleDB.rb +46 -0
- data/lib/MockAWS/clock.rb +67 -0
- data/lib/OriginalAWS/AWS.rb +475 -0
- data/lib/OriginalAWS/EC2.rb +783 -0
- data/lib/OriginalAWS/S3.rb +559 -0
- data/lib/OriginalAWS/SQS.rb +159 -0
- data/lib/OriginalAWS/SimpleDB.rb +460 -0
- data/lib/RetryAWS/EC2.rb +88 -0
- data/lib/RetryAWS/S3.rb +77 -0
- data/lib/RetryAWS/SQS.rb +109 -0
- data/lib/RetryAWS/SimpleDB.rb +118 -0
- data/lib/SafeAWS/EC2.rb +63 -0
- data/lib/SafeAWS/S3.rb +56 -0
- data/lib/SafeAWS/SQS.rb +75 -0
- data/lib/SafeAWS/SimpleDB.rb +88 -0
- data/lib/aws_context.rb +165 -0
- data/lib/basic_configuration.rb +120 -0
- data/lib/clock.rb +10 -0
- data/lib/factory.rb +14 -0
- data/lib/file_logger.rb +36 -0
- data/lib/inifile.rb +148 -0
- data/lib/instance_logger.rb +25 -0
- data/lib/logger_factory.rb +38 -0
- data/lib/periodic.rb +29 -0
- data/lib/string_logger.rb +29 -0
- data/lib/sys_logger.rb +40 -0
- data/lib/user_data.rb +30 -0
- data/test/aws-config.ini +9 -0
- data/test/cloudmaster-tests.rb +329 -0
- data/test/configuration-test.rb +62 -0
- data/test/daytime-policy-tests.rb +47 -0
- data/test/enumerator-test.rb +47 -0
- data/test/fixed-policy-tests.rb +50 -0
- data/test/instance-pool-test.rb +359 -0
- data/test/instance-test.rb +98 -0
- data/test/job-policy-test.rb +95 -0
- data/test/manual-policy-tests.rb +63 -0
- data/test/named-queue-test.rb +90 -0
- data/test/resource-policy-tests.rb +126 -0
- data/test/suite +17 -0
- data/test/test-config.ini +47 -0
- metadata +111 -0
data/lib/aws_context.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
|
2
|
+
require 'AWS/SQS'
|
3
|
+
require 'AWS/EC2'
|
4
|
+
require 'AWS/S3'
|
5
|
+
require 'AWS/SimpleDB'
|
6
|
+
require 'SafeAWS/SQS'
|
7
|
+
require 'SafeAWS/EC2'
|
8
|
+
require 'SafeAWS/S3'
|
9
|
+
require 'SafeAWS/SimpleDB'
|
10
|
+
require 'RetryAWS/SQS'
|
11
|
+
require 'RetryAWS/EC2'
|
12
|
+
require 'RetryAWS/S3'
|
13
|
+
require 'RetryAWS/SimpleDB'
|
14
|
+
require 'MockAWS/EC2'
|
15
|
+
require 'MockAWS/S3'
|
16
|
+
require 'MockAWS/SQS'
|
17
|
+
require 'MockAWS/SimpleDB'
|
18
|
+
require 'logger'
|
19
|
+
|
20
|
+
# Make sure there is a Clock implementation.
|
21
|
+
# If not, supply one.
|
22
|
+
# Caller may supply a mock implementation instead of the standard one.
|
23
|
+
begin
|
24
|
+
Clock.now
|
25
|
+
rescue
|
26
|
+
require 'clock'
|
27
|
+
end
|
28
|
+
|
29
|
+
# Creates and caches EC2, SQS, and S3 interface implementations.
|
30
|
+
# Can serve up AWS, SafeAWS, RetryAWS, or MockAWS interfaces.
|
31
|
+
# Every time we create one, we reset the interfaces by forcing the
|
32
|
+
# creation of new objects.
|
33
|
+
# This is treated as a global. It is initialized by calling "AwsContext.setup"
|
34
|
+
# and then anyone can get a copy by calling "AwsContext.instance".
|
35
|
+
class AwsContext
|
36
|
+
private_class_method :new
|
37
|
+
@@instance = nil
|
38
|
+
|
39
|
+
def initialize(context, logger)
|
40
|
+
@context = context
|
41
|
+
@logger = logger
|
42
|
+
@ec2 = @sqs = @s3 = @sdb = nil
|
43
|
+
end
|
44
|
+
|
45
|
+
# Create a AwsContext.
|
46
|
+
#
|
47
|
+
# The context here can be one of
|
48
|
+
# * :aws -- use the standard AWS interface
|
49
|
+
# * :safe -- use the SafeAWS interface
|
50
|
+
# * :retry -- use the RetryAWS interface
|
51
|
+
# * :mock -- use the MockAWS interface
|
52
|
+
#
|
53
|
+
# The interface is established the first time you use it. The
|
54
|
+
# returned interface is retained, and used for subsequent requests.
|
55
|
+
# Thus only one instance of each interface is created.
|
56
|
+
def AwsContext.setup(context, logger = nil)
|
57
|
+
@@instance = new(context, logger)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return the instance that was already created.
|
61
|
+
# If none created yet, then create AWS context.
|
62
|
+
def AwsContext.instance
|
63
|
+
if @@instance.nil?
|
64
|
+
setup(:aws)
|
65
|
+
end
|
66
|
+
@@instance
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
# Create an EC2 interface.
|
72
|
+
def create_ec2(*params)
|
73
|
+
case @context
|
74
|
+
when :aws
|
75
|
+
@ec2 = AWS::EC2.new(*params)
|
76
|
+
when :safe
|
77
|
+
@ec2 = SafeAWS::EC2.new(*params)
|
78
|
+
when :retry
|
79
|
+
@ec2 = RetryAWS::EC2.new(*params)
|
80
|
+
when :mock
|
81
|
+
@ec2 = MockAWS::EC2.new(*params)
|
82
|
+
@ec2.reset
|
83
|
+
@ec2.logger = @logger if @logger
|
84
|
+
end
|
85
|
+
@ec2
|
86
|
+
end
|
87
|
+
|
88
|
+
# Create an sqs interface.
|
89
|
+
def create_sqs(*params)
|
90
|
+
case @context
|
91
|
+
when :aws
|
92
|
+
@sqs = AWS::SQS.new(*params)
|
93
|
+
when :safe
|
94
|
+
@sqs = SafeAWS::SQS.new(*params)
|
95
|
+
when :retry
|
96
|
+
@sqs = RetryAWS::SQS.new(*params)
|
97
|
+
when :mock
|
98
|
+
@sqs = MockAWS::SQS.new(*params)
|
99
|
+
@sqs.reset
|
100
|
+
@sqs.logger = @logger if @logger
|
101
|
+
end
|
102
|
+
@sqs
|
103
|
+
end
|
104
|
+
|
105
|
+
# Create an S3 interface.
|
106
|
+
def create_s3(*params)
|
107
|
+
case @context
|
108
|
+
when :aws
|
109
|
+
@s3 = AWS::S3.new(*params)
|
110
|
+
when :safe
|
111
|
+
@s3 = SafeAWS::S3.new(*params)
|
112
|
+
when :retry
|
113
|
+
@s3 = RetryAWS::S3.new(*params)
|
114
|
+
when :mock
|
115
|
+
@s3 = MockAWS::S3.new(*params)
|
116
|
+
@s3.logger = @logger if @logger
|
117
|
+
@s3.reset
|
118
|
+
end
|
119
|
+
@s3
|
120
|
+
end
|
121
|
+
|
122
|
+
# Create a SimpleDB interface.
|
123
|
+
def create_sdb(*params)
|
124
|
+
case @context
|
125
|
+
when :aws
|
126
|
+
@sdb = AWS::SimpleDB.new(*params)
|
127
|
+
when :safe
|
128
|
+
@sdb = SafeAWS::SimpleDB.new(*params)
|
129
|
+
when :retry
|
130
|
+
@sdb = RetryAWS::SimpleDB.new(*params)
|
131
|
+
when :mock
|
132
|
+
@sdb = MockAWS::SimpleDB.new(*params)
|
133
|
+
@sdb.logger = @logger if @logger
|
134
|
+
@sdb.reset
|
135
|
+
end
|
136
|
+
@sdb
|
137
|
+
end
|
138
|
+
|
139
|
+
public
|
140
|
+
|
141
|
+
# Return an EC2 interface. Create on if needed.
|
142
|
+
# Note that the parameters (if given) are only used if the interface is created.
|
143
|
+
def ec2(*params)
|
144
|
+
@ec2 || create_ec2(*params)
|
145
|
+
end
|
146
|
+
|
147
|
+
# Return an SQS interface. Create on if needed.
|
148
|
+
# Note that the parameters (if given) are only used if the interface is created.
|
149
|
+
def sqs(*params)
|
150
|
+
@sqs || create_sqs(*params)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Return a S3 interface. Create on if needed.
|
154
|
+
# Note that the parameters (if given) are only used if the interface is created.
|
155
|
+
def s3(*params)
|
156
|
+
@s3 || create_s3(*params)
|
157
|
+
end
|
158
|
+
|
159
|
+
# Return a SimpleDB interface. Create on if needed.
|
160
|
+
# Note that the parameters (if given) are only used if the interface is created.
|
161
|
+
def sdb(*params)
|
162
|
+
@sdb || create_sdb(*params)
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require 'inifile'
|
2
|
+
require 'pp'
|
3
|
+
|
4
|
+
# BasicConfiguration
|
5
|
+
# Read an ini file and create a configuration.
|
6
|
+
# The configuration contains the aws configuration only.
|
7
|
+
|
8
|
+
class BasicConfiguration
|
9
|
+
attr_reader :aws
|
10
|
+
|
11
|
+
# Default list of config files to search for
|
12
|
+
DEFAULT_CONFIG_FILES = ['aws-config.ini', 'default-config.ini', 'config.ini']
|
13
|
+
# Search for config files in these directories
|
14
|
+
DEFAULT_SEARCH_PATH = [ ".", ENV['AWS_HOME'], ENV['HOME'], File.dirname(__FILE__)]
|
15
|
+
|
16
|
+
@@config_files = DEFAULT_CONFIG_FILES
|
17
|
+
@@search_path = DEFAULT_SEARCH_PATH
|
18
|
+
|
19
|
+
# Set up the list of config files that is read when looking for configurations.
|
20
|
+
# If this is not called, a default set of files is read.
|
21
|
+
def BasicConfiguration.setup_config_files(config_files = [])
|
22
|
+
@@config_files = config_files
|
23
|
+
end
|
24
|
+
|
25
|
+
# Set up the search path.
|
26
|
+
# If this is not called, a default path is used
|
27
|
+
def BasicConfiguration.setup_search_path(search_path = [])
|
28
|
+
@@search_path = search_path
|
29
|
+
end
|
30
|
+
|
31
|
+
# Add the given array of files to the list that we read.
|
32
|
+
def BasicConfiguration.add_config_files(config_files)
|
33
|
+
@@config_files |= config_files
|
34
|
+
end
|
35
|
+
|
36
|
+
# Add the following set of search paths to the ones that we use.
|
37
|
+
def BasicConfiguration.add_search_paths(search_paths)
|
38
|
+
@@search_path |= search_paths
|
39
|
+
end
|
40
|
+
|
41
|
+
# Create a config structure by reading the given config_filenames.
|
42
|
+
# If config files or search_paths are given, they apply only to this
|
43
|
+
# instance, but are retained for use by refresh.
|
44
|
+
# Create default aws config items based on environment varbiables, in
|
45
|
+
# case we can't find a config file.
|
46
|
+
def initialize(config_files = [], search_paths = [])
|
47
|
+
@config_files = @@config_files | config_files
|
48
|
+
@search_path = @@search_path | search_paths
|
49
|
+
refresh
|
50
|
+
end
|
51
|
+
|
52
|
+
# Read the configuration from the existing config file using
|
53
|
+
# the existing filenames.
|
54
|
+
# This is useful for reinitiaizing on a SIGTERM
|
55
|
+
def refresh
|
56
|
+
@aws = get_aws_from_environment
|
57
|
+
read_config
|
58
|
+
end
|
59
|
+
|
60
|
+
def keys
|
61
|
+
[ @aws[:aws_access_key], @aws[:aws_secret_key]]
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
# Looks up an environment variable, and returns the value, if there is one.
|
67
|
+
# If the caller asks for some environment variable that is not
|
68
|
+
# present in the environment, then the default is returned.
|
69
|
+
def get_environment(var, default = nil)
|
70
|
+
ENV[var] || default
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def get_aws_from_environment
|
75
|
+
# Get aws config from the environment
|
76
|
+
aws_user = get_environment('AWS_USER', 'aws')
|
77
|
+
key_file = File.join(ENV['HOME'], 'keys', "#{aws_user}-kp.pem")
|
78
|
+
|
79
|
+
# Set up our credentials from the environment
|
80
|
+
# These sere as a default to the credentials in the
|
81
|
+
# config.ini file.
|
82
|
+
{ :aws_env => ENV['AWS_ENV'],
|
83
|
+
:aws_access_key => get_environment('AWS_ACCESS_KEY'),
|
84
|
+
:aws_secret_key => get_environment('AWS_SECRET_KEY'),
|
85
|
+
:aws_user => aws_user,
|
86
|
+
:aws_bucket => get_environment('AWS_BUCKET'),
|
87
|
+
:aws_key => get_environment('AWS_KEY', key_file)
|
88
|
+
}
|
89
|
+
end
|
90
|
+
|
91
|
+
# Read all the config files in order
|
92
|
+
def read_config
|
93
|
+
@config_files.each {|config_file| read(config_file)}
|
94
|
+
end
|
95
|
+
|
96
|
+
# Read the config file and store aws section.
|
97
|
+
def read(config_file)
|
98
|
+
ini = IniFile.load(find_on_search_path(config_file))
|
99
|
+
return nil unless ini
|
100
|
+
# Merge in the items from the 'aws' section, overriding the defaults.
|
101
|
+
# This needs to be first, so others can use it.
|
102
|
+
@aws.merge!(ini['aws'])
|
103
|
+
ini
|
104
|
+
end
|
105
|
+
|
106
|
+
# If filename starts with "/" then return it unchanged.
|
107
|
+
# Otherwise try various prefixes on it.
|
108
|
+
# Return the first one that is actually a file.
|
109
|
+
# Retun nil if the file does not exist at any of the places.
|
110
|
+
def find_on_search_path(filename)
|
111
|
+
return filename if filename[0..0] == File::SEPARATOR
|
112
|
+
@search_path.each do |prefix|
|
113
|
+
unless prefix.nil?
|
114
|
+
fn = File.join(prefix, filename)
|
115
|
+
return fn if File.exists?(fn)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
nil
|
119
|
+
end
|
120
|
+
end
|
data/lib/clock.rb
ADDED
data/lib/factory.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# This contains common factory methods.
|
2
|
+
|
3
|
+
module Factory
|
4
|
+
# Given a class name as a string, create an instance of that class
|
5
|
+
# and initialize it with the given arguments.
|
6
|
+
def Factory.create_object_from_string(class_name, *args)
|
7
|
+
ObjectSpace.each_object(Class) do |x|
|
8
|
+
if x.name == class_name || x.name == "Cloudmaster::#{class_name}"
|
9
|
+
return x.new(*args)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
end
|
data/lib/file_logger.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# The default logger writes to a file descriptor.
|
2
|
+
# This could be an actual file, or a stream such as STDOUT.
|
3
|
+
class FileLogger
|
4
|
+
def initialize(file = nil, *args)
|
5
|
+
case
|
6
|
+
when file.nil?
|
7
|
+
@fd = STDOUT
|
8
|
+
@needs_close = false
|
9
|
+
when file.is_a?(String)
|
10
|
+
@fd = File.new(file, "a")
|
11
|
+
@needs_close = true
|
12
|
+
else
|
13
|
+
@fd = file
|
14
|
+
@needs_close = false
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def puts(msg)
|
19
|
+
@fd.puts msg
|
20
|
+
end
|
21
|
+
|
22
|
+
def close
|
23
|
+
@fd.close if @needs_close
|
24
|
+
end
|
25
|
+
|
26
|
+
alias debug puts
|
27
|
+
alias info puts
|
28
|
+
alias notice puts
|
29
|
+
alias warning puts
|
30
|
+
alias err puts
|
31
|
+
alias error puts
|
32
|
+
alias alert puts
|
33
|
+
alias emerg puts
|
34
|
+
alias crit puts
|
35
|
+
end
|
36
|
+
|
data/lib/inifile.rb
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
#
|
2
|
+
# This class represents the INI file and can be used to parse INI files.
|
3
|
+
# Derived from IniFile gem, found on http://rubyforge.org/projects/inifile/
|
4
|
+
#
|
5
|
+
class IniFile
|
6
|
+
|
7
|
+
#
|
8
|
+
# call-seq:
|
9
|
+
# IniFile.load( filename )
|
10
|
+
# IniFile.load( filename, options )
|
11
|
+
#
|
12
|
+
# Open the given _filename_ and load the contents of the INI file.
|
13
|
+
# The following _options_ can be passed to this method:
|
14
|
+
#
|
15
|
+
# :comment => ';' The line comment character(s)
|
16
|
+
# :parameter => '=' The parameter / value separator
|
17
|
+
#
|
18
|
+
def self.load( filename, opts = {} )
|
19
|
+
if filename
|
20
|
+
new(filename, opts)
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize( filename, opts = {} )
|
27
|
+
@fn = filename
|
28
|
+
@comment = opts[:comment] || '#'
|
29
|
+
@param = opts[:parameter] || '='
|
30
|
+
@ini = Hash.new {|h,k| h[k] = Hash.new}
|
31
|
+
|
32
|
+
@rgxp_comment = /^\s*$|^\s*[#{@comment}]/
|
33
|
+
@rgxp_section = /^\s*\[([^\]]+)\]/
|
34
|
+
@rgxp_param = /^([^#{@param}]+)#{@param}(.*)$/
|
35
|
+
|
36
|
+
parse
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# call-seq:
|
41
|
+
# each {|section, parameter, value| block}
|
42
|
+
#
|
43
|
+
# Yield each _section_, _parameter_, _value_ in turn to the given
|
44
|
+
# _block_. The method returns immediately if no block is supplied.
|
45
|
+
#
|
46
|
+
def each
|
47
|
+
return unless block_given?
|
48
|
+
@ini.each do |section,hash|
|
49
|
+
hash.each do |param,val|
|
50
|
+
yield section, param, val
|
51
|
+
end
|
52
|
+
end
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
#
|
57
|
+
# call-seq:
|
58
|
+
# each_section {|section| block}
|
59
|
+
#
|
60
|
+
# Yield each _section_ in turn to the given _block_. The method returns
|
61
|
+
# immediately if no block is supplied.
|
62
|
+
#
|
63
|
+
def each_section
|
64
|
+
return unless block_given?
|
65
|
+
@ini.each_key {|section| yield section}
|
66
|
+
self
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# call-seq:
|
71
|
+
# ini_file[section]
|
72
|
+
#
|
73
|
+
# Get the hash of parameter/value pairs for the given _section_.
|
74
|
+
#
|
75
|
+
def []( section )
|
76
|
+
return nil if section.nil?
|
77
|
+
@ini[section.to_s]
|
78
|
+
end
|
79
|
+
|
80
|
+
#
|
81
|
+
# call-seq:
|
82
|
+
# has_section?( section )
|
83
|
+
#
|
84
|
+
# Returns +true+ if the named _section_ exists in the INI file.
|
85
|
+
#
|
86
|
+
def has_section?( section )
|
87
|
+
@ini.has_key? section.to_s
|
88
|
+
end
|
89
|
+
|
90
|
+
#
|
91
|
+
# call-seq:
|
92
|
+
# sections
|
93
|
+
#
|
94
|
+
# Returns an array of the section names.
|
95
|
+
#
|
96
|
+
def sections
|
97
|
+
@ini.keys
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def cleanup(str)
|
103
|
+
str = str.strip
|
104
|
+
first = str[0..0]; last = str[-1..-1]
|
105
|
+
str = str[1..-2] if first == last && (first == '"' || first == "'")
|
106
|
+
end
|
107
|
+
#
|
108
|
+
# call-seq
|
109
|
+
# parse
|
110
|
+
#
|
111
|
+
# Parse the ini file contents.
|
112
|
+
#
|
113
|
+
def parse
|
114
|
+
return unless ::Kernel.test ?f, @fn
|
115
|
+
section = nil
|
116
|
+
|
117
|
+
::File.open(@fn, 'r') do |f|
|
118
|
+
while line = f.gets
|
119
|
+
line = line.chomp
|
120
|
+
|
121
|
+
case line
|
122
|
+
# ignore blank lines and comment lines
|
123
|
+
when @rgxp_comment: next
|
124
|
+
|
125
|
+
# this is a section declaration
|
126
|
+
when @rgxp_section: section = @ini[$1.strip.downcase]
|
127
|
+
|
128
|
+
# otherwise we have a parameter
|
129
|
+
when @rgxp_param
|
130
|
+
begin
|
131
|
+
val = $2.strip
|
132
|
+
val = val[1..-2] if val[0..0] == "'" || val[-1..-1] == '"'
|
133
|
+
section[$1.strip.downcase.to_sym] = val
|
134
|
+
rescue NoMethodError
|
135
|
+
raise "Bad configuration - inifile parameter encountered before first section"
|
136
|
+
end
|
137
|
+
|
138
|
+
else
|
139
|
+
raise "Bad configuration -- inifile could not parse line '#{line}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
|
148
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# The instance logger writes to a file in a given directory.
|
2
|
+
# The file is determined by the instance_id in the message.
|
3
|
+
# The file is opened and closed each time something is written.
|
4
|
+
class InstanceLogger
|
5
|
+
def initialize(dir)
|
6
|
+
@directory = dir
|
7
|
+
end
|
8
|
+
|
9
|
+
def puts(instance, msg)
|
10
|
+
File.open(File.join(@directory, instance), "a") do |fd|
|
11
|
+
fd.puts msg
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
alias debug puts
|
16
|
+
alias info puts
|
17
|
+
alias notice puts
|
18
|
+
alias warning puts
|
19
|
+
alias err puts
|
20
|
+
alias error puts
|
21
|
+
alias alert puts
|
22
|
+
alias emerg puts
|
23
|
+
alias crit puts
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'factory'
|
2
|
+
require 'sys_logger'
|
3
|
+
require 'string_logger'
|
4
|
+
require 'file_logger'
|
5
|
+
|
6
|
+
class LoggerFactory
|
7
|
+
include Factory
|
8
|
+
@@filename = 'logfile'
|
9
|
+
@@program = 'unknown'
|
10
|
+
|
11
|
+
def LoggerFactory.setup(filename, program = 'unknown')
|
12
|
+
@@filename = filename
|
13
|
+
@@program = program
|
14
|
+
end
|
15
|
+
|
16
|
+
def LoggerFactory.create(type, *params)
|
17
|
+
filename = filename || @@filename
|
18
|
+
program = program || @@program
|
19
|
+
name = type.to_s
|
20
|
+
require name.downcase + '_logger'
|
21
|
+
class_name = name.capitalize + 'Logger'
|
22
|
+
logger = Factory.create_object_from_string(class_name, filename, program)
|
23
|
+
raise "Bad configuration -- no logger #{class_name}" unless logger
|
24
|
+
logger
|
25
|
+
|
26
|
+
# case type.to_s
|
27
|
+
# when 'syslog'
|
28
|
+
# SysLogger.new(program)
|
29
|
+
# when 'string'
|
30
|
+
# StringLogger.new
|
31
|
+
# when 'stdout'
|
32
|
+
# FileLogger.new(STDOUT, false)
|
33
|
+
# when 'file'
|
34
|
+
# FileLogger.new(File.new(filename, "a"), true)
|
35
|
+
# end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
data/lib/periodic.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Used to execute tasks periodically.
|
2
|
+
# Execute at most once each interval (seconds).
|
3
|
+
# If interval is < 0, never execute.
|
4
|
+
# If interval is 0, execute every time.
|
5
|
+
class Periodic
|
6
|
+
# Create a periodic execution at this interval.
|
7
|
+
def initialize(interval)
|
8
|
+
@last_time = Clock.at(0)
|
9
|
+
@interval = interval
|
10
|
+
end
|
11
|
+
|
12
|
+
# Runs if it has not executed in the interval,.
|
13
|
+
# Skip otherwise.
|
14
|
+
def check #expects a block
|
15
|
+
case
|
16
|
+
when @interval < 0
|
17
|
+
return
|
18
|
+
when @interval == 0
|
19
|
+
yield
|
20
|
+
when @interval > 0
|
21
|
+
now = Clock.now
|
22
|
+
if (@last_time + @interval) < now
|
23
|
+
yield
|
24
|
+
@last_time = now
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# Logs to a string.
|
2
|
+
# This is useful in testing so that we can read back what
|
3
|
+
# was put into the log, to see if it was what was expected.
|
4
|
+
class StringLogger
|
5
|
+
def initialize(*params)
|
6
|
+
@log = StringIO.new("", "w")
|
7
|
+
end
|
8
|
+
def close
|
9
|
+
end
|
10
|
+
|
11
|
+
def puts(msg)
|
12
|
+
@log.puts(msg)
|
13
|
+
end
|
14
|
+
|
15
|
+
def string
|
16
|
+
@log.string
|
17
|
+
end
|
18
|
+
|
19
|
+
alias debug puts
|
20
|
+
alias info puts
|
21
|
+
alias notice puts
|
22
|
+
alias warning puts
|
23
|
+
alias err puts
|
24
|
+
alias error err
|
25
|
+
alias alert puts
|
26
|
+
alias emerg puts
|
27
|
+
alias crit puts
|
28
|
+
end
|
29
|
+
|
data/lib/sys_logger.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'syslog'
|
2
|
+
|
3
|
+
# Logs using the syslog facility.
|
4
|
+
class SysLogger
|
5
|
+
def initialize(dummy, program_name)
|
6
|
+
@log = Syslog.open(program_name)
|
7
|
+
end
|
8
|
+
|
9
|
+
def close
|
10
|
+
end
|
11
|
+
def puts(msg)
|
12
|
+
@log.info(msg)
|
13
|
+
end
|
14
|
+
def debug(msg)
|
15
|
+
@log.debug(msg)
|
16
|
+
end
|
17
|
+
def info(msg)
|
18
|
+
@log.info(msg)
|
19
|
+
end
|
20
|
+
def notice(msg)
|
21
|
+
@log.notice(msg)
|
22
|
+
end
|
23
|
+
def warning(msg)
|
24
|
+
@log.warning(msg)
|
25
|
+
end
|
26
|
+
def err(msg)
|
27
|
+
@log.err(msg)
|
28
|
+
end
|
29
|
+
def alert(msg)
|
30
|
+
@log.alert(msg)
|
31
|
+
end
|
32
|
+
def emerg(msg)
|
33
|
+
@log.emerg(msg)
|
34
|
+
end
|
35
|
+
def crit(msg)
|
36
|
+
@log.crit(msg)
|
37
|
+
end
|
38
|
+
alias error err
|
39
|
+
end
|
40
|
+
|
data/lib/user_data.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# This class loads user data.
|
2
|
+
|
3
|
+
require 'open-uri'
|
4
|
+
require 'yaml'
|
5
|
+
|
6
|
+
class UserData
|
7
|
+
# Load user data
|
8
|
+
def self.load
|
9
|
+
begin
|
10
|
+
iid = open('http://169.254.169.254/latest/meta-data/instance-id').read(200)
|
11
|
+
user_data = open('http://169.254.169.254/latest/user-data').read(2000)
|
12
|
+
data = YAML.load(user_data)
|
13
|
+
aws = { :aws_env => data[:aws_env],
|
14
|
+
:aws_access_key => data[:aws_access_key],
|
15
|
+
:aws_secret_key => data[:aws_secret_key]
|
16
|
+
}
|
17
|
+
rescue
|
18
|
+
# when running locally, use fake iid
|
19
|
+
iid = "unknown"
|
20
|
+
user_data = nil
|
21
|
+
aws = {}
|
22
|
+
end
|
23
|
+
@@data = {:aws => aws, :iid => iid, :user_data => user_data}
|
24
|
+
@@data
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.keys
|
28
|
+
[@@data[:aws][:aws_access_key], @@data[:aws][:aws_secret_key]] if @@data
|
29
|
+
end
|
30
|
+
end
|