mystro-common 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +51 -0
- data/lib/mystro/account.rb +97 -0
- data/lib/mystro/capistrano.rb +50 -0
- data/lib/mystro/common/version.rb +11 -0
- data/lib/mystro/config.rb +29 -0
- data/lib/mystro/connect/balancer.rb +91 -0
- data/lib/mystro/connect/compute.rb +100 -0
- data/lib/mystro/connect/dns.rb +38 -0
- data/lib/mystro/connect/environment.rb +31 -0
- data/lib/mystro/connect.rb +123 -0
- data/lib/mystro/dsl/template.rb +281 -0
- data/lib/mystro/ext/fog/balancer.rb +15 -0
- data/lib/mystro/job.rb +0 -0
- data/lib/mystro/log.rb +58 -0
- data/lib/mystro/model.rb +71 -0
- data/lib/mystro/plugin.rb +73 -0
- data/lib/mystro/userdata.rb +42 -0
- data/lib/mystro-common.rb +66 -0
- data/mystro-common.gemspec +26 -0
- metadata +164 -0
@@ -0,0 +1,123 @@
|
|
1
|
+
module Mystro
|
2
|
+
module Connect
|
3
|
+
class Base
|
4
|
+
class << self
|
5
|
+
attr_accessor :model
|
6
|
+
attr_accessor :collection
|
7
|
+
|
8
|
+
def cname
|
9
|
+
self.name.split("::").last.downcase
|
10
|
+
end
|
11
|
+
|
12
|
+
def fog
|
13
|
+
Mystro.send(cname).fog || nil rescue nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def after(event, &block)
|
17
|
+
@hooks ||= {}
|
18
|
+
@hooks[event] ||= []
|
19
|
+
@hooks[event] << block
|
20
|
+
end
|
21
|
+
|
22
|
+
def hooks(event, *args)
|
23
|
+
Mystro::Log.debug "#{cname}:hooks:#{event} #{@hooks[event].count}"
|
24
|
+
@hooks[event].each do |e|
|
25
|
+
Mystro::Log.debug "#{cname}:hooks:#{event} #{e}"
|
26
|
+
e.call(*args) if e
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_reader :cfg
|
32
|
+
attr_reader :opt
|
33
|
+
attr_reader :fog
|
34
|
+
|
35
|
+
def initialize(account)
|
36
|
+
a = account.data
|
37
|
+
c = cname
|
38
|
+
|
39
|
+
# opt is used to initialize fog in connect classes
|
40
|
+
defaults = a.connect!.fog? ? a.connect.fog : {}
|
41
|
+
overrides = a[c] && a[c].fog? ? a[c].fog : {}
|
42
|
+
raw = defaults.deep_merge(overrides)
|
43
|
+
@opt = Hashie::Mash.new(raw)
|
44
|
+
|
45
|
+
# cfg is the additional configuration parms (aside from the fog block)
|
46
|
+
raw = {}
|
47
|
+
if a[c]
|
48
|
+
raw = a[c].to_hash
|
49
|
+
raw.delete(:fog) if raw[:fog]
|
50
|
+
end
|
51
|
+
@cfg = Hashie::Mash.new(raw)
|
52
|
+
|
53
|
+
self.class.after :create do |e, model|
|
54
|
+
Mystro::Plugin.run "#{cname}:create", e, model
|
55
|
+
end
|
56
|
+
|
57
|
+
self.class.after :destroy do |e, tags|
|
58
|
+
Mystro::Plugin.run "#{cname}:destroy", e, tags
|
59
|
+
end
|
60
|
+
|
61
|
+
connect
|
62
|
+
end
|
63
|
+
|
64
|
+
def connect
|
65
|
+
@fog ||= model.new(opt) if opt
|
66
|
+
rescue => e
|
67
|
+
Mystro::Log.error "#{cname} connect failed: #{e.message} at #{e.backtrace.first}"
|
68
|
+
end
|
69
|
+
|
70
|
+
def connected?
|
71
|
+
fog.nil? ? false : true
|
72
|
+
end
|
73
|
+
|
74
|
+
def find(id)
|
75
|
+
fog.send(collection).get(id)
|
76
|
+
end
|
77
|
+
|
78
|
+
def all
|
79
|
+
fog.send(collection).all
|
80
|
+
end
|
81
|
+
|
82
|
+
def create(model)
|
83
|
+
Mystro::Log.debug "#{cname}#create #{model.inspect}"
|
84
|
+
Mystro::Log.debug "#{cname}#create #{fog.inspect}"
|
85
|
+
e = fog.send(collection).create(model.fog_options)
|
86
|
+
e
|
87
|
+
end
|
88
|
+
|
89
|
+
def destroy(models)
|
90
|
+
list = [*models].flatten
|
91
|
+
list.each do |m|
|
92
|
+
Mystro::Log.debug "#{cname}#destroy #{m.rid}"
|
93
|
+
e = find(m.rid)
|
94
|
+
e.destroy if e
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def model
|
99
|
+
raise "model not set for '#{cname}'" unless self.class.model
|
100
|
+
@model ||= self.class.model.constantize
|
101
|
+
end
|
102
|
+
|
103
|
+
def collection
|
104
|
+
raise "collection not set for '#{cname}'" unless self.class.collection
|
105
|
+
@collection ||= self.class.collection
|
106
|
+
end
|
107
|
+
|
108
|
+
def cname
|
109
|
+
self.class.cname
|
110
|
+
end
|
111
|
+
|
112
|
+
def after(*args)
|
113
|
+
self.class.after(*args)
|
114
|
+
end
|
115
|
+
|
116
|
+
def hooks(*args)
|
117
|
+
self.class.hooks(*args)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
Dir["#{File.dirname(__FILE__)}/connect/*.rb"].each {|file| require "#{file.gsub(/\.rb/,'')}" }
|
@@ -0,0 +1,281 @@
|
|
1
|
+
module Mystro
|
2
|
+
module DSL
|
3
|
+
module Template
|
4
|
+
class << self
|
5
|
+
def load(name_or_file)
|
6
|
+
@templates ||= {}
|
7
|
+
template_name = nil
|
8
|
+
template_file = nil
|
9
|
+
if File.exists?(name_or_file)
|
10
|
+
template_name = File.basename(name_or_file).gsub(/\.rb$/, "").to_sym
|
11
|
+
template_file = name_or_file
|
12
|
+
elsif File.exists?("#{dir}/#{name_or_file}.rb")
|
13
|
+
template_name = name.to_sym
|
14
|
+
template_file = "#{dir}/#{name}.rb"
|
15
|
+
end
|
16
|
+
raise "could not load template #{template_name} (#{template_file})" unless template_file && File.file?(template_file)
|
17
|
+
#raise "template already loaded #{template_name}" if @templates[template_name]
|
18
|
+
@templates[template_name] ||= begin
|
19
|
+
t = Mystro::DSL::Template::DSL.new(template_name)
|
20
|
+
t.instance_eval(File.read(template_file), "Template(#{template_file})")
|
21
|
+
@templates[template_name] = t
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def load_yaml_file(path)
|
26
|
+
file = File.expand_path(path)
|
27
|
+
raise "Configuration not found: #{path} (#{file})" unless File.exists?(file)
|
28
|
+
yaml = YAML.load_file(file)
|
29
|
+
yaml = yaml[yaml.keys.first] if yaml.keys.count == 1
|
30
|
+
|
31
|
+
yaml
|
32
|
+
end
|
33
|
+
|
34
|
+
def list
|
35
|
+
Dir["#{dir}/*"].inject({}) do |h, e|
|
36
|
+
f = e.gsub("#{dir}/", "")
|
37
|
+
f = File.basename(f, ".yml")
|
38
|
+
h[f.to_sym] = e
|
39
|
+
h
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
def dir
|
45
|
+
"#{Mystro.directory}/templates"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class DSL
|
50
|
+
attr_reader :balancers, :servers
|
51
|
+
|
52
|
+
def initialize(name)
|
53
|
+
@name = name.to_sym
|
54
|
+
@balancers = []
|
55
|
+
@servers = []
|
56
|
+
end
|
57
|
+
|
58
|
+
def template(&block)
|
59
|
+
instance_eval &block
|
60
|
+
end
|
61
|
+
|
62
|
+
def balancer(name, &block)
|
63
|
+
balancer = Balancer.new(name)
|
64
|
+
balancer.instance_eval &block
|
65
|
+
@balancers << balancer
|
66
|
+
end
|
67
|
+
|
68
|
+
def server(name, &block)
|
69
|
+
server = Server.new(name)
|
70
|
+
server.instance_eval &block
|
71
|
+
@servers << server
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
class Base
|
76
|
+
def attr(name, value=nil)
|
77
|
+
@attrs[name] = value unless value.nil?
|
78
|
+
@attrs[name]
|
79
|
+
end
|
80
|
+
|
81
|
+
def list_attr(name, value=nil)
|
82
|
+
@attrs[name] ||= []
|
83
|
+
unless value.nil?
|
84
|
+
if value.kind_of?(Array)
|
85
|
+
@attrs[name] += value
|
86
|
+
else
|
87
|
+
@attrs[name] << value
|
88
|
+
end
|
89
|
+
end
|
90
|
+
@attrs[name]
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
class Server < Base
|
95
|
+
def initialize(name)
|
96
|
+
@attrs = {
|
97
|
+
:name => name.to_sym,
|
98
|
+
:roles => [],
|
99
|
+
:groups => [],
|
100
|
+
:count => 1,
|
101
|
+
:image => nil,
|
102
|
+
:flavor => nil,
|
103
|
+
:keypair => nil,
|
104
|
+
:userdata => "default",
|
105
|
+
:dnsnames => [],
|
106
|
+
}
|
107
|
+
end
|
108
|
+
|
109
|
+
def name
|
110
|
+
@attrs[:name]
|
111
|
+
end
|
112
|
+
|
113
|
+
def roles
|
114
|
+
@attrs[:roles]
|
115
|
+
end
|
116
|
+
|
117
|
+
def groups
|
118
|
+
@attrs[:groups]
|
119
|
+
end
|
120
|
+
|
121
|
+
def dnsnames
|
122
|
+
@attrs[:dnsnames]
|
123
|
+
end
|
124
|
+
|
125
|
+
def role(r)
|
126
|
+
list_attr(:roles, r)
|
127
|
+
end
|
128
|
+
|
129
|
+
def count(c=nil)
|
130
|
+
attr(:count, c)
|
131
|
+
end
|
132
|
+
|
133
|
+
def image(i=nil)
|
134
|
+
attr(:image, i)
|
135
|
+
end
|
136
|
+
|
137
|
+
def flavor(f=nil)
|
138
|
+
attr(:flavor, f)
|
139
|
+
end
|
140
|
+
|
141
|
+
def group(g)
|
142
|
+
list_attr(:groups, g)
|
143
|
+
end
|
144
|
+
|
145
|
+
def keypair(k=nil)
|
146
|
+
attr(:keypair, k)
|
147
|
+
end
|
148
|
+
|
149
|
+
def userdata(u=nil)
|
150
|
+
attr(:userdata, u)
|
151
|
+
end
|
152
|
+
|
153
|
+
def balancer(b=nil, &block)
|
154
|
+
if block_given?
|
155
|
+
raise "balancer block must specify name" unless b
|
156
|
+
Mystro::DSL::Template::DSL.balancer(b, &block)
|
157
|
+
end
|
158
|
+
attr(:balancer, b)
|
159
|
+
end
|
160
|
+
|
161
|
+
def dns(name)
|
162
|
+
n = name.gsub(Mystro.get_config(:dns_zone), "")
|
163
|
+
list_attr(:dnsnames, n)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class Balancer
|
168
|
+
attr_reader :name, :sticky, :primary, :sticky_type, :sticky_arg
|
169
|
+
|
170
|
+
def initialize(name)
|
171
|
+
@listeners = []
|
172
|
+
@name = name.to_sym
|
173
|
+
@primary = false
|
174
|
+
@sticky = false
|
175
|
+
end
|
176
|
+
|
177
|
+
def primary(enable = nil)
|
178
|
+
enable.nil? ? @primary : @primary = enable
|
179
|
+
end
|
180
|
+
|
181
|
+
def listener(&block)
|
182
|
+
listener = Listener.new
|
183
|
+
listener.instance_eval &block
|
184
|
+
@listeners << listener
|
185
|
+
end
|
186
|
+
|
187
|
+
def health(&block)
|
188
|
+
healthcheck = HealthCheck.new
|
189
|
+
healthcheck.instance_eval &block
|
190
|
+
@healthcheck = healthcheck
|
191
|
+
end
|
192
|
+
|
193
|
+
def listeners
|
194
|
+
@listeners.map { |e| e.spec }
|
195
|
+
end
|
196
|
+
|
197
|
+
def sticky(type=nil, expires_or_cookie=nil)
|
198
|
+
if type && expires_or_cookie
|
199
|
+
@sticky = true
|
200
|
+
@sticky_type = type
|
201
|
+
@sticky_arg = expires_or_cookie
|
202
|
+
end
|
203
|
+
@sticky
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
class Listener
|
208
|
+
def initialize
|
209
|
+
@from_proto = nil
|
210
|
+
@from_port = nil
|
211
|
+
@to_proto = nil
|
212
|
+
@to_port = nil
|
213
|
+
@cert = nil
|
214
|
+
end
|
215
|
+
|
216
|
+
def from(proto, port)
|
217
|
+
@from_proto = proto
|
218
|
+
@from_port = port
|
219
|
+
end
|
220
|
+
|
221
|
+
def to(proto, port)
|
222
|
+
@to_proto = proto
|
223
|
+
@to_port = port
|
224
|
+
end
|
225
|
+
|
226
|
+
def cert(cert)
|
227
|
+
@cert = cert
|
228
|
+
end
|
229
|
+
|
230
|
+
def spec
|
231
|
+
{
|
232
|
+
:from => "#@from_proto:#@from_port",
|
233
|
+
:to => "#@to_proto:#@to_port",
|
234
|
+
:cert => @cert,
|
235
|
+
}
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
239
|
+
class HealthCheck
|
240
|
+
def initialize
|
241
|
+
@healthy = 10
|
242
|
+
@unhealthy = 2
|
243
|
+
@interval = 30
|
244
|
+
@target = nil
|
245
|
+
@timeout = 5
|
246
|
+
end
|
247
|
+
|
248
|
+
def healthy(v)
|
249
|
+
@healthy = v
|
250
|
+
end
|
251
|
+
|
252
|
+
def unhealthy(v)
|
253
|
+
@unhealthy = v
|
254
|
+
end
|
255
|
+
|
256
|
+
def interval(v)
|
257
|
+
@interval = v
|
258
|
+
end
|
259
|
+
|
260
|
+
def target(v)
|
261
|
+
@target = v
|
262
|
+
end
|
263
|
+
|
264
|
+
def timeout(v)
|
265
|
+
@timeout = v
|
266
|
+
end
|
267
|
+
|
268
|
+
def spec
|
269
|
+
raise "target not specified for health check" unless @target
|
270
|
+
{
|
271
|
+
healthy: @healthy,
|
272
|
+
unhealthy: @unhealthy,
|
273
|
+
interval: @interval,
|
274
|
+
target: @target,
|
275
|
+
timeout: @timeout,
|
276
|
+
}
|
277
|
+
end
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# make load balancers act more like other models in Fog
|
2
|
+
# ultimately a hack, but makes things work for now.
|
3
|
+
module Fog
|
4
|
+
class Balancer
|
5
|
+
def self.new(attributes)
|
6
|
+
attributes = attributes.dup
|
7
|
+
case provider = attributes.delete(:provider).to_s.downcase.to_sym
|
8
|
+
when :aws
|
9
|
+
Fog::AWS::ELB.new(attributes)
|
10
|
+
else
|
11
|
+
raise ArgumentError.new("#{provider} is not a recognized balancer provider")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/mystro/job.rb
ADDED
File without changes
|
data/lib/mystro/log.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "yell"
|
2
|
+
|
3
|
+
module Mystro
|
4
|
+
class Log
|
5
|
+
class << self
|
6
|
+
attr_reader :loggers
|
7
|
+
|
8
|
+
def init
|
9
|
+
@loggers = { }
|
10
|
+
@loggers["STDOUT"] = Yell.new(STDOUT, :level => [:info, :warn], :format => Yell::NoFormat)
|
11
|
+
@loggers["STDERR"] = Yell.new(STDERR, :level => [:error, :fatal], :format => Yell::NoFormat)
|
12
|
+
#@loggers["/tmp/mystro.log"] = Yell.new(:datefile, "/tmp/mystro.log", :level => :debug, :format => Yell::DefaultFormat, :keep => 7, :symlink => true)
|
13
|
+
end
|
14
|
+
|
15
|
+
def add(level, dest, format=Yell::DefaultFormat)
|
16
|
+
if [STDOUT, STDERR].include?(dest)
|
17
|
+
console_disable
|
18
|
+
@loggers["STDOUT"] = Yell.new(dest, :level => level, :format => format)
|
19
|
+
else
|
20
|
+
@loggers.delete(dest) if @loggers[dest]
|
21
|
+
FileUtils.mkdir_p(File.dirname(dest))
|
22
|
+
@loggers[dest] = Yell.new(:datefile, dest,
|
23
|
+
:level => level, :format => format,
|
24
|
+
:keep => 7, :symlink => true)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def console_disable
|
29
|
+
%w{STDOUT STDERR}.each { |s| @loggers.delete(s) }
|
30
|
+
end
|
31
|
+
|
32
|
+
def console_debug
|
33
|
+
console_disable
|
34
|
+
@loggers["STDOUT"] = Yell.new(STDOUT, :level => [:debug, :info, :warn], :format => Yell::NoFormat)
|
35
|
+
@loggers["STDERR"] = Yell.new(STDERR, :level => [:error, :fatal], :format => Yell::NoFormat)
|
36
|
+
end
|
37
|
+
|
38
|
+
def console_quiet
|
39
|
+
console_disable
|
40
|
+
@loggers["STDOUT"] = Yell.new(STDOUT, :level => [:warn], :format => Yell::NoFormat)
|
41
|
+
@loggers["STDERR"] = Yell.new(STDERR, :level => [:error, :fatal], :format => Yell::NoFormat)
|
42
|
+
end
|
43
|
+
|
44
|
+
%w{debug info warn error fatal}.each do |method_name|
|
45
|
+
class_eval(<<-METHOD_DEFN, __FILE__, __LINE__)
|
46
|
+
def #{method_name}(msg=nil, &block)
|
47
|
+
@loggers.each {|k, l| l.#{method_name}(msg, &block) }
|
48
|
+
end
|
49
|
+
METHOD_DEFN
|
50
|
+
end
|
51
|
+
|
52
|
+
def reset
|
53
|
+
@loggers = {}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
Mystro::Log.init
|
data/lib/mystro/model.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'mystro-common'
|
2
|
+
|
3
|
+
module Mystro
|
4
|
+
module Model
|
5
|
+
class Base
|
6
|
+
attr_reader :attributes
|
7
|
+
|
8
|
+
def initialize(attributes={ })
|
9
|
+
# all the stringify keys calls are to make sure that we normalize EVERYTHING before merges
|
10
|
+
d = defaults.stringify_keys!
|
11
|
+
c = load_from_config.stringify_keys!
|
12
|
+
a = attributes.stringify_keys!
|
13
|
+
# attributes should ALWAYS be stringified keys
|
14
|
+
@attributes = d.deep_merge(c).deep_merge(a).stringify_keys!
|
15
|
+
end
|
16
|
+
|
17
|
+
def defaults
|
18
|
+
self.class.defaults || {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def fog_tags(hash=self.class.tagnames.each {|t| hash[t] = send(t) })
|
22
|
+
hash.inject({ }) do |h, e|
|
23
|
+
(k, v) = e
|
24
|
+
h["#{k.to_s.capitalize}"] = v
|
25
|
+
h
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def load_from_config
|
32
|
+
cname = self.class.name.split("::").last.downcase
|
33
|
+
config = { }
|
34
|
+
if Mystro.account && Mystro.account[cname]
|
35
|
+
config = Mystro.account[cname].to_hash
|
36
|
+
end
|
37
|
+
config["account"] = Mystro.selected
|
38
|
+
config
|
39
|
+
end
|
40
|
+
|
41
|
+
class << self
|
42
|
+
attr_reader :tagnames
|
43
|
+
attr_reader :attrnames
|
44
|
+
attr_reader :defaults
|
45
|
+
|
46
|
+
def attr(*list)
|
47
|
+
@attrnames = list
|
48
|
+
list.each do |a|
|
49
|
+
define_method(a) do
|
50
|
+
@attributes[a.to_s]
|
51
|
+
end
|
52
|
+
define_method("#{a}=") do |val|
|
53
|
+
@attributes[a.to_s] = val
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def tag(*list)
|
59
|
+
@tagnames = list
|
60
|
+
attr(*list)
|
61
|
+
end
|
62
|
+
|
63
|
+
def default(hash)
|
64
|
+
@defaults = hash
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
Dir["#{File.dirname(__FILE__)}/model/*.rb"].each { |file| require file.gsub(/\.rb/, '') }
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Mystro
|
2
|
+
module Plugin
|
3
|
+
class << self
|
4
|
+
def run(event, *args)
|
5
|
+
return if Mystro.config.mock
|
6
|
+
|
7
|
+
@hooks ||= []
|
8
|
+
@hooks.select { |e| e[:event] == event }.each do |plugin|
|
9
|
+
klass = plugin[:class]
|
10
|
+
block = plugin[:block]
|
11
|
+
begin
|
12
|
+
Mystro::Log.debug "calling #{klass} :: #{event}"
|
13
|
+
block.call(args.dup)
|
14
|
+
rescue => e
|
15
|
+
Mystro::Log.error "failed to run event #{event} for #{klass}: #{e.message}"
|
16
|
+
Mystro::Log.debug e
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def on(klass, event, &block)
|
22
|
+
@hooks ||= []
|
23
|
+
@hooks << { :event => event, :class => klass, :block => block }
|
24
|
+
end
|
25
|
+
|
26
|
+
def load(plugins={ })
|
27
|
+
plugins.each do |plugin, data|
|
28
|
+
begin
|
29
|
+
f = "#{Mystro.directory}/plugins/#{plugin}"
|
30
|
+
Mystro::Log.debug "loading plugin: #{plugin} #{f}"
|
31
|
+
require f
|
32
|
+
rescue LoadError, StandardError => e
|
33
|
+
Mystro::Log.error "error while loading plugin: #{plugin}: #{e.message} at #{e.backtrace.first}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def register(plugin, type, klass)
|
39
|
+
@plugins ||= {}
|
40
|
+
@plugins[type] ||= {}
|
41
|
+
@plugins[type][plugin] = klass
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module Base
|
46
|
+
def self.included(base)
|
47
|
+
base.extend self
|
48
|
+
end
|
49
|
+
|
50
|
+
def config_for(klass)
|
51
|
+
name = klass.name.split('::').last.downcase.to_sym
|
52
|
+
return Mystro.account.plugins[name] if Mystro.account.plugins && Mystro.account.plugins[name]
|
53
|
+
{ }
|
54
|
+
end
|
55
|
+
|
56
|
+
def on(event, &block)
|
57
|
+
Mystro::Plugin.on(self, event, &block)
|
58
|
+
end
|
59
|
+
|
60
|
+
def command(name, desc, klass=nil, &block)
|
61
|
+
on "commands:loaded" do |args|
|
62
|
+
Mystro::Log.debug "loading commands for #{name}"
|
63
|
+
command = args.shift
|
64
|
+
if klass
|
65
|
+
command.subcommand name, "#{desc} (#{self})", klass
|
66
|
+
else
|
67
|
+
command.subcommand name, "#{desc} (#{self})", &block
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
|
3
|
+
module Mystro
|
4
|
+
class Userdata
|
5
|
+
class << self
|
6
|
+
def create(name, roles, environment, opts={ })
|
7
|
+
package = opts.delete(:package)
|
8
|
+
dependencies = opts.delete(:dependencies)
|
9
|
+
gems = opts.delete(:gems)
|
10
|
+
files = opts.delete(:files)
|
11
|
+
directory = "#{Mystro.directory}/userdata/#{package}"
|
12
|
+
file = "#{directory}/userdata.yml"
|
13
|
+
raise "userdata error: package not specified" unless package
|
14
|
+
raise "userdata error: pacakge #{package} directory does not exist (#{directory})" unless File.directory?(directory)
|
15
|
+
raise "userdata error: configuration file does not exist (#{file})" unless File.exists?(file)
|
16
|
+
config = YAML.load_file(file)
|
17
|
+
|
18
|
+
data = {
|
19
|
+
:name => name,
|
20
|
+
:roles => roles,
|
21
|
+
:environment => environment,
|
22
|
+
:nickname => name,
|
23
|
+
:account => "unknown",
|
24
|
+
:zone => "unknown.local",
|
25
|
+
:dependencies => [],
|
26
|
+
:gems => [],
|
27
|
+
:files => [],
|
28
|
+
:directory => directory,
|
29
|
+
:template => "userdata.sh.erb",
|
30
|
+
}.deep_merge(config.symbolize_keys!).deep_merge(opts.symbolize_keys!)
|
31
|
+
|
32
|
+
data[:gems] += gems if gems
|
33
|
+
data[:dependencies] += dependencies if dependencies
|
34
|
+
data[:files] += files if files
|
35
|
+
|
36
|
+
template = File.open("#{directory}/#{data[:template]}").read
|
37
|
+
erb = Erubis::Eruby.new(template)
|
38
|
+
out = erb.evaluate(data)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|