r10k 2.5.5 → 2.6.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 CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1751a994285442b34b30d2274ed0049c242ad7b4
4
- data.tar.gz: bea09a73ff5954f2f434ab018c307f3efc59e420
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ NTZjY2UzMDMyMTJlNjIzZmQzNzk4MGViMGMzMjM0Yzc2MzdkZjg2MQ==
5
+ data.tar.gz: !binary |-
6
+ YTE1ZjhkYzBiZjY1YTFiOGUyMTliM2Q2MDAzNzg3YzA4NjUyN2Q0Ng==
5
7
  SHA512:
6
- metadata.gz: 727021b3144cdf93ccadb11c9718ceccc2f054bc310614fdec5881e1ae704b65b50a385ceed17f68b446cc31ee5ed5bdd194c7c3ae66bf1183c0fd17de55b10d
7
- data.tar.gz: 9975f54ffa36bdbd0a5c27d0478fca297f95a151a957b931fc12749f5d0fe62c5655afa3979f03bf6c4ea09cc0cd31dc40c4b7ed85caa1ecd63e3a0a990c7737
8
+ metadata.gz: !binary |-
9
+ NDRiNTI5NDA3NGQzNmVjODZjN2NlNmMyYjVjMjVjM2ZkYjNiMmY0ZWUyMjNj
10
+ NWI1NjExNTk2NDJhM2M0NjFlN2ExZTVmNGU5MzRmNjJjYWY1NzliMGY2Mzgy
11
+ NmUyN2FlNzZjMDAwMWFhMTdmZDA4ZTY4NThiZTBlMmM5MWZjOGE=
12
+ data.tar.gz: !binary |-
13
+ MmM4YzFlNTBmNTYyMzMxYjA0Zjc2YWU0OTJlMzQ1YzFmM2E2NDEzZGM2MWZi
14
+ NTczNzVhODdhNTc0Yjg0OWVhYjIxOTUwY2NkOTUyYmY0MzMyY2FhNDc1Mzhj
15
+ YWNlYTVjMGMwYjJmNjUwMDIxMTFiOTg4NTE4Yjk3ODVlNjg3Mzg=
@@ -5,6 +5,7 @@ script: "bundle exec rspec --color --format documentation spec/unit"
5
5
  notifications:
6
6
  email: false
7
7
  sudo: false
8
+ before_install: gem update bundler
8
9
  rvm:
9
10
  - "2.3.0"
10
11
  - "2.2.0"
@@ -1,6 +1,26 @@
1
1
  CHANGELOG
2
2
  =========
3
3
 
4
+ 2.6.0
5
+ -----
6
+
7
+ ### New Features
8
+
9
+ (RK-307) Branches can now be ignored by prefixes during deployment.
10
+
11
+ (RK-305) Add --no-force to deploy action to avoid overwriting local module changes.
12
+
13
+ (RK-264) Add --force action to puppetfile install to force overwriting local
14
+ module changes.
15
+
16
+ (RK-291) (RK-304) Add caching of forge modules.
17
+
18
+ ### Changes
19
+
20
+ (RK-306) Remove the dependency on semantic_puppet.
21
+
22
+ (RK-161) Deprecate the usage of PUPPETFILE and PUPPETFILE_DIR environment variables.
23
+
4
24
  2.5.5
5
25
  -----
6
26
 
@@ -356,6 +356,32 @@ sources:
356
356
  * if `false` (default) environment folder will not be prefixed
357
357
  * if `String` environment folder will be prefixed with the `prefix` value.
358
358
 
359
+ ### ignore_branch_prefixes
360
+
361
+ The 'ignore_branch_prefixes' setting causes environments to be ignored which match in part or whole
362
+ to any of the prefixes listed in the setting.
363
+ The setting is a list of strings. Each branch in
364
+ the 'git' repo will have its name tested against all prefixes and, if the prefix
365
+ is found, then an environment will not be deployed for this branch.
366
+ If no 'ignore_branch_prefixes' is specified, then all branches in the 'git' repo will
367
+ be deployed (default behavior).
368
+
369
+ #### ignore_branch_prefixes behaviour
370
+ * if empty, deploy environments for all branches
371
+ * for each branch in git repo
372
+ ** if `branch.name` has a prefix found in `ignore_branch_prefixes`, then do not deploy an environment for branch
373
+
374
+ Example: do not deploy branches with names starting with (or completely named) 'test' or 'dev'.
375
+ ```yaml
376
+ ---
377
+ sources:
378
+ mysource:
379
+ basedir: '/etc/puppet/environments'
380
+ ignore_branch_prefixes:
381
+ - 'test'
382
+ - 'dev'
383
+ ```
384
+
359
385
  Examples
360
386
  --------
361
387
 
@@ -306,7 +306,7 @@ The given 'install\_path' can be an absolute path or a path relative to the base
306
306
  the environment. Note that r10k will exit with an error if you attempt to set the
307
307
  'path' option to a directory outside of the environment.
308
308
 
309
- ## Environment variables
309
+ ## Environment variables (**DEPRECATED** as of 2.5.6)
310
310
 
311
311
  It is possible to set an alternate name/location for your `Puppetfile` and
312
312
  `modules` directory. This is useful if you want to control multiple environments
@@ -76,6 +76,10 @@ def r10k_revert_environment(host, commit_sha, git_repo_path)
76
76
  #Force push changes to remote.
77
77
  git_on(host, 'push origin --mirror --force', git_repo_path)
78
78
  git_on(host, 'push origin --mirror --force', git_repo_path)
79
+
80
+ #Remove r10k cache
81
+ cachedir = '/var/cache/r10k'
82
+ on(master, "rm -rf #{cachedir}")
79
83
  end
80
84
 
81
85
  # Clean-up the r10k environment on the master to bring it back to a known good state.
@@ -102,6 +106,13 @@ def clean_up_r10k(master, commit_sha, git_repo_path)
102
106
  step 'Reset Git Repo to Known Good State'
103
107
  r10k_revert_environment(master, commit_sha, git_repo_path)
104
108
 
