zergrush 0.0.2 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +33 -2
- data/data/ke.schema +11 -250
- data/features/hive.feature +2 -1
- data/lib/zerg.rb +1 -2
- data/lib/zerg/erbalize.rb +35 -0
- data/lib/zerg/gem_plugin.rb +334 -0
- data/lib/zerg/hive.rb +51 -25
- data/lib/zerg/runner.rb +26 -199
- data/lib/zerg/version.rb +1 -1
- data/zerg.gemspec +3 -1
- metadata +21 -10
- data/data/driver/vagrant/bridging.template +0 -1
- data/data/driver/vagrant/hostonly.template +0 -1
- data/data/driver/vagrant/machine.template +0 -22
- data/data/driver/vagrant/main.template +0 -11
- data/data/driver/vagrant/provider.template +0 -3
- data/lib/zerg/driver_renderer.rb +0 -190
@@ -0,0 +1,334 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
# GemPlugin is copyrighted free software by Zed A. Shaw
|
5
|
+
# <zedshaw at zedshaw dot com> You can redistribute it and/or modify it under
|
6
|
+
# either the terms of the GPL or the conditions below:
|
7
|
+
|
8
|
+
# 1. You may make and give away verbatim copies of the source form of the
|
9
|
+
# software without restriction, provided that you duplicate all of the
|
10
|
+
# original copyright notices and associated disclaimers.
|
11
|
+
|
12
|
+
# 2. You may modify your copy of the software in any way, provided that
|
13
|
+
# you do at least ONE of the following:
|
14
|
+
|
15
|
+
# a) place your modifications in the Public Domain or otherwise make them
|
16
|
+
# Freely Available, such as by posting said modifications to Usenet or an
|
17
|
+
# equivalent medium, or by allowing the author to include your
|
18
|
+
# modifications in the software.
|
19
|
+
|
20
|
+
# b) use the modified software only within your corporation or
|
21
|
+
# organization.
|
22
|
+
|
23
|
+
# c) rename any non-standard executables so the names do not conflict with
|
24
|
+
# standard executables, which must also be provided.
|
25
|
+
|
26
|
+
# d) make other distribution arrangements with the author.
|
27
|
+
|
28
|
+
# 3. You may distribute the software in object code or executable
|
29
|
+
# form, provided that you do at least ONE of the following:
|
30
|
+
|
31
|
+
# a) distribute the executables and library files of the software,
|
32
|
+
# together with instructions (in the manual page or equivalent) on where
|
33
|
+
# to get the original distribution.
|
34
|
+
|
35
|
+
# b) accompany the distribution with the machine-readable source of the
|
36
|
+
# software.
|
37
|
+
|
38
|
+
# c) give non-standard executables non-standard names, with
|
39
|
+
# instructions on where to get the original software distribution.
|
40
|
+
|
41
|
+
# d) make other distribution arrangements with the author.
|
42
|
+
|
43
|
+
# 4. You may modify and include the part of the software into any other
|
44
|
+
# software (possibly commercial). But some files in the distribution
|
45
|
+
# are not written by the author, so that they are not under this terms.
|
46
|
+
|
47
|
+
# 5. The scripts and library files supplied as input to or produced as
|
48
|
+
# output from the software do not automatically fall under the
|
49
|
+
# copyright of the software, but belong to whomever generated them,
|
50
|
+
# and may be sold commercially, and may be aggregated with this
|
51
|
+
# software.
|
52
|
+
|
53
|
+
# 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
54
|
+
# IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
55
|
+
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
56
|
+
# PURPOSE.
|
57
|
+
|
58
|
+
# Implements a dynamic plugin loading, configuration, and discovery system
|
59
|
+
# based on RubyGems and a simple additional name space that looks like a URI.
|
60
|
+
#
|
61
|
+
# A plugin is created and put into a category with the following code:
|
62
|
+
#
|
63
|
+
# class MyThing < GemPlugin::Plugin "/things"
|
64
|
+
# ...
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# What this does is sets up your MyThing in the plugin registry via GemPlugin::Manager.
|
68
|
+
# You can then later get this plugin with GemPlugin::Manager.create("/things/mything")
|
69
|
+
# and can also pass in options as a second parameter.
|
70
|
+
#
|
71
|
+
# This isn't such a big deal, but the power is really from the GemPlugin::Manager.load
|
72
|
+
# method. This method will go through the installed gems and require_gem any
|
73
|
+
# that depend on the zergrush RubyGem. You can arbitrarily include or exclude
|
74
|
+
# gems based on what they also depend on, thus letting you load these gems when appropriate.
|
75
|
+
#
|
76
|
+
# Since this system was written originally for the Mongrel project that'll be the
|
77
|
+
# best example of using it.
|
78
|
+
#
|
79
|
+
# Imagine you have a neat plugin for Mongrel called snazzy_command that gives the
|
80
|
+
# mongrel_rails a new command snazzy (like: mongrel_rails snazzy). You'd like
|
81
|
+
# people to be able to grab this plugin if they want and use it, because it's snazzy.
|
82
|
+
#
|
83
|
+
# First thing you do is create a gem of your project and make sure that it depends
|
84
|
+
# on "mongrel" AND "zergrush". This signals to the GemPlugin system that this is
|
85
|
+
# a plugin for mongrel.
|
86
|
+
#
|
87
|
+
# Next you put this code into a file like lib/init.rb (can be anything really):
|
88
|
+
#
|
89
|
+
# class Snazzy < ZergGemPlugin::Plugin "/commands"
|
90
|
+
# ...
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# Then when you create your gem you have the following bits in your Rakefile:
|
94
|
+
#
|
95
|
+
# spec.add_dependency('mongrel', '>= 0.3.9')
|
96
|
+
# spec.add_dependency('zergrush', '>= 0.1')
|
97
|
+
# spec.autorequire = 'init.rb'
|
98
|
+
#
|
99
|
+
# Finally, you just have to now publish this gem for people to install and Mongrel
|
100
|
+
# will "magically" be able to install it.
|
101
|
+
#
|
102
|
+
# The "magic" part though is pretty simple and done via the GemPlugin::Manager.load
|
103
|
+
# method. Read that to see how it is really done.
|
104
|
+
module ZergGemPlugin
|
105
|
+
|
106
|
+
EXCLUDE = true
|
107
|
+
INCLUDE = false
|
108
|
+
|
109
|
+
class PluginNotLoaded < StandardError; end
|
110
|
+
|
111
|
+
|
112
|
+
# This class is used by people who use gem plugins (but don't necessarily make them)
|
113
|
+
# to add plugins to their own systems. It provides a way to load plugins, list them,
|
114
|
+
# and create them as needed.
|
115
|
+
#
|
116
|
+
# It is a singleton so you use like this: GemPlugins::Manager.instance.load
|
117
|
+
class Manager
|
118
|
+
include Singleton
|
119
|
+
attr_reader :plugins
|
120
|
+
attr_reader :gems
|
121
|
+
|
122
|
+
|
123
|
+
def initialize
|
124
|
+
# plugins that have been loaded
|
125
|
+
@plugins = {}
|
126
|
+
|
127
|
+
# keeps track of gems which have been loaded already by the manager *and*
|
128
|
+
# where they came from so that they can be referenced later
|
129
|
+
@gems = {}
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
# Responsible for going through the list of available gems and loading
|
134
|
+
# any plugins requested. It keeps track of what it's loaded already
|
135
|
+
# and won't load them again.
|
136
|
+
#
|
137
|
+
# It accepts one parameter which is a hash of gem depends that should include
|
138
|
+
# or exclude a gem from being loaded. A gem must depend on zergrush to be
|
139
|
+
# considered, but then each system has to add it's own INCLUDE to make sure
|
140
|
+
# that only plugins related to it are loaded.
|
141
|
+
#
|
142
|
+
# An example again comes from Mongrel. In order to load all Mongrel plugins:
|
143
|
+
#
|
144
|
+
# GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE
|
145
|
+
#
|
146
|
+
# Which will load all plugins that depend on mongrel AND zergrush. Now, one
|
147
|
+
# extra thing we do is we delay loading Rails Mongrel plugins until after rails
|
148
|
+
# is configured. Do do this the mongrel_rails script has:
|
149
|
+
#
|
150
|
+
# GemPlugin::Manager.instance.load "mongrel" => GemPlugin::INCLUDE, "rails" => GemPlugin::EXCLUDE
|
151
|
+
# The only thing to remember is that this is saying "include a plugin if it
|
152
|
+
# depends on zergrush, mongrel, but NOT rails". If a plugin also depends on other
|
153
|
+
# stuff then it's loaded just fine. Only zergrush, mongrel, and rails are
|
154
|
+
# ever used to determine if it should be included.
|
155
|
+
#
|
156
|
+
# NOTE: Currently RubyGems will run autorequire on gems that get required AND
|
157
|
+
# on their dependencies. This really messes with people running edge rails
|
158
|
+
# since activerecord or other stuff gets loaded for just touching a gem plugin.
|
159
|
+
# To prevent this load requires the full path to the "init.rb" file, which
|
160
|
+
# avoids the RubyGems autorequire magic.
|
161
|
+
def load(needs = {})
|
162
|
+
needs = needs.merge({"zergrush" => INCLUDE})
|
163
|
+
|
164
|
+
Gem::Specification.each { |gem|
|
165
|
+
# don't load gems more than once
|
166
|
+
next if @gems.has_key? gem.name
|
167
|
+
check = needs.dup
|
168
|
+
|
169
|
+
# rolls through the depends and inverts anything it finds
|
170
|
+
gem.dependencies.each do |dep|
|
171
|
+
# this will fail if a gem is depended more than once
|
172
|
+
if check.has_key? dep.name
|
173
|
+
check[dep.name] = !check[dep.name]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
# now since excluded gems start as true, inverting them
|
178
|
+
# makes them false so we'll skip this gem if any excludes are found
|
179
|
+
if (check.select {|name,test| !test}).length == 0
|
180
|
+
# looks like no needs were set to false, so it's good
|
181
|
+
if gem.metadata["zergrushplugin"] != nil
|
182
|
+
require File.join(gem.gem_dir, "lib", gem.name, "init.rb")
|
183
|
+
@gems[gem.name] = gem.gem_dir
|
184
|
+
end
|
185
|
+
end
|
186
|
+
}
|
187
|
+
|
188
|
+
return nil
|
189
|
+
end
|
190
|
+
|
191
|
+
|
192
|
+
# Not necessary for you to call directly, but this is
|
193
|
+
# how GemPlugin::Base.inherited actually adds a
|
194
|
+
# plugin to a category.
|
195
|
+
def register(category, name, klass)
|
196
|
+
@plugins[category] ||= {}
|
197
|
+
@plugins[category][name.downcase] = klass
|
198
|
+
end
|
199
|
+
|
200
|
+
|
201
|
+
# Resolves the given name (should include /category/name) to
|
202
|
+
# find the plugin class and create an instance. You can
|
203
|
+
# pass a second hash option that is then given to the Plugin
|
204
|
+
# to configure it.
|
205
|
+
def create(name, options = {})
|
206
|
+
last_slash = name.rindex("/")
|
207
|
+
category = name[0 ... last_slash]
|
208
|
+
plugin = name[last_slash .. -1]
|
209
|
+
|
210
|
+
map = @plugins[category]
|
211
|
+
if not map
|
212
|
+
raise "Plugin category #{category} does not exist"
|
213
|
+
elsif not map.has_key? plugin
|
214
|
+
raise "Plugin #{plugin} does not exist in category #{category}"
|
215
|
+
else
|
216
|
+
map[plugin].new(options)
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
220
|
+
|
221
|
+
# Simply says whether the given gem has been loaded yet or not.
|
222
|
+
def loaded?(gem_name)
|
223
|
+
@gems.has_key? gem_name
|
224
|
+
end
|
225
|
+
|
226
|
+
|
227
|
+
# GemPlugins can have a 'resources' directory which is packaged with them
|
228
|
+
# and can hold any data resources the plugin may need. The main problem
|
229
|
+
# is that it's difficult to figure out where these resources are
|
230
|
+
# actually located on the file system. The resource method tries to
|
231
|
+
# locate the real path for a given resource path.
|
232
|
+
#
|
233
|
+
# Let's say you have a 'resources/stylesheets/default.css' file in your
|
234
|
+
# gem distribution, then finding where this file really is involves:
|
235
|
+
#
|
236
|
+
# Manager.instance.resource("mygem", "/stylesheets/default.css")
|
237
|
+
#
|
238
|
+
# You either get back the full path to the resource or you get a nil
|
239
|
+
# if it doesn't exist.
|
240
|
+
#
|
241
|
+
# If you request a path for a GemPlugin that hasn't been loaded yet
|
242
|
+
# then it will throw an PluginNotLoaded exception. The gem may be
|
243
|
+
# present on your system in this case, but you just haven't loaded
|
244
|
+
# it with Manager.instance.load properly.
|
245
|
+
def resource(gem_name, path)
|
246
|
+
if not loaded? gem_name
|
247
|
+
raise PluginNotLoaded.new("Plugin #{gem_name} not loaded when getting resource #{path}")
|
248
|
+
end
|
249
|
+
|
250
|
+
file = File.join(@gems[gem_name], "resources", path)
|
251
|
+
|
252
|
+
if File.exist? file
|
253
|
+
return file
|
254
|
+
else
|
255
|
+
return nil
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
|
260
|
+
# While Manager.resource will find arbitrary resources, a special
|
261
|
+
# case is when you need to load a set of configuration defaults.
|
262
|
+
# GemPlugin normalizes this to be if you have a file "resources/defaults.yaml"
|
263
|
+
# then you'll be able to load them via Manager.config.
|
264
|
+
#
|
265
|
+
# How you use the method is you get the options the user wants set, pass
|
266
|
+
# them to Manager.instance.config, and what you get back is a new Hash
|
267
|
+
# with the user's settings overriding the defaults.
|
268
|
+
#
|
269
|
+
# opts = Manager.instance.config "mygem", :age => 12, :max_load => .9
|
270
|
+
#
|
271
|
+
# In the above case, if defaults had {:age => 14} then it would be
|
272
|
+
# changed to 12.
|
273
|
+
#
|
274
|
+
# This loads the .yaml file on the fly every time, so doing it a
|
275
|
+
# whole lot is very stupid. If you need to make frequent calls to
|
276
|
+
# this, call it once with no options (Manager.instance.config) then
|
277
|
+
# use the returned defaults directly from then on.
|
278
|
+
def config(gem_name, options={})
|
279
|
+
config_file = Manager.instance.resource(gem_name, "/defaults.yaml")
|
280
|
+
if config_file
|
281
|
+
begin
|
282
|
+
defaults = YAML.load_file(config_file)
|
283
|
+
return defaults.merge(options)
|
284
|
+
rescue
|
285
|
+
raise "Error loading config #{config_file} for gem #{gem_name}"
|
286
|
+
end
|
287
|
+
else
|
288
|
+
return options
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
# This base class for plugins really does nothing
|
294
|
+
# more than wire up the new class into the right category.
|
295
|
+
# It is not thread-safe yet but will be soon.
|
296
|
+
class Base
|
297
|
+
|
298
|
+
attr_reader :options
|
299
|
+
|
300
|
+
|
301
|
+
# See Mongrel::Plugin for an explanation.
|
302
|
+
def Base.inherited(klass)
|
303
|
+
name = "/" + klass.to_s.downcase
|
304
|
+
Manager.instance.register(@@category, name, klass)
|
305
|
+
@@category = nil
|
306
|
+
end
|
307
|
+
|
308
|
+
# See Mongrel::Plugin for an explanation.
|
309
|
+
def Base.category=(category)
|
310
|
+
@@category = category
|
311
|
+
end
|
312
|
+
|
313
|
+
def initialize(options = {})
|
314
|
+
@options = options
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# This nifty function works with the GemPlugin::Base to give you
|
319
|
+
# the syntax:
|
320
|
+
#
|
321
|
+
# class MyThing < GemPlugin::Plugin "/things"
|
322
|
+
# ...
|
323
|
+
# end
|
324
|
+
#
|
325
|
+
# What it does is temporarily sets the GemPlugin::Base.category, and then
|
326
|
+
# returns GemPlugin::Base. Since the next immediate thing Ruby does is
|
327
|
+
# use this returned class to create the new class, GemPlugin::Base.inherited
|
328
|
+
# gets called. GemPlugin::Base.inherited then uses the set category, class name,
|
329
|
+
# and class to register the plugin in the right way.
|
330
|
+
def ZergGemPlugin::Plugin(c)
|
331
|
+
Base.category = c
|
332
|
+
Base
|
333
|
+
end
|
334
|
+
end
|
data/lib/zerg/hive.rb
CHANGED
@@ -27,11 +27,12 @@ require 'json-schema'
|
|
27
27
|
require 'fileutils'
|
28
28
|
require 'singleton'
|
29
29
|
require 'highline/import'
|
30
|
+
require_relative 'erbalize'
|
30
31
|
|
31
32
|
module Zerg
|
32
33
|
class Hive
|
33
34
|
include Singleton
|
34
|
-
attr_reader :hive
|
35
|
+
attr_reader :hive, :load_path
|
35
36
|
|
36
37
|
def loaded
|
37
38
|
@loaded || false
|
@@ -42,12 +43,12 @@ module Zerg
|
|
42
43
|
return
|
43
44
|
end
|
44
45
|
|
45
|
-
load_path = (ENV['HIVE_CWD'] == nil) ? File.join("#{Dir.pwd}", ".hive") : File.join("#{ENV['HIVE_CWD']}", ".hive")
|
46
|
-
abort("ERROR: '.hive' not found at #{load_path}. Run 'zerg init', change HIVE_CWD or run zerg from a different path.") unless File.directory?(load_path)
|
46
|
+
@load_path = (ENV['HIVE_CWD'] == nil) ? File.join("#{Dir.pwd}", ".hive") : File.join("#{ENV['HIVE_CWD']}", ".hive")
|
47
|
+
abort("ERROR: '.hive' not found at #{@load_path}. Run 'zerg init', change HIVE_CWD or run zerg from a different path.") unless File.directory?(@load_path)
|
47
48
|
|
48
49
|
# load all .ke files into one big hash
|
49
50
|
@hive = Hash.new
|
50
|
-
Dir.glob(File.join("#{load_path}", "*.ke")) do |ke_file|
|
51
|
+
Dir.glob(File.join("#{@load_path}", "*.ke")) do |ke_file|
|
51
52
|
# do work on files ending in .rb in the desired directory
|
52
53
|
begin
|
53
54
|
ke_file_hash = JSON.parse( IO.read(ke_file) )
|
@@ -82,20 +83,32 @@ module Zerg
|
|
82
83
|
end
|
83
84
|
|
84
85
|
def self.verify
|
85
|
-
|
86
|
-
abort("ERROR: '.hive' not found at #{load_path}. Run 'zerg init', change HIVE_CWD or run zerg from a different path.") unless File.directory?(load_path)
|
86
|
+
instance.load
|
87
87
|
|
88
|
-
Dir.glob(File.join("#{load_path}", "*.ke")) do |ke_file|
|
88
|
+
Dir.glob(File.join("#{instance.load_path}", "*.ke")) do |ke_file|
|
89
89
|
begin
|
90
|
-
ke_file_hash = JSON.parse(
|
90
|
+
ke_file_hash = JSON.parse( File.open(ke_file, 'r').read )
|
91
91
|
|
92
92
|
# verify against schema.
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
# first get the tasks schema piece from the driver
|
94
|
+
pmgr = ZergGemPlugin::Manager.instance
|
95
|
+
pmgr.load
|
96
|
+
abort("ERROR: 'drivertype' is missing from #{ke_file}") unless ke_file_hash["vm"]["driver"]["drivertype"] != nil
|
97
|
+
driver = pmgr.create("/driver/#{ke_file_hash["vm"]["driver"]["drivertype"]}")
|
98
|
+
driver_schema = driver.task_schema
|
99
|
+
|
100
|
+
schema_template = File.open(File.join("#{File.dirname(__FILE__)}", "..", "..", "data", "ke.schema"), 'r').read
|
101
|
+
sources = {
|
102
|
+
:driver_tasks_schema => driver_schema
|
103
|
+
}
|
104
|
+
full_schema = JSON.parse(Erbalize.erbalize_hash(schema_template, sources))
|
105
|
+
|
106
|
+
errors = JSON::Validator.fully_validate(full_schema, ke_file_hash, :errors_as_objects => true)
|
107
|
+
abort("ERROR: #{ke_file} failed validation. Errors: #{errors.ai}") unless errors.empty?
|
97
108
|
rescue JSON::ParserError => err
|
98
109
|
abort("ERROR: Could not parse #{ke_file}. Likely invalid JSON.")
|
110
|
+
rescue ZergGemPlugin::PluginNotLoaded
|
111
|
+
abort("ERROR: driver #{ke_file_hash["vm"]["driver"]["drivertype"]} not found. Did you install the plugin gem?")
|
99
112
|
end
|
100
113
|
end
|
101
114
|
|
@@ -103,18 +116,32 @@ module Zerg
|
|
103
116
|
end
|
104
117
|
|
105
118
|
def self.import(file, force)
|
106
|
-
|
107
|
-
abort("ERROR: '.hive' not found at #{load_path}. Run 'zerg init', change HIVE_CWD or run zerg from a different path.") unless File.directory?(load_path)
|
119
|
+
instance.load
|
108
120
|
abort("ERROR: '#{file}' not found!") unless File.exist?(file)
|
109
|
-
abort("ERROR: '#{File.basename(file)}' already exists in hive!") unless !File.exist?(File.join(load_path, File.basename(file))) || force == true
|
121
|
+
abort("ERROR: '#{File.basename(file)}' already exists in hive!") unless !File.exist?(File.join(instance.load_path, File.basename(file))) || force == true
|
110
122
|
|
111
123
|
# check the file against schema.
|
112
124
|
begin
|
113
|
-
ke_file_hash = JSON.parse( IO.read(file) )
|
114
|
-
errors = JSON::Validator.fully_validate(File.join("#{File.dirname(__FILE__)}", "../../data/ke.schema"), ke_file_hash, :errors_as_objects => true)
|
115
|
-
abort("ERROR: #{file} failed validation. Errors: #{errors.ai}") unless errors.empty?
|
116
125
|
|
117
|
-
|
126
|
+
ke_file_hash = JSON.parse( File.open(file, 'r').read )
|
127
|
+
|
128
|
+
# get the tasks schema piece from the driver
|
129
|
+
pmgr = ZergGemPlugin::Manager.instance
|
130
|
+
pmgr.load
|
131
|
+
abort("ERROR: 'drivertype' is missing from #{ke_file}") unless ke_file_hash["vm"]["driver"]["drivertype"] != nil
|
132
|
+
driver = pmgr.create("/driver/#{ke_file_hash["vm"]["driver"]["drivertype"]}")
|
133
|
+
driver_schema = driver.task_schema
|
134
|
+
|
135
|
+
schema_template = File.open(File.join("#{File.dirname(__FILE__)}", "..", "..", "data", "ke.schema"), 'r').read
|
136
|
+
sources = {
|
137
|
+
:driver_tasks_schema => driver_schema
|
138
|
+
}
|
139
|
+
full_schema = JSON.parse(Erbalize.erbalize_hash(schema_template, sources))
|
140
|
+
|
141
|
+
errors = JSON::Validator.fully_validate(full_schema, ke_file_hash, :errors_as_objects => true)
|
142
|
+
abort("ERROR: #{ke_file} failed validation. Errors: #{errors.ai}") unless errors.empty?
|
143
|
+
|
144
|
+
FileUtils.cp(file, File.join(instance.load_path, File.basename(file)))
|
118
145
|
rescue JSON::ParserError => err
|
119
146
|
abort("ERROR: Could not parse #{file}. Likely invalid JSON.")
|
120
147
|
end
|
@@ -122,12 +149,11 @@ module Zerg
|
|
122
149
|
end
|
123
150
|
|
124
151
|
def self.remove(taskname, force)
|
125
|
-
|
126
|
-
abort("ERROR: '
|
127
|
-
abort("ERROR: '#{taskname}' not found!") unless File.exist?(File.join(load_path, "#{taskname}.ke"))
|
152
|
+
instance.load
|
153
|
+
abort("ERROR: '#{taskname}' not found!") unless File.exist?(File.join(instance.load_path, "#{taskname}.ke"))
|
128
154
|
|
129
155
|
# check the file against schema.
|
130
|
-
taskfile = File.join(load_path, "#{taskname}.ke")
|
156
|
+
taskfile = File.join(instance.load_path, "#{taskname}.ke")
|
131
157
|
|
132
158
|
agreed = true
|
133
159
|
if force != true
|
@@ -136,8 +162,8 @@ module Zerg
|
|
136
162
|
|
137
163
|
abort("Cancelled!") unless agreed == true
|
138
164
|
|
139
|
-
FileUtils.rm_rf(File.join(load_path, "driver", taskname))
|
140
|
-
FileUtils.rm(File.join(load_path, "#{taskname}.ke"))
|
165
|
+
FileUtils.rm_rf(File.join(instance.load_path, "driver", taskname))
|
166
|
+
FileUtils.rm(File.join(instance.load_path, "#{taskname}.ke"))
|
141
167
|
|
142
168
|
puts "SUCCESS!"
|
143
169
|
end
|