staugaard-cloudmaster 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|