109
+ # RK-297 workaround. Without this, tests will fail with an error like the following:
110
+ # [2017-06-02 11:11:46 - ERROR] Object not found - no match for id (60e4ea82c9fdf86974a13f78b839a497325de04b)
111
+ # This cleanup should not be necessary when RK-297 has been resolved.
112
+ #
113
+ step 'Remove git directories from codedir to prevent cache errors'
114
+ on(master, "find #{environment_path } -name .git -type d -print0 | xargs -r0 -- rm -r")
115
+
105
116
  step 'Restore Original "production" Environment'
106
117
  on(master, "#{r10k_fqp} deploy environment -v")
107
118
 
@@ -66,7 +66,5 @@ git_add_commit_push(master, 'production', 'add Puppetfile', git_environments_pat
66
66
  on(master, "#{r10k_fqp} deploy environment -p", :accept_all_exit_codes => true) do |r|
67
67
  regex = /proxy.*ilovecatvideos\.com/
68
68
  assert(r.exit_code == 1, 'expected error code was not observed')
69
- expect_failure('Failure due to RK-262') do
70
- assert_match(regex, r.stderr, 'The expected error message was not observed' )
71
- end
69
+ assert_match(regex, r.stderr, 'The expected error message was not observed' )
72
70
  end
@@ -13,6 +13,8 @@ module R10K
13
13
 
14
14
  include R10K::Action::Deploy::DeployHelpers
15
15
 
16
+ attr_reader :force
17
+
16
18
  def initialize(opts, argv, settings = nil)
17
19
  settings ||= {}
18
20
  @purge_levels = settings.fetch(:deploy, {}).fetch(:purge_levels, [])
@@ -20,6 +22,8 @@ module R10K
20
22
 
21
23
  super
22
24
 
25
+ # @force here is used to make it easier to reason about
26
+ @force = !@no_force
23
27
  @argv = @argv.map { |arg| arg.gsub(/\W/,'_') }
24
28
  end
25
29
 
@@ -117,7 +121,7 @@ module R10K
117
121
 
118
122
  def visit_module(mod)
119
123
  logger.info _("Deploying Puppetfile content %{mod_path}") % {mod_path: mod.path}
120
- mod.sync
124
+ mod.sync(force: @force)
121
125
  end
122
126
 
123
127
  def write_environment_info!(environment, started_at, success)
@@ -142,7 +146,7 @@ module R10K
142
146
  end
143
147
 
144
148
  def allowed_initialize_opts
145
- super.merge(puppetfile: :self, cachedir: :self)
149
+ super.merge(puppetfile: :self, cachedir: :self, :'no-force' => :self)
146
150
  end
147
151
  end
148
152
  end
@@ -10,6 +10,17 @@ module R10K
10
10
 
11
11
  include R10K::Action::Deploy::DeployHelpers
12
12
 
13
+ attr_reader :force
14
+
15
+ def initialize(opts, argv, settings = nil)
16
+ settings ||= {}
17
+
18
+ super
19
+
20
+ # @force here is used to make it easier to reason about
21
+ @force = !@no_force
22
+ end
23
+
13
24
  def call
14
25
  @visit_ok = true
15
26
 
@@ -50,14 +61,14 @@ module R10K
50
61
  def visit_module(mod)
51
62
  if @argv.include?(mod.name)
52
63
  logger.info _("Deploying module %{mod_path}") % {mod_path: mod.path}
53
- mod.sync
64
+ mod.sync(force: @force)
54
65
  else
55
66
  logger.debug1(_("Only updating modules %{modules}, skipping module %{mod_name}") % {modules: @argv.inspect, mod_name: mod.name})
56
67
  end
57
68
  end
58
69
 
59
70
  def allowed_initialize_opts
60
- super.merge(environment: true)
71
+ super.merge(environment: true, :'no-force' => :self)
61
72
  end
62
73
  end
63
74
  end
@@ -8,10 +8,16 @@ module R10K
8
8
  #
9
9
  # @api private
10
10
  # @deprecated The use of these environment variables is deprecated and
11
- # will be removed in 2.0.0.
11
+ # will be removed in 3.0.0.
12
12
  class CriRunner < R10K::Action::CriRunner
13
+
14
+ include R10K::Logging
15
+
13
16
  def handle_opts(opts)
14
17
  opts[:root] ||= wd
18
+ if env['PUPPETFILE_DIR'] || env['PUPPETFILE']
19
+ logger.warn _("The use of the PUPPETFILE and PUPPETFILE_DIR environment variables is deprecated.")
20
+ end
15
21
  opts[:moduledir] ||= env['PUPPETFILE_DIR']
16
22
  opts[:puppetfile] ||= env['PUPPETFILE']
17
23
  super(opts)
@@ -10,7 +10,7 @@ module R10K
10
10
 
11
11
  def call
12
12
  @visit_ok = true
13
- pf = R10K::Puppetfile.new(@root, @moduledir, @puppetfile)
13
+ pf = R10K::Puppetfile.new(@root, @moduledir, @puppetfile, nil , @force)
14
14
  pf.accept(self)
15
15
  @visit_ok
16
16
  end
@@ -26,17 +26,18 @@ module R10K
26
26
  end
27
27
 
28
28
  def visit_module(mod)
29
+ @force ||= false
29
30
  logger.info _("Updating module %{mod_path}") % {mod_path: mod.path}
30
31
 
31
32
  if mod.respond_to?(:desired_ref) && mod.desired_ref == :control_branch
32
33
  logger.warn _("Cannot track control repo branch for content '%{name}' when not part of a 'deploy' action, will use default if available." % {name: mod.name})
33
34
  end
34
35
 
35
- mod.sync(force: false) # Don't force sync for 'puppetfile install' RK-265
36
+ mod.sync(force: @force)
36
37
  end
37
38
 
38
39
  def allowed_initialize_opts
39
- super.merge(root: :self, puppetfile: :self, moduledir: :self)
40
+ super.merge(root: :self, puppetfile: :self, moduledir: :self, force: :self )
40
41
  end
41
42
  end
42
43
  end
@@ -22,6 +22,7 @@ module R10K::CLI
22
22
  DESCRIPTION
23
23
 
24
24
  required nil, :cachedir, 'Specify a cachedir, overriding the value in config'
25
+ flag nil, :'no-force', 'Prevent the overwriting of local module modifications'
25
26
 
26
27
  run do |opts, args, cmd|
27
28
  puts cmd.help(:verbose => opts[:verbose])
@@ -30,10 +30,9 @@ Puppetfile (http://bombasticmonkey.com/librarian-puppet/).
30
30
  name 'install'
31
31
  usage 'install'
32
32
  summary 'Install all modules from a Puppetfile'
33
-
34
33
  required nil, :moduledir, 'Path to install modules to'
35
34
  required nil, :puppetfile, 'Path to puppetfile'
36
- # @todo add --no-purge option
35
+ flag nil, :force, 'Force locally changed files to be overwritten'
37
36
  runner R10K::Action::Puppetfile::CriRunner.wrap(R10K::Action::Puppetfile::Install)
38
37
  end
39
38
  end
@@ -13,6 +13,7 @@ module R10K
13
13
 
14
14
  def_setting_attr :proxy
15
15
  def_setting_attr :baseurl
16
+ def_setting_attr :cache_root, File.expand_path(ENV['HOME'] ? '~/.r10k/cache': '/root/.r10k/cache')
16
17
 
17
18
  include R10K::Logging
18
19
 
@@ -27,6 +28,18 @@ module R10K
27
28
  # @return [Pathname] Where the module tarball will be downloaded to.
28
29
  attr_accessor :download_path
29
30
 
31
+ # @!attribute [rw] tarball_cache_path
32
+ # @return [Pathname] Where the module tarball will be cached to.
33
+ attr_accessor :tarball_cache_path
34
+
35
+ # @!attribute [rw] tarball_cache_root
36
+ # @return [Pathname] Directory where the module tarball will be cached to.
37
+ attr_accessor :tarball_cache_root
38
+
39
+ # @!attribute [rw] md5_file_path
40
+ # @return [Pathname] Where the md5 of the cached tarball is stored.
41
+ attr_accessor :md5_file_path
42
+
30
43
  # @!attribute [rw] unpack_path
31
44
  # @return [Pathname] Where the module will be unpacked to.
32
45
  attr_accessor :unpack_path
@@ -41,9 +54,17 @@ module R10K
41
54
  # objects are created in the class instances and thus are not shared with
42
55
  # subclasses.
43
56
  PuppetForge::V3::Release.conn = PuppetForge::V3::Base.conn
57
+
44
58
  @forge_release = PuppetForge::V3::Release.new({ :name => @full_name, :version => @version, :slug => "#{@full_name}-#{@version}" })
45
59
 
46
- @download_path = Pathname.new(Dir.mktmpdir) + (@forge_release.slug + '.tar.gz')
60
+ tarball_name = @forge_release.slug + '.tar.gz'
61
+ @download_path = Pathname.new(Dir.mktmpdir) + (tarball_name)
62
+ @tarball_cache_root = Pathname.new(settings[:cache_root]) + (@forge_release.slug + "/tarball/")
63
+ @tarball_cache_path = @tarball_cache_root + tarball_name
64
+
65
+ md5_filename = @forge_release.slug + '.md5'
66
+ @md5_file_path = @tarball_cache_root + md5_filename
67
+
47
68
  @unpack_path = Pathname.new(Dir.mktmpdir) + @forge_release.slug
48
69
  end
49
70
 
@@ -65,34 +86,83 @@ module R10K
65
86
  cleanup
66
87
  end
67
88
 
68
- # Download the module release to {#download_path}
89
+ # Download the module release to {#download_path} and cache to {#tarball_cache_path}
69
90
  #
70
91
  # @return [void]
71
92
  def download
72
- logger.debug1 "Downloading #{@forge_release.slug} from #{PuppetForge::Release.conn.url_prefix} to #{@download_path}"
73
- @forge_release.download(download_path)
93
+ if @tarball_cache_path.exist?
94
+ logger.debug1 "Using cached copy of #{@forge_release.slug} tarball"
95
+ else
96
+ logger.debug1 "Downloading #{@forge_release.slug} from #{PuppetForge::Release.conn.url_prefix} to #{@download_path}"
97
+ @forge_release.download(download_path)
98
+ FileUtils::mkdir_p(@tarball_cache_root)
99
+ FileUtils::mv(@download_path, @tarball_cache_path)
100
+ end
74
101
  end
75
102
 
76
- # Verify the module release downloaded to {#download_path} against the
77
- # module release checksum given by the Puppet Forge
103
+ # Verify the module release cached in {#tarball_cache_path} against the
104
+ # module release checksum given by the Puppet Forge. On mismatch, remove
105
+ # the cached copy.
78
106
  #
79
- # @raise [PuppetForge::V3::Release::ChecksumMismatch] The
80
- # downloaded module release checksum doesn't match the expected Forge
81
- # module release checksum.
82
107
  # @return [void]
83
108
  def verify
84
- logger.debug1 "Verifying that #{download_path} matches checksum #{@forge_release.file_md5}"
85
- @forge_release.verify(download_path)
109
+ logger.debug1 "Verifying that #{@tarball_cache_path} matches checksum"
110
+
111
+ md5_of_tarball = Digest::MD5.hexdigest(File.read(@tarball_cache_path))
112
+
113
+ if @md5_file_path.exist?
114
+ verify_from_md5_file(md5_of_tarball)
115
+ else
116
+ verify_from_forge(md5_of_tarball)
117
+ end
86
118
  end
87
119
 
88
- # Unpack the module release at {#download_path} into the given target_dir
120
+ # Verify the md5 of the cached tarball against the
121
+ # module release checksum stored in the cache as well.
122
+ # On mismatch, remove the cached copy of both files.
123
+ #
124
+ # @raise [PuppetForge::V3::Release::ChecksumMismatch] The
125
+ # cached module release checksum doesn't match the cached checksum.
126
+ #
127
+ # @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
134
+ raise PuppetForge::V3::Release::ChecksumMismatch.new
135
+ end
136
+ end
137
+
138
+ # Verify the md5 of the cached tarball against the
139
+ # module release checksum from the forge.
140
+ # On mismatch, remove the cached copy of the tarball.
141
+ #
142
+ # @raise [PuppetForge::V3::Release::ChecksumMismatch] The
143
+ # cached module release checksum doesn't match the forge checksum.
144
+ #
145
+ # @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
152
+ raise PuppetForge::V3::Release::ChecksumMismatch.new
153
+ else
154
+ File.write(@md5_file_path, md5_from_forge)
155
+ end
156
+ end
157
+
158
+ # Unpack the module release at {#tarball_cache_path} into the given target_dir
89
159
  #
90
160
  # @param target_dir [Pathname] The final path where the module release
91
161
  # should be unpacked/installed into.
92
162
  # @return [void]
93
163
  def unpack(target_dir)
94
- logger.debug1 _("Unpacking %{download_path} to %{target_dir} (with tmpdir %{tmp_path})") % {download_path: download_path, target_dir: target_dir, tmp_path: unpack_path}
95
- file_lists = PuppetForge::Unpacker.unpack(download_path.to_s, target_dir.to_s, unpack_path.to_s)
164
+ logger.debug1 _("Unpacking %{tarball_cache_path} to %{target_dir} (with tmpdir %{tmp_path})") % {tarball_cache_path: tarball_cache_path, target_dir: target_dir, tmp_path: unpack_path}
165
+ file_lists = PuppetForge::Unpacker.unpack(tarball_cache_path.to_s, target_dir.to_s, unpack_path.to_s)
96
166
  logger.debug2 _("Valid files unpacked: %{valid_files}") % {valid_files: file_lists[:valid]}
97
167
  if !file_lists[:invalid].empty?
98
168
  logger.debug1 _("These files existed in the module's tar file, but are invalid filetypes and were not unpacked: %{invalid_files}") % {invalid_files: file_lists[:invalid]}
@@ -121,6 +191,20 @@ module R10K
121
191
  download_path.delete
122
192
  end
123
193
  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
124
208
  end
125
209
  end
126
210
  end
@@ -31,6 +31,7 @@ module R10K
31
31
  end
32
32
 
33
33
  with_setting(:cachedir) { |value| R10K::Git::Cache.settings[:cache_root] = value }
34
+ with_setting(:cachedir) { |value| R10K::Forge::ModuleRelease.settings[:cache_root] = value }
34
35
 
35
36
  with_setting(:git) { |value| GitInitializer.new(value).call }
36
37
  with_setting(:forge) { |value| ForgeInitializer.new(value).call }
@@ -6,7 +6,7 @@ require 'r10k/forge/module_release'
6
6
 
7
7
  require 'pathname'
8
8
  require 'fileutils'
9
- require 'puppet_forge'
9
+ require 'puppet_forge/util'
10
10
 
11
11
  class R10K::Module::Forge < R10K::Module::Base
12
12
 
@@ -17,7 +17,7 @@ class R10K::Module::Forge < R10K::Module::Base
17
17
  end
18
18
 
19
19
  def self.valid_version?(expected_version)
20
- expected_version == :latest || expected_version.nil? || SemanticPuppet::Version.valid?(expected_version)
20
+ expected_version == :latest || expected_version.nil? || PuppetForge::Util.version_valid?(expected_version)
21
21
  end
22
22
 
23
23
  # @!attribute [r] metadata
@@ -33,11 +33,18 @@ class Puppetfile
33
33
  # @return [R10K::Environment] Optional R10K::Environment that this Puppetfile belongs to.
34
34
  attr_accessor :environment
35
35
 
36
+ # @!attribute [rw] force
37
+ # @return [Boolean] Overwrite any locally made changes
38
+ attr_accessor :force
39
+
36
40
  # @param [String] basedir
37
41
  # @param [String] moduledir The directory to install the modules, default to #{basedir}/modules
38
42
  # @param [String] puppetfile_path The path to the Puppetfile, default to #{basedir}/Puppetfile
39
- def initialize(basedir, moduledir = nil, puppetfile_path = nil)
43
+ # @param [String] puppetfile_name The name of the Puppetfile, default to 'Puppetfile'
44
+ # @param [Boolean] force Shall we overwrite locally made changes?
45
+ def initialize(basedir, moduledir = nil, puppetfile_path = nil, puppetfile_name = nil, force = nil )
40
46
  @basedir = basedir
47
+ @force = force || false
41
48
  @moduledir = moduledir || File.join(basedir, 'modules')
42
49
  @puppetfile_path = puppetfile_path || File.join(basedir, 'Puppetfile')
43
50
 
@@ -51,6 +51,10 @@ module R10K
51
51
  :desc => "An optional proxy server to use when interacting with Git sources via HTTP(S).",
52
52
  :default => :inherit,
53
53
  }),
54
+
55
+ Definition.new(:ignore_branch_prefixes, {
56
+ :desc => "Array of strings used to prefix branch names that will not be deployed as environments.",
57
+ }),
54
58
  ])
55
59
  },
56
60
  {
@@ -36,6 +36,11 @@ class R10K::Source::Git < R10K::Source::Base
36
36
  # Puppet environments will be handled.
37
37
  attr_reader :invalid_branches
38
38
 
39
+ # @!attribute [r] ignore_branch_prefixes
40
+ # @return [Array<String>] Array of strings used to remove repository branches
41
+ # that will be deployed as environments.
42
+ attr_reader :ignore_branch_prefixes
43
+
39
44
  # Initialize the given source.
40
45
  #
41
46
  # @param name [String] The identifier for this source.
@@ -53,8 +58,9 @@ class R10K::Source::Git < R10K::Source::Base
53
58
 
54
59
  @environments = []
55
60
 
56
- @remote = options[:remote]
61
+ @remote = options[:remote]
57
62
  @invalid_branches = (options[:invalid_branches] || 'correct_and_warn')
63
+ @ignore_branch_prefixes = options[:ignore_branch_prefixes]
58
64
 
59
65
  @cache = R10K::Git.cache.generate(@remote)
60
66
  end
@@ -109,11 +115,27 @@ class R10K::Source::Git < R10K::Source::Base
109
115
  environments.map {|env| env.dirname }
110
116
  end
111
117
 
118
+ def filter_branches(branches, ignore_prefixes)
119
+ filter = Regexp.new("^#{Regexp.union(ignore_prefixes)}")
120
+ branches = branches.reject do |branch|
121
+ result = filter.match(branch)
122
+ if result
123
+ logger.warn _("Branch %{branch} filtered out by ignore_branch_prefixes %{ibp}") % {branch: branch, ibp: @ignore_branch_prefixes}
124
+ end
125
+ result
126
+ end
127
+ branches
128
+ end
129
+
112
130
  private
113
131
 
114
132
  def branch_names
115
133
  opts = {:prefix => @prefix, :invalid => @invalid_branches, :source => @name}
116
- @cache.branches.map do |branch|
134
+ branches = @cache.branches
135
+ if @ignore_branch_prefixes && !@ignore_branch_prefixes.empty?
136
+ branches = filter_branches(branches, @ignore_branch_prefixes)
137
+ end
138
+ branches.map do |branch|
117
139
  R10K::Environment::Name.new(branch, opts)
118
140
  end
119
141
  end
@@ -37,6 +37,11 @@ class R10K::Source::SVN < R10K::Source::Base
37
37
  # @api private
38
38
  attr_reader :password
39
39
 
40
+ # @!attribute [r] ignore_branch_prefixes
41
+ # @return [Array<String>] Array of strings used to remove repository branches
42
+ # that will be deployed as environments.
43
+ attr_reader :ignore_branch_prefixes
44
+
40
45
  include R10K::Util::Setopts
41
46
 
42
47
  # Initialize the given source.
@@ -56,6 +61,7 @@ class R10K::Source::SVN < R10K::Source::Base
56
61
  setopts(options, {:remote => :self, :username => :self, :password => :self})
57
62
  @environments = []
58
63
  @svn_remote = R10K::SVN::Remote.new(@remote, :username => @username, :password => @password)
64
+ @ignore_branch_prefixes = options[:ignore_branch_prefixes]
59
65
  end
60
66
 
61
67
  # Enumerate the environments associated with this SVN source.
@@ -97,18 +103,32 @@ class R10K::Source::SVN < R10K::Source::Base
97
103
 
98
104
  include R10K::Logging
99
105
 
106
+ def filter_branches(branches, ignore_prefixes)
107
+ filter = Regexp.new("^(#{ignore_prefixes.join('|')})")
108
+ branches = branches.reject do |branch|
109
+ result = filter.match(branch)
110
+ if result
111
+ logger.warn _("Branch %{branch} filtered out by ignore_branch_prefixes %{ibp}") % {branch: branch, ibp: @ignore_branch_prefixes}
112
+ end
113
+ result
114
+ end
115
+ branches
116
+ end
117
+
100
118
  private
101
119
 
102
120
  def names_and_paths
103
121
  branches = []
104
-
105
122
  opts = {:prefix => @prefix, :correct => false, :validate => false, :source => @name}
106
-
107
123
  branches << [R10K::Environment::Name.new('production', opts), "#{@remote}/trunk"]
108
- @svn_remote.branches.each do |branch|
109
- branches << [R10K::Environment::Name.new(branch, opts), "#{@remote}/branches/#{branch}"]
124
+ additional_branch_names = @svn_remote.branches
125
+ if @ignore_branch_prefixes && !@ignore_branch_prefixes.empty?
126
+ additional_branch_names = filter_branches(additional_branch_names, @ignore_branch_prefixes)
110
127
  end
111
128
 
129
+ additional_branch_names.each do |branch|
130
+ branches << [R10K::Environment::Name.new(branch, opts), "#{@remote}/branches/#{branch}"]
131
+ end
112
132
  branches
113
133
  end
114
134
  end
@@ -39,9 +39,11 @@ module R10K
39
39
  when NilClass, FalseClass
40
40
  # Ignore nil options
41
41
  when :self, TrueClass
42
- instance_variable_set("@#{key}".to_sym, value)
42
+ # tr here is because instance variables cannot have hyphens in their names.
43
+ instance_variable_set("@#{key}".tr('-','_').to_sym, value)
43
44
  else
44
- instance_variable_set("@#{rhs}".to_sym, value)
45
+ # tr here same as previous
46
+ instance_variable_set("@#{rhs}".tr('-','_').to_sym, value)
45
47
  end
46
48
  else
47
49
  raise ArgumentError, _("%{class_name} cannot handle option '%{key}'") % {class_name: self.class.name, key: key}
@@ -1,3 +1,3 @@
1
1
  module R10K
2
- VERSION = '2.5.5'
2
+ VERSION = '2.6.0'
3
3
  end
@@ -28,8 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_dependency 'log4r', '1.1.10'
29
29
  s.add_dependency 'multi_json', '~> 1.10'
30
30
 
31
- s.add_dependency 'puppet_forge', '~> 2.2'
32
- s.add_dependency 'semantic_puppet', '~> 0.1.0'
31
+ s.add_dependency 'puppet_forge', '~> 2.2.8'
33
32
 
34
33
  s.add_dependency 'gettext-setup', '~> 0.5'
35
34
 
@@ -13,5 +13,27 @@ shared_examples_for "a puppetfile action" do
13
13
  it "accepts the :moduledir option" do
14
14
  described_class.new({moduledir: "/some/nonexistent/path/modules"}, [])
15
15
  end
16
+
17
+ end
18
+ end
19
+
20
+ shared_examples_for "a puppetfile install action" do
21
+ describe "initializing" do
22
+ it "accepts the :root option" do
23
+ described_class.new({root: "/some/nonexistent/path"}, [])
24
+ end
25
+
26
+ it "accepts the :puppetfile option" do
27
+ described_class.new({puppetfile: "/some/nonexistent/path/Puppetfile"}, [])
28
+ end
29
+
30
+ it "accepts the :moduledir option" do
31
+ described_class.new({moduledir: "/some/nonexistent/path/modules"}, [])
32
+ end
33
+
34
+ it "accepts the :force option" do
35
+ described_class.new({force: true}, [])
36
+ end
37
+
16
38
  end
17
39
  end
@@ -19,6 +19,10 @@ describe R10K::Action::Deploy::Environment do
19
19
  described_class.new({puppetfile: true}, [])
20
20
  end
21
21
 
22
+ it "can accept a no-force option" do
23
+ described_class.new({:'no-force' => true}, [])
24
+ end
25
+
22
26
  it "normalizes environment names in the arg vector"
23
27
  end
24
28
 
@@ -53,6 +57,14 @@ describe R10K::Action::Deploy::Environment do
53
57
  end
54
58
  end
55
59
 
60
+ describe "with no-force" do
61
+ subject { described_class.new({ config: "/some/nonexistent/path", puppetfile: true, :'no-force' => true}, %w[first]) }
62
+
63
+ it "tries to preserve local modifications" do
64
+ expect(subject.force).to equal(false)
65
+ end
66
+ end
67
+
56
68
  describe "purge_levels" do
57
69
  let(:settings) { { deploy: { purge_levels: purge_levels } } }
58
70
 
@@ -13,5 +13,18 @@ describe R10K::Action::Deploy::Module do
13
13
  it "accepts an environment option" do
14
14
  described_class.new({environment: "production"}, [])
15
15
  end
16
+
17
+ it "can accept a no-force option" do
18
+ described_class.new({:'no-force' => true}, [])
19
+ end
20
+ end
21
+
22
+ describe "with no-force" do
23
+
24
+ subject { described_class.new({ config: "/some/nonexistent/path", :'no-force' => true}, [] )}
25
+
26
+ it "tries to preserve local modifications" do
27
+ expect(subject.force).to equal(false)
28
+ end
16
29
  end
17
30
  end
@@ -7,11 +7,12 @@ describe R10K::Action::Puppetfile::Install do
7
7
 
8
8
  let(:puppetfile) { R10K::Puppetfile.new('/some/nonexistent/path', nil, nil) }
9
9
 
10
- before do
11
- allow(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, nil).and_return(puppetfile)
10
+ before(:each) do
11
+ allow(puppetfile).to receive(:load!).and_return(nil)
12
+ allow(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, nil, nil, nil).and_return(puppetfile)
12
13
  end
13
14
 
14
- it_behaves_like "a puppetfile action"
15
+ it_behaves_like "a puppetfile install action"
15
16
 
16
17
  describe "installing modules" do
17
18
  let(:modules) do
@@ -55,14 +56,27 @@ describe R10K::Action::Puppetfile::Install do
55
56
 
56
57
  it "can use a custom puppetfile path" do
57
58
  subject = described_class.new({root: "/some/nonexistent/path", puppetfile: "/some/other/path/Puppetfile"}, [])
58
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, "/some/other/path/Puppetfile").and_return(puppetfile)
59
+ expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, "/some/other/path/Puppetfile", nil, nil).and_return(puppetfile)
59
60
  subject.call
60
61
  end
61
62
 
62
63
  it "can use a custom moduledir path" do
63
64
  subject = described_class.new({root: "/some/nonexistent/path", moduledir: "/some/other/path/site-modules"}, [])
64
- expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", "/some/other/path/site-modules", nil).and_return(puppetfile)
65
+ expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", "/some/other/path/site-modules", nil, nil, nil).and_return(puppetfile)
65
66
  subject.call
66
67
  end
67
68
  end
69
+
70
+ describe "forcing to overwrite local changes" do
71
+ before do
72
+ allow(puppetfile).to receive(:modules).and_return([])
73
+ end
74
+
75
+ it "can use the force overwrite option" do
76
+ subject = described_class.new({root: "/some/nonexistent/path", force: true}, [])
77
+ expect(R10K::Puppetfile).to receive(:new).with("/some/nonexistent/path", nil, nil, nil, true).and_return(puppetfile)
78
+ subject.call
79
+ end
80
+
81
+ end
68
82
  end
@@ -7,35 +7,105 @@ describe R10K::Forge::ModuleRelease do
7
7
  subject { described_class.new('branan-eight_hundred', '8.0.0') }
8
8
 
9
9
  let(:forge_release_class) { PuppetForge::V3::Release }
10
+ let(:md5_digest_class) { Digest::MD5 }
10
11
 
11
12
  let(:download_path) { instance_double('Pathname') }
13
+ let(:tarball_cache_path) { instance_double('Pathname') }
14
+ let(:tarball_cache_root) { instance_double('Pathname') }
12
15
  let(:unpack_path) { instance_double('Pathname') }
13
16
  let(:target_dir) { instance_double('Pathname') }
17
+ let(:md5_file_path) { instance_double('Pathname') }
18
+
14
19
  let(:file_lists) { {:valid=>['valid_ex'], :invalid=>[], :symlinks=>['symlink_ex']} }
15
20
 
21
+ let(:file_contents) { "skeletor's closet" }
22
+ let(:md5_of_tarball) { "something_hexy" }
23
+ let(:good_md5) { md5_of_tarball }
24
+ let(:bad_md5) { "different_hexy_thing" }
25
+
16
26
  before do
17
27
  subject.download_path = download_path
28
+ subject.tarball_cache_path = tarball_cache_path
29
+ subject.tarball_cache_root = tarball_cache_root
18
30
  subject.unpack_path = unpack_path
31
+ subject.md5_file_path = md5_file_path
32
+ end
33
+
34
+ context "no cached tarball" do
35
+ describe '#download' do
36
+ it "downloads the module from the forge into `download_path`" do
37
+ expect(tarball_cache_path).to receive(:exist?).and_return(false)
38
+ expect(subject.forge_release).to receive(:download).with(download_path)
39
+ allow(FileUtils).to receive(:mkdir_p).with(tarball_cache_root)
40
+ expect(FileUtils).to receive(:mv).with(download_path, tarball_cache_path)
41
+ subject.download
42
+ end
43
+ end
19
44
  end
20
45
 
21
- describe '#download' do
22
- it "downloads the module from the forge into `download_path`" do
23
- expect(subject.forge_release).to receive(:download).with(download_path)
24
- subject.download
46
+ context "with cached tarball" do
47
+ describe '#download' do
48
+ it "does not download a new tarball" do
49
+ expect(tarball_cache_path).to receive(:exist?).and_return(true)
50
+ expect(subject.forge_release).not_to receive(:download).with(download_path)
51
+ subject.download
52
+ end
25
53
  end
26
54
  end
27
55
 
28
56
  describe '#verify' do
29
- it "verifies the module checksum based on the Forge file checksum" do
30
- allow(subject.forge_release).to receive(:file_md5).and_return('something')
31
- expect(subject.forge_release).to receive(:verify).with(download_path)
57
+
58
+ it "verifies using the file md5, if that exists" do
59
+ allow(File).to receive(:read).and_return(file_contents)
60
+ allow(md5_digest_class).to receive(:hexdigest).and_return(md5_of_tarball)
61
+ allow(md5_file_path).to receive(:exist?).and_return(true)
62
+ expect(subject).to receive(:verify_from_md5_file).with(md5_of_tarball)
32
63
  subject.verify
33
64
  end
65
+
66
+ it "verifies using the forge file_md5, if no md5 file exists" do
67
+ allow(File).to receive(:read).and_return(file_contents)
68
+ allow(md5_digest_class).to receive(:hexdigest).and_return(md5_of_tarball)
69
+ allow(md5_file_path).to receive(:exist?).and_return(false)
70
+ expect(subject).to receive(:verify_from_forge).with(md5_of_tarball)
71
+ subject.verify
72
+ end
73
+ end
74
+
75
+ describe '#verify_from_md5_file' do
76
+
77
+ it "does nothing when the checksums match" do
78
+ expect(File).to receive(:read).with(md5_file_path).and_return(good_md5)
79
+ expect(subject).not_to receive(:cleanup_cached_tarball_path)
80
+ subject.verify_from_md5_file(md5_of_tarball)
81
+ end
82
+
83
+ it "raises an error and cleans up when the checksums do not match" do
84
+ expect(File).to receive(:read).with(md5_file_path).and_return(bad_md5)
85
+ expect(subject).to receive(:cleanup_cached_tarball_path)
86
+ expect(subject).to receive(:cleanup_md5_file_path)
87
+ expect { subject.verify_from_md5_file(md5_of_tarball) }.to raise_error(PuppetForge::V3::Release::ChecksumMismatch)
88
+ end
89
+ end
90
+
91
+ describe '#verify_from_forge' do
92
+ it "write the md5 to file when the checksums match" do
93
+ expect(subject.forge_release).to receive(:file_md5).and_return(good_md5)
94
+ expect(subject).not_to receive(:cleanup_cached_tarball_path)
95
+ expect(File).to receive(:write).with(md5_file_path, good_md5)
96
+ subject.verify_from_forge(md5_of_tarball)
97
+ end
98
+
99
+ it "raises an error and cleans up when the checksums do not match" do
100
+ expect(subject.forge_release).to receive(:file_md5).and_return(bad_md5)
101
+ expect(subject).to receive(:cleanup_cached_tarball_path)
102
+ expect { subject.verify_from_forge(md5_of_tarball) }.to raise_error(PuppetForge::V3::Release::ChecksumMismatch)
103
+ end
34
104
  end
35
105
 
36
106
  describe '#unpack' do
37
- it "unpacks the module tarball in `download_path` into the provided target path" do
38
- expect(PuppetForge::Unpacker).to receive(:unpack).with(download_path.to_s, target_dir.to_s, unpack_path.to_s).\
107
+ it "unpacks the module tarball in `tarball_cache_path` into the provided target path" do
108
+ expect(PuppetForge::Unpacker).to receive(:unpack).with(tarball_cache_path.to_s, target_dir.to_s, unpack_path.to_s).\
39
109
  and_return({:valid=>["extractedmodule/metadata.json"], :invalid=>[], :symlinks=>[]})
40
110
  subject.unpack(target_dir)
41
111
  end
@@ -52,7 +122,7 @@ describe R10K::Forge::ModuleRelease do
52
122
  end
53
123
 
54
124
  describe "#cleanup" do
55
- it "cleans up the download and unpack paths" do
125
+ it "cleans up the unpack paths" do
56
126
  expect(subject).to receive(:cleanup_unpack_path)
57
127
  expect(subject).to receive(:cleanup_download_path)
58
128
  subject.cleanup
@@ -62,6 +62,40 @@ describe R10K::Source::Git do
62
62
  expect(master_env.dirname).to eq 'master'
63
63
  end
64
64
  end
65
+
66
+ describe "generate_environments respects ignore_branch_prefixes setting" do
67
+ before do
68
+ allow(subject.cache).to receive(:branches).and_return ['master', 'development', 'production', 'not_dev_test_me', 'dev_test', 'dev', 'test_2']
69
+ subject.instance_variable_set(:@ignore_branch_prefixes, ['dev', 'test'])
70
+ end
71
+
72
+ let(:environments) { subject.generate_environments }
73
+
74
+ it "creates an environment for each branch not in ignore_branch_prefixes" do
75
+ expect(subject.generate_environments.size).to eq(3)
76
+ end
77
+
78
+ it "copies the source remote to the environment" do
79
+ expect(environments[0].remote).to eq subject.remote
80
+ expect(environments[1].remote).to eq subject.remote
81
+ expect(environments[2].remote).to eq subject.remote
82
+ end
83
+
84
+ it "uses the branch name as the directory by default" do
85
+ expect(environments[0].dirname).to eq 'master'
86
+ expect(environments[1].dirname).to eq 'production'
87
+ expect(environments[2].dirname).to eq 'not_dev_test_me'
88
+ end
89
+ end
90
+
91
+ describe "filtering branches with ignore prefixes" do
92
+ let(:branches) { ['master', 'development', 'production', 'not_dev_test_me', 'dev_test', 'dev', 'test_2'] }
93
+ let(:ignore_prefixes) { ['dev', 'test'] }
94
+
95
+ it "filters branches" do
96
+ expect(subject.filter_branches(branches, ignore_prefixes)).to eq(['master', 'production', 'not_dev_test_me'])
97
+ end
98
+ end
65
99
  end
66
100
 
67
101
  describe R10K::Source::Git, "handling invalid branch names" do
@@ -61,6 +61,34 @@ describe R10K::Source::SVN do
61
61
  expect(environments[3].dirname).to eq 'robobutler'
62
62
  end
63
63
  end
64
+
65
+ describe "generate_environments respects ignore_branch_prefixes setting" do
66
+ before do
67
+ allow(subject.svn_remote).to receive(:branches).and_return ['master', 'development', 'not_dev_test_me', 'dev_test', 'dev', 'test_2']
68
+ subject.instance_variable_set(:@ignore_branch_prefixes, ['dev', 'test'])
69
+ end
70
+
71
+ let(:environments) { subject.generate_environments }
72
+
73
+ it "creates an environment for each branch not in ignore_branch_prefixes" do
74
+ expect(subject.generate_environments.size).to eq(3)
75
+ end
76
+
77
+ it "uses the branch name as the directory by default" do
78
+ expect(environments[0].name).to eq 'production'
79
+ expect(environments[1].name).to eq 'master'
80
+ expect(environments[2].name).to eq 'not_dev_test_me'
81
+ end
82
+ end
83
+
84
+ describe "filtering branches with ignore prefixes" do
85
+ let(:branches) { ['master', 'development', 'production', 'not_dev_test_me', 'dev_test', 'dev', 'test_2'] }
86
+ let(:ignore_prefixes) { ['dev', 'test'] }
87
+
88
+ it "filters branches" do
89
+ expect(subject.filter_branches(branches, ignore_prefixes)).to eq(['master', 'production', 'not_dev_test_me'])
90
+ end
91
+ end
64
92
  end
65
93
 
66
94
  describe R10K::Source::SVN, 'when prefixing is enabled' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: r10k
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.5
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrien Thebo
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-02 00:00:00.000000000 Z
11
+ date: 2017-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colored
@@ -28,14 +28,14 @@ dependencies:
28
28
  name: cri
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ~>
32
32
  - !ruby/object:Gem::Version
33
33
  version: 2.6.1
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ~>
39
39
  - !ruby/object:Gem::Version
40
40
  version: 2.6.1
41
41
  - !ruby/object:Gem::Dependency
@@ -56,126 +56,111 @@ dependencies:
56
56
  name: multi_json
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '1.10'
62
62
  type: :runtime
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.10'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: puppet_forge
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: '2.2'
75
+ version: 2.2.8
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: '2.2'
83
- - !ruby/object:Gem::Dependency
84
- name: semantic_puppet
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: 0.1.0
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: 0.1.0
82
+ version: 2.2.8
97
83
  - !ruby/object:Gem::Dependency
98
84
  name: gettext-setup
99
85
  requirement: !ruby/object:Gem::Requirement
100
86
  requirements:
101
- - - "~>"
87
+ - - ~>
102
88
  - !ruby/object:Gem::Version
103
89
  version: '0.5'
104
90
  type: :runtime
105
91
  prerelease: false
106
92
  version_requirements: !ruby/object:Gem::Requirement
107
93
  requirements:
108
- - - "~>"
94
+ - - ~>
109
95
  - !ruby/object:Gem::Version
110
96
  version: '0.5'
111
97
  - !ruby/object:Gem::Dependency
112
98
  name: rspec
113
99
  requirement: !ruby/object:Gem::Requirement
114
100
  requirements:
115
- - - "~>"
101
+ - - ~>
116
102
  - !ruby/object:Gem::Version
117
103
  version: '3.1'
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
- - - "~>"
108
+ - - ~>
123
109
  - !ruby/object:Gem::Version
124
110
  version: '3.1'
125
111
  - !ruby/object:Gem::Dependency
126
112
  name: rake
127
113
  requirement: !ruby/object:Gem::Requirement
128
114
  requirements:
129
- - - ">="
115
+ - - ! '>='
130
116
  - !ruby/object:Gem::Version
131
117
  version: '0'
132
118
  type: :development
133
119
  prerelease: false
134
120
  version_requirements: !ruby/object:Gem::Requirement
135
121
  requirements:
136
- - - ">="
122
+ - - ! '>='
137
123
  - !ruby/object:Gem::Version
138
124
  version: '0'
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: yard
141
127
  requirement: !ruby/object:Gem::Requirement
142
128
  requirements:
143
- - - "~>"
129
+ - - ~>
144
130
  - !ruby/object:Gem::Version
145
131
  version: 0.8.7.3
146
132
  type: :development
147
133
  prerelease: false
148
134
  version_requirements: !ruby/object:Gem::Requirement
149
135
  requirements:
150
- - - "~>"
136
+ - - ~>
151
137
  - !ruby/object:Gem::Version
152
138
  version: 0.8.7.3
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: minitar
155
141
  requirement: !ruby/object:Gem::Requirement
156
142
  requirements:
157
- - - "~>"
143
+ - - ~>
158
144
  - !ruby/object:Gem::Version
159
145
  version: 0.6.1
160
146
  type: :development
161
147
  prerelease: false
162
148
  version_requirements: !ruby/object:Gem::Requirement
163
149
  requirements:
164
- - - "~>"
150
+ - - ~>
165
151
  - !ruby/object:Gem::Version
166
152
  version: 0.6.1
167
- description: |2
168
- R10K provides a general purpose toolset for deploying Puppet environments and modules.
169
- It implements the Puppetfile format and provides a native implementation of Puppet
170
- dynamic environments.
153
+ description: ! " R10K provides a general purpose toolset for deploying Puppet environments
154
+ and modules.\n It implements the Puppetfile format and provides a native implementation
155
+ of Puppet\n dynamic environments.\n"
171
156
  email: adrien@somethingsinistral.net
172
157
  executables:
173
158
  - r10k
174
159
  extensions: []
175
160
  extra_rdoc_files: []
176
161
  files:
177
- - ".gitignore"
178
- - ".travis.yml"
162
+ - .gitignore
163
+ - .travis.yml
179
164
  - CHANGELOG.mkd
180
165
  - CONTRIBUTING.mkd
181
166
  - Gemfile
@@ -515,18 +500,19 @@ require_paths:
515
500
  - lib
516
501
  required_ruby_version: !ruby/object:Gem::Requirement
517
502
  requirements:
518
- - - ">="
503
+ - - ! '>='
519
504
  - !ruby/object:Gem::Version
520
505
  version: 1.9.3
521
506
  required_rubygems_version: !ruby/object:Gem::Requirement
522
507
  requirements:
523
- - - ">="
508
+ - - ! '>='
524
509
  - !ruby/object:Gem::Version
525
510
  version: '0'
526
511
  requirements: []
527
512
  rubyforge_project:
528
- rubygems_version: 2.2.5
513
+ rubygems_version: 2.4.8
529
514
  signing_key:
530
515
  specification_version: 4
531
516
  summary: Puppet environment and module deployment
532
517
  test_files: []
518
+ has_rdoc: