r10k 2.3.1 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.mkd +40 -13
- data/Gemfile +1 -2
- data/README.mkd +25 -0
- data/Rakefile +3 -0
- data/doc/dynamic-environments/configuration.mkd +91 -14
- data/doc/dynamic-environments/workflow-guide.mkd +3 -3
- data/doc/puppetfile.mkd +89 -40
- data/integration/Gemfile +2 -0
- data/integration/Rakefile +41 -0
- data/integration/tests/purging/content_not_purged_at_root.rb +89 -0
- data/integration/tests/purging/default_purging.rb +125 -0
- data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module_ref.rb +1 -1
- data/lib/r10k.rb +8 -1
- data/lib/r10k/action/deploy/deploy_helpers.rb +3 -3
- data/lib/r10k/action/deploy/environment.rb +35 -14
- data/lib/r10k/action/deploy/module.rb +4 -4
- data/lib/r10k/action/puppetfile/check.rb +1 -1
- data/lib/r10k/action/puppetfile/install.rb +1 -1
- data/lib/r10k/action/runner.rb +3 -3
- data/lib/r10k/deployment.rb +8 -4
- data/lib/r10k/deployment/config.rb +1 -1
- data/lib/r10k/environment/base.rb +32 -3
- data/lib/r10k/environment/git.rb +19 -6
- data/lib/r10k/feature.rb +6 -6
- data/lib/r10k/forge/module_release.rb +4 -6
- data/lib/r10k/git.rb +7 -7
- data/lib/r10k/git/alternates.rb +1 -1
- data/lib/r10k/git/cache.rb +2 -2
- data/lib/r10k/git/rugged/bare_repository.rb +29 -9
- data/lib/r10k/git/rugged/credentials.rb +8 -8
- data/lib/r10k/git/rugged/thin_repository.rb +17 -3
- data/lib/r10k/git/rugged/working_repository.rb +12 -5
- data/lib/r10k/git/shellgit/thin_repository.rb +5 -1
- data/lib/r10k/git/shellgit/working_repository.rb +16 -2
- data/lib/r10k/git/stateful_repository.rb +33 -23
- data/lib/r10k/initializers.rb +1 -1
- data/lib/r10k/keyed_factory.rb +2 -2
- data/lib/r10k/logging.rb +1 -1
- data/lib/r10k/module.rb +4 -3
- data/lib/r10k/module/base.rb +3 -2
- data/lib/r10k/module/forge.rb +9 -4
- data/lib/r10k/module/git.rb +39 -22
- data/lib/r10k/module/local.rb +1 -1
- data/lib/r10k/module/metadata_file.rb +1 -1
- data/lib/r10k/module/svn.rb +3 -1
- data/lib/r10k/puppetfile.rb +72 -11
- data/lib/r10k/settings.rb +20 -0
- data/lib/r10k/settings/collection.rb +2 -2
- data/lib/r10k/settings/container.rb +1 -1
- data/lib/r10k/settings/enum_definition.rb +11 -3
- data/lib/r10k/settings/helpers.rb +2 -2
- data/lib/r10k/settings/list.rb +1 -1
- data/lib/r10k/settings/loader.rb +6 -6
- data/lib/r10k/settings/uri_definition.rb +1 -1
- data/lib/r10k/source/base.rb +2 -2
- data/lib/r10k/source/git.rb +4 -4
- data/lib/r10k/svn/working_dir.rb +1 -1
- data/lib/r10k/util/basedir.rb +9 -9
- data/lib/r10k/util/license.rb +3 -3
- data/lib/r10k/util/purgeable.rb +50 -24
- data/lib/r10k/util/setopts.rb +1 -1
- data/lib/r10k/util/subprocess.rb +3 -3
- data/lib/r10k/util/symbolize_keys.rb +1 -1
- data/lib/r10k/version.rb +1 -1
- data/locales/config.yaml +21 -0
- data/r10k.gemspec +3 -0
- data/spec/fixtures/unit/puppetfile/valid-forge-with-version/Puppetfile +1 -0
- data/spec/fixtures/unit/puppetfile/valid-forge-without-version/Puppetfile +1 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/expected_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_expected_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/subdir_unmanaged_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_one/unmanaged_1 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_two/expected_2 +0 -0
- data/spec/fixtures/unit/util/purgeable/managed_two/unmanaged_2 +0 -0
- data/spec/integration/git/stateful_repository_spec.rb +39 -21
- data/spec/r10k-mocks/mock_config.rb +4 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/action/deploy/environment_spec.rb +71 -13
- data/spec/unit/environment/base_spec.rb +71 -0
- data/spec/unit/forge/module_release_spec.rb +7 -10
- data/spec/unit/git/stateful_repository_spec.rb +6 -6
- data/spec/unit/module/git_spec.rb +156 -5
- data/spec/unit/module_spec.rb +3 -3
- data/spec/unit/puppetfile_spec.rb +115 -0
- data/spec/unit/util/purgeable_spec.rb +230 -0
- metadata +45 -18
- data/integration/test_run_scripts/README.mkd +0 -5
- data/integration/test_run_scripts/all_tests-rugged-pe-centos6.sh +0 -20
- data/integration/test_run_scripts/all_tests-rugged-pe-rhel7.sh +0 -20
- data/integration/test_run_scripts/all_tests-rugged-pe-sles11.sh +0 -20
- data/integration/test_run_scripts/all_tests-rugged-pe-ubuntu1204.sh +0 -20
- data/integration/test_run_scripts/all_tests-rugged-pe-ubuntu1404.sh +0 -20
- data/integration/test_run_scripts/all_tests-shellgit-pe-centos6.sh +0 -20
- data/integration/test_run_scripts/all_tests-shellgit-pe-rhel7.sh +0 -20
- data/integration/test_run_scripts/all_tests-shellgit-pe-sles11.sh +0 -20
- data/integration/test_run_scripts/all_tests-shellgit-pe-ubuntu1204.sh +0 -20
- data/integration/test_run_scripts/all_tests-shellgit-pe-ubuntu1404.sh +0 -20
- data/integration/test_run_scripts/basic_functionality/all_tests-pe-centos6.sh +0 -20
- data/integration/test_run_scripts/command_line/all_tests-pe-centos6.sh +0 -20
- data/integration/test_run_scripts/git_source/all_tests-pe-centos6.sh +0 -20
- data/integration/test_run_scripts/user_scenario/basic_workflow/all_tests-pe-centos6.sh +0 -20
- data/integration/test_run_scripts/user_scenario/complex_workflow/all_tests-pe-centos6.sh +0 -20
data/lib/r10k/puppetfile.rb
CHANGED
@@ -29,30 +29,39 @@ class Puppetfile
|
|
29
29
|
# @return [String] The path to the Puppetfile
|
30
30
|
attr_reader :puppetfile_path
|
31
31
|
|
32
|
+
# @!attribute [rw] environment
|
33
|
+
# @return [R10K::Environment] Optional R10K::Environment that this Puppetfile belongs to.
|
34
|
+
attr_accessor :environment
|
35
|
+
|
32
36
|
# @param [String] basedir
|
33
|
-
# @param [String]
|
34
|
-
|
37
|
+
# @param [String] moduledir The directory to install the modules, default to #{basedir}/modules
|
38
|
+
# @param [String] puppetfile_path The path to the Puppetfile, default to #{basedir}/Puppetfile
|
39
|
+
def initialize(basedir, moduledir = nil, puppetfile_path = nil)
|
35
40
|
@basedir = basedir
|
36
41
|
@moduledir = moduledir || File.join(basedir, 'modules')
|
37
|
-
@puppetfile_path =
|
42
|
+
@puppetfile_path = puppetfile_path || File.join(basedir, 'Puppetfile')
|
38
43
|
|
39
44
|
@modules = []
|
45
|
+
@managed_content = {}
|
40
46
|
@forge = 'forgeapi.puppetlabs.com'
|
47
|
+
|
48
|
+
@loaded = false
|
41
49
|
end
|
42
50
|
|
43
51
|
def load
|
44
52
|
if File.readable? @puppetfile_path
|
45
53
|
self.load!
|
46
54
|
else
|
47
|
-
logger.debug "Puppetfile
|
55
|
+
logger.debug _("Puppetfile %{path} missing or unreadable") % {path: @puppetfile_path.inspect}
|
48
56
|
end
|
49
57
|
end
|
50
58
|
|
51
59
|
def load!
|
52
60
|
dsl = R10K::Puppetfile::DSL.new(self)
|
53
61
|
dsl.instance_eval(puppetfile_contents, @puppetfile_path)
|
62
|
+
@loaded = true
|
54
63
|
rescue SyntaxError, LoadError, ArgumentError => e
|
55
|
-
raise R10K::Error.wrap(e, "Failed to evaluate
|
64
|
+
raise R10K::Error.wrap(e, _("Failed to evaluate %{path}") % {path: @puppetfile_path})
|
56
65
|
end
|
57
66
|
|
58
67
|
# @param [String] forge
|
@@ -72,20 +81,49 @@ class Puppetfile
|
|
72
81
|
# @param [String] name
|
73
82
|
# @param [*Object] args
|
74
83
|
def add_module(name, args)
|
75
|
-
|
84
|
+
if args.is_a?(Hash) && install_path = args.delete(:install_path)
|
85
|
+
install_path = resolve_install_path(install_path)
|
86
|
+
validate_install_path(install_path, name)
|
87
|
+
else
|
88
|
+
install_path = @moduledir
|
89
|
+
end
|
90
|
+
|
91
|
+
# Keep track of all the content this Puppetfile is managing to enable purging.
|
92
|
+
@managed_content[install_path] = Array.new unless @managed_content.has_key?(install_path)
|
93
|
+
|
94
|
+
mod = R10K::Module.new(name, install_path, args, @environment)
|
95
|
+
|
96
|
+
@managed_content[install_path] << mod.name
|
97
|
+
@modules << mod
|
76
98
|
end
|
77
99
|
|
78
100
|
include R10K::Util::Purgeable
|
79
101
|
|
80
|
-
def
|
81
|
-
@
|
102
|
+
def managed_directories
|
103
|
+
self.load unless @loaded
|
104
|
+
|
105
|
+
@managed_content.keys
|
82
106
|
end
|
83
107
|
|
84
|
-
#
|
108
|
+
# Returns an array of the full paths to all the content being managed.
|
85
109
|
# @note This implements a required method for the Purgeable mixin
|
86
110
|
# @return [Array<String>]
|
87
111
|
def desired_contents
|
88
|
-
|
112
|
+
self.load unless @loaded
|
113
|
+
|
114
|
+
@managed_content.flat_map do |install_path, modnames|
|
115
|
+
modnames.collect { |name| File.join(install_path, name) }
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def purge_exclusions
|
120
|
+
exclusions = managed_directories
|
121
|
+
|
122
|
+
if environment && environment.respond_to?(:desired_contents)
|
123
|
+
exclusions += environment.desired_contents
|
124
|
+
end
|
125
|
+
|
126
|
+
exclusions
|
89
127
|
end
|
90
128
|
|
91
129
|
def accept(visitor)
|
@@ -102,6 +140,29 @@ class Puppetfile
|
|
102
140
|
File.read(@puppetfile_path)
|
103
141
|
end
|
104
142
|
|
143
|
+
def resolve_install_path(path)
|
144
|
+
pn = Pathname.new(path)
|
145
|
+
|
146
|
+
unless pn.absolute?
|
147
|
+
pn = Pathname.new(File.join(basedir, path))
|
148
|
+
end
|
149
|
+
|
150
|
+
# .cleanpath is as good as we can do without touching the filesystem.
|
151
|
+
# The .realpath methods will also choke if some of the intermediate
|
152
|
+
# paths are missing, even though we will create them later as needed.
|
153
|
+
pn.cleanpath.to_s
|
154
|
+
end
|
155
|
+
|
156
|
+
def validate_install_path(path, modname)
|
157
|
+
real_basedir = Pathname.new(basedir).cleanpath.to_s
|
158
|
+
|
159
|
+
unless /^#{Regexp.escape(real_basedir)}.*/ =~ path
|
160
|
+
raise R10K::Error.new("Puppetfile cannot manage content '#{modname}' outside of containing environment: #{path} is not within #{real_basedir}")
|
161
|
+
end
|
162
|
+
|
163
|
+
true
|
164
|
+
end
|
165
|
+
|
105
166
|
class DSL
|
106
167
|
# A barebones implementation of the Puppetfile DSL
|
107
168
|
#
|
@@ -124,7 +185,7 @@ class Puppetfile
|
|
124
185
|
end
|
125
186
|
|
126
187
|
def method_missing(method, *args)
|
127
|
-
raise NoMethodError, "unrecognized declaration '
|
188
|
+
raise NoMethodError, _("unrecognized declaration '%{method}'") % {method: method}
|
128
189
|
end
|
129
190
|
end
|
130
191
|
end
|
data/lib/r10k/settings.rb
CHANGED
@@ -84,6 +84,26 @@ module R10K
|
|
84
84
|
end
|
85
85
|
end
|
86
86
|
}),
|
87
|
+
|
88
|
+
EnumDefinition.new(:purge_levels, {
|
89
|
+
:desc => "Controls how aggressively r10k will purge unmanaged content from the target directory. Should be a list of values indicating at what levels unmanaged content should be purged. Options are 'deployment', 'environment', and 'puppetfile'. For backwards compatibility, the default is ['deployment', 'puppetfile'].",
|
90
|
+
:multi => true,
|
91
|
+
:enum => [:deployment, :environment, :puppetfile],
|
92
|
+
:default => [:deployment, :puppetfile],
|
93
|
+
:normalize => lambda do |input|
|
94
|
+
if input.respond_to?(:collect)
|
95
|
+
input.collect { |val| val.to_sym }
|
96
|
+
else
|
97
|
+
# Convert single values to a list of one symbolized value.
|
98
|
+
[input.to_sym]
|
99
|
+
end
|
100
|
+
end,
|
101
|
+
}),
|
102
|
+
|
103
|
+
Definition.new(:purge_whitelist, {
|
104
|
+
:desc => "A list of filename patterns to be excluded from any purge operations. Patterns are matched relative to the root of each deployed environment, if you want a pattern to match recursively you need to use the '**' glob in your pattern. Basic shell style globs are supported.",
|
105
|
+
:default => [],
|
106
|
+
}),
|
87
107
|
])
|
88
108
|
end
|
89
109
|
|
@@ -74,9 +74,9 @@ module R10K
|
|
74
74
|
|
75
75
|
if !errors.empty?
|
76
76
|
if @name
|
77
|
-
msg = "Validation failed for '
|
77
|
+
msg = _("Validation failed for '%{name}' settings group") % {name: @name}
|
78
78
|
else
|
79
|
-
msg = "Validation failed for settings group"
|
79
|
+
msg = _("Validation failed for settings group")
|
80
80
|
end
|
81
81
|
|
82
82
|
raise ValidationError.new(msg, :errors => errors)
|
@@ -6,8 +6,16 @@ module R10K
|
|
6
6
|
|
7
7
|
def validate
|
8
8
|
if @value
|
9
|
-
if
|
10
|
-
|
9
|
+
if @multi && @value.respond_to?(:select)
|
10
|
+
invalid = @value.select { |val| !@enum.include?(val) }
|
11
|
+
|
12
|
+
if invalid.size > 0
|
13
|
+
raise ArgumentError, _("Setting %{name} may only contain %{enums}; the disallowed values %{invalid} were present") % {name: @name, enums: @enum.inspect, invalid: invalid.inspect}
|
14
|
+
end
|
15
|
+
else
|
16
|
+
if !@enum.include?(@value)
|
17
|
+
raise ArgumentError, _("Setting %{name} should be one of %{enums}, not '%{value}'") % {name: @name, enums: @enum.inspect, value: @value}
|
18
|
+
end
|
11
19
|
end
|
12
20
|
end
|
13
21
|
end
|
@@ -15,7 +23,7 @@ module R10K
|
|
15
23
|
private
|
16
24
|
|
17
25
|
def allowed_initialize_opts
|
18
|
-
super.merge({:enum => true})
|
26
|
+
super.merge({:enum => true, :multi => true})
|
19
27
|
end
|
20
28
|
end
|
21
29
|
end
|
@@ -16,11 +16,11 @@ module R10K
|
|
16
16
|
# @param new_parent [R10K::Settings::Collection] Parent collection
|
17
17
|
def parent=(new_parent)
|
18
18
|
unless @parent.nil?
|
19
|
-
raise R10K::Error.new("
|
19
|
+
raise R10K::Error.new(_("%{class} instances cannot be reassigned to a new parent.") % {class: self.class} )
|
20
20
|
end
|
21
21
|
|
22
22
|
unless new_parent.is_a?(R10K::Settings::Collection) || new_parent.is_a?(R10K::Settings::List)
|
23
|
-
raise R10K::Error.new("
|
23
|
+
raise R10K::Error.new(_("%{class} instances may only belong to a settings collection or list.") % {class: self.class} )
|
24
24
|
end
|
25
25
|
|
26
26
|
@parent = new_parent
|
data/lib/r10k/settings/list.rb
CHANGED
@@ -63,7 +63,7 @@ module R10K
|
|
63
63
|
end
|
64
64
|
|
65
65
|
if !errors.empty?
|
66
|
-
raise ValidationError.new("Validation failed for '
|
66
|
+
raise ValidationError.new(_("Validation failed for '%{name}' settings list") % {name: @name}, :errors => errors)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
data/lib/r10k/settings/loader.rb
CHANGED
@@ -42,15 +42,15 @@ module R10K
|
|
42
42
|
|
43
43
|
# If both default files are present, issue a warning.
|
44
44
|
if (File.file? DEFAULT_LOCATION) && (File.file? OLD_DEFAULT_LOCATION)
|
45
|
-
logger.warn "Both
|
46
|
-
logger.warn "
|
45
|
+
logger.warn _("Both %{default_path} and %{old_default_path} configuration files exist.") % {default_path: DEFAULT_LOCATION, old_default_path: OLD_DEFAULT_LOCATION}
|
46
|
+
logger.warn _("%{default_path} will be used.") % {default_path: DEFAULT_LOCATION}
|
47
47
|
end
|
48
48
|
|
49
49
|
path = @loadpath.find {|filename| File.file? filename}
|
50
50
|
|
51
51
|
if path == OLD_DEFAULT_LOCATION
|
52
|
-
logger.warn "The r10k configuration file at
|
53
|
-
logger.warn "Please move your r10k configuration to
|
52
|
+
logger.warn _("The r10k configuration file at %{old_default_path} is deprecated.") % {old_default_path: OLD_DEFAULT_LOCATION}
|
53
|
+
logger.warn _("Please move your r10k configuration to %{default_path}.") % {default_path: DEFAULT_LOCATION}
|
54
54
|
end
|
55
55
|
|
56
56
|
path
|
@@ -60,13 +60,13 @@ module R10K
|
|
60
60
|
path = search(override)
|
61
61
|
|
62
62
|
if path.nil?
|
63
|
-
raise ConfigError, "No configuration file given, no config file found in current directory, and no global config present"
|
63
|
+
raise ConfigError, _("No configuration file given, no config file found in current directory, and no global config present")
|
64
64
|
end
|
65
65
|
|
66
66
|
begin
|
67
67
|
contents = ::YAML.load_file(path)
|
68
68
|
rescue => e
|
69
|
-
raise ConfigError, "Couldn't load config file:
|
69
|
+
raise ConfigError, _("Couldn't load config file: %{error_msg}") % {error_msg: e.message}
|
70
70
|
end
|
71
71
|
|
72
72
|
R10K::Util::SymbolizeKeys.symbolize_keys!(contents, true)
|
@@ -9,7 +9,7 @@ module R10K
|
|
9
9
|
begin
|
10
10
|
URI.parse(@value)
|
11
11
|
rescue URI::Error
|
12
|
-
raise ArgumentError, "Setting
|
12
|
+
raise ArgumentError, _("Setting %{name} requires a URL but '%{value}' could not be parsed as a URL") % {name: @name, value: @value}
|
13
13
|
end
|
14
14
|
end
|
15
15
|
super
|
data/lib/r10k/source/base.rb
CHANGED
@@ -28,7 +28,7 @@ class R10K::Source::Base
|
|
28
28
|
# Defaults to false for no environment prefix.
|
29
29
|
def initialize(name, basedir, options = {})
|
30
30
|
@name = name
|
31
|
-
@basedir = basedir
|
31
|
+
@basedir = Pathname.new(basedir).cleanpath.to_s
|
32
32
|
@prefix = options.delete(:prefix)
|
33
33
|
@options = options
|
34
34
|
end
|
@@ -55,7 +55,7 @@ class R10K::Source::Base
|
|
55
55
|
# @return [Array<R10K::Environment::Base>] An array of environments created
|
56
56
|
# from this source.
|
57
57
|
def environments
|
58
|
-
raise NotImplementedError, "
|
58
|
+
raise NotImplementedError, _("%{class} has not implemented method %{method}") % {class: self.class, method: __method__}
|
59
59
|
end
|
60
60
|
|
61
61
|
def accept(visitor)
|
data/lib/r10k/source/git.rb
CHANGED
@@ -63,10 +63,10 @@ class R10K::Source::Git < R10K::Source::Base
|
|
63
63
|
#
|
64
64
|
# @return [void]
|
65
65
|
def preload!
|
66
|
-
logger.debug "Fetching '
|
66
|
+
logger.debug _("Fetching '%{remote}' to determine current branches.") % {remote: @remote}
|
67
67
|
@cache.sync
|
68
68
|
rescue => e
|
69
|
-
raise R10K::Error.wrap(e, "Unable to determine current branches for Git source '
|
69
|
+
raise R10K::Error.wrap(e, _("Unable to determine current branches for Git source '%{name}' (%{basedir})") % {name: @name, basedir: @basedir})
|
70
70
|
end
|
71
71
|
alias fetch_remote preload!
|
72
72
|
|
@@ -91,11 +91,11 @@ class R10K::Source::Git < R10K::Source::Base
|
|
91
91
|
envs << R10K::Environment::Git.new(bn.name, @basedir, bn.dirname,
|
92
92
|
{:remote => remote, :ref => bn.name})
|
93
93
|
elsif bn.correct?
|
94
|
-
logger.warn "Environment
|
94
|
+
logger.warn _("Environment %{env_name} contained non-word characters, correcting name to %{corrected_env_name}") % {env_name: bn.name.inspect, corrected_env_name: bn.dirname}
|
95
95
|
envs << R10K::Environment::Git.new(bn.name, @basedir, bn.dirname,
|
96
96
|
{:remote => remote, :ref => bn.name})
|
97
97
|
elsif bn.validate?
|
98
|
-
logger.error "Environment
|
98
|
+
logger.error _("Environment %{env_name} contained non-word characters, ignoring it.") % {env_name: bn.name.inspect}
|
99
99
|
end
|
100
100
|
end
|
101
101
|
|
data/lib/r10k/svn/working_dir.rb
CHANGED
@@ -40,7 +40,7 @@ module R10K
|
|
40
40
|
setopts(opts, {:username => :self, :password => :self})
|
41
41
|
|
42
42
|
if !!(@username) ^ !!(@password)
|
43
|
-
raise ArgumentError, "Both username and password must be specified"
|
43
|
+
raise ArgumentError, _("Both username and password must be specified")
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
data/lib/r10k/util/basedir.rb
CHANGED
@@ -31,7 +31,7 @@ module R10K
|
|
31
31
|
# @param sources [Array<#desired_contents>] A list of objects that may create filesystem entries
|
32
32
|
def initialize(path, sources)
|
33
33
|
if sources.is_a? R10K::Deployment
|
34
|
-
raise ArgumentError, "Expected Array<#desired_contents>, got R10K::Deployment"
|
34
|
+
raise ArgumentError, _("Expected Array<#desired_contents>, got R10K::Deployment")
|
35
35
|
end
|
36
36
|
@path = path
|
37
37
|
@sources = sources
|
@@ -39,25 +39,25 @@ module R10K
|
|
39
39
|
|
40
40
|
# Return the path of the basedir
|
41
41
|
# @note This implements a required method for the Purgeable mixin
|
42
|
-
# @return [
|
43
|
-
def
|
44
|
-
@path
|
42
|
+
# @return [Array]
|
43
|
+
def managed_directories
|
44
|
+
[@path]
|
45
45
|
end
|
46
46
|
|
47
47
|
# List all environments that should exist in this basedir
|
48
48
|
# @note This implements a required method for the Purgeable mixin
|
49
49
|
# @return [Array<String>]
|
50
50
|
def desired_contents
|
51
|
-
@sources.
|
51
|
+
@sources.flat_map do |src|
|
52
|
+
src.desired_contents.collect { |env| File.join(@path, env) }
|
53
|
+
end
|
52
54
|
end
|
53
55
|
|
54
56
|
def purge!
|
55
57
|
@sources.each do |source|
|
56
|
-
logger.debug1 "Source
|
57
|
-
end
|
58
|
-
if !stale_contents.empty?
|
59
|
-
logger.debug "The path #{@path} has unmanaged contents #{stale_contents.inspect}"
|
58
|
+
logger.debug1 _("Source %{source_name} in %{path} manages contents %{contents}") % {source_name: source.name, path: @path, contents: source.desired_contents.inspect}
|
60
59
|
end
|
60
|
+
|
61
61
|
super
|
62
62
|
end
|
63
63
|
end
|
data/lib/r10k/util/license.rb
CHANGED
@@ -8,14 +8,14 @@ module R10K
|
|
8
8
|
|
9
9
|
def self.load
|
10
10
|
if R10K::Features.available?(:pe_license)
|
11
|
-
logger.debug2 "pe_license feature is available, loading PE license key"
|
11
|
+
logger.debug2 _("pe_license feature is available, loading PE license key")
|
12
12
|
begin
|
13
13
|
return PELicense.load_license_key
|
14
14
|
rescue PELicense::InvalidLicenseError => e
|
15
|
-
raise R10K::Error.wrap(e, "Invalid PE license detected:
|
15
|
+
raise R10K::Error.wrap(e, _("Invalid PE license detected: %{error_msg}") % {error_msg: e.message} )
|
16
16
|
end
|
17
17
|
else
|
18
|
-
logger.debug2 "pe_license feature is not available, PE only Puppet modules will not be downloadable."
|
18
|
+
logger.debug2 _("pe_license feature is not available, PE only Puppet modules will not be downloadable.")
|
19
19
|
nil
|
20
20
|
end
|
21
21
|
end
|
data/lib/r10k/util/purgeable.rb
CHANGED
@@ -15,43 +15,69 @@ module R10K
|
|
15
15
|
|
16
16
|
# @!method desired_contents
|
17
17
|
# @abstract Including classes must implement this method to list the
|
18
|
-
# expected filenames of
|
19
|
-
# @return [Array<String>]
|
18
|
+
# expected filenames of managed_directories
|
19
|
+
# @return [Array<String>] The full paths to all the content this object is managing
|
20
20
|
|
21
|
-
# @!method
|
22
|
-
# @abstract Including classes must implement this method to return
|
23
|
-
#
|
24
|
-
# @return [String] The
|
21
|
+
# @!method managed_directories
|
22
|
+
# @abstract Including classes must implement this method to return an array of
|
23
|
+
# paths that can be purged
|
24
|
+
# @return [Array<String>] The paths to the directories to be purged
|
25
25
|
|
26
|
-
# @return [Array<String>] The present directory entries in `self.
|
27
|
-
def current_contents
|
28
|
-
|
29
|
-
glob_exp = File.join(dir, '*')
|
26
|
+
# @return [Array<String>] The present directory entries in `self.managed_directories`
|
27
|
+
def current_contents(recurse)
|
28
|
+
dirs = self.managed_directories
|
30
29
|
|
31
|
-
|
32
|
-
|
30
|
+
dirs.flat_map do |dir|
|
31
|
+
if recurse
|
32
|
+
glob_exp = File.join(dir, '**', '{*,.[^.]*}')
|
33
|
+
else
|
34
|
+
glob_exp = File.join(dir, '*')
|
35
|
+
end
|
36
|
+
|
37
|
+
Dir.glob(glob_exp)
|
33
38
|
end
|
34
39
|
end
|
35
40
|
|
36
41
|
# @return [Array<String>] Directory contents that are expected but not present
|
37
|
-
def pending_contents
|
38
|
-
desired_contents - current_contents
|
42
|
+
def pending_contents(recurse)
|
43
|
+
desired_contents - current_contents(recurse)
|
39
44
|
end
|
40
45
|
|
41
46
|
# @return [Array<String>] Directory contents that are present but not expected
|
42
|
-
def stale_contents
|
43
|
-
current_contents - desired_contents
|
47
|
+
def stale_contents(recurse, exclusions, whitelist)
|
48
|
+
(current_contents(recurse) - desired_contents).reject do |item|
|
49
|
+
if exclusion_match = exclusions.find { |ex_item| File.fnmatch?(ex_item, item, File::FNM_PATHNAME | File::FNM_DOTMATCH) }
|
50
|
+
logger.debug2 _("Not purging %{item} due to internal exclusion match: %{exclusion_match}") % {item: item, exclusion_match: exclusion_match}
|
51
|
+
elsif whitelist_match = whitelist.find { |wl_item| File.fnmatch?(wl_item, item, File::FNM_PATHNAME | File::FNM_DOTMATCH) }
|
52
|
+
logger.debug _("Not purging %{item} due to whitelist match: %{whitelist_match}") % {item: item, whitelist_match: whitelist_match}
|
53
|
+
end
|
54
|
+
|
55
|
+
!!exclusion_match || !!whitelist_match
|
56
|
+
end
|
44
57
|
end
|
45
58
|
|
46
|
-
# Forcibly remove all unmanaged content in `self.
|
47
|
-
def purge!
|
48
|
-
|
49
|
-
|
59
|
+
# Forcibly remove all unmanaged content in `self.managed_directories`
|
60
|
+
def purge!(opts={})
|
61
|
+
recurse = opts[:recurse] || false
|
62
|
+
whitelist = opts[:whitelist] || []
|
63
|
+
|
64
|
+
exclusions = self.respond_to?(:purge_exclusions) ? purge_exclusions : []
|
65
|
+
|
66
|
+
stale = stale_contents(recurse, exclusions, whitelist)
|
67
|
+
|
68
|
+
if stale.empty?
|
69
|
+
logger.debug1 _("No unmanaged contents in %{managed_dirs}, nothing to purge") % {managed_dirs: managed_directories.join(', ')}
|
50
70
|
else
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
71
|
+
stale.each do |fpath|
|
72
|
+
begin
|
73
|
+
FileUtils.rm_r(fpath, :secure => true)
|
74
|
+
logger.info _("Removing unmanaged path %{path}") % {path: fpath}
|
75
|
+
rescue Errno::ENOENT
|
76
|
+
# Don't log on ENOENT since we may encounter that from recursively deleting
|
77
|
+
# this item's parent earlier in the purge.
|
78
|
+
rescue
|
79
|
+
logger.debug1 _("Unable to remove unmanaged path: %{path}") % {path: fpath}
|
80
|
+
end
|
55
81
|
end
|
56
82
|
end
|
57
83
|
end
|