r10k 3.3.0 → 3.3.1
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/.travis.yml +2 -11
- data/CHANGELOG.mkd +68 -35
- data/CODEOWNERS +1 -0
- data/README.mkd +0 -6
- data/azure-pipelines.yml +58 -58
- data/doc/dynamic-environments/usage.mkd +12 -0
- data/doc/faq.mkd +6 -1
- data/docker/Gemfile +4 -14
- data/docker/Makefile +6 -7
- data/docker/r10k/Dockerfile +15 -5
- data/docker/{r10k/spec → spec}/dockerfile_spec.rb +1 -10
- data/docker/{r10k/spec → spec}/fixtures/Puppetfile +0 -0
- data/lib/r10k/action/deploy/environment.rb +20 -2
- data/lib/r10k/cli/deploy.rb +1 -0
- data/lib/r10k/forge/module_release.rb +51 -33
- data/lib/r10k/module/git.rb +5 -0
- data/lib/r10k/puppetfile.rb +28 -5
- data/lib/r10k/util/platform.rb +12 -0
- data/lib/r10k/version.rb +1 -1
- data/locales/r10k.pot +10 -6
- data/r10k.gemspec +1 -1
- data/spec/fixtures/unit/puppetfile/default-branch-override/Puppetfile +5 -0
- data/spec/unit/action/deploy/environment_spec.rb +63 -0
- data/spec/unit/forge/module_release_spec.rb +63 -27
- data/spec/unit/puppetfile_spec.rb +19 -0
- metadata +8 -8
- data/docker/ci/build.ps1 +0 -108
- data/integration/tests/basic_functionality/negative/attempt_to_install_peonly_module_without_license.rb +0 -71
data/docker/Makefile
CHANGED
@@ -4,18 +4,18 @@ git_describe = $(shell git describe)
|
|
4
4
|
vcs_ref := $(shell git rev-parse HEAD)
|
5
5
|
build_date := $(shell date -u +%FT%T)
|
6
6
|
hadolint_available := $(shell hadolint --help > /dev/null 2>&1; echo $$?)
|
7
|
-
hadolint_command := hadolint --ignore DL3008 --ignore DL3018 --ignore DL4000 --ignore DL4001
|
7
|
+
hadolint_command := hadolint --ignore DL3008 --ignore DL3018 --ignore DL3028 --ignore DL4000 --ignore DL4001
|
8
8
|
hadolint_container := hadolint/hadolint:latest
|
9
9
|
pwd := $(shell pwd)
|
10
10
|
export BUNDLE_PATH = $(pwd)/.bundle/gems
|
11
11
|
export BUNDLE_BIN = $(pwd)/.bundle/bin
|
12
12
|
export GEMFILE = $(pwd)/Gemfile
|
13
13
|
|
14
|
-
version
|
14
|
+
version := $(shell command grep VERSION ../lib/r10k/version.rb | awk '{print $$3}' | sed "s/'//g")
|
15
15
|
dockerfile := Dockerfile
|
16
16
|
|
17
17
|
prep:
|
18
|
-
@git fetch --unshallow ||:
|
18
|
+
@git fetch --unshallow 2> /dev/null ||:
|
19
19
|
@git fetch origin 'refs/tags/*:refs/tags/*'
|
20
20
|
|
21
21
|
lint:
|
@@ -34,8 +34,7 @@ build: prep
|
|
34
34
|
--build-arg version=$(version) \
|
35
35
|
--build-arg pupperware_analytics_stream=$(PUPPERWARE_ANALYTICS_STREAM) \
|
36
36
|
--file r10k/$(dockerfile) \
|
37
|
-
--tag $(NAMESPACE)/r10k:$(version)
|
38
|
-
r10k
|
37
|
+
--tag $(NAMESPACE)/r10k:$(version) $(pwd)/..
|
39
38
|
ifeq ($(IS_LATEST),true)
|
40
39
|
@docker tag $(NAMESPACE)/r10k:$(version) puppet/r10k:latest
|
41
40
|
endif
|
@@ -44,7 +43,7 @@ test: prep
|
|
44
43
|
@bundle install --path $$BUNDLE_PATH --gemfile $$GEMFILE
|
45
44
|
@PUPPET_TEST_DOCKER_IMAGE=$(NAMESPACE)/r10k:$(version) \
|
46
45
|
bundle exec --gemfile $$GEMFILE \
|
47
|
-
rspec
|
46
|
+
rspec spec
|
48
47
|
|
49
48
|
push-image: prep
|
50
49
|
@docker push $(NAMESPACE)/r10k:$(version)
|
@@ -64,4 +63,4 @@ push-readme:
|
|
64
63
|
|
65
64
|
publish: push-image push-readme
|
66
65
|
|
67
|
-
.PHONY:
|
66
|
+
.PHONY: lint build test prep publish push-image push-readme
|
data/docker/r10k/Dockerfile
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
FROM alpine:3.9 as build
|
2
|
+
|
3
|
+
RUN apk add --no-cache ruby git
|
4
|
+
RUN mkdir /workspace
|
5
|
+
WORKDIR /workspace
|
6
|
+
COPY . /workspace
|
7
|
+
RUN gem build r10k.gemspec && \
|
8
|
+
mv r10k*.gem r10k.gem
|
9
|
+
|
1
10
|
FROM alpine:3.9
|
2
11
|
|
3
12
|
ARG vcs_ref
|
@@ -23,14 +32,15 @@ LABEL org.label-schema.maintainer="Puppet Release Team <release@puppet.com>" \
|
|
23
32
|
org.label-schema.dockerfile="/Dockerfile"
|
24
33
|
|
25
34
|
RUN apk add --no-cache ruby openssh-client git ruby-rugged curl ruby-dev make gcc musl-dev
|
35
|
+
COPY --from=build /workspace/r10k.gem /
|
36
|
+
RUN gem install --no-doc r10k.gem json etc && \
|
37
|
+
rm -f r10k.gem
|
26
38
|
|
27
|
-
|
28
|
-
|
29
|
-
COPY docker-entrypoint.sh /
|
39
|
+
COPY docker/r10k/docker-entrypoint.sh /
|
30
40
|
RUN chmod +x /docker-entrypoint.sh
|
31
|
-
COPY docker-entrypoint.d /docker-entrypoint.d
|
41
|
+
COPY docker/r10k/docker-entrypoint.d /docker-entrypoint.d
|
32
42
|
|
33
43
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
34
44
|
CMD ["help"]
|
35
45
|
|
36
|
-
COPY Dockerfile /
|
46
|
+
COPY docker/r10k/Dockerfile /
|
@@ -14,16 +14,7 @@ describe 'r10k container' do
|
|
14
14
|
end
|
15
15
|
|
16
16
|
before(:all) do
|
17
|
-
@image =
|
18
|
-
if @image.nil?
|
19
|
-
error_message = <<-MSG
|
20
|
-
* * * * *
|
21
|
-
PUPPET_TEST_DOCKER_IMAGE environment variable must be set so we
|
22
|
-
know which image to test against!
|
23
|
-
* * * * *
|
24
|
-
MSG
|
25
|
-
fail error_message
|
26
|
-
end
|
17
|
+
@image = require_test_image
|
27
18
|
end
|
28
19
|
|
29
20
|
after(:all) do
|
File without changes
|
@@ -129,7 +129,7 @@ module R10K
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def visit_puppetfile(puppetfile)
|
132
|
-
puppetfile.load
|
132
|
+
puppetfile.load(@opts[:'default-branch-override'])
|
133
133
|
|
134
134
|
yield
|
135
135
|
|
@@ -145,11 +145,24 @@ module R10K
|
|
145
145
|
end
|
146
146
|
|
147
147
|
def write_environment_info!(environment, started_at, success)
|
148
|
+
module_deploys = []
|
149
|
+
begin
|
150
|
+
environment.puppetfile.modules.each do |mod|
|
151
|
+
name = mod.name
|
152
|
+
version = mod.version
|
153
|
+
sha = mod.repo.head rescue nil
|
154
|
+
module_deploys.push({:name => name, :version => version, :sha => sha})
|
155
|
+
end
|
156
|
+
rescue
|
157
|
+
logger.debug("Unable to get environment module deploy data for .r10k-deploy.json at #{environment.path}")
|
158
|
+
end
|
159
|
+
|
148
160
|
File.open("#{environment.path}/.r10k-deploy.json", 'w') do |f|
|
149
161
|
deploy_info = environment.info.merge({
|
150
162
|
:started_at => started_at,
|
151
163
|
:finished_at => Time.new,
|
152
164
|
:deploy_success => success,
|
165
|
+
:module_deploys => module_deploys,
|
153
166
|
})
|
154
167
|
|
155
168
|
f.puts(JSON.pretty_generate(deploy_info))
|
@@ -166,7 +179,12 @@ module R10K
|
|
166
179
|
end
|
167
180
|
|
168
181
|
def allowed_initialize_opts
|
169
|
-
super.merge(puppetfile: :self,
|
182
|
+
super.merge(puppetfile: :self,
|
183
|
+
cachedir: :self,
|
184
|
+
'no-force': :self,
|
185
|
+
'generate-types': :self,
|
186
|
+
'puppet-path': :self,
|
187
|
+
'default-branch-override': :self)
|
170
188
|
end
|
171
189
|
end
|
172
190
|
end
|
data/lib/r10k/cli/deploy.rb
CHANGED
@@ -61,6 +61,7 @@ scheduled. On subsequent deployments, Puppetfile deployment will default to off.
|
|
61
61
|
DESCRIPTION
|
62
62
|
|
63
63
|
flag :p, :puppetfile, 'Deploy modules from a puppetfile'
|
64
|
+
required nil, :'default-branch-override', 'Specify a branchname to override the default branch in the puppetfile'
|
64
65
|
|
65
66
|
runner R10K::Action::CriRunner.wrap(R10K::Action::Deploy::Environment)
|
66
67
|
end
|
@@ -40,6 +40,10 @@ module R10K
|
|
40
40
|
# @return [Pathname] Where the md5 of the cached tarball is stored.
|
41
41
|
attr_accessor :md5_file_path
|
42
42
|
|
43
|
+
# @!attribute [rw] sha256_file_path
|
44
|
+
# @return [Pathname] Where the SHA256 of the cached tarball is stored.
|
45
|
+
attr_accessor :sha256_file_path
|
46
|
+
|
43
47
|
# @!attribute [rw] unpack_path
|
44
48
|
# @return [Pathname] Where the module will be unpacked to.
|
45
49
|
attr_accessor :unpack_path
|
@@ -65,6 +69,9 @@ module R10K
|
|
65
69
|
md5_filename = @forge_release.slug + '.md5'
|
66
70
|
@md5_file_path = @tarball_cache_root + md5_filename
|
67
71
|
|
72
|
+
sha256_filename = @forge_release.slug + '.sha256'
|
73
|
+
@sha256_file_path = @tarball_cache_root + sha256_filename
|
74
|
+
|
68
75
|
@unpack_path = Pathname.new(Dir.mktmpdir) + @forge_release.slug
|
69
76
|
end
|
70
77
|
|
@@ -104,54 +111,79 @@ module R10K
|
|
104
111
|
# module release checksum given by the Puppet Forge. On mismatch, remove
|
105
112
|
# the cached copy.
|
106
113
|
#
|
114
|
+
# @raise [R10K::Error] when no SHA256 is available and FIPS mode is on
|
107
115
|
# @return [void]
|
108
116
|
def verify
|
109
117
|
logger.debug1 "Verifying that #{@tarball_cache_path} matches checksum"
|
110
118
|
|
111
|
-
|
119
|
+
sha256_of_tarball = Digest::SHA256.file(@tarball_cache_path).hexdigest
|
112
120
|
|
113
|
-
if @
|
114
|
-
|
121
|
+
if @sha256_file_path.exist?
|
122
|
+
verify_from_file(sha256_of_tarball, @sha256_file_path)
|
115
123
|
else
|
116
|
-
|
124
|
+
if @forge_release.respond_to?(:file_sha256) && !@forge_release.file_sha256.nil? && !@forge_release.file_sha256.size.zero?
|
125
|
+
forge_256_checksum = @forge_release.file_sha256
|
126
|
+
verify_from_forge(sha256_of_tarball, forge_256_checksum, @sha256_file_path)
|
127
|
+
else
|
128
|
+
if R10K::Util::Platform.fips?
|
129
|
+
raise R10K::Error, "Could not verify module, no SHA256 checksum available, and MD5 checksums not allowed in FIPS mode"
|
130
|
+
end
|
131
|
+
|
132
|
+
logger.debug1 "No SHA256 checksum available, falling back to MD5"
|
133
|
+
md5_of_tarball = Digest::MD5.file(@tarball_cache_path).hexdigest
|
134
|
+
if @md5_file_path.exist?
|
135
|
+
verify_from_file(md5_of_tarball, @md5_file_path)
|
136
|
+
else
|
137
|
+
verify_from_forge(md5_of_tarball, @forge_release.file_md5, @md5_file_path)
|
138
|
+
end
|
139
|
+
end
|
117
140
|
end
|
118
141
|
end
|
119
142
|
|
120
|
-
# Verify the
|
143
|
+
# Verify the checksum of the cached tarball against the
|
121
144
|
# module release checksum stored in the cache as well.
|
122
145
|
# On mismatch, remove the cached copy of both files.
|
146
|
+
# @param tarball_checksum [String] the checksum (either md5 or SHA256)
|
147
|
+
# of the downloaded module tarball
|
148
|
+
# @param file [Pathname] the file containing the checksum as downloaded
|
149
|
+
# previously from the forge
|
150
|
+
# @param digest_class [Digest::SHA256, Digest::MD5] which checksum type
|
151
|
+
# to verify with
|
123
152
|
#
|
124
153
|
# @raise [PuppetForge::V3::Release::ChecksumMismatch] The
|
125
154
|
# cached module release checksum doesn't match the cached checksum.
|
126
155
|
#
|
127
156
|
# @return [void]
|
128
|
-
def
|
129
|
-
|
130
|
-
if
|
131
|
-
logger.error "
|
132
|
-
|
133
|
-
|
157
|
+
def verify_from_file(tarball_checksum, checksum_file_path)
|
158
|
+
checksum_from_file = File.read(checksum_file_path).strip
|
159
|
+
if tarball_checksum != checksum_from_file
|
160
|
+
logger.error "Checksum of #{@tarball_cache_path} (#{tarball_checksum}) does not match checksum #{checksum_from_file} in #{checksum_file_path}. Removing both files."
|
161
|
+
@tarball_cache_path.delete
|
162
|
+
checksum_file_path.delete
|
134
163
|
raise PuppetForge::V3::Release::ChecksumMismatch.new
|
135
164
|
end
|
136
165
|
end
|
137
166
|
|
138
|
-
# Verify the
|
167
|
+
# Verify the checksum of the cached tarball against the
|
139
168
|
# module release checksum from the forge.
|
140
169
|
# On mismatch, remove the cached copy of the tarball.
|
170
|
+
# @param tarball_checksum [String] the checksum (either md5 or SHA256)
|
171
|
+
# of the downloaded module tarball
|
172
|
+
# @param forge_checksum [String] the checksum downloaded from the Forge
|
173
|
+
# @param checksum_file_path [Pathname] the path to write the verified
|
174
|
+
# checksum to
|
141
175
|
#
|
142
176
|
# @raise [PuppetForge::V3::Release::ChecksumMismatch] The
|
143
177
|
# cached module release checksum doesn't match the forge checksum.
|
144
178
|
#
|
145
179
|
# @return [void]
|
146
|
-
def verify_from_forge(
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
logger.debug1 "MD5 of #{@tarball_cache_path} (#{md5_of_tarball}) does not match checksum #{md5_from_forge} found on the forge. Removing tarball."
|
151
|
-
cleanup_cached_tarball_path
|
180
|
+
def verify_from_forge(tarball_checksum, forge_checksum, checksum_file_path)
|
181
|
+
if tarball_checksum != forge_checksum
|
182
|
+
logger.debug1 "Checksum of #{@tarball_cache_path} (#{tarball_checksum}) does not match checksum #{forge_checksum} found on the forge. Removing tarball."
|
183
|
+
@tarball_cache_path.delete
|
152
184
|
raise PuppetForge::V3::Release::ChecksumMismatch.new
|
153
185
|
else
|
154
|
-
File.write(
|
186
|
+
File.write(checksum_file_path, forge_checksum)
|
155
187
|
end
|
156
188
|
end
|
157
189
|
|
@@ -191,20 +223,6 @@ module R10K
|
|
191
223
|
download_path.parent.rmtree
|
192
224
|
end
|
193
225
|
end
|
194
|
-
|
195
|
-
# Remove the cached module release.
|
196
|
-
def cleanup_cached_tarball_path
|
197
|
-
if tarball_cache_path.exist?
|
198
|
-
tarball_cache_path.delete
|
199
|
-
end
|
200
|
-
end
|
201
|
-
|
202
|
-
# Remove the module release md5.
|
203
|
-
def cleanup_md5_file_path
|
204
|
-
if md5_file_path.exist?
|
205
|
-
md5_file_path.delete
|
206
|
-
end
|
207
|
-
end
|
208
226
|
end
|
209
227
|
end
|
210
228
|
end
|
data/lib/r10k/module/git.rb
CHANGED
@@ -23,6 +23,11 @@ class R10K::Module::Git < R10K::Module::Base
|
|
23
23
|
# @return [String]
|
24
24
|
attr_reader :desired_ref
|
25
25
|
|
26
|
+
# @!attribute [r] default_ref
|
27
|
+
# @api private
|
28
|
+
# @return [String]
|
29
|
+
attr_reader :default_ref
|
30
|
+
|
26
31
|
def initialize(title, dirname, args, environment=nil)
|
27
32
|
super
|
28
33
|
|
data/lib/r10k/puppetfile.rb
CHANGED
@@ -63,17 +63,20 @@ class Puppetfile
|
|
63
63
|
@loaded = false
|
64
64
|
end
|
65
65
|
|
66
|
-
def load
|
66
|
+
def load(default_branch_override = nil)
|
67
67
|
if File.readable? @puppetfile_path
|
68
|
-
self.load!
|
68
|
+
self.load!(default_branch_override)
|
69
69
|
else
|
70
70
|
logger.debug _("Puppetfile %{path} missing or unreadable") % {path: @puppetfile_path.inspect}
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
def load!
|
74
|
+
def load!(default_branch_override = nil)
|
75
|
+
@default_branch_override = default_branch_override
|
76
|
+
|
75
77
|
dsl = R10K::Puppetfile::DSL.new(self)
|
76
78
|
dsl.instance_eval(puppetfile_contents, @puppetfile_path)
|
79
|
+
|
77
80
|
validate_no_duplicate_names(@modules)
|
78
81
|
@loaded = true
|
79
82
|
rescue SyntaxError, LoadError, ArgumentError, NameError => e
|
@@ -118,6 +121,10 @@ class Puppetfile
|
|
118
121
|
install_path = @moduledir
|
119
122
|
end
|
120
123
|
|
124
|
+
if args.is_a?(Hash) && @default_branch_override != nil
|
125
|
+
args[:default_branch] = @default_branch_override
|
126
|
+
end
|
127
|
+
|
121
128
|
# Keep track of all the content this Puppetfile is managing to enable purging.
|
122
129
|
@managed_content[install_path] = Array.new unless @managed_content.has_key?(install_path)
|
123
130
|
|
@@ -179,7 +186,21 @@ class Puppetfile
|
|
179
186
|
logger.debug _("Updating modules with %{pool_size} threads") % {pool_size: pool_size}
|
180
187
|
mods_queue = modules_queue(visitor)
|
181
188
|
thread_pool = pool_size.times.map { visitor_thread(visitor, mods_queue) }
|
182
|
-
|
189
|
+
thread_exception = nil
|
190
|
+
|
191
|
+
# If any threads raise an exception the deployment is considered a failure.
|
192
|
+
# In that event clear the queue, wait for other threads to finish their
|
193
|
+
# current work, then re-raise the first exception caught.
|
194
|
+
begin
|
195
|
+
thread_pool.each(&:join)
|
196
|
+
rescue => e
|
197
|
+
logger.error _("Error during concurrent deploy of a module: %{message}") % {message: e.message}
|
198
|
+
mods_queue.clear
|
199
|
+
thread_exception ||= e
|
200
|
+
retry
|
201
|
+
ensure
|
202
|
+
raise thread_exception unless thread_exception.nil?
|
203
|
+
end
|
183
204
|
end
|
184
205
|
|
185
206
|
def modules_queue(visitor)
|
@@ -195,8 +216,10 @@ class Puppetfile
|
|
195
216
|
begin
|
196
217
|
while mod = mods_queue.pop(true) do mod.accept(visitor) end
|
197
218
|
rescue ThreadError => e
|
198
|
-
logger.
|
219
|
+
logger.debug _("Module thread %{id} exiting: %{message}") % {message: e.message, id: Thread.current.object_id}
|
199
220
|
Thread.exit
|
221
|
+
rescue => e
|
222
|
+
Thread.main.raise(e)
|
200
223
|
end
|
201
224
|
end
|
202
225
|
end
|
data/lib/r10k/util/platform.rb
CHANGED
@@ -3,6 +3,8 @@ require 'rbconfig'
|
|
3
3
|
module R10K
|
4
4
|
module Util
|
5
5
|
module Platform
|
6
|
+
FIPS_FILE = "/proc/sys/crypto/fips_enabled"
|
7
|
+
|
6
8
|
def self.platform
|
7
9
|
# Test JRuby first to handle JRuby on Windows as well.
|
8
10
|
if self.jruby?
|
@@ -14,6 +16,16 @@ module R10K
|
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
19
|
+
# We currently only suport FIPS mode on redhat 7, where it is
|
20
|
+
# toggled via a file.
|
21
|
+
def self.fips?
|
22
|
+
if File.exist?(FIPS_FILE)
|
23
|
+
File.read(FIPS_FILE).chomp == "1"
|
24
|
+
else
|
25
|
+
false
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
17
29
|
def self.windows?
|
18
30
|
RbConfig::CONFIG['host_os'] =~ /mswin|win32|dos|mingw|cygwin/i
|
19
31
|
end
|
data/lib/r10k/version.rb
CHANGED
data/locales/r10k.pot
CHANGED
@@ -6,11 +6,11 @@
|
|
6
6
|
#, fuzzy
|
7
7
|
msgid ""
|
8
8
|
msgstr ""
|
9
|
-
"Project-Id-Version: r10k 3.
|
9
|
+
"Project-Id-Version: r10k 3.3.0-7-g6a2159a\n"
|
10
10
|
"\n"
|
11
11
|
"Report-Msgid-Bugs-To: docs@puppetlabs.com\n"
|
12
|
-
"POT-Creation-Date: 2019-
|
13
|
-
"PO-Revision-Date: 2019-
|
12
|
+
"POT-Creation-Date: 2019-06-14 22:40+0000\n"
|
13
|
+
"PO-Revision-Date: 2019-06-14 22:40+0000\n"
|
14
14
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
15
15
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
16
16
|
"Language: \n"
|
@@ -343,11 +343,15 @@ msgstr ""
|
|
343
343
|
msgid "Updating modules with %{pool_size} threads"
|
344
344
|
msgstr ""
|
345
345
|
|
346
|
-
#: ../lib/r10k/puppetfile.rb:
|
347
|
-
msgid "
|
346
|
+
#: ../lib/r10k/puppetfile.rb:190
|
347
|
+
msgid "Error during concurrent deploy of a module: %{message}"
|
348
348
|
msgstr ""
|
349
349
|
|
350
|
-
#: ../lib/r10k/puppetfile.rb:
|
350
|
+
#: ../lib/r10k/puppetfile.rb:212
|
351
|
+
msgid "Module thread %{id} exiting: %{message}"
|
352
|
+
msgstr ""
|
353
|
+
|
354
|
+
#: ../lib/r10k/puppetfile.rb:269
|
351
355
|
msgid "unrecognized declaration '%{method}'"
|
352
356
|
msgstr ""
|
353
357
|
|