choria-mcorpc-support 2.20.5 → 2.21.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/lib/mcollective.rb +1 -1
  3. data/lib/mcollective/application/facts.rb +8 -0
  4. data/lib/mcollective/application/plugin.rb +19 -7
  5. data/lib/mcollective/applications.rb +2 -1
  6. data/lib/mcollective/ddl/agentddl.rb +17 -11
  7. data/lib/mcollective/ddl/base.rb +34 -20
  8. data/lib/mcollective/ddl/dataddl.rb +5 -5
  9. data/lib/mcollective/ddl/discoveryddl.rb +2 -2
  10. data/lib/mcollective/ddl/validatorddl.rb +1 -1
  11. data/lib/mcollective/pluginpackager/agent_definition.rb +33 -19
  12. data/lib/mcollective/pluginpackager/{puppet_module_packager.rb → forge_packager.rb} +57 -50
  13. data/lib/mcollective/pluginpackager/standard_definition.rb +23 -12
  14. data/lib/mcollective/pluginpackager/templates/{puppet_module → forge}/README.md.erb +1 -1
  15. data/lib/mcollective/pluginpackager/templates/{puppet_module → forge}/data/defaults.yaml.erb +0 -0
  16. data/lib/mcollective/pluginpackager/templates/{puppet_module → forge}/data/plugin.yaml.erb +0 -0
  17. data/lib/mcollective/pluginpackager/templates/{puppet_module → forge}/hiera.yaml.erb +0 -0
  18. data/lib/mcollective/pluginpackager/templates/{puppet_module → forge}/manifests/init.pp.erb +2 -0
  19. data/lib/mcollective/pluginpackager/templates/{puppet_module → forge}/metadata.json.erb +2 -2
  20. data/lib/mcollective/validator.rb +2 -2
  21. data/lib/mcollective/validator/array_validator.rb +1 -1
  22. data/lib/mcollective/validator/ipv4address_validator.rb +5 -7
  23. data/lib/mcollective/validator/ipv6address_validator.rb +5 -7
  24. data/lib/mcollective/validator/shellsafe_validator.rb +1 -1
  25. data/lib/mcollective/validator/typecheck_validator.rb +19 -15
  26. metadata +11 -25
  27. data/lib/mcollective/pluginpackager/debpackage_packager.rb +0 -237
  28. data/lib/mcollective/pluginpackager/modulepackage_packager.rb +0 -127
  29. data/lib/mcollective/pluginpackager/ospackage_packager.rb +0 -59
  30. data/lib/mcollective/pluginpackager/rpmpackage_packager.rb +0 -180
  31. data/lib/mcollective/pluginpackager/templates/debian/Makefile.erb +0 -7
  32. data/lib/mcollective/pluginpackager/templates/debian/changelog.erb +0 -5
  33. data/lib/mcollective/pluginpackager/templates/debian/compat.erb +0 -1
  34. data/lib/mcollective/pluginpackager/templates/debian/control.erb +0 -15
  35. data/lib/mcollective/pluginpackager/templates/debian/copyright.erb +0 -8
  36. data/lib/mcollective/pluginpackager/templates/debian/rules.erb +0 -6
  37. data/lib/mcollective/pluginpackager/templates/module/Modulefile.erb +0 -5
  38. data/lib/mcollective/pluginpackager/templates/module/README.md.erb +0 -37
  39. data/lib/mcollective/pluginpackager/templates/module/_manifest.pp.erb +0 -9
  40. data/lib/mcollective/pluginpackager/templates/redhat/rpm_spec.erb +0 -63
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f2b40e519fe1594ef21f3842e4786bdfbe9359f1
4
- data.tar.gz: ae87678ad14ba3d22805143c59c5558f271286c4
3
+ metadata.gz: c7838c880fe400df6a4ba9cc315b99f8e53cf5ed
4
+ data.tar.gz: eb1af548ab4d9f79abf4accb138d6aa6becbe620
5
5
  SHA512:
