kafo 0.7.6 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 35bc59bbfe6e1ff266439493be2e8c8342c6a2d9
4
- data.tar.gz: e3dd61d73c8799f13d66f5774c03d3b84d7a7196
3
+ metadata.gz: 6bce70ac2eb5590a3268fc61fa1d5b26eec0a231
4
+ data.tar.gz: 6c68b15f3208c75fd702601f5059c355d3e98383
5
5
  SHA512:
6
- metadata.gz: 7f4247cd5325ec3c2b78008e92f9cc3e6b149f04a44280e619f8025b688387766a18228652acc47588a14e69652f3d3fdd072ec18d820f505ea963920e6647bc
7
- data.tar.gz: 14109f9b4d7de650e88c601ea1b247b4eb85979b1445d39740fa80d023e75d764e844c73cd11fdba5c32301490c51615f96952f2d16688a3e9bfbeba3dd917eb
6
+ metadata.gz: a749d272c84c6a4ff863c9c67438e3f1e046b5949d4e4c491032d533d05fabe5f31c52e672bccd6d3c444bf056ca636894c878fcaf9dc0c745161a039a34f17a
7
+ data.tar.gz: 54587849902f34872edc974a28fa11a63adb20f5000dd7086b534d325681fb1af69b0fef0eaf11d7116a81496826d20240b6f8746a7e623fb5aa4c188f3fb256
data/README.md CHANGED
@@ -190,6 +190,25 @@ disable saving answer by passing a ```--dont-save-answers``` argument (or -d for
190
190
 
191
191
  Note that running ```--noop``` implies ```--dont-save-answers```.
192
192
 
193
+ ## Executing Puppet with multiple versions
194
+
195
+ Kafo calls the `puppet` binary during an installer run to both compute default
196
+ parameter values and perform the actual installer changes. This relies on
197
+ `puppet` being in the PATH environment variable or as fallback, in
198
+ `/opt/puppetlabs/bin`.
199
+
200
+ When using Puppet via a Gemfile, Bundler should set up PATH to point at the
201
+ gem version. If using a system/packaged version, it will typically find and
202
+ execute /usr/bin/puppet from the regular PATH.
203
+
204
+ When using an AIO/PC1 packaged version of Puppet, other versions of Puppet from
205
+ PATH will be preferred if they exist, so they should either be removed or PATH
206
+ set to prefer /opt/puppetlabs/bin, i.e. `export PATH=/opt/puppetlabs/bin:$PATH`.
207
+ Debug logs from Kafo should indicate the full path of the binary used.
208
+
209
+ Note that Kafo parsers supports specific versions of Puppet, and may require
210
+ extra modules (such as puppet-strings on Puppet 4+) to parse manifests.
211
+
193
212
  ## Parameters prefixes
194
213
 
195
214
  As a default every module parameter is prefixed by the module name.
@@ -317,6 +336,13 @@ Sample migration adding new module could look like as follows:
317
336
  EOF
318
337
  ```
319
338
 
339
+ The migration can also call `facts`, which returns a hash of symbol fact names to values (from
340
+ Facter), to help determine new parameter values.
341
+
342
+ ```ruby
343
+ answers['module']['foo'] = 'bar' if facts[:osfamily] == 'Debian'
344
+ ```
345
+
320
346
  ### Enabling/disabling scenarios
321
347
 
322
348
  Scenarios that are deprecated or wanted to be hidden on the system can be disabled with:
@@ -631,11 +657,13 @@ If you use "params_path" for this purpose, "params_name" is ignored.
631
657
  ## Validations
632
658
 
633
659
  If you specify validations of parameters in your init.pp manifest they
634
- will be replaced with your values even before puppet is run. In order to do this
660
+ will be replaced with your values even before Puppet is run. In order to do this
635
661
  you must follow a few rules however:
636
662
 
637
663
  * you must use standard validation functions (e.g. validate_array, validate_re, ...)
638
- * you must have stdlib in modules directory
664
+
665
+ These functions are re-implemented in Kafo from common stdlib functions, so please
666
+ contribute any missing ones.
639
667
 
640
668
  ## Enabling or disabling module
641
669
 
@@ -85,7 +85,7 @@ module Kafo
85
85
  end
86
86
 
87
87
  def modules
88
- @modules ||= @data.keys.map { |mod| PuppetModule.new(mod, KafoParsers::PuppetModuleParser, self).parse }.sort
88
+ @modules ||= @data.keys.map { |mod| PuppetModule.new(mod, PuppetModule.find_parser, self).parse }.sort
89
89
  end
90
90
 
91
91
  def root_dir
@@ -109,7 +109,7 @@ module Kafo
109
109
  end
110
110
 
111
111
  def add_module(name)
112
- mod = PuppetModule.new(name, KafoParsers::PuppetModuleParser, self).parse
112
+ mod = PuppetModule.new(name, PuppetModule.find_parser, self).parse
113
113
  unless modules.map(&:name).include?(mod.name)
114
114
  mod.enable
115
115
  @modules << mod
@@ -233,16 +233,8 @@ module Kafo
233
233
  File.join(app[:log_dir], app[:log_name])
234
234
  end
235
235
 
236
- def log_files_pattern
237
- log_file.sub(/(\.log)\Z/i) { |suffix| "{.[0-9]*,}#{suffix}" }
238
- end
239
-
240
- def log_files
241
- Dir.glob(log_files_pattern)
242
- end
243
-
244
236
  def log_exists?
245
- log_files.any? { |f| File.size(f) > 0 }
237
+ File.exists?(log_file) && File.size(log_file) > 0
246
238
  end
247
239
 
248
240
  def answers
@@ -259,7 +251,6 @@ module Kafo
259
251
  migrations.store_applied
260
252
  @logger.info("#{migrations.migrations.count} migration/s were applied. Updated configuration was saved.")
261
253
  end
262
- migrations.migrations.count
263
254
  end
264
255
 
265
256
  def migrations_dir
@@ -6,6 +6,9 @@ module Kafo
6
6
  class ConditionError < StandardError
7
7
  end
8
8
 
9
+ class ParserError < StandardError
10
+ end
11
+
9
12
  class TypeError < StandardError
10
13
  end
11
14
  end
@@ -57,9 +57,9 @@ module Kafo
57
57
  setup_config(config_file)
58
58
 
59
59
  self.class.hooking.execute(:pre_migrations)
60
- reload_config
61
- applied_total = self.class.config.run_migrations
62
- request_config_reload if applied_total > 0
60
+
61
+ # run migrations
62
+ self.class.config.run_migrations
63
63
 
64
64
  if ARGV.include?('--migrations-only')
65
65
  self.class.verbose = (ARGV.include?('--verbose') || ARGV.include?('-v'))
@@ -68,7 +68,13 @@ module Kafo
68
68
  self.class.exit(0)
69
69
  end
70
70
 
71
- reload_config
71
+ # reload config
72
+ if @config_reload_requested
73
+ scenario_manager = setup_scenario_manager
74
+ self.class.scenario_manager = scenario_manager
75
+ setup_config(self.class.config_file)
76
+ self.class.logger.info('Installer configuration was reloaded')
77
+ end
72
78
 
73
79
  if scenario_manager.configured?
74
80
  scenario_manager.check_scenario_change(self.class.config_file)
@@ -235,16 +241,6 @@ module Kafo
235
241
  self.class.hooking.kafo = self
236
242
  end
237
243
 
238
- def reload_config
239
- if @config_reload_requested
240
- scenario_manager = setup_scenario_manager
241
- self.class.scenario_manager = scenario_manager
242
- setup_config(self.class.config_file)
243
- self.class.logger.info('Installer configuration was reloaded')
244
- @config_reload_requested = false
245
- end
246
- end
247
-
248
244
  def setup_scenario_manager
249
245
  ScenarioManager.new((defined?(CONFIG_DIR) && CONFIG_DIR) || (defined?(CONFIG_FILE) && CONFIG_FILE))
250
246
  end
data/lib/kafo/logger.rb CHANGED
@@ -105,7 +105,7 @@ module Kafo
105
105
 
106
106
  def self.dump_buffer(buffer)
107
107
  buffer.each do |log|
108
- self.loggers.each { |logger| logger.send log[0], *([log[1]].flatten(1)), &log[2] }
108
+ self.loggers.each { |logger| logger.send log[0], *log[1], &log[2] }
109
109
  end
110
110
  buffer.clear
111
111
  end
@@ -17,5 +17,21 @@ module Kafo
17
17
  def logger
18
18
  KafoConfigure.logger
19
19
  end
20
+
21
+ def facts
22
+ self.class.facts
23
+ end
24
+
25
+ private
26
+
27
+ def self.facts
28
+ @facts ||= begin
29
+ YAML.load(`#{facter_path} --yaml`).inject({}) { |facts,(k,v)| facts.update(k.to_sym => v) }
30
+ end
31
+ end
32
+
33
+ def self.facter_path
34
+ @facter_path ||= PuppetCommand.search_puppet_path('facter')
35
+ end
20
36
  end
21
37
  end
data/lib/kafo/param.rb CHANGED
@@ -73,24 +73,20 @@ module Kafo
73
73
  end
74
74
 
75
75
  def valid?
76
- validations = self.module.validations(self)
77
76
  # we get validations that can also run on other arguments, we need to take only current param
78
77
  # also we want to clone validations so we don't interfere
79
- validations.map! do |v|
80
- v = v.clone
81
- if v.name == 'validate_re'
82
- # validate_re does not take more variables as arguments, instead we need to pass all arguments
83
- args = v.arguments
78
+ validations = self.module.validations(self).map do |v|
79
+ # These functions do not take more variables as arguments, instead we need to pass all arguments
80
+ if v.name == 'validate_re' || v.name == 'validate_integer'
81
+ args = v.arguments.to_a
84
82
  else
85
83
  args = v.arguments.select { |a| a.to_s == "$#{self.name}" }
86
84
  end
87
- v.arguments = Puppet::Parser::AST::ASTArray.new :children => args
88
- v
85
+ {:name => v.name, :arguments => interpret_validation_args(args)}
89
86
  end
90
87
 
91
- validator = Validator.new([self])
92
- validations.map! { |v| v.evaluate(validator) }
93
- validations.all?
88
+ validator = Validator.new
89
+ validations.all? { |v| validator.send(v[:name], v[:arguments]) }
94
90
  end
95
91
 
96
92
  # To be overwritten in children
@@ -119,6 +115,24 @@ module Kafo
119
115
  def evaluate_condition(context = [])
120
116
  Condition.new(condition, context).evaluate
121
117
  end
118
+
119
+ def interpret_validation_args(args)
120
+ args.map do |arg|
121
+ if arg.to_s == "$#{self.name}"
122
+ self.value
123
+ elsif arg.class.name == 'Puppet::Parser::AST::ASTArray'
124
+ interpret_validation_args(arg.to_a)
125
+ elsif arg.class.name == 'Puppet::Parser::AST::Concat'
126
+ interpret_validation_args(arg.value).join
127
+ elsif arg.respond_to? :value
128
+ arg.value
129
+ else
130
+ arg
131
+ end
132
+ end.map do |arg|
133
+ arg == :undef ? nil : arg
134
+ end
135
+ end
122
136
  end
123
137
  end
124
138
 
@@ -13,6 +13,7 @@ module Kafo
13
13
  @lines = 0
14
14
  @all_lines = 0
15
15
  @total = :unknown
16
+ @term_width = HighLine::SystemExtensions.terminal_size[0]
16
17
  @bar = PowerBar.new
17
18
  @bar.settings.tty.infinite.template.main = infinite_template
18
19
  @bar.settings.tty.finite.template.main = finite_template
@@ -5,7 +5,8 @@ module Kafo
5
5
  private
6
6
 
7
7
  def finite_template
8
- 'Installing'.ljust(22) + ' ${<msg>} [${<percent>%}] [${<bar>}]'
8
+ 'Installing'.ljust(22) + ' ${<msg>} [${<percent>%}]' +
9
+ (@term_width >= 83 ? ' [${<bar>}]' : '')
9
10
  end
10
11
 
11
12
  def infinite_template
@@ -16,7 +16,7 @@ module Kafo
16
16
  'Installing'.ljust(22) +
17
17
  ANSI::Code.yellow { ' ${<msg>}' } +
18
18
  ANSI::Code.green { ' [${<percent>%}]' } +
19
- ' [${<bar>}]'
19
+ (@term_width >= 83 ? ' [${<bar>}]' : '')
20
20
  end
21
21
 
22
22
  def infinite_template
@@ -25,7 +25,7 @@ module Kafo
25
25
  "echo '$kafo_config_file=\"#{@configuration.config_file}\" #{custom_answer_file} #{add_progress} #{@command}'",
26
26
  '|',
27
27
  "RUBYLIB=#{["#{@configuration.gem_root}/modules", ::ENV['RUBYLIB']].join(File::PATH_SEPARATOR)}",
28
- "puppet apply #{@options.join(' ')} #{@suffix}",
28
+ "#{puppet_path} apply #{@options.join(' ')} #{@suffix}",
29
29
  ].join(' ')
30
30
  @logger.debug result
31
31
  result
@@ -36,6 +36,13 @@ module Kafo
36
36
  self
37
37
  end
38
38
 
39
+ def self.search_puppet_path(bin_name)
40
+ bin_path = (::ENV['PATH'].split(File::PATH_SEPARATOR) + ['/opt/puppetlabs/bin']).find do |path|
41
+ File.executable?(File.join(path, bin_name))
42
+ end
43
+ File.join([bin_path, bin_name].compact)
44
+ end
45
+
39
46
  private
40
47
 
41
48
  def modules_path
@@ -44,5 +51,9 @@ module Kafo
44
51
  @configuration.kafo_modules_dir,
45
52
  ].flatten.join(':')
46
53
  end
54
+
55
+ def puppet_path
56
+ @puppet_path ||= self.class.search_puppet_path('puppet')
57
+ end
47
58
  end
48
59
  end
@@ -2,7 +2,7 @@
2
2
  require 'kafo/param'
3
3
  require 'kafo/param_builder'
4
4
  require 'kafo/parser_cache_reader'
5
- require 'kafo_parsers/puppet_module_parser'
5
+ require 'kafo_parsers/parsers'
6
6
  require 'kafo/validator'
7
7
 
8
8
  module Kafo
@@ -12,7 +12,21 @@ module Kafo
12
12
  attr_reader :name, :identifier, :params, :dir_name, :class_name, :manifest_name, :manifest_path,
