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.
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 = $(shell echo $(git_describe) | sed 's/-.*//')
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 r10k/spec
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: prep lint build test publish push-image push-readme
66
+ .PHONY: lint build test prep publish push-image push-readme
@@ -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
- RUN gem install --no-doc r10k:"$R10K_VERSION" json etc
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 = ENV['PUPPET_TEST_DOCKER_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, cachedir: :self, 'no-force': :self, 'generate-types': :self, 'puppet-path': :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
@@ -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
- md5_of_tarball = Digest::MD5.hexdigest(File.read(@tarball_cache_path, mode: 'rb'))
119
+ sha256_of_tarball = Digest::SHA256.file(@tarball_cache_path).hexdigest
112
120
 
113
- if @md5_file_path.exist?
114
- verify_from_md5_file(md5_of_tarball)
121
+ if @sha256_file_path.exist?
122
+ verify_from_file(sha256_of_tarball, @sha256_file_path)
115
123
  else
116
- verify_from_forge(md5_of_tarball)
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 md5 of the cached tarball against 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 verify_from_md5_file(md5_of_tarball)
129
- md5_from_file = File.read(@md5_file_path).strip
130
- if md5_of_tarball != md5_from_file
131
- logger.error "MD5 of #{@tarball_cache_path} (#{md5_of_tarball}) does not match checksum #{md5_from_file} in #{@md5_file_path}. Removing both files."
132
- cleanup_cached_tarball_path
133
- cleanup_md5_file_path
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 md5 of the cached tarball against 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(md5_of_tarball)
147
- md5_from_forge = @forge_release.file_md5
148
- #compare file_md5 to md5_of_tarball
149
- if md5_of_tarball != md5_from_forge
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(@md5_file_path, md5_from_forge)
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
@@ -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
 
@@ -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
- thread_pool.each(&:join)
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.error _("Thread error during concurrent module deploy: %{message}") % {message: e.message}
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
@@ -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
@@ -1,3 +1,3 @@
1
1
  module R10K
2
- VERSION = '3.3.0'
2
+ VERSION = '3.3.1'
3
3
  end
data/locales/r10k.pot CHANGED
@@ -6,11 +6,11 @@
6
6
  #, fuzzy
7
7
  msgid ""
8
8
  msgstr ""
9
- "Project-Id-Version: r10k 3.2.0-7-g213f14b\n"
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-04-18 21:10+0000\n"
13
- "PO-Revision-Date: 2019-04-18 21:10+0000\n"
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:198
347
- msgid "Thread error during concurrent module deploy: %{message}"
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:253
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