zergrush 0.0.2 → 0.0.4
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.
- 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
|