6
- metadata.gz: 92c39adc948b47af880815b13597c4205a4e0dcb3058c82d5e2c8e762cc11a15b7ae15028093bf3a04e9f01458bde03e3a91b678b783fbb49875ea93bbc85786
7
- data.tar.gz: e49b19a7e16acec11b619e1492ef6e7f3cadb819bf93ac0759889fa1032e53529e7432404b8a10cbde6e8152204e069372d493bf0c6ff908ce87684bfd3add8b
6
+ metadata.gz: 8e1a3b75838b504abc5e16cd6a4e653ccc70eba34a5c2fb40ac39ff4d764f5960a4535b5e6eace6ab28fc75d839c7b57f9c67613d3886f3d37364ae873878df4
7
+ data.tar.gz: b0dadeac2193e6a043a00e6bc90592485db8bfdf35563787e024457b248c391b7fe5628510af7cb7d3a0ddf455359cf148968c43db0d3cd80b304ea3f97fd9b6
@@ -54,7 +54,7 @@ module MCollective
54
54
  require "mcollective/util"
55
55
  require "mcollective/validator"
56
56
 
57
- VERSION = "2.20.5".freeze
57
+ VERSION = "2.21.1".freeze
58
58
 
59
59
  def self.version
60
60
  VERSION
@@ -12,6 +12,8 @@ class MCollective::Application::Facts
12
12
  def show_single_fact_report(fact, facts, verbose=false)
13
13
  puts("Report for fact: #{fact}\n\n")
14
14
 
15
+ facts = stringify_facts_hash(facts)
16
+
15
17
  field_size = MCollective::Util.field_size(facts.keys)
16
18
  facts.keys.sort.each do |k|
17
19
  printf(" %-#{field_size}s found %d times\n", k, facts[k].size)
@@ -28,6 +30,12 @@ class MCollective::Application::Facts
28
30
  end
29
31
  end
30
32
 
33
+ def stringify_facts_hash(facts)
34
+ res = Hash.new([])
35
+ facts.each { |k, v| res[k.to_s] += v }
36
+ res
37
+ end
38
+
31
39
  def main
32
40
  rpcutil = rpcclient("rpcutil")
33
41
  rpcutil.progress = false
@@ -213,7 +213,7 @@ mco plugin package [options]
213
213
  def load_plugin_ddl(plugin, type)
214
214
  [plugin, "#{plugin}_#{type}"].each do |p|
215
215
  ddl = DDL.new(p, type, false)
216
- if ddl.findddlfile(p, type)
216
+ if ddl.client_activated? && ddl.findddlfile(p, type)
217
217
  ddl.loadddlfile
218
218
  return ddl
219
219
  end
@@ -224,9 +224,14 @@ mco plugin package [options]
224
224
 
225
225
  # Show application list and plugin help
226
226
  def doc_command
227
- known_plugin_types = [["Agents", :agent], ["Aggregate", :aggregate],
228
- ["Connectors", :connector], ["Data Queries", :data],
229
- ["Discovery Methods", :discovery], ["Validator Plugins", :validator]]
227
+ known_plugin_types = [
228
+ ["Agents", :agent],
229
+ ["Aggregate", :aggregate],
230
+ ["Connectors", :connector],
231
+ ["Data Queries", :data],
232
+ ["Discovery Methods", :discovery],
233
+ ["Validator Plugins", :validator]
234
+ ]
230
235
 
231
236
  if configuration.include?(:target) && configuration[:target] != "."
232
237
  if configuration[:target] =~ /^(.+?)\/(.+)$/
@@ -265,7 +270,11 @@ mco plugin package [options]
265
270
 
266
271
  PluginManager.find(plugin_type[1], "ddl").each do |ddl|
267
272
  begin