13
13
  :groups, :params_path, :params_class_name, :configuration, :raw_data
14
14
 
15
- def initialize(identifier, parser = KafoParsers::PuppetModuleParser, configuration = KafoConfigure.config)
15
+ def self.find_parser
16
+ @parser ||= begin
17
+ logger = KafoConfigure.logger
18
+ parser = KafoParsers::Parsers.find_available(:logger => logger)
19
+ if parser
20
+ logger.debug "Using Puppet module parser #{parser}"
21
+ parser
22
+ else
23
+ logger.debug "No available Puppet module parser found"
24
+ :none # prevent continually re-checking
25
+ end
26
+ end
27
+ end
28
+
29
+ def initialize(identifier, parser = self.class.find_parser, configuration = KafoConfigure.config)
16
30
  @identifier = identifier
17
31
  @configuration = configuration
18
32
  @name = get_name
@@ -49,9 +63,15 @@ module Kafo
49
63
  end
50
64
 
51
65
  def parse(builder_klass = ParamBuilder)
52
- @params = []
53
- @raw_data = @parser_cache.get(identifier, manifest_path) if @parser_cache
54
- @raw_data ||= @parser.parse(manifest_path)
66
+ @raw_data = @parser_cache.get(identifier, manifest_path) if @parser_cache
67
+ if @raw_data.nil?
68
+ if @parser.nil? || @parser == :none
69
+ raise ParserError.new("No Puppet module parser is installed and no cache of the file #{manifest_path} is available. Please check debug logs and install optional dependencies for the parser.")
70
+ else
71
+ @raw_data = @parser.parse(manifest_path)
72
+ end
73
+ end
74
+
55
75
  builder = builder_klass.new(self, @raw_data)
56
76
  @validations = @raw_data[:validations]
57
77
 
@@ -91,13 +91,10 @@ module Kafo
91
91
  (available_scenarios.keys.count == 1 && available_scenarios.keys.first) ||
92
92
  select_scenario_interactively
93
93
  if scenario.nil?
94
- fail_now("No installation scenario was selected, the installer can not continue.\n" +
95
- " Even --help content is dependent on selected scenario.\n" +
96
- " Select scenario with --scenario SCENARIO or list available scenarios with --list-scenarios.", :unknown_scenario)
94
+ fail_now("Scenario was not selected, can not continue. Use --list-scenarios to list available options.", :unknown_scenario)
97
95
  elsif !scenario_enabled?(scenario)
98
- fail_now("Selected scenario is DISABLED, can not continue.\n" +
99
- " Use --list-scenarios to list available options.\n" +
100
- " You can also --enable-scenario SCENARIO to make the selected scenario available.", :scenario_error)
96
+ fail_now("Selected scenario is DISABLED, can not continue. Use --list-scenarios to list available options." \
97
+ " You can also --enable-scenario SCENARIO to make the selected scenario available.", :scenario_error)
101
98
  end
102
99
  scenario
103
100
  end
@@ -2,79 +2,112 @@
2
2
  module Kafo
3
3
  class Validator
4
4
 
5
- def self.prepare_functions
6
- return true if @reset || !Puppet::Parser::Functions.respond_to?(:reset)
7
- Puppet::Parser::Functions.reset
8
- @reset = true
5
+ def initialize
6
+ @logger = KafoConfigure.logger
9
7
  end
10
8
 
11
- def initialize(params)
12
- self.class.prepare_functions
13
- definitions = KafoConfigure.module_dirs.map do |dir|
14
- validate_files = dir + '/*/lib/puppet/parser/functions/validate_*.rb'
15
- is_function_files = dir + '/*/lib/puppet/parser/functions/is_*.rb'
16
- Dir.glob(validate_files) + Dir.glob(is_function_files)
17
- end.flatten
18
-
19
- definitions.each do |file|
20
- require File.expand_path(file)
9
+ def validate_absolute_path(args)
10
+ args.each do |arg|
11
+ unless arg.to_s.start_with?('/')
12
+ @logger.error "#{arg.inspect} is not an absolute path."
13
+ return false
14
+ end
21
15
  end
16
+ return true
17
+ end
22
18
 
23
- @params = params
24
- @logger = KafoConfigure.logger
19
+ def validate_array(args)
20
+ args.each do |arg|
21
+ unless arg.is_a?(Array)
22
+ @logger.error "#{arg.inspect} is not a valid array."
23
+ return false
24
+ end
25
+ end
26
+ return true
27
+ end
25
28
 
26
- @cache ||= Hash.new do |hash, key|
27
- @logger.debug "Looked for #{key}"
28
- param = @params.select { |p| p.name == key.to_s }.first
29
- hash[key] = param.nil? ? nil : param.value
29
+ def validate_bool(args)
30
+ args.each do |arg|
31
+ unless arg.is_a?(TrueClass) || arg.is_a?(FalseClass)
32
+ @logger.error "#{arg.inspect} is not a valid boolean."
33
+ return false
34
+ end
30
35
  end
36
+ return true
31
37
  end
32
38
 
33
- def lookupvar(name, options = {})
34
- @cache[name]
39
+ def validate_hash(args)
40
+ args.each do |arg|
41
+ unless arg.is_a?(Hash)
42
+ @logger.error "#{arg.inspect} is not a valid hash."
43
+ return false
44
+ end
45
+ end
46
+ return true
35
47
  end
36
48
 
37
- # for puppet >= 3
38
- def include?(value)
39
- true
49
+ def validate_integer(args)
50
+ value = args[0]
51
+ max = args[1]
52
+ min = args[2]
53
+ int = Integer(value.to_s)
54
+ if min && int < min.to_i
55
+ @logger.error "#{value} must be at least #{min}."
56
+ return false
57
+ end
58
+ if max && int > max.to_i
59
+ @logger.error "#{value} must be less than #{max}."
60
+ return false
61
+ end
62
+ return true
63
+ rescue TypeError, ArgumentError
64
+ @logger.error "#{value.inspect} is not a valid integer."
65
+ return false
40
66
  end
41
67
 
42
- # for puppet >= 3
43
- def [](value, *args)
44
- lookupvar(value)
68
+ # Non-standard validation is from theforeman/foreman_proxy module
69
+ def validate_listen_on(args)
70
+ valid_values = ['http', 'https', 'both']
71
+ args.each do |arg|
72
+ unless valid_values.include?(arg)
73
+ @logger.error "#{arg.inspect} is not a valid value. Valid values are: #{valid_values.join(", ")}"
74
+ return false
75
+ end
76
+ end
77
+ return true
45
78
  end
46
79
 
47
- def method_missing(method, *args, &block)
48
- method.to_s =~ /^function_(.*)$/
49
- super unless $1
50
- super unless Puppet::Parser::Functions.function($1)
51
- # In odd circumstances, this might not end up defined by the previous
52
- # method, so we might as well be certain.
53
- if engine.respond_to? method
54
- @logger.debug "calling #{method.inspect} with #{args.inspect}"
55
- engine.send(method, *args)
56
- true
80
+ def validate_re(args)
81
+ value = args[0]
82
+ regexes = args[1]
83
+ regexes = [regexes] unless regexes.is_a?(Array)
84
+ message = args[2] || "#{value.inspect} does not match the accepted inputs: #{regexes.join(", ")}"
85
+
86
+ if regexes.any? { |rx| value =~ Regexp.compile(rx) }
87
+ return true
57
88
  else
58
- raise Puppet::DevError, "Function #{$1} not defined despite being loaded!"
89
+ @logger.error message
90
+ return false
59
91
  end
60
- rescue Puppet::ParseError => e
61
- @logger.error e.message
62
- return false
63
92
  end
64
93
 
65
- private
66
-
67
- def engine
68
- @engine ||= begin
69
- klass = Class.new
70
- env = Puppet::PUPPETVERSION.start_with?('2.') ? nil : lookup_current_environment
71
- klass.send :include, Puppet::Parser::Functions.environment_module(env)
72
- klass.new
94
+ def validate_string(args)
95
+ args.each do |arg|
96
+ unless arg.is_a?(String)
97
+ @logger.error "#{arg.inspect} is not a valid string."
98
+ return false
99
+ end
73
100
  end
101
+ return true
74
102
  end
75
103
 
76
- def lookup_current_environment
77
- @current_environment ||= Puppet.respond_to?(:lookup) ? Puppet.lookup(:current_environment) : Puppet::Node::Environment.current
104
+ def method_missing(method, *args, &block)
105
+ if method.to_s.start_with?('validate_')
106
+ @logger.debug "Skipping validation with #{method} as it's not implemented in Kafo"
107
+ return true
108
+ else
109
+ super
110
+ end
78
111
  end
79
112
  end
80
113
  end
data/lib/kafo/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # encoding: UTF-8
2
2
  module Kafo
3
- VERSION = "0.7.6"
3
+ VERSION = "0.8.0"
4
4
  end
@@ -6,7 +6,7 @@ module Puppet::Parser::Functions
6
6
  options<< false if Puppet::PUPPETVERSION.start_with?('2.6')
7
7
  data = args.map do |arg|
8
8
  found_value = lookupvar(arg, *options)
9
- [arg, found_value.nil? ? arg : found_value]
9
+ [arg, found_value]
10
10
  end
11
11
  data = Hash[data]
12
12
 
@@ -9,7 +9,7 @@ module Puppet::Parser::Functions
9
9
  if value.is_a?(Hash)
10
10
  data[key] = function_convert([value])
11
11
  else
12
- data[key] = value.nil? ? :undef : value
12
+ data[key] = value unless value.nil?
13
13
  end
14
14
  end
15
15
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kafo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.6
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Marek Hulan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-20 00:00:00.000000000 Z
11
+ date: 2016-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,14 +114,14 @@ dependencies:
114
114
  requirements:
115
115
  - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: 0.1.0
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
122
  - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: 0.1.0
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: puppet
127
127
  requirement: !ruby/object:Gem::Requirement
@@ -129,7 +129,7 @@ dependencies:
129
129
  - - "<"
130
130
  - !ruby/object:Gem::Version
131
131
  version: 4.0.0
132
- type: :runtime
132
+ type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
@@ -297,9 +297,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
297
297
  version: '0'
298
298
  requirements: []
299
299
  rubyforge_project:
300
- rubygems_version: 2.2.0
300
+ rubygems_version: 2.4.5
301
301
  signing_key:
302
302
  specification_version: 4
303
303
  summary: If you write puppet modules for installing your software, you can use kafo
304
304
  to create powerful installer
305
305
  test_files: []
306
+ has_rdoc: