r10k 3.9.0 → 3.10.0
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/.github/pull_request_template.md +1 -1
- data/.github/workflows/rspec_tests.yml +1 -1
- data/.github/workflows/stale.yml +19 -0
- data/CHANGELOG.mkd +24 -0
- data/doc/dynamic-environments/configuration.mkd +13 -6
- data/integration/Rakefile +1 -1
- data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +3 -9
- data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +8 -14
- data/lib/r10k/action/base.rb +10 -0
- data/lib/r10k/action/deploy/display.rb +42 -9
- data/lib/r10k/action/deploy/environment.rb +70 -41
- data/lib/r10k/action/deploy/module.rb +51 -29
- data/lib/r10k/action/puppetfile/check.rb +3 -1
- data/lib/r10k/action/puppetfile/install.rb +20 -23
- data/lib/r10k/action/puppetfile/purge.rb +8 -2
- data/lib/r10k/action/runner.rb +11 -6
- data/lib/r10k/content_synchronizer.rb +83 -0
- data/lib/r10k/deployment.rb +1 -1
- data/lib/r10k/environment/base.rb +21 -1
- data/lib/r10k/environment/git.rb +0 -3
- data/lib/r10k/environment/svn.rb +4 -6
- data/lib/r10k/environment/with_modules.rb +18 -10
- data/lib/r10k/git/cache.rb +1 -1
- data/lib/r10k/initializers.rb +7 -0
- data/lib/r10k/module.rb +1 -1
- data/lib/r10k/module/base.rb +17 -1
- data/lib/r10k/module/forge.rb +29 -19
- data/lib/r10k/module/git.rb +23 -14
- data/lib/r10k/module/local.rb +1 -0
- data/lib/r10k/module/svn.rb +12 -9
- data/lib/r10k/module_loader/puppetfile.rb +195 -0
- data/lib/r10k/module_loader/puppetfile/dsl.rb +37 -0
- data/lib/r10k/puppetfile.rb +111 -202
- data/lib/r10k/settings.rb +3 -0
- data/lib/r10k/source/base.rb +14 -0
- data/lib/r10k/source/git.rb +19 -6
- data/lib/r10k/source/hash.rb +1 -3
- data/lib/r10k/source/svn.rb +4 -2
- data/lib/r10k/util/cleaner.rb +21 -0
- data/lib/r10k/util/purgeable.rb +70 -8
- data/lib/r10k/version.rb +1 -1
- data/locales/r10k.pot +67 -71
- data/spec/fixtures/unit/action/r10k_forge_auth.yaml +4 -0
- data/spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml +3 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_subdir_2/ignored_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_two/.hidden/unmanaged_3 +0 -0
- data/spec/r10k-mocks/mock_source.rb +1 -1
- data/spec/shared-examples/puppetfile-action.rb +7 -7
- data/spec/unit/action/deploy/display_spec.rb +32 -6
- data/spec/unit/action/deploy/environment_spec.rb +85 -48
- data/spec/unit/action/deploy/module_spec.rb +163 -31
- data/spec/unit/action/puppetfile/check_spec.rb +2 -2
- data/spec/unit/action/puppetfile/install_spec.rb +31 -10
- data/spec/unit/action/puppetfile/purge_spec.rb +25 -5
- data/spec/unit/action/runner_spec.rb +49 -25
- data/spec/unit/git/cache_spec.rb +14 -0
- data/spec/unit/module/forge_spec.rb +23 -14
- data/spec/unit/module/git_spec.rb +8 -8
- data/spec/unit/module_loader/puppetfile_spec.rb +330 -0
- data/spec/unit/module_spec.rb +22 -5
- data/spec/unit/puppetfile_spec.rb +123 -203
- data/spec/unit/settings_spec.rb +6 -2
- data/spec/unit/util/purgeable_spec.rb +40 -14
- metadata +12 -2
data/lib/r10k/git/cache.rb
CHANGED
@@ -111,6 +111,6 @@ class R10K::Git::Cache
|
|
111
111
|
|
112
112
|
# Reformat the remote name into something that can be used as a directory
|
113
113
|
def sanitized_dirname
|
114
|
-
@sanitized_dirname ||= @remote.gsub(/[^@\w\.-]/, '-')
|
114
|
+
@sanitized_dirname ||= @remote.gsub(/(\w+:\/\/)(.*)(@)/, '\1').gsub(/[^@\w\.-]/, '-')
|
115
115
|
end
|
116
116
|
end
|
data/lib/r10k/initializers.rb
CHANGED
@@ -63,6 +63,13 @@ module R10K
|
|
63
63
|
def call
|
64
64
|
with_setting(:baseurl) { |value| PuppetForge.host = value }
|
65
65
|
with_setting(:proxy) { |value| PuppetForge::Connection.proxy = value }
|
66
|
+
with_setting(:authorization_token) { |value|
|
67
|
+
if @settings[:baseurl]
|
68
|
+
PuppetForge::Connection.authorization = value
|
69
|
+
else
|
70
|
+
raise R10K::Error, "Cannot specify a Forge authorization token without configuring a custom baseurl."
|
71
|
+
end
|
72
|
+
}
|
66
73
|
end
|
67
74
|
end
|
68
75
|
end
|
data/lib/r10k/module.rb
CHANGED
@@ -17,7 +17,7 @@ module R10K::Module
|
|
17
17
|
#
|
18
18
|
# @param [String] name The unique name of the module
|
19
19
|
# @param [String] basedir The root to install the module in
|
20
|
-
# @param [
|
20
|
+
# @param [Hash] args An arbitary Hash that specifies the implementation
|
21
21
|
# @param [R10K::Environment] environment Optional environment that this module is a part of
|
22
22
|
#
|
23
23
|
# @return [Object < R10K::Module] A member of the implementing subclass
|
data/lib/r10k/module/base.rb
CHANGED
@@ -51,7 +51,11 @@ class R10K::Module::Base
|
|
51
51
|
@owner, @name = parse_title(@title)
|
52
52
|
@path = Pathname.new(File.join(@dirname, @name))
|
53
53
|
@environment = environment
|
54
|
+
@overrides = args.delete(:overrides) || {}
|
54
55
|
@origin = 'external' # Expect Puppetfile or R10k::Environment to set this to a specific value
|
56
|
+
|
57
|
+
@requested_modules = @overrides.dig(:modules, :requested_modules) || []
|
58
|
+
@should_sync = (@requested_modules.empty? || @requested_modules.include?(@name))
|
55
59
|
end
|
56
60
|
|
57
61
|
# @deprecated
|
@@ -61,11 +65,22 @@ class R10K::Module::Base
|
|
61
65
|
end
|
62
66
|
|
63
67
|
# Synchronize this module with the indicated state.
|
64
|
-
# @
|
68
|
+
# @param [Hash] opts Deprecated
|
65
69
|
def sync(opts={})
|
66
70
|
raise NotImplementedError
|
67
71
|
end
|
68
72
|
|
73
|
+
def should_sync?
|
74
|
+
if @should_sync
|
75
|
+
logger.info _("Deploying module to %{path}") % {path: path}
|
76
|
+
true
|
77
|
+
else
|
78
|
+
logger.debug1(_("Only updating modules %{modules}, skipping module %{name}") % {modules: @requested_modules.inspect, name: name})
|
79
|
+
false
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
69
84
|
# Return the desired version of this module
|
70
85
|
# @abstract
|
71
86
|
def version
|
@@ -87,6 +102,7 @@ class R10K::Module::Base
|
|
87
102
|
raise NotImplementedError
|
88
103
|
end
|
89
104
|
|
105
|
+
# Deprecated
|
90
106
|
def accept(visitor)
|
91
107
|
visitor.visit(:module, self)
|
92
108
|
end
|
data/lib/r10k/module/forge.rb
CHANGED
@@ -13,7 +13,12 @@ class R10K::Module::Forge < R10K::Module::Base
|
|
13
13
|
R10K::Module.register(self)
|
14
14
|
|
15
15
|
def self.implement?(name, args)
|
16
|
-
|
16
|
+
args[:type].to_s == 'forge' ||
|
17
|
+
(!!
|
18
|
+
((args.keys & %i{git svn type}).empty? &&
|
19
|
+
args.has_key?(:version) &&
|
20
|
+
name.match(%r[\w+[/-]\w+]) &&
|
21
|
+
valid_version?(args[:version])))
|
17
22
|
end
|
18
23
|
|
19
24
|
def self.valid_version?(expected_version)
|
@@ -40,28 +45,29 @@ class R10K::Module::Forge < R10K::Module::Base
|
|
40
45
|
@metadata_file = R10K::Module::MetadataFile.new(path + 'metadata.json')
|
41
46
|
@metadata = @metadata_file.read
|
42
47
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
@expected_version = opts || current_version || :latest
|
52
|
-
end
|
48
|
+
setopts(opts, {
|
49
|
+
# Standard option interface
|
50
|
+
:version => :expected_version,
|
51
|
+
:source => ::R10K::Util::Setopts::Ignore,
|
52
|
+
:type => ::R10K::Util::Setopts::Ignore,
|
53
|
+
}, :raise_on_unhandled => false)
|
54
|
+
|
55
|
+
@expected_version ||= current_version || :latest
|
53
56
|
|
54
57
|
@v3_module = PuppetForge::V3::Module.new(:slug => @title)
|
55
58
|
end
|
56
59
|
|
60
|
+
# @param [Hash] opts Deprecated
|
57
61
|
def sync(opts={})
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
62
|
+
if should_sync?
|
63
|
+
case status
|
64
|
+
when :absent
|
65
|
+
install
|
66
|
+
when :outdated
|
67
|
+
upgrade
|
68
|
+
when :mismatched
|
69
|
+
reinstall
|
70
|
+
end
|
65
71
|
end
|
66
72
|
end
|
67
73
|
|
@@ -77,7 +83,11 @@ class R10K::Module::Forge < R10K::Module::Base
|
|
77
83
|
def expected_version
|
78
84
|
if @expected_version == :latest
|
79
85
|
begin
|
80
|
-
|
86
|
+
if @v3_module.current_release
|
87
|
+
@expected_version = @v3_module.current_release.version
|
88
|
+
else
|
89
|
+
raise PuppetForge::ReleaseNotFound, _("The module %{title} does not appear to have any published releases, cannot determine latest version.") % { title: @title }
|
90
|
+
end
|
81
91
|
rescue Faraday::ResourceNotFound => e
|
82
92
|
raise PuppetForge::ReleaseNotFound, _("The module %{title} does not exist on %{url}.") % {title: @title, url: PuppetForge::V3::Release.conn.url_prefix}, e.backtrace
|
83
93
|
end
|
data/lib/r10k/module/git.rb
CHANGED
@@ -8,7 +8,7 @@ class R10K::Module::Git < R10K::Module::Base
|
|
8
8
|
R10K::Module.register(self)
|
9
9
|
|
10
10
|
def self.implement?(name, args)
|
11
|
-
args.
|
11
|
+
args.has_key?(:git) || args[:type].to_s == 'git'
|
12
12
|
rescue
|
13
13
|
false
|
14
14
|
end
|
@@ -36,27 +36,35 @@ class R10K::Module::Git < R10K::Module::Base
|
|
36
36
|
include R10K::Util::Setopts
|
37
37
|
|
38
38
|
def initialize(title, dirname, opts, environment=nil)
|
39
|
+
|
39
40
|
super
|
40
41
|
setopts(opts, {
|
41
42
|
# Standard option interface
|
42
|
-
:version
|
43
|
-
:source
|
44
|
-
:type
|
43
|
+
:version => :desired_ref,
|
44
|
+
:source => :remote,
|
45
|
+
:type => ::R10K::Util::Setopts::Ignore,
|
45
46
|
|
46
47
|
# Type-specific options
|
47
|
-
:branch
|
48
|
-
:tag
|
49
|
-
:commit
|
50
|
-
:ref
|
51
|
-
:git
|
48
|
+
:branch => :desired_ref,
|
49
|
+
:tag => :desired_ref,
|
50
|
+
:commit => :desired_ref,
|
51
|
+
:ref => :desired_ref,
|
52
|
+
:git => :remote,
|
52
53
|
:default_branch => :default_ref,
|
53
54
|
:default_branch_override => :default_override_ref,
|
54
|
-
})
|
55
|
+
}, :raise_on_unhandled => false)
|
56
|
+
|
57
|
+
force = @overrides.dig(:modules, :force)
|
58
|
+
@force = force == false ? false : true
|
55
59
|
|
56
60
|
@desired_ref ||= 'master'
|
57
61
|
|
58
|
-
if @desired_ref == :control_branch
|
59
|
-
@
|
62
|
+
if @desired_ref == :control_branch
|
63
|
+
if @environment && @environment.respond_to?(:ref)
|
64
|
+
@desired_ref = @environment.ref
|
65
|
+
else
|
66
|
+
logger.warn _("Cannot track control repo branch for content '%{name}' when not part of a git-backed environment, will use default if available." % {name: name})
|
67
|
+
end
|
60
68
|
end
|
61
69
|
|
62
70
|
@repo = R10K::Git::StatefulRepository.new(@remote, @dirname, @name)
|
@@ -74,9 +82,10 @@ class R10K::Module::Git < R10K::Module::Base
|
|
74
82
|
}
|
75
83
|
end
|
76
84
|
|
85
|
+
# @param [Hash] opts Deprecated
|
77
86
|
def sync(opts={})
|
78
|
-
force = opts
|
79
|
-
@repo.sync(version, force)
|
87
|
+
force = opts[:force] || @force
|
88
|
+
@repo.sync(version, force) if should_sync?
|
80
89
|
end
|
81
90
|
|
82
91
|
def status
|
data/lib/r10k/module/local.rb
CHANGED
data/lib/r10k/module/svn.rb
CHANGED
@@ -7,7 +7,7 @@ class R10K::Module::SVN < R10K::Module::Base
|
|
7
7
|
R10K::Module.register(self)
|
8
8
|
|
9
9
|
def self.implement?(name, args)
|
10
|
-
args.
|
10
|
+
args.has_key?(:svn) || args[:type].to_s == 'svn'
|
11
11
|
end
|
12
12
|
|
13
13
|
# @!attribute [r] expected_revision
|
@@ -50,7 +50,7 @@ class R10K::Module::SVN < R10K::Module::Base
|
|
50
50
|
:revision => :expected_revision,
|
51
51
|
:username => :self,
|
52
52
|
:password => :self
|
53
|
-
})
|
53
|
+
}, :raise_on_unhandled => false)
|
54
54
|
|
55
55
|
@working_dir = R10K::SVN::WorkingDir.new(@path, :username => @username, :password => @password)
|
56
56
|
end
|
@@ -69,14 +69,17 @@ class R10K::Module::SVN < R10K::Module::Base
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
# @param [Hash] opts Deprecated
|
72
73
|
def sync(opts={})
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
74
|
+
if should_sync?
|
75
|
+
case status
|
76
|
+
when :absent
|
77
|
+
install
|
78
|
+
when :mismatched
|
79
|
+
reinstall
|
80
|
+
when :outdated
|
81
|
+
update
|
82
|
+
end
|
80
83
|
end
|
81
84
|
end
|
82
85
|
|
@@ -0,0 +1,195 @@
|
|
1
|
+
module R10K
|
2
|
+
module ModuleLoader
|
3
|
+
class Puppetfile
|
4
|
+
|
5
|
+
DEFAULT_MODULEDIR = 'modules'
|
6
|
+
DEFAULT_PUPPETFILE_NAME = 'Puppetfile'
|
7
|
+
DEFAULT_FORGE_API = 'forgeapi.puppetlabs.com'
|
8
|
+
|
9
|
+
attr_accessor :default_branch_override, :environment
|
10
|
+
attr_reader :modules, :moduledir,
|
11
|
+
:managed_directories, :desired_contents, :purge_exclusions
|
12
|
+
|
13
|
+
# @param basedir [String] The path that contains the moduledir &
|
14
|
+
# Puppetfile by default. May be an environment, project, or
|
15
|
+
# simple directory.
|
16
|
+
# @param puppetfile [String] The path to the Puppetfile, either an
|
17
|
+
# absolute full path or a relative path with regards to the basedir.
|
18
|
+
# @param moduledir [String] The path to the moduledir, either an
|
19
|
+
# absolute full path or a relative path with regards to the basedir.
|
20
|
+
# @param forge [String] The url (without protocol) to the Forge
|
21
|
+
# @param overrides [Hash] Configuration for loaded modules' behavior
|
22
|
+
# @param environment [R10K::Environment] When provided, the environment
|
23
|
+
# in which loading takes place
|
24
|
+
def initialize(basedir:,
|
25
|
+
moduledir: DEFAULT_MODULEDIR,
|
26
|
+
puppetfile: DEFAULT_PUPPETFILE_NAME,
|
27
|
+
forge: DEFAULT_FORGE_API,
|
28
|
+
overrides: {},
|
29
|
+
environment: nil)
|
30
|
+
|
31
|
+
@basedir = cleanpath(basedir)
|
32
|
+
@moduledir = resolve_path(@basedir, moduledir)
|
33
|
+
@puppetfile = resolve_path(@basedir, puppetfile)
|
34
|
+
@forge = forge
|
35
|
+
@overrides = overrides
|
36
|
+
@environment = environment
|
37
|
+
@default_branch_override = @overrides.dig(:environments, :default_branch_override)
|
38
|
+
|
39
|
+
@modules = []
|
40
|
+
|
41
|
+
@managed_directories = []
|
42
|
+
@desired_contents = []
|
43
|
+
@purge_exclusions = []
|
44
|
+
end
|
45
|
+
|
46
|
+
def load
|
47
|
+
dsl = R10K::ModuleLoader::Puppetfile::DSL.new(self)
|
48
|
+
dsl.instance_eval(puppetfile_content(@puppetfile), @puppetfile)
|
49
|
+
|
50
|
+
validate_no_duplicate_names(@modules)
|
51
|
+
@modules
|
52
|
+
|
53
|
+
managed_content = @modules.group_by(&:dirname)
|
54
|
+
|
55
|
+
@managed_directories = determine_managed_directories(managed_content)
|
56
|
+
@desired_contents = determine_desired_contents(managed_content)
|
57
|
+
@purge_exclusions = determine_purge_exclusions(@managed_directories)
|
58
|
+
|
59
|
+
{
|
60
|
+
modules: @modules,
|
61
|
+
managed_directories: @managed_directories,
|
62
|
+
desired_contents: @desired_contents,
|
63
|
+
purge_exclusions: @purge_exclusions
|
64
|
+
}
|
65
|
+
|
66
|
+
rescue SyntaxError, LoadError, ArgumentError, NameError => e
|
67
|
+
raise R10K::Error.wrap(e, _("Failed to evaluate %{path}") % {path: @puppetfile})
|
68
|
+
end
|
69
|
+
|
70
|
+
|
71
|
+
##
|
72
|
+
## set_forge, set_moduledir, and add_module are used directly by the DSL class
|
73
|
+
##
|
74
|
+
|
75
|
+
# @param [String] forge
|
76
|
+
def set_forge(forge)
|
77
|
+
@forge = forge
|
78
|
+
end
|
79
|
+
|
80
|
+
# @param [String] moduledir
|
81
|
+
def set_moduledir(moduledir)
|
82
|
+
@moduledir = resolve_path(@basedir, moduledir)
|
83
|
+
end
|
84
|
+
|
85
|
+
# @param [String] name
|
86
|
+
# @param [Hash, String, Symbol, nil] module_info Calling with
|
87
|
+
# anything but a Hash is deprecated. The DSL will now convert
|
88
|
+
# String and Symbol versions to Hashes of the shape
|
89
|
+
# { version: <String or Symbol> }
|
90
|
+
#
|
91
|
+
# String inputs should be valid module versions, the Symbol
|
92
|
+
# `:latest` is allowed, as well as `nil`.
|
93
|
+
#
|
94
|
+
# Non-Hash inputs are only ever used by Forge modules. In
|
95
|
+
# future versions this method will require the caller (the
|
96
|
+
# DSL class, not the Puppetfile author) to do this conversion
|
97
|
+
# itself.
|
98
|
+
#
|
99
|
+
def add_module(name, module_info)
|
100
|
+
if !module_info.is_a?(Hash)
|
101
|
+
module_info = { version: module_info }
|
102
|
+
end
|
103
|
+
|
104
|
+
module_info[:overrides] = @overrides
|
105
|
+
|
106
|
+
if install_path = module_info.delete(:install_path)
|
107
|
+
install_path = resolve_path(@basedir, install_path)
|
108
|
+
validate_install_path(install_path, name)
|
109
|
+
else
|
110
|
+
install_path = @moduledir
|
111
|
+
end
|
112
|
+
|
113
|
+
if @default_branch_override
|
114
|
+
module_info[:default_branch_override] = @default_branch_override
|
115
|
+
end
|
116
|
+
|
117
|
+
mod = R10K::Module.new(name, install_path, module_info, @environment)
|
118
|
+
mod.origin = :puppetfile
|
119
|
+
|
120
|
+
# Do not save modules if they would conflict with the attached
|
121
|
+
# environment
|
122
|
+
if @environment && @environment.module_conflicts?(mod)
|
123
|
+
return @modules
|
124
|
+
end
|
125
|
+
|
126
|
+
@modules << mod
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
# @param [Array<R10K::Module>] modules
|
132
|
+
def validate_no_duplicate_names(modules)
|
133
|
+
dupes = modules
|
134
|
+
.group_by { |mod| mod.name }
|
135
|
+
.select { |_, mods| mods.size > 1 }
|
136
|
+
.map(&:first)
|
137
|
+
unless dupes.empty?
|
138
|
+
msg = _('Puppetfiles cannot contain duplicate module names.')
|
139
|
+
msg += ' '
|
140
|
+
msg += _("Remove the duplicates of the following modules: %{dupes}" % { dupes: dupes.join(' ') })
|
141
|
+
raise R10K::Error.new(msg)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def resolve_path(base, path)
|
146
|
+
if Pathname.new(path).absolute?
|
147
|
+
cleanpath(path)
|
148
|
+
else
|
149
|
+
cleanpath(File.join(base, path))
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def validate_install_path(path, modname)
|
154
|
+
unless /^#{Regexp.escape(@basedir)}.*/ =~ path
|
155
|
+
raise R10K::Error.new("Puppetfile cannot manage content '#{modname}' outside of containing environment: #{path} is not within #{@basedir}")
|
156
|
+
end
|
157
|
+
|
158
|
+
true
|
159
|
+
end
|
160
|
+
|
161
|
+
def determine_managed_directories(managed_content)
|
162
|
+
managed_content.keys.reject { |dir| dir == @basedir }
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns an array of the full paths to all the content being managed.
|
166
|
+
# @return [Array<String>]
|
167
|
+
def determine_desired_contents(managed_content)
|
168
|
+
managed_content.flat_map do |install_path, mods|
|
169
|
+
mods.collect { |mod| File.join(install_path, mod.name) }
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def determine_purge_exclusions(managed_dirs)
|
174
|
+
if environment && environment.respond_to?(:desired_contents)
|
175
|
+
managed_dirs + environment.desired_contents
|
176
|
+
else
|
177
|
+
managed_dirs
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
# .cleanpath is as close to a canonical path as we can do without touching
|
182
|
+
# the filesystem. The .realpath methods will choke if some of the
|
183
|
+
# intermediate paths are missing, even though in some cases we will create
|
184
|
+
# them later as needed.
|
185
|
+
def cleanpath(path)
|
186
|
+
Pathname.new(path).cleanpath.to_s
|
187
|
+
end
|
188
|
+
|
189
|
+
# For testing purposes only
|
190
|
+
def puppetfile_content(path)
|
191
|
+
File.read(path)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|