r10k 3.9.3 → 3.12.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rspec_tests.yml +1 -1
  3. data/.travis.yml +0 -10
  4. data/CHANGELOG.mkd +33 -0
  5. data/README.mkd +6 -0
  6. data/doc/dynamic-environments/configuration.mkd +25 -0
  7. data/doc/dynamic-environments/usage.mkd +26 -0
  8. data/doc/puppetfile.mkd +18 -5
  9. data/integration/Rakefile +3 -1
  10. data/integration/tests/basic_functionality/basic_deployment.rb +176 -0
  11. data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +3 -9
  12. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +21 -25
  13. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +3 -3
  14. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +3 -3
  15. data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +3 -3
  16. data/lib/r10k/action/base.rb +1 -1
  17. data/lib/r10k/action/deploy/deploy_helpers.rb +4 -0
  18. data/lib/r10k/action/deploy/display.rb +1 -1
  19. data/lib/r10k/action/deploy/environment.rb +22 -9
  20. data/lib/r10k/action/deploy/module.rb +41 -11
  21. data/lib/r10k/action/puppetfile/check.rb +7 -5
  22. data/lib/r10k/action/puppetfile/install.rb +22 -16
  23. data/lib/r10k/action/puppetfile/purge.rb +12 -9
  24. data/lib/r10k/action/runner.rb +45 -10
  25. data/lib/r10k/action/visitor.rb +3 -0
  26. data/lib/r10k/cli/deploy.rb +5 -0
  27. data/lib/r10k/cli/puppetfile.rb +0 -1
  28. data/lib/r10k/content_synchronizer.rb +16 -4
  29. data/lib/r10k/environment/base.rb +64 -11
  30. data/lib/r10k/environment/with_modules.rb +6 -10
  31. data/lib/r10k/git/cache.rb +1 -1
  32. data/lib/r10k/git/rugged/credentials.rb +77 -0
  33. data/lib/r10k/git/stateful_repository.rb +8 -0
  34. data/lib/r10k/git.rb +3 -0
  35. data/lib/r10k/initializers.rb +4 -0
  36. data/lib/r10k/module/base.rb +42 -1
  37. data/lib/r10k/module/definition.rb +64 -0
  38. data/lib/r10k/module/forge.rb +16 -3
  39. data/lib/r10k/module/git.rb +23 -1
  40. data/lib/r10k/module/local.rb +6 -3
  41. data/lib/r10k/module/svn.rb +11 -0
  42. data/lib/r10k/module.rb +20 -2
  43. data/lib/r10k/module_loader/puppetfile/dsl.rb +42 -0
  44. data/lib/r10k/module_loader/puppetfile.rb +276 -0
  45. data/lib/r10k/puppetfile.rb +82 -160
  46. data/lib/r10k/settings/definition.rb +1 -1
  47. data/lib/r10k/settings.rb +58 -2
  48. data/lib/r10k/source/base.rb +10 -0
  49. data/lib/r10k/source/git.rb +5 -0
  50. data/lib/r10k/source/svn.rb +4 -0
  51. data/lib/r10k/util/purgeable.rb +74 -8
  52. data/lib/r10k/util/setopts.rb +2 -0
  53. data/lib/r10k/util/subprocess.rb +1 -0
  54. data/lib/r10k/version.rb +1 -1
  55. data/locales/r10k.pot +165 -65
  56. data/r10k.gemspec +2 -0
  57. data/spec/fixtures/unit/action/r10k_forge_auth.yaml +4 -0
  58. data/spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml +3 -0
  59. data/spec/fixtures/unit/puppetfile/forge-override/Puppetfile +8 -0
  60. data/spec/fixtures/unit/puppetfile/various-modules/Puppetfile +10 -0
  61. data/spec/fixtures/unit/puppetfile/various-modules/Puppetfile.new +10 -0
  62. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_subdir_2/ignored_1 +0 -0
  63. data/spec/fixtures/unit/util/purgeable/managed_two/.hidden/unmanaged_3 +0 -0
  64. data/spec/r10k-mocks/mock_env.rb +3 -0
  65. data/spec/r10k-mocks/mock_source.rb +7 -3
  66. data/spec/unit/action/deploy/environment_spec.rb +105 -30
  67. data/spec/unit/action/deploy/module_spec.rb +232 -42
  68. data/spec/unit/action/puppetfile/check_spec.rb +17 -5
  69. data/spec/unit/action/puppetfile/install_spec.rb +42 -36
  70. data/spec/unit/action/puppetfile/purge_spec.rb +15 -17
  71. data/spec/unit/action/runner_spec.rb +122 -26
  72. data/spec/unit/environment/base_spec.rb +30 -17
  73. data/spec/unit/environment/git_spec.rb +2 -2
  74. data/spec/unit/environment/svn_spec.rb +4 -3
  75. data/spec/unit/environment/with_modules_spec.rb +2 -1
  76. data/spec/unit/git/cache_spec.rb +14 -0
  77. data/spec/unit/git/rugged/credentials_spec.rb +29 -0
  78. data/spec/unit/git/stateful_repository_spec.rb +5 -0
  79. data/spec/unit/module/base_spec.rb +54 -8
  80. data/spec/unit/module/forge_spec.rb +59 -5
  81. data/spec/unit/module/git_spec.rb +67 -9
  82. data/spec/unit/module/svn_spec.rb +35 -5
  83. data/spec/unit/module_loader/puppetfile_spec.rb +405 -0
  84. data/spec/unit/module_spec.rb +12 -1
  85. data/spec/unit/puppetfile_spec.rb +125 -189
  86. data/spec/unit/settings_spec.rb +47 -2
  87. data/spec/unit/util/purgeable_spec.rb +38 -6
  88. metadata +29 -3
@@ -0,0 +1,276 @@
1
+ require 'r10k/errors'
2
+ require 'r10k/logging'
3
+ require 'r10k/module'
4
+ require 'r10k/module_loader/puppetfile/dsl'
5
+
6
+ require 'pathname'
7
+
8
+ module R10K
9
+ module ModuleLoader
10
+ class Puppetfile
11
+
12
+ include R10K::Logging
13
+
14
+ DEFAULT_MODULEDIR = 'modules'
15
+ DEFAULT_PUPPETFILE_NAME = 'Puppetfile'
16
+
17
+ attr_accessor :default_branch_override, :environment
18
+ attr_reader :modules, :moduledir, :puppetfile_path,
19
+ :managed_directories, :desired_contents, :purge_exclusions
20
+
21
+ # @param basedir [String] The path that contains the moduledir &
22
+ # Puppetfile by default. May be an environment, project, or
23
+ # simple directory.
24
+ # @param puppetfile [String] The path to the Puppetfile, either an
25
+ # absolute full path or a relative path with regards to the basedir.
26
+ # @param moduledir [String] The path to the moduledir, either an
27
+ # absolute full path or a relative path with regards to the basedir.
28
+ # @param forge [String] The url (without protocol) to the Forge
29
+ # @param overrides [Hash] Configuration for loaded modules' behavior
30
+ # @param environment [R10K::Environment] When provided, the environment
31
+ # in which loading takes place
32
+ def initialize(basedir:,
33
+ moduledir: DEFAULT_MODULEDIR,
34
+ puppetfile: DEFAULT_PUPPETFILE_NAME,
35
+ overrides: {},
36
+ environment: nil)
37
+
38
+ @basedir = cleanpath(basedir)
39
+ @moduledir = resolve_path(@basedir, moduledir)
40
+ @puppetfile_path = resolve_path(@basedir, puppetfile)
41
+ @overrides = overrides
42
+ @environment = environment
43
+ @default_branch_override = @overrides.dig(:environments, :default_branch_override)
44
+ @allow_puppetfile_forge = @overrides.dig(:forge, :allow_puppetfile_override)
45
+
46
+ @existing_module_metadata = []
47
+ @existing_module_versions_by_name = {}
48
+ @modules = []
49
+
50
+ @managed_directories = []
51
+ @desired_contents = []
52
+ @purge_exclusions = []
53
+ end
54
+
55
+ def load
56
+ with_readable_puppetfile(@puppetfile_path) do
57
+ self.load!
58
+ end
59
+ end
60
+
61
+ def load!
62
+ logger.info _("Using Puppetfile '%{puppetfile}'") % {puppetfile: @puppetfile_path}
63
+ logger.debug _("Using moduledir '%{moduledir}'") % {moduledir: @moduledir}
64
+
65
+ dsl = R10K::ModuleLoader::Puppetfile::DSL.new(self)
66
+ dsl.instance_eval(puppetfile_content(@puppetfile_path), @puppetfile_path)
67
+
68
+ validate_no_duplicate_names(@modules)
69
+
70
+ managed_content = @modules.group_by(&:dirname)
71
+
72
+ @managed_directories = determine_managed_directories(managed_content)
73
+ @desired_contents = determine_desired_contents(managed_content)
74
+ @purge_exclusions = determine_purge_exclusions(@managed_directories)
75
+
76
+ {
77
+ modules: @modules,
78
+ managed_directories: @managed_directories,
79
+ desired_contents: @desired_contents,
80
+ purge_exclusions: @purge_exclusions
81
+ }
82
+
83
+ rescue SyntaxError, LoadError, ArgumentError, NameError => e
84
+ raise R10K::Error.wrap(e, _("Failed to evaluate %{path}") % {path: @puppetfile_path})
85
+ end
86
+
87
+ def load_metadata
88
+ with_readable_puppetfile(@puppetfile_path) do
89
+ self.load_metadata!
90
+ end
91
+ end
92
+
93
+ def load_metadata!
94
+ dsl = R10K::ModuleLoader::Puppetfile::DSL.new(self, metadata_only: true)
95
+ dsl.instance_eval(puppetfile_content(@puppetfile_path), @puppetfile_path)
96
+
97
+ @existing_module_versions_by_name = @existing_module_metadata.map {|mod| [ mod.name, mod.version ] }.to_h
98
+ empty_load_output.merge(modules: @existing_module_metadata)
99
+
100
+ rescue SyntaxError, LoadError, ArgumentError, NameError => e
101
+ logger.warn _("Unable to preload Puppetfile because of %{msg}" % { msg: e.message })
102
+ end
103
+
104
+ def add_module_metadata(name, info)
105
+ install_path, metadata_info, _ = parse_module_definition(name, info)
106
+
107
+ mod = R10K::Module.from_metadata(name, install_path, metadata_info, @environment)
108
+
109
+ @existing_module_metadata << mod
110
+ end
111
+
112
+ ##
113
+ ## set_forge, set_moduledir, and add_module are used directly by the DSL class
114
+ ##
115
+
116
+ # @param [String] forge
117
+ def set_forge(forge)
118
+ if @allow_puppetfile_forge
119
+ logger.debug _("Using Forge from Puppetfile: %{forge}") % { forge: forge }
120
+ PuppetForge.host = forge
121
+ else
122
+ logger.debug _("Ignoring Forge declaration in Puppetfile, using value from settings: %{forge}.") % { forge: PuppetForge.host }
123
+ end
124
+ end
125
+
126
+ # @param [String] moduledir
127
+ def set_moduledir(moduledir)
128
+ @moduledir = resolve_path(@basedir, moduledir)
129
+ end
130
+
131
+ # @param [String] name
132
+ # @param [Hash, String, Symbol, nil] info Calling with
133
+ # anything but a Hash is deprecated. The DSL will now convert
134
+ # String and Symbol versions to Hashes of the shape
135
+ # { version: <String or Symbol> }
136
+ #
137
+ # String inputs should be valid module versions, the Symbol
138
+ # `:latest` is allowed, as well as `nil`.
139
+ #
140
+ # Non-Hash inputs are only ever used by Forge modules. In
141
+ # future versions this method will require the caller (the
142
+ # DSL class, not the Puppetfile author) to do this conversion
143
+ # itself.
144
+ #
145
+ def add_module(name, info)
146
+ install_path, metadata_info, spec_deletable = parse_module_definition(name, info)
147
+
148
+ mod = R10K::Module.from_metadata(name, install_path, metadata_info, @environment)
149
+ mod.origin = :puppetfile
150
+ mod.spec_deletable = spec_deletable
151
+
152
+ # Do not save modules if they would conflict with the attached
153
+ # environment
154
+ if @environment && @environment.module_conflicts?(mod)
155
+ return @modules
156
+ end
157
+
158
+ # If this module's metadata has a static version and that version
159
+ # matches the existing module declaration use it, otherwise create
160
+ # a regular module to sync.
161
+ unless mod.version && (mod.version == @existing_module_versions_by_name[mod.name])
162
+ mod = mod.to_implementation
163
+ end
164
+
165
+ @modules << mod
166
+ end
167
+
168
+ private
169
+
170
+ def empty_load_output
171
+ {
172
+ modules: [],
173
+ managed_directories: [],
174
+ desired_contents: [],
175
+ purge_exclusions: []
176
+ }
177
+ end
178
+
179
+ def with_readable_puppetfile(puppetfile_path, &block)
180
+ if File.readable?(puppetfile_path)
181
+ block.call
182
+ else
183
+ logger.debug _("Puppetfile %{path} missing or unreadable") % {path: puppetfile_path.inspect}
184
+
185
+ empty_load_output
186
+ end
187
+ end
188
+
189
+ def parse_module_definition(name, info)
190
+ if !info.is_a?(Hash)
191
+ info = { version: info }
192
+ end
193
+
194
+ info[:overrides] = @overrides
195
+
196
+ if @default_branch_override
197
+ info[:default_branch_override] = @default_branch_override
198
+ end
199
+
200
+ spec_deletable = false
201
+ if install_path = info.delete(:install_path)
202
+ install_path = resolve_path(@basedir, install_path)
203
+ validate_install_path(install_path, name)
204
+ else
205
+ install_path = @moduledir
206
+ spec_deletable = true
207
+ end
208
+
209
+ return [ install_path, info, spec_deletable ]
210
+ end
211
+
212
+ # @param [Array<R10K::Module>] modules
213
+ def validate_no_duplicate_names(modules)
214
+ dupes = modules
215
+ .group_by { |mod| mod.name }
216
+ .select { |_, mods| mods.size > 1 }
217
+ .map(&:first)
218
+ unless dupes.empty?
219
+ msg = _('Puppetfiles cannot contain duplicate module names.')
220
+ msg += ' '
221
+ msg += _("Remove the duplicates of the following modules: %{dupes}" % { dupes: dupes.join(' ') })
222
+ raise R10K::Error.new(msg)
223
+ end
224
+ end
225
+
226
+ def resolve_path(base, path)
227
+ if Pathname.new(path).absolute?
228
+ cleanpath(path)
229
+ else
230
+ cleanpath(File.join(base, path))
231
+ end
232
+ end
233
+
234
+ def validate_install_path(path, modname)
235
+ unless /^#{Regexp.escape(@basedir)}.*/ =~ path
236
+ raise R10K::Error.new("Puppetfile cannot manage content '#{modname}' outside of containing environment: #{path} is not within #{@basedir}")
237
+ end
238
+
239
+ true
240
+ end
241
+
242
+ def determine_managed_directories(managed_content)
243
+ managed_content.keys.reject { |dir| dir == @basedir }
244
+ end
245
+
246
+ # Returns an array of the full paths to all the content being managed.
247
+ # @return [Array<String>]
248
+ def determine_desired_contents(managed_content)
249
+ managed_content.flat_map do |install_path, mods|
250
+ mods.collect { |mod| File.join(install_path, mod.name) }
251
+ end
252
+ end
253
+
254
+ def determine_purge_exclusions(managed_dirs)
255
+ if environment && environment.respond_to?(:desired_contents)
256
+ managed_dirs + environment.desired_contents
257
+ else
258
+ managed_dirs
259
+ end
260
+ end
261
+
262
+ # .cleanpath is as close to a canonical path as we can do without touching
263
+ # the filesystem. The .realpath methods will choke if some of the
264
+ # intermediate paths are missing, even though in some cases we will create
265
+ # them later as needed.
266
+ def cleanpath(path)
267
+ Pathname.new(path).cleanpath.to_s
268
+ end
269
+
270
+ # For testing purposes only
271
+ def puppetfile_content(path)
272
+ File.read(path)
273
+ end
274
+ end
275
+ end
276
+ end
@@ -4,10 +4,17 @@ require 'r10k/module'
4
4
  require 'r10k/util/purgeable'
5
5
  require 'r10k/errors'
6
6
  require 'r10k/content_synchronizer'
7
+ require 'r10k/module_loader/puppetfile/dsl'
8
+ require 'r10k/module_loader/puppetfile'
7
9
 
8
10
  module R10K
11
+
12
+ # Deprecated, use R10K::ModuleLoader::Puppetfile#load to load content,
13
+ # provide the `:modules` key of the returned Hash to
14
+ # R10K::ContentSynchronizer (either the `serial_sync` or `concurrent_sync`)
15
+ # and the remaining keys (`:managed_directories`, `:desired_contents`, and
16
+ # `:purge_exclusions`) to R10K::Util::Cleaner.
9
17
  class Puppetfile
10
- # Defines the data members of a Puppetfile
11
18
 
12
19
  include R10K::Settings::Mixin
13
20
 
@@ -19,25 +26,13 @@ class Puppetfile
19
26
  # @return [String] The URL to use for the Puppet Forge
20
27
  attr_reader :forge
21
28
 
22
- # @!attribute [r] modules
23
- # @return [Array<R10K::Module>]
24
- attr_reader :modules
25
-
26
29
  # @!attribute [r] basedir
27
30
  # @return [String] The base directory that contains the Puppetfile
28
31
  attr_reader :basedir
29
32
 
30
- # @!attribute [r] moduledir
31
- # @return [String] The directory to install the modules #{basedir}/modules
32
- attr_reader :moduledir
33
-
34
- # @!attrbute [r] puppetfile_path
35
- # @return [String] The path to the Puppetfile
36
- attr_reader :puppetfile_path
37
-
38
- # @!attribute [rw] environment
33
+ # @!attribute [r] environment
39
34
  # @return [R10K::Environment] Optional R10K::Environment that this Puppetfile belongs to.
40
- attr_accessor :environment
35
+ attr_reader :environment
41
36
 
42
37
  # @!attribute [rw] force
43
38
  # @return [Boolean] Overwrite any locally made changes
@@ -47,6 +42,10 @@ class Puppetfile
47
42
  # @return [Hash] Various settings overridden from normal configs
48
43
  attr_reader :overrides
49
44
 
45
+ # @!attribute [r] loader
46
+ # @return [R10K::ModuleLoader::Puppetfile] The internal module loader
47
+ attr_reader :loader
48
+
50
49
  # @param [String] basedir
51
50
  # @param [Hash, String, nil] options_or_moduledir The directory to install the modules or a Hash of options.
52
51
  # Usage as moduledir is deprecated. Only use as options, defaults to nil
@@ -65,144 +64,122 @@ class Puppetfile
65
64
 
66
65
  @force = deprecated_force_arg || options.delete(:force) || false
67
66
  @moduledir = deprecated_moduledir_arg || options.delete(:moduledir) || File.join(basedir, 'modules')
68
- @puppetfile_name = deprecated_name_arg || options.delete(:puppetfile_name) || 'Puppetfile'
69
- @puppetfile_path = deprecated_path_arg || options.delete(:puppetfile_path) || File.join(basedir, @puppetfile_name)
67
+ puppetfile_name = deprecated_name_arg || options.delete(:puppetfile_name) || 'Puppetfile'
68
+ puppetfile_path = deprecated_path_arg || options.delete(:puppetfile_path)
69
+ @puppetfile = puppetfile_path || puppetfile_name
70
+ @environment = options.delete(:environment)
70
71
 
71
72
  @overrides = options.delete(:overrides) || {}
73
+ @default_branch_override = @overrides.dig(:environments, :default_branch_override)
72
74
 
73
- logger.info _("Using Puppetfile '%{puppetfile}'") % {puppetfile: @puppetfile_path}
74
-
75
- @modules = []
76
- @managed_content = {}
77
75
  @forge = 'forgeapi.puppetlabs.com'
78
76
 
77
+ @loader = ::R10K::ModuleLoader::Puppetfile.new(
78
+ basedir: @basedir,
79
+ moduledir: @moduledir,
80
+ puppetfile: @puppetfile,
81
+ overrides: @overrides,
82
+ environment: @environment
83
+ )
84
+
85
+ @loaded_content = {
86
+ modules: [],
87
+ managed_directories: [],
88
+ desired_contents: [],
89
+ purge_exclusions: []
90
+ }
91
+
79
92
  @loaded = false
80
93
  end
81
94
 
95
+ # @param [String] default_branch_override The default branch to use
96
+ # instead of one specified in the module declaration, if applicable.
97
+ # Deprecated, use R10K::ModuleLoader::Puppetfile directly and pass
98
+ # the default_branch_override as an option on initialization.
82
99
  def load(default_branch_override = nil)
83
- return true if self.loaded?
84
- if File.readable? @puppetfile_path
85
- self.load!(default_branch_override)
100
+ if self.loaded?
101
+ return @loaded_content
86
102
  else
87
- logger.debug _("Puppetfile %{path} missing or unreadable") % {path: @puppetfile_path.inspect}
103
+ if !File.readable?(puppetfile_path)
104
+ logger.debug _("Puppetfile %{path} missing or unreadable") % {path: puppetfile_path.inspect}
105
+ else
106
+ self.load!(default_branch_override)
107
+ end
88
108
  end
89
109
  end
90
110
 
111
+ # @param [String] default_branch_override The default branch to use
112
+ # instead of one specified in the module declaration, if applicable.
113
+ # Deprecated, use R10K::ModuleLoader::Puppetfile directly and pass
114
+ # the default_branch_override as an option on initialization.
91
115
  def load!(default_branch_override = nil)
92
- @default_branch_override = default_branch_override
93
116
 
94
- dsl = R10K::Puppetfile::DSL.new(self)
95
- dsl.instance_eval(puppetfile_contents, @puppetfile_path)
117
+ if default_branch_override && (default_branch_override != @default_branch_override)
118
+ logger.warn("Mismatch between passed and initialized default branch overrides, preferring passed value.")
119
+ @loader.default_branch_override = default_branch_override
120
+ end
96
121
 
97
- validate_no_duplicate_names(@modules)
122
+ @loaded_content = @loader.load!
98
123
  @loaded = true
99
- rescue SyntaxError, LoadError, ArgumentError, NameError => e
100
- raise R10K::Error.wrap(e, _("Failed to evaluate %{path}") % {path: @puppetfile_path})
124
+
125
+ @loaded_content
101
126
  end
102
127
 
103
128
  def loaded?
104
129
  @loaded
105
130
  end
106
131
 
107
- # @param [Array<String>] modules
108
- def validate_no_duplicate_names(modules)
109
- dupes = modules
110
- .group_by { |mod| mod.name }
111
- .select { |_, v| v.size > 1 }
112
- .map(&:first)
113
- unless dupes.empty?
114
- msg = _('Puppetfiles cannot contain duplicate module names.')
115
- msg += ' '
116
- msg += _("Remove the duplicates of the following modules: %{dupes}" % { dupes: dupes.join(' ') })
117
- raise R10K::Error.new(msg)
118
- end
132
+ def modules
133
+ @loaded_content[:modules]
119
134
  end
120
135
 
121
- # @param [String] forge
122
- def set_forge(forge)
123
- @forge = forge
136
+ # @see R10K::ModuleLoader::Puppetfile#add_module for upcoming signature changes
137
+ def add_module(name, args)
138
+ @loader.add_module(name, args)
124
139
  end
125
140
 
126
- # @param [String] moduledir
127
- def set_moduledir(moduledir)
128
- @moduledir = if Pathname.new(moduledir).absolute?
129
- moduledir
130
- else
131
- File.join(basedir, moduledir)
132
- end
141
+ def set_moduledir(dir)
142
+ @loader.set_moduledir(dir)
133
143
  end
134
144
 
135
- # @param [String] name
136
- # @param [Hash, String, Symbol] args Calling with anything but a Hash is
137
- # deprecated. The DSL will now convert String and Symbol versions to
138
- # Hashes of the shape
139
- # { version: <String or Symbol> }
140
- #
141
- def add_module(name, args)
142
- if !args.is_a?(Hash)
143
- args = { version: args }
144
- end
145
-
146
- args[:overrides] = @overrides
147
-
148
- if install_path = args.delete(:install_path)
149
- install_path = resolve_install_path(install_path)
150
- validate_install_path(install_path, name)
151
- else
152
- install_path = @moduledir
153
- end
154
-
155
- if @default_branch_override != nil
156
- args[:default_branch_override] = @default_branch_override
157
- end
158
-
159
-
160
- mod = R10K::Module.new(name, install_path, args, @environment)
161
- mod.origin = :puppetfile
145
+ def set_forge(forge)
146
+ @loader.set_forge(forge)
147
+ end
162
148
 
163
- # Do not load modules if they would conflict with the attached
164
- # environment
165
- if environment && environment.module_conflicts?(mod)
166
- mod = nil
167
- return @modules
168
- end
149
+ def moduledir
150
+ @loader.moduledir
151
+ end
169
152
 
170
- # Keep track of all the content this Puppetfile is managing to enable purging.
171
- @managed_content[install_path] = Array.new unless @managed_content.has_key?(install_path)
172
- @managed_content[install_path] << mod.name
153
+ def puppetfile_path
154
+ @loader.puppetfile_path
155
+ end
173
156
 
174
- @modules << mod
157
+ def environment=(env)
158
+ @loader.environment = env
159
+ @environment = env
175
160
  end
176
161
 
177
162
  include R10K::Util::Purgeable
178
163
 
179
164
  def managed_directories
180
- self.load unless @loaded
165
+ self.load
181
166
 
182
- dirs = @managed_content.keys
183
- dirs.delete(real_basedir)
184
- dirs
167
+ @loaded_content[:managed_directories]
185
168
  end
186
169
 
187
170
  # Returns an array of the full paths to all the content being managed.
188
171
  # @note This implements a required method for the Purgeable mixin
189
172
  # @return [Array<String>]
190
173
  def desired_contents
191
- self.load unless @loaded
174
+ self.load
192
175
 
193
- @managed_content.flat_map do |install_path, modnames|
194
- modnames.collect { |name| File.join(install_path, name) }
195
- end
176
+ @loaded_content[:desired_contents]
196
177
  end
197
178
 
198
179
  def purge_exclusions
199
- exclusions = managed_directories
200
-
201
- if environment && environment.respond_to?(:desired_contents)
202
- exclusions += environment.desired_contents
203
- end
180
+ self.load
204
181
 
205
- exclusions
182
+ @loaded_content[:purge_exclusions]
206
183
  end
207
184
 
208
185
  def accept(visitor)
@@ -225,65 +202,10 @@ class Puppetfile
225
202
 
226
203
  private
227
204
 
228
- def puppetfile_contents
229
- File.read(@puppetfile_path)
230
- end
231
-
232
- def resolve_install_path(path)
233
- pn = Pathname.new(path)
234
-
235
- unless pn.absolute?
236
- pn = Pathname.new(File.join(basedir, path))
237
- end
238
-
239
- # .cleanpath is as good as we can do without touching the filesystem.
240
- # The .realpath methods will also choke if some of the intermediate
241
- # paths are missing, even though we will create them later as needed.
242
- pn.cleanpath.to_s
243
- end
244
-
245
- def validate_install_path(path, modname)
246
- unless /^#{Regexp.escape(real_basedir)}.*/ =~ path
247
- raise R10K::Error.new("Puppetfile cannot manage content '#{modname}' outside of containing environment: #{path} is not within #{real_basedir}")
248
- end
249
-
250
- true
251
- end
252
-
253
205
  def real_basedir
254
206
  Pathname.new(basedir).cleanpath.to_s
255
207
  end
256
208
 
257
- class DSL
258
- # A barebones implementation of the Puppetfile DSL
259
- #
260
- # @api private
261
-
262
- def initialize(librarian)
263
- @librarian = librarian
264
- end
265
-
266
- def mod(name, args = nil)
267
- if args.is_a?(Hash)
268
- opts = args
269
- else
270
- opts = { version: args }
271
- end
272
-
273
- @librarian.add_module(name, opts)
274
- end
275
-
276
- def forge(location)
277
- @librarian.set_forge(location)
278
- end
279
-
280
- def moduledir(location)
281
- @librarian.set_moduledir(location)
282
- end
283
-
284
- def method_missing(method, *args)
285
- raise NoMethodError, _("unrecognized declaration '%{method}'") % {method: method}
286
- end
287
- end
209
+ DSL = R10K::ModuleLoader::Puppetfile::DSL
288
210
  end
289
211
  end
@@ -90,7 +90,7 @@ module R10K
90
90
  def resolve
91
91
  if !@value.nil?
92
92
  @value
93
- elsif @default
93
+ elsif !@default.nil?
94
94
  if @default == :inherit
95
95
  # walk all the way up to root, starting with grandparent
96
96
  ancestor = parent