268
- help = DDL.new(ddl, plugin_type[1])
273
+ help = DDL.new(ddl, plugin_type[1], false)
274
+
275
+ next unless help.client_activated?
276
+
277
+ help.loadddlfile
269
278
  pluginname = ddl.gsub(/_#{plugin_type[1]}$/, "")
270
279
  puts " %-25s %s" % [pluginname, help.meta[:description]]
271
280
  rescue => e
@@ -289,7 +298,7 @@ mco plugin package [options]
289
298
  # Creates the correct package plugin object.
290
299
  def prepare_plugin
291
300
  plugintype = set_plugin_type unless configuration[:plugintype]
292
- configuration[:format] = "puppet_module" unless configuration[:format]
301
+ configuration[:format] = "forge" unless configuration[:format]
293
302
  PluginPackager.load_packagers
294
303
  plugin_class = PluginPackager[configuration[:plugintype]]
295
304
 
@@ -299,7 +308,10 @@ mco plugin package [options]
299
308
  configuration[:dependency].map!{|dep| {:name => dep, :version => nil}}
300
309
  end
301
310
 
302
- mcdependency = {:mcname => configuration[:mcname], :mcversion => configuration[:mcversion]}
311
+ mcdependency = {
312
+ :mcname => configuration[:mcname],
313
+ :mcversion => configuration[:mcversion]
314
+ }
303
315
 
304
316
  # Deprecation warning for --iteration
305
317
  if configuration[:iteration]
@@ -10,7 +10,7 @@ module MCollective
10
10
 
11
11
  begin
12
12
  load_application(appname)
13
- rescue Exception # rubocop:disable Lint/RescueException
13
+ rescue Exception => e # rubocop:disable Lint/RescueException
14
14
  e.backtrace.first << Util.colorize(:red, " <----")
15
15
  STDERR.puts "Application '%s' failed to load:" % appname
16
16
  STDERR.puts
@@ -98,6 +98,7 @@ module MCollective
98
98
 
99
99
  # avoid option parsers own internal version handling that sux
100
100
  parser.on("-v", "--verbose")
101
+ parser.on("--version")
101
102
 
102
103
  if original_extra_opts
103
104
  begin
@@ -37,13 +37,17 @@ module MCollective
37
37
  # aggregate summary(:value)
38
38
  # end
39
39
  # end
40
- class AgentDDL<Base
40
+ class AgentDDL < Base
41
41
  def initialize(plugin, plugintype=:agent, loadddl=true)
42
42
  @process_aggregate_functions = nil
43
43
 
44
44
  super
45
45
  end
46
46
 
47
+ def client_activated?
48
+ Util.str_to_bool(@config.pluginconf.fetch("%s.activate_client" % @pluginname, ACTIVATION_DEFAULT.to_s))
49
+ end
50
+
47
51
  def input(argument, properties)
48
52
  raise "Input needs a :optional property" unless properties.include?(:optional)
49
53
 
@@ -61,18 +65,18 @@ module MCollective
61
65
  def summarize(&block)
62
66
  unless @config.mode == :server
63
67
  @process_aggregate_functions = true
64
- block.call
68
+ yield
65
69
  @process_aggregate_functions = nil
66
70
  end
67
71
  end
68
72
 
69
73
  # Sets the aggregate array for the given action
70
- def aggregate(function, format = {:format => nil})
74
+ def aggregate(function, format={:format => nil})
71
75
  raise(DDLValidationError, "Formats supplied to aggregation functions should be a hash") unless format.is_a?(Hash)
72
76
  raise(DDLValidationError, "Formats supplied to aggregation functions must have a :format key") unless format.keys.include?(:format)
73
77
  raise(DDLValidationError, "Functions supplied to aggregate should be a hash") unless function.is_a?(Hash)
74
78
 
75
- unless (function.keys.include?(:args)) && function[:args]
79
+ unless function.keys.include?(:args) && function[:args]
76
80
  raise DDLValidationError, "aggregate method for action '%s' missing a function parameter" % entities[@current_entity][:action]
77
81
  end
78
82
 
@@ -129,7 +133,7 @@ module MCollective
129
133
  # we set @current_entity so the input block can know what its talking
130
134
  # to, this is probably an epic hack, need to improve.
131
135
  @current_entity = name
132
- block.call if block_given?
136
+ yield if block_given?
133
137
  @current_entity = nil
134
138
  end
135
139
 
@@ -137,11 +141,13 @@ module MCollective
137
141
  # with args as a hash. This will only be active if the @process_aggregate_functions
138
142
  # is set to true which only happens in the #summarize block
139
143
  def method_missing(name, *args, &block)
140
- unless @process_aggregate_functions || is_function?(name)
141
- raise NoMethodError, "undefined local variable or method `#{name}'", caller
142
- end
144
+ super unless @process_aggregate_functions || is_function?(name)
145
+
146
+ {:function => name, :args => args}
147
+ end
143
148
 
144
- return {:function => name, :args => args}
149
+ def respond_to_missing?(method, *)
150
+ @process_aggregate_functions || is_function?(name) || super
145
151
  end
146
152
 
147
153
  # Checks if a method name matches a aggregate plugin.
@@ -165,7 +171,7 @@ module MCollective
165
171
 
166
172
  return unless input
167
173
 
168
- input.keys.each do |key|
174
+ input.each_key do |key|
169
175
  if key.is_a?(Symbol) && arguments.include?(key.to_s) && !input.include?(key.to_s)
170
176
  compat_arg = key.to_s
171
177
  else
@@ -224,7 +230,7 @@ module MCollective
224
230
  input = action_interface(action)[:input] || {}
225
231
  compatible_args = symbolize_basic_input_arguments(input, arguments)
226
232
 
227
- input.keys.each do |key|
233
+ input.each_key do |key|
228
234
  unless input[key][:optional]
229
235
  unless compatible_args.include?(key)
230
236
  raise DDLValidationError, "Action #{action} needs a #{key} argument"
@@ -19,6 +19,8 @@ module MCollective
19
19
  class Base
20
20
  attr_reader :meta, :entities, :pluginname, :plugintype, :usage, :requirements
21
21
 
22
+ ACTIVATION_DEFAULT = true
23
+
22
24
  def initialize(plugin, plugintype=:agent, loadddl=true)
23
25
  @entities = {}
24
26
  @meta = {}
@@ -40,7 +42,7 @@ module MCollective
40
42
  # the config dir and if that does not exist, default to
41
43
  # /etc/mcollective
42
44
  def help(template=nil)
43
- template = template_for_plugintype unless template
45
+ template ||= template_for_plugintype
44
46
  template = Util.templatepath(template) unless Util.absolute_path?(template)
45
47
 
46
48
  template = File.read(template)
@@ -50,14 +52,15 @@ module MCollective
50
52
  unless template == "metadata-help.erb"
51
53
  metadata_template = Util.templatepath("metadata-help.erb")
52
54
  metadata_template = File.read(metadata_template)
53
- metastring = ERB.new(metadata_template, 0, '%')
55
+ metastring = ERB.new(metadata_template, 0, "%")
54
56
  metastring = metastring.result(binding)
55
57
  end
56
58
 
57
- erb = ERB.new(template, 0, '%')
59
+ erb = ERB.new(template, 0, "%")
58
60
  erb.result(binding)
59
61
  end
60
62
 
63
+ # rubocop:disable Lint/DuplicateMethods, Style/TrivialAccessors
61
64
  def usage(usage_text)
62
65
  @usage = usage_text
63
66
  end
@@ -65,18 +68,22 @@ module MCollective
65
68
  def template_for_plugintype
66
69
  case @plugintype
67
70
  when :agent
68
- return "rpc-help.erb"
71
+ "rpc-help.erb"
69
72
  else
70
- if File.exists?(Util.templatepath("#{@plugintype}-help.erb"))
71
- return "#{@plugintype}-help.erb"
73
+ if File.exist?(Util.templatepath("#{@plugintype}-help.erb"))
74
+ "#{@plugintype}-help.erb"
72
75
  else
73
76
  # Default help template gets loaded if plugintype-help does not exist.
74
- return "metadata-help.erb"
77
+ "metadata-help.erb"
75
78
  end
76
79
  end
77
80
  end
78
81
 
79
82
  def loadddlfile
83
+ if @config.mode == :client && !client_activated?
84
+ raise("%s/%s is disabled, cannot load DDL file" % [@plugintype, @pluginname])
85
+ end
86
+
80
87
  if ddlfile = findddlfile
81
88
  instance_eval(File.read(ddlfile), ddlfile, 1)
82
89
  else
@@ -85,8 +92,8 @@ module MCollective
85
92
  end
86
93
 
87
94
  def findddlfile(ddlname=nil, ddltype=nil)
88
- ddlname = @pluginname unless ddlname
89
- ddltype = @plugintype unless ddltype
95
+ ddlname ||= @pluginname
96
+ ddltype ||= @plugintype
90
97
 
91
98
  @config.libdir.each do |libdir|
92
99
  ddlfile = File.join([libdir, "mcollective", ddltype.to_s, "#{ddlname}.ddl"])
@@ -95,7 +102,12 @@ module MCollective
95
102
  return ddlfile
96
103
  end
97
104
  end
98
- return false
105
+
106
+ false
107
+ end
108
+
109
+ def client_activated?
110
+ ACTIVATION_DEFAULT
99
111
  end
100
112
 
101
113
  def validate_requirements
@@ -137,7 +149,7 @@ module MCollective
137
149
 
138
150
  return true
139
151
  rescue => e
140
- raise DDLValidationError, "Cannot validate input %s: %s" % [key, e.to_s]
152
+ raise DDLValidationError, "Cannot validate input %s: %s" % [key, e.to_s], e.backtrace
141
153
  end
142
154
 
143
155
  # Registers an input argument for a given action
@@ -159,17 +171,17 @@ module MCollective
159
171
  :optional => properties[:optional]}
160
172
 
161
173
  case properties[:type]
162
- when :string
163
- raise "Input type :string needs a :validation argument" unless properties.include?(:validation)
164
- raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength)
174
+ when :string
175
+ raise "Input type :string needs a :validation argument" unless properties.include?(:validation)
176
+ raise "Input type :string needs a :maxlength argument" unless properties.include?(:maxlength)
165
177
 
166
- @entities[entity][:input][argument][:validation] = properties[:validation]
167
- @entities[entity][:input][argument][:maxlength] = properties[:maxlength]
178
+ @entities[entity][:input][argument][:validation] = properties[:validation]
179
+ @entities[entity][:input][argument][:maxlength] = properties[:maxlength]
168
180
 
169
- when :list
170
- raise "Input type :list needs a :list argument" unless properties.include?(:list)
181
+ when :list
182
+ raise "Input type :list needs a :list argument" unless properties.include?(:list)
171
183
 
172
- @entities[entity][:input][argument][:list] = properties[:list]
184
+ @entities[entity][:input][argument][:list] = properties[:list]
173
185
  end
174
186
  end
175
187
 
@@ -186,6 +198,8 @@ module MCollective
186
198
  @entities[action][:output][argument] = {:description => properties[:description],
187
199
  :display_as => properties[:display_as],
188
200
  :default => properties[:default]}
201
+
202
+ @entities[action][:output][argument][:type] = properties[:type] if properties[:type]
189
203
  end
190
204
 
191
205
  def requires(requirement)
@@ -193,7 +207,7 @@ module MCollective
193
207
 
194
208
  valid_requirements = [:mcollective]
195
209
 
196
- requirement.keys.each do |key|
210
+ requirement.each_key do |key|
197
211
  unless valid_requirements.include?(key)
198
212
  raise "Requirement %s is not a valid requirement, only %s is supported" % [key, valid_requirements.join(", ")]
199
213
  end
@@ -27,17 +27,17 @@ module MCollective
27
27
  # :display_as => item.to_s.capitalize
28
28
  # end
29
29
  # end
30
- class DataDDL<Base
30
+ class DataDDL < Base
31
31
  def dataquery(input, &block)
32
32
  raise "Data queries need a :description" unless input.include?(:description)
33
33
  raise "Data queries can only have one definition" if @entities[:data]
34
34
 
35
- @entities[:data] = {:description => input[:description],
36
- :input => {},
37
- :output => {}}
35
+ @entities[:data] = {:description => input[:description],
36
+ :input => {},
37
+ :output => {}}
38
38
 
39
39
  @current_entity = :data
40
- block.call if block_given?
40
+ yield if block_given?
41
41
  @current_entity = nil
42
42
  end
43
43
 
@@ -13,7 +13,7 @@ module MCollective
13
13
  # discovery do
14
14
  # capabilities [:classes, :facts, :identity, :agents, :compound]
15
15
  # end
16
- class DiscoveryDDL<Base
16
+ class DiscoveryDDL < Base
17
17
  def discovery_interface
18
18
  @entities[:discovery]
19
19
  end
@@ -44,7 +44,7 @@ module MCollective
44
44
  @entities[:discovery] = {:capabilities => []}
45
45
 
46
46
  @current_entity = :discovery
47
- block.call if block_given?
47
+ yield if block_given?
48
48
  @current_entity = nil
49
49
  end
50
50
  end
@@ -1,6 +1,6 @@
1
1
  module MCollective
2
2
  module DDL
3
- class ValidatorDDL<Base
3
+ class ValidatorDDL < Base
4
4
  end
5
5
  end
6
6
  end
@@ -12,15 +12,17 @@ module MCollective
12
12
  @revision = configuration[:revision] || 1
13
13
  @preinstall = configuration[:preinstall]
14
14
  @postinstall = configuration[:postinstall]
15
- @vendor = configuration[:vendor] || "Puppet Labs"
15
+ @vendor = configuration[:vendor] || "Choria.IO User"
16
16
  @dependencies = configuration[:dependency] || []
17
17
  @target_path = File.expand_path(@path)
18
18
  @metadata, mcversion = PluginPackager.get_metadata(@path, "agent")
19
- @mcname = mcdependency[:mcname] || "mcollective"
19
+ @mcname = mcdependency[:mcname] || "mcollective"
20
20
  @mcversion = mcdependency[:mcversion] || mcversion
21
21
  @metadata[:version] = (configuration[:version] || @metadata[:version])
22
22
  @dependencies << {:name => "#{@mcname}-common", :version => @mcversion}
23
+ @agent_name = @metadata[:name].downcase
23
24
  @metadata[:name] = (configuration[:pluginname] || @metadata[:name]).downcase.gsub(/\s+|_/, "-")
25
+
24
26
  identify_packages
25
27
  end
26
28
 
@@ -36,27 +38,35 @@ module MCollective
36
38
 
37
39
  # Obtain Agent package files and dependencies.
38
40
  def agent
39
- agent = {:files => [],
40
- :dependencies => @dependencies.clone,
41
- :description => "Agent plugin for #{@metadata[:name]}"}
41
+ agent = {
42
+ :files => [],
43
+ :executable_files => [],
44
+ :dependencies => @dependencies.clone,
45
+ :description => "Agent plugin for #{@metadata[:name]}"
46
+ }
42
47
 
43
48
  agentdir = File.join(@path, "agent")
44
49
 
45
- if (PluginPackager.check_dir_present(agentdir))
46
- ddls = Dir.glob(File.join(agentdir, "*.ddl"))
47
- agent[:files] = (Dir.glob(File.join(agentdir, "**", "**")) - ddls)
48
- else
49
- return nil
50
- end
50
+ return nil unless PluginPackager.check_dir_present(agentdir)
51
+
52
+ ddls = Dir.glob(File.join(agentdir, "*.{ddl,json}"))
53
+ agent[:files] = (Dir.glob(File.join(agentdir, "**", "**")) - ddls)
51
54
  agent[:plugindependency] = {:name => "#{@mcname}-#{@metadata[:name]}-common", :version => @metadata[:version], :revision => @revision}
55
+
56
+ if @metadata[:provider] == "external"
57
+ agent[:executable_files] << File.join(agentdir, @agent_name)
58
+ end
59
+
52
60
  agent
53
61
  end
54
62
 
55
63
  # Obtain client package files and dependencies.
56
64
  def client
57
- client = {:files => [],
58
- :dependencies => @dependencies.clone,
59
- :description => "Client plugin for #{@metadata[:name]}"}
65
+ client = {
66
+ :files => [],
67
+ :dependencies => @dependencies.clone,
68
+ :description => "Client plugin for #{@metadata[:name]}"
69
+ }
60
70
 
61
71
  clientdir = File.join(@path, "application")
62
72
  aggregatedir = File.join(@path, "aggregate")
@@ -69,13 +79,15 @@ module MCollective
69
79
 
70
80
  # Obtain common package files and dependencies.
71
81
  def common
72
- common = {:files =>[],
73
- :dependencies => @dependencies.clone,
74
- :description => "Common libraries for #{@metadata[:name]}"}
82
+ common = {
83
+ :files => [],
84
+ :dependencies => @dependencies.clone,
85
+ :description => "Common libraries for #{@metadata[:name]}"
86
+ }
75
87
 
76
88
  datadir = File.join(@path, "data", "**")
77
89
  utildir = File.join(@path, "util", "**", "**")
78
- ddldir = File.join(@path, "agent", "*.ddl")
90
+ ddldir = File.join(@path, "agent", "*.{ddl,json}")
79
91
  validatordir = File.join(@path, "validator", "**")
80
92
 
81
93
  [datadir, utildir, validatordir, ddldir].each do |directory|
@@ -84,9 +96,11 @@ module MCollective
84
96
 
85
97
  # We fail if there is no ddl file present
86
98
  if common[:files].grep(/^.*\.ddl$/).empty?
87
- raise "cannot create package - No ddl file found in #{File.join(@path, "agent")}"
99
+ raise "cannot create package - No ddl file found in #{File.join(@path, 'agent')}"
88
100
  end
89
101
 
102
+ common[:files].uniq!
103
+
90
104
  common[:files].empty? ? nil : common
91
105
  end
92
106
  end