r10k 3.10.0 → 3.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +0 -10
  3. data/CHANGELOG.mkd +33 -0
  4. data/README.mkd +6 -0
  5. data/doc/dynamic-environments/configuration.mkd +25 -7
  6. data/doc/dynamic-environments/usage.mkd +26 -0
  7. data/doc/puppetfile.mkd +18 -5
  8. data/integration/Rakefile +2 -0
  9. data/integration/tests/basic_functionality/basic_deployment.rb +176 -0
  10. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +15 -13
  11. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +3 -3
  12. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +3 -3
  13. data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +3 -3
  14. data/lib/r10k/action/base.rb +1 -1
  15. data/lib/r10k/action/deploy/deploy_helpers.rb +4 -0
  16. data/lib/r10k/action/deploy/display.rb +1 -1
  17. data/lib/r10k/action/deploy/environment.rb +19 -9
  18. data/lib/r10k/action/deploy/module.rb +41 -11
  19. data/lib/r10k/action/puppetfile/check.rb +7 -5
  20. data/lib/r10k/action/puppetfile/install.rb +22 -16
  21. data/lib/r10k/action/puppetfile/purge.rb +12 -9
  22. data/lib/r10k/action/runner.rb +40 -4
  23. data/lib/r10k/action/visitor.rb +3 -0
  24. data/lib/r10k/cli/deploy.rb +5 -0
  25. data/lib/r10k/cli/puppetfile.rb +0 -1
  26. data/lib/r10k/content_synchronizer.rb +16 -4
  27. data/lib/r10k/environment/bare.rb +4 -7
  28. data/lib/r10k/environment/base.rb +64 -11
  29. data/lib/r10k/environment/plain.rb +16 -0
  30. data/lib/r10k/environment/with_modules.rb +6 -10
  31. data/lib/r10k/environment.rb +1 -0
  32. data/lib/r10k/errors.rb +5 -0
  33. data/lib/r10k/git/rugged/credentials.rb +77 -0
  34. data/lib/r10k/git/stateful_repository.rb +8 -0
  35. data/lib/r10k/git.rb +3 -0
  36. data/lib/r10k/initializers.rb +14 -7
  37. data/lib/r10k/logging.rb +78 -1
  38. data/lib/r10k/module/base.rb +42 -1
  39. data/lib/r10k/module/definition.rb +64 -0
  40. data/lib/r10k/module/forge.rb +11 -2
  41. data/lib/r10k/module/git.rb +23 -1
  42. data/lib/r10k/module/local.rb +6 -3
  43. data/lib/r10k/module/svn.rb +11 -0
  44. data/lib/r10k/module.rb +20 -2
  45. data/lib/r10k/module_loader/puppetfile/dsl.rb +8 -3
  46. data/lib/r10k/module_loader/puppetfile.rb +109 -28
  47. data/lib/r10k/puppetfile.rb +11 -13
  48. data/lib/r10k/settings/definition.rb +1 -1
  49. data/lib/r10k/settings.rb +89 -1
  50. data/lib/r10k/source/yaml.rb +1 -1
  51. data/lib/r10k/util/purgeable.rb +6 -2
  52. data/lib/r10k/util/setopts.rb +2 -0
  53. data/lib/r10k/util/subprocess.rb +1 -0
  54. data/lib/r10k/version.rb +1 -1
  55. data/locales/r10k.pot +168 -68
  56. data/r10k.gemspec +2 -0
  57. data/r10k.yaml.example +28 -0
  58. data/spec/fixtures/unit/action/r10k_logging.yaml +12 -0
  59. data/spec/fixtures/unit/puppetfile/forge-override/Puppetfile +8 -0
  60. data/spec/fixtures/unit/puppetfile/various-modules/Puppetfile +10 -0
  61. data/spec/fixtures/unit/puppetfile/various-modules/Puppetfile.new +10 -0
  62. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/managed_symlink_file +1 -0
  63. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/{managed_subdir_2 → subdir_allowlisted_2}/ignored_1 +0 -0
  64. data/spec/fixtures/unit/util/purgeable/managed_one/managed_subdir_1/unmanaged_symlink_dir +1 -0
  65. data/spec/fixtures/unit/util/purgeable/managed_one/managed_symlink_dir +1 -0
  66. data/spec/fixtures/unit/util/purgeable/managed_one/unmanaged_symlink_file +1 -0
  67. data/spec/integration/util/purageable_spec.rb +41 -0
  68. data/spec/r10k-mocks/mock_env.rb +3 -0
  69. data/spec/r10k-mocks/mock_source.rb +7 -3
  70. data/spec/unit/action/deploy/environment_spec.rb +96 -30
  71. data/spec/unit/action/deploy/module_spec.rb +217 -51
  72. data/spec/unit/action/puppetfile/check_spec.rb +17 -5
  73. data/spec/unit/action/puppetfile/install_spec.rb +42 -36
  74. data/spec/unit/action/puppetfile/purge_spec.rb +15 -17
  75. data/spec/unit/action/runner_spec.rb +132 -9
  76. data/spec/unit/environment/bare_spec.rb +13 -0
  77. data/spec/unit/environment/base_spec.rb +30 -17
  78. data/spec/unit/environment/git_spec.rb +2 -2
  79. data/spec/unit/environment/plain_spec.rb +8 -0
  80. data/spec/unit/environment/svn_spec.rb +4 -3
  81. data/spec/unit/environment/with_modules_spec.rb +3 -2
  82. data/spec/unit/git/rugged/credentials_spec.rb +29 -0
  83. data/spec/unit/git/stateful_repository_spec.rb +5 -0
  84. data/spec/unit/module/base_spec.rb +54 -8
  85. data/spec/unit/module/forge_spec.rb +51 -4
  86. data/spec/unit/module/git_spec.rb +67 -9
  87. data/spec/unit/module/svn_spec.rb +35 -5
  88. data/spec/unit/module_loader/puppetfile_spec.rb +108 -33
  89. data/spec/unit/module_spec.rb +12 -1
  90. data/spec/unit/puppetfile_spec.rb +33 -3
  91. data/spec/unit/settings_spec.rb +43 -2
  92. data/spec/unit/util/purgeable_spec.rb +22 -11
  93. metadata +31 -3
@@ -3,9 +3,10 @@ require 'r10k/action/puppetfile/install'
3
3
 
4
4
  describe R10K::Action::Puppetfile::Install do
5
5
  let(:default_opts) { { root: "/some/nonexistent/path" } }
6
- let(:puppetfile) {
7
- R10K::Puppetfile.new('/some/nonexistent/path',
8
- {:moduledir => nil, :puppetfile_path => nil, :force => false})
6
+ let(:loader) {
7
+ R10K::ModuleLoader::Puppetfile.new(
8
+ basedir: '/some/nonexistent/path',
9
+ overrides: {force: false})
9
10
  }
10
11
 
11
12
  def installer(opts = {}, argv = [], settings = {})
@@ -14,11 +15,11 @@ describe R10K::Action::Puppetfile::Install do
14
15
  end
15
16
 
16
17
  before(:each) do
17
- allow(puppetfile).to receive(:load!).and_return(nil)
18
- allow(R10K::Puppetfile).to receive(:new).
19
- with("/some/nonexistent/path",
20
- {:moduledir => nil, :puppetfile_path => nil, :force => false}).
21
- and_return(puppetfile)
18
+ allow(loader).to receive(:load!).and_return({})
19
+ allow(R10K::ModuleLoader::Puppetfile).to receive(:new).
20
+ with({basedir: "/some/nonexistent/path",
21
+ overrides: {force: false}}).
22
+ and_return(loader)
22
23
  end
23
24
 
24
25
  it_behaves_like "a puppetfile install action"
@@ -26,13 +27,19 @@ describe R10K::Action::Puppetfile::Install do
26
27
  describe "installing modules" do
27
28
  let(:modules) do
28
29
  (1..4).map do |idx|
29
- R10K::Module::Base.new("author/modname#{idx}", "/some/nonexistent/path/modname#{idx}", {})
30
+ R10K::Module::Base.new("author/modname#{idx}",
31
+ "/some/nonexistent/path/modname#{idx}",
32
+ {})
30
33
  end
31
34
  end
32
35
 
33
36
  before do
34
- allow(puppetfile).to receive(:modules).and_return(modules)
35
- allow(puppetfile).to receive(:modules_by_vcs_cachedir).and_return({none: modules})
37
+ allow(loader).to receive(:load!).and_return({
38
+ modules: modules,
39
+ managed_directories: [],
40
+ desired_contents: [],
41
+ purge_exclusions: []
42
+ })
36
43
  end
37
44
 
38
45
  it "syncs each module in the Puppetfile" do
@@ -50,15 +57,15 @@ describe R10K::Action::Puppetfile::Install do
50
57
  end
51
58
 
52
59
  describe "purging" do
53
- before do
54
- allow(puppetfile).to receive(:modules).and_return([])
55
- end
56
-
57
60
  it "purges the moduledir after installation" do
61
+ allow(loader).to receive(:load!).and_return({
62
+ modules: [],
63
+ desired_contents: [ 'root/foo' ],
64
+ managed_directories: [ 'root' ],
65
+ purge_exclusions: [ 'root/**/**.rb' ]
66
+ })
67
+
58
68
  mock_cleaner = double("cleaner")
59
- allow(puppetfile).to receive(:desired_contents).and_return(["root/foo"])
60
- allow(puppetfile).to receive(:managed_directories).and_return(["root"])
61
- allow(puppetfile).to receive(:purge_exclusions).and_return(["root/**/**.rb"])
62
69
 
63
70
  expect(R10K::Util::Cleaner).to receive(:new).
64
71
  with(["root"], ["root/foo"], ["root/**/**.rb"]).
@@ -70,35 +77,34 @@ describe R10K::Action::Puppetfile::Install do
70
77
  end
71
78
 
72
79
  describe "using custom paths" do
73
- it "can use a custom puppetfile path" do
74
- expect(R10K::Puppetfile).to receive(:new).
75
- with("/some/nonexistent/path",
76
- {:moduledir => nil, :force => false, puppetfile_path: "/some/other/path/Puppetfile"}).
77
- and_return(puppetfile)
80
+ it "can use a custom moduledir path" do
81
+ expect(R10K::ModuleLoader::Puppetfile).to receive(:new).
82
+ with({basedir: "/some/nonexistent/path",
83
+ overrides: { force: false },
84
+ puppetfile: "/some/other/path/Puppetfile"}).
85
+ and_return(loader)
78
86
 
79
87
  installer({puppetfile: "/some/other/path/Puppetfile"}).call
80
- end
81
88
 
82
- it "can use a custom moduledir path" do
83
- expect(R10K::Puppetfile).to receive(:new).
84
- with("/some/nonexistent/path",
85
- {:puppetfile_path => nil, :force => false, moduledir: "/some/other/path/site-modules"}).
86
- and_return(puppetfile)
89
+ expect(R10K::ModuleLoader::Puppetfile).to receive(:new).
90
+ with({basedir: "/some/nonexistent/path",
91
+ overrides: { force: false },
92
+ moduledir: "/some/other/path/site-modules"}).
93
+ and_return(loader)
87
94
 
88
95
  installer({moduledir: "/some/other/path/site-modules"}).call
89
96
  end
90
97
  end
91
98
 
92
99
  describe "forcing to overwrite local changes" do
93
- before do
94
- allow(puppetfile).to receive(:modules).and_return([])
95
- end
96
-
97
100
  it "can use the force overwrite option" do
101
+ allow(loader).to receive(:load!).and_return({ modules: [] })
102
+
98
103
  subject = described_class.new({root: "/some/nonexistent/path", force: true}, [], {})
99
- expect(R10K::Puppetfile).to receive(:new).
100
- with("/some/nonexistent/path", {:moduledir => nil, :puppetfile_path => nil, :force => true}).
101
- and_return(puppetfile)
104
+ expect(R10K::ModuleLoader::Puppetfile).to receive(:new).
105
+ with({basedir: "/some/nonexistent/path",
106
+ overrides: { force: true }}).
107
+ and_return(loader)
102
108
  subject.call
103
109
  end
104
110
 
@@ -4,11 +4,13 @@ require 'r10k/action/puppetfile/purge'
4
4
  describe R10K::Action::Puppetfile::Purge do
5
5
  let(:default_opts) { {root: "/some/nonexistent/path"} }
6
6
  let(:puppetfile) do
7
- instance_double('R10K::Puppetfile',
8
- :load! => nil,
9
- :managed_directories => %w{foo},
10
- :desired_contents => %w{bar},
11
- :purge_exclusions => %w{baz})
7
+ instance_double('R10K::ModuleLoader::Puppetfile',
8
+ :load! => {
9
+ :modules => %w{mod},
10
+ :managed_directories => %w{foo},
11
+ :desired_contents => %w{bar},
12
+ :purge_exclusions => %w{baz}
13
+ })
12
14
  end
13
15
 
14
16
  def purger(opts = {}, argv = [], settings = {})
@@ -17,8 +19,8 @@ describe R10K::Action::Puppetfile::Purge do
17
19
  end
18
20
 
19
21
  before(:each) do
20
- allow(R10K::Puppetfile).to receive(:new).
21
- with("/some/nonexistent/path", {moduledir: nil, puppetfile_path: nil}).
22
+ allow(R10K::ModuleLoader::Puppetfile).to receive(:new).
23
+ with({basedir: "/some/nonexistent/path"}).
22
24
  and_return(puppetfile)
23
25
  end
24
26
 
@@ -37,23 +39,19 @@ describe R10K::Action::Puppetfile::Purge do
37
39
  end
38
40
 
39
41
  describe "using custom paths" do
40
- before(:each) do
41
- allow(puppetfile).to receive(:purge!)
42
- end
43
-
44
42
  it "can use a custom puppetfile path" do
45
- expect(R10K::Puppetfile).to receive(:new).
46
- with("/some/nonexistent/path",
47
- {moduledir: nil, puppetfile_path: "/some/other/path/Puppetfile"}).
43
+ expect(R10K::ModuleLoader::Puppetfile).to receive(:new).
44
+ with({basedir: "/some/nonexistent/path",
45
+ puppetfile: "/some/other/path/Puppetfile"}).
48
46
  and_return(puppetfile)
49
47
 
50
48
  purger({puppetfile: "/some/other/path/Puppetfile"}).call
51
49
  end
52
50
 
53
51
  it "can use a custom moduledir path" do
54
- expect(R10K::Puppetfile).to receive(:new).
55
- with("/some/nonexistent/path",
56
- {moduledir: "/some/other/path/site-modules", puppetfile_path: nil}).
52
+ expect(R10K::ModuleLoader::Puppetfile).to receive(:new).
53
+ with({basedir: "/some/nonexistent/path",
54
+ moduledir: "/some/other/path/site-modules"}).
57
55
  and_return(puppetfile)
58
56
 
59
57
  purger({moduledir: "/some/other/path/site-modules"}).call
@@ -159,10 +159,61 @@ describe R10K::Action::Runner do
159
159
  end
160
160
 
161
161
  describe "configuring logging" do
162
+ before(:each) do
163
+ R10K::Logging.outputters.clear
164
+ end
165
+
162
166
  it "sets the log level if :loglevel is provided" do
163
167
  runner = described_class.new({:opts => :yep, :loglevel => 'FATAL'}, %w[args yes], action_class)
164
- expect(R10K::Logging).to receive(:level=).with('FATAL')
168
+ # The settings/overrides system causes the level to be set twice
169
+ expect(R10K::Logging).to receive(:level=).with('FATAL').twice
170
+ runner.call
171
+ end
172
+
173
+ # The logging fixture tests require a platform with syslog
174
+ if !R10K::Util::Platform.windows?
175
+ it "sets the log level if the logging.level setting is provided" do
176
+ runner = described_class.new({ opts: :yep, config: 'spec/fixtures/unit/action/r10k_logging.yaml'}, %w[args yes], action_class)
177
+ expect(R10K::Logging).to receive(:level=).with('FATAL')
178
+ runner.call
179
+ end
180
+
181
+ it "sets the outputters if logging.outputs is provided" do
182
+ runner = described_class.new({ opts: :yep, config: 'spec/fixtures/unit/action/r10k_logging.yaml' }, %w[args yes], action_class)
183
+ expect(R10K::Logging).to receive(:add_outputters).with([
184
+ { type: 'file', parameters: { filename: 'r10k.log' } },
185
+ { type: 'syslog' }
186
+ ])
187
+ runner.call
188
+ end
189
+
190
+ it "disables the default outputter if the logging.disable_default_stderr setting is provided" do
191
+ runner = described_class.new({ opts: :yep, config: 'spec/fixtures/unit/action/r10k_logging.yaml'}, %w[args yes], action_class)
192
+ expect(R10K::Logging).to receive(:disable_default_stderr=).with(true)
193
+ runner.call
194
+ end
195
+
196
+ it "adds additional log outputs if the logging.outputs setting is provided" do
197
+ runner = described_class.new({ opts: :yep, config: 'spec/fixtures/unit/action/r10k_logging.yaml'}, %w[args yes], action_class)
198
+ runner.call
199
+ expect(R10K::Logging.outputters).to_not be_empty
200
+ end
201
+
202
+ it "disables the default output if the logging.disable_default_stderr setting is provided" do
203
+ runner = described_class.new({ opts: :yep, config: 'spec/fixtures/unit/action/r10k_logging.yaml'}, %w[args yes], action_class)
204
+ runner.call
205
+ expect(runner.logger.outputters).to satisfy { |outputs| outputs.any? { |output| output.is_a?(R10K::Logging::TerminalOutputter) && output.level == Log4r::OFF } }
206
+ end
207
+ end
208
+
209
+ it "doesn't add additional log outputs if the logging.outputs setting is not provided" do
210
+ runner.call
211
+ expect(R10K::Logging.outputters).to be_empty
212
+ end
213
+
214
+ it "includes the default stderr outputter" do
165
215
  runner.call
216
+ expect(runner.logger.outputters).to satisfy { |outputs| outputs.any? { |output| output.is_a? R10K::Logging::TerminalOutputter } }
166
217
  end
167
218
 
168
219
  it "does not modify the loglevel if :loglevel is not provided" do
@@ -171,6 +222,86 @@ describe R10K::Action::Runner do
171
222
  end
172
223
  end
173
224
 
225
+ describe "configuring github app credentials" do
226
+ it 'errors if app id is passed without ssl key' do
227
+ runner = described_class.new(
228
+ { 'github-app-id': '/nonexistent', },
229
+ %w[args yes],
230
+ action_class
231
+ )
232
+ expect{ runner.call }.to raise_error(R10K::Error, /Must specify both id and SSL private key/)
233
+ end
234
+
235
+ it 'errors if ssl key is passed without app id' do
236
+ runner = described_class.new(
237
+ { 'github-app-key': '/nonexistent', },
238
+ %w[args yes],
239
+ action_class
240
+ )
241
+ expect{ runner.call }.to raise_error(R10K::Error, /Must specify both id and SSL private key/)
242
+ end
243
+
244
+ it 'errors if both app id and token paths are passed' do
245
+ runner = described_class.new(
246
+ { 'github-app-id': '/nonexistent', 'oauth-token': '/also/fake' },
247
+ %w[args yes],
248
+ action_class
249
+ )
250
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
251
+ end
252
+
253
+ it 'errors if both ssl key and token paths are passed' do
254
+ runner = described_class.new(
255
+ { 'github-app-key': '/nonexistent', 'oauth-token': '/also/fake' },
256
+ %w[args yes],
257
+ action_class
258
+ )
259
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
260
+ end
261
+
262
+ it 'errors if both ssl key and ssh key paths are passed' do
263
+ runner = described_class.new(
264
+ { 'github-app-key': '/nonexistent', 'private-key': '/also/fake' },
265
+ %w[args yes],
266
+ action_class
267
+ )
268
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
269
+ end
270
+
271
+ it 'errors if both app id and ssh key are passed' do
272
+ runner = described_class.new(
273
+ { 'github-app-id': '/nonexistent', 'private-key': '/also/fake' },
274
+ %w[args yes],
275
+ action_class
276
+ )
277
+ expect{ runner.call }.to raise_error(R10K::Error, /Cannot specify both/)
278
+ end
279
+
280
+ it 'saves the parameters in settings hash' do
281
+ runner = described_class.new(
282
+ { 'github-app-id': '123456', 'github-app-key': '/my/ssl/key', 'github-app-ttl': '600' },
283
+ %w[args yes],
284
+ action_class
285
+ )
286
+ runner.call
287
+ expect(runner.instance.settings[:git][:github_app_id]).to eq('123456')
288
+ expect(runner.instance.settings[:git][:github_app_key]).to eq('/my/ssl/key')
289
+ expect(runner.instance.settings[:git][:github_app_ttl]).to eq('600')
290
+ end
291
+
292
+ it 'saves the parameters in settings hash without ttl and uses its default value' do
293
+ runner = described_class.new(
294
+ { 'github-app-id': '123456', 'github-app-key': '/my/ssl/key', },
295
+ %w[args yes],
296
+ action_class
297
+ )
298
+ runner.call
299
+ expect(runner.instance.settings[:git][:github_app_id]).to eq('123456')
300
+ expect(runner.instance.settings[:git][:github_app_key]).to eq('/my/ssl/key')
301
+ expect(runner.instance.settings[:git][:github_app_ttl]).to eq('120')
302
+ end
303
+ end
304
+
174
305
  describe "configuring git credentials" do
175
306
  it 'errors if both token and key paths are passed' do
176
307
  runner = described_class.new({ 'oauth-token': '/nonexistent',
@@ -230,14 +361,6 @@ describe R10K::Action::Runner do
230
361
  runner.setup_settings
231
362
  runner.setup_authorization
232
363
  end
233
-
234
- it 'errors if no custom forge URL is set' do
235
- options = { config: "spec/fixtures/unit/action/r10k_forge_auth_no_url.yaml" }
236
- runner = described_class.new(options, %w[args yes], action_class)
237
- expect(PuppetForge::Connection).not_to receive(:authorization=).with('faketoken')
238
-
239
- expect { runner.setup_settings }.to raise_error(R10K::Error, /Cannot specify a Forge auth/)
240
- end
241
364
  end
242
365
 
243
366
  context "license auth" do
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+ require 'r10k/environment'
3
+
4
+ describe R10K::Environment::Bare do
5
+ it "warns on initialization" do
6
+ logger_spy = spy('logger')
7
+ allow_any_instance_of(described_class).to receive(:logger).and_return(logger_spy)
8
+
9
+ described_class.new('envname', '/basedir', 'dirname', {})
10
+
11
+ expect(logger_spy).to have_received(:warn).with(%r{deprecated.*envname})
12
+ end
13
+ end
@@ -3,10 +3,13 @@ require 'r10k/environment'
3
3
 
4
4
  describe R10K::Environment::Base do
5
5
 
6
- subject(:environment) { described_class.new('envname', '/some/imaginary/path', 'env_name', {}) }
6
+ let(:basepath) { '/some/imaginary/path' }
7
+ let(:envname) { 'env_name' }
8
+ let(:path) { File.join(basepath, envname) }
9
+ subject(:environment) { described_class.new('envname', basepath, envname, {}) }
7
10
 
8
11
  it "can return the fully qualified path" do
9
- expect(environment.path).to eq(Pathname.new('/some/imaginary/path/env_name'))
12
+ expect(environment.path).to eq(Pathname.new(path))
10
13
  end
11
14
 
12
15
  it "raises an exception when #sync is called" do
@@ -49,45 +52,55 @@ describe R10K::Environment::Base do
49
52
  describe "#purge_exclusions" do
50
53
  let(:mock_env) { instance_double("R10K::Environment::Base") }
51
54
  let(:mock_puppetfile) { instance_double("R10K::Puppetfile", :environment= => true, :environment => mock_env) }
55
+ let(:loader) do
56
+ instance_double("R10K::ModuleLoader::Puppetfile",
57
+ :environment= => nil,
58
+ :load => { :modules => @modules,
59
+ :managed_directories => @managed_dirs,
60
+ :desired_contents => @desired_contents,
61
+ :purge_exclusions => @purge_ex })
62
+ end
52
63
 
53
64
  before(:each) do
54
- allow(mock_puppetfile).to receive(:managed_directories).and_return([])
55
- allow(mock_puppetfile).to receive(:desired_contents).and_return([])
56
- allow(R10K::Puppetfile).to receive(:new).and_return(mock_puppetfile)
65
+ @modules = []
66
+ @managed_dirs = []
67
+ @desired_contents = []
68
+ @purge_exclusions = []
57
69
  end
58
70
 
59
71
  it "excludes .r10k-deploy.json" do
72
+ allow(R10K::ModuleLoader::Puppetfile).to receive(:new).and_return(loader)
73
+ subject.deploy
74
+
60
75
  expect(subject.purge_exclusions).to include(/r10k-deploy\.json/)
61
76
  end
62
77
 
63
78
  it "excludes puppetfile managed directories" do
64
- managed_dirs = [
79
+ @managed_dirs = [
65
80
  '/some/imaginary/path/env_name/modules',
66
81
  '/some/imaginary/path/env_name/data',
67
82
  ]
68
83
 
69
- expect(mock_puppetfile).to receive(:managed_directories).and_return(managed_dirs)
84
+ allow(R10K::ModuleLoader::Puppetfile).to receive(:new).and_return(loader)
85
+ subject.deploy
70
86
 
71
87
  exclusions = subject.purge_exclusions
72
88
 
73
- managed_dirs.each do |dir|
89
+ @managed_dirs.each do |dir|
74
90
  expect(exclusions).to include(dir)
75
91
  end
76
92
  end
77
93
 
78
94
  describe "puppetfile desired contents" do
79
- let(:desired_contents) do
80
- basedir = subject.path.to_s
81
-
82
- [ 'modules/apache', 'data/local/site' ].collect do |c|
83
- File.join(basedir, c)
84
- end
85
- end
86
95
 
87
96
  before(:each) do
88
- allow(File).to receive(:directory?).with(/^\/some\/imaginary\/path/).and_return(true)
97
+ @desired_contents = [ 'modules/apache', 'data/local/site' ].collect do |c|
98
+ File.join(path, c)
99
+ end
89
100
 
90
- expect(mock_puppetfile).to receive(:desired_contents).and_return(desired_contents)
101
+ allow(File).to receive(:directory?).and_return true
102
+ allow(R10K::ModuleLoader::Puppetfile).to receive(:new).and_return(loader)
103
+ subject.deploy
91
104
  end
92
105
 
93
106
  it "excludes desired directory contents with glob" do
@@ -78,9 +78,9 @@ describe R10K::Environment::Git do
78
78
 
79
79
  describe "enumerating modules" do
80
80
  it "loads the Puppetfile and returns modules in that puppetfile" do
81
+ loaded = { desired_contents: [], managed_directories: [], purge_exclusions: [] }
81
82
  mod = double('A module', :name => 'dbl')
82
- expect(subject.puppetfile).to receive(:load)
83
- expect(subject.puppetfile).to receive(:modules).and_return [mod]
83
+ expect(subject.loader).to receive(:load).and_return(loaded.merge(modules: [mod]))
84
84
  expect(subject.modules).to eq([mod])
85
85
  end
86
86
  end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'r10k/environment'
3
+
4
+ describe R10K::Environment::Plain do
5
+ it "initializes successfully" do
6
+ expect(described_class.new('envname', '/basedir', 'dirname', {})).to be_a_kind_of(described_class)
7
+ end
8
+ end
@@ -78,9 +78,10 @@ describe R10K::Environment::SVN do
78
78
 
79
79
  describe "enumerating modules" do
80
80
  it "loads the Puppetfile and returns modules in that puppetfile" do
81
- expect(subject.puppetfile).to receive(:load)
82
- expect(subject.puppetfile).to receive(:modules).and_return [:modules]
83
- expect(subject.modules).to eq([:modules])
81
+ loaded = { managed_directories: [], desired_contents: [], purge_exclusions: [] }
82
+ mod = double('A module', :name => 'dbl')
83
+ expect(subject.loader).to receive(:load).and_return(loaded.merge(modules: [mod]))
84
+ expect(subject.modules).to eq([mod])
84
85
  end
85
86
  end
86
87
 
@@ -8,7 +8,7 @@ describe R10K::Environment::WithModules do
8
8
  '/some/nonexistent/environmentdir',
9
9
  'prefix_release42',
10
10
  {
11
- :type => 'bare',
11
+ :type => 'plain',
12
12
  :modules => {
13
13
  'puppetlabs-stdlib' => { local: true },
14
14
  'puppetlabs-concat' => { local: true },
@@ -65,8 +65,9 @@ describe R10K::Environment::WithModules do
65
65
 
66
66
  describe "modules method" do
67
67
  it "returns the configured modules, and Puppetfile modules" do
68
+ loaded = { managed_directories: [], desired_contents: [], purge_exclusions: [] }
68
69
  puppetfile_mod = instance_double('R10K::Module::Base', name: 'zebra')
69
- expect(subject.puppetfile).to receive(:modules).and_return [puppetfile_mod]
70
+ expect(subject.loader).to receive(:load).and_return(loaded.merge(modules: [puppetfile_mod]))
70
71
  returned_modules = subject.modules
71
72
  expect(returned_modules.map(&:name).sort).to eq(%w[concat exec stdlib zebra])
72
73
  end
@@ -79,6 +79,35 @@ describe R10K::Git::Rugged::Credentials, :unless => R10K::Util::Platform.jruby?
79
79
  end
80
80
  end
81
81
 
82
+ describe "generating github app tokens" do
83
+ it 'errors if app id has invalid characters' do
84
+ expect { subject.github_app_token("123A567890", "fake", "300")
85
+ }.to raise_error(R10K::Git::GitError, /App id contains invalid characters/)
86
+ end
87
+ it 'errors if app ttl has invalid characters' do
88
+ expect { subject.github_app_token("123456", "fake", "abc")
89
+ }.to raise_error(R10K::Git::GitError, /Github App token ttl contains/)
90
+ end
91
+ it 'errors if private file does not exist' do
92
+ R10K::Git.settings[:github_app_key] = "/missing/token/file"
93
+ expect(File).to receive(:readable?).with(R10K::Git.settings[:github_app_key]).and_return false
94
+ expect {
95
+ subject.github_app_token("123456", R10K::Git.settings[:github_app_key], "300")
96
+ }.to raise_error(R10K::Git::GitError, /App key is missing or unreadable/)
97
+ end
98
+ it 'errors if file is not a valid SSL key' do
99
+ token_file = Tempfile.new('token')
100
+ token_file.write('my_token')
101
+ token_file.close
102
+ R10K::Git.settings[:github_app_key] = token_file.path
103
+ expect(File).to receive(:readable?).with(token_file.path).and_return true
104
+ expect {
105
+ subject.github_app_token("123456", R10K::Git.settings[:github_app_key], "300")
106
+ }.to raise_error(R10K::Git::GitError, /App key is not a valid SSL key/)
107
+ token_file.unlink
108
+ end
109
+ end
110
+
82
111
  describe "generating token credentials" do
83
112
  it 'errors if token file does not exist' do
84
113
  R10K::Git.settings[:oauth_token] = "/missing/token/file"
@@ -19,6 +19,11 @@ describe R10K::Git::StatefulRepository do
19
19
  expect(subject.sync_cache?(ref)).to eq true
20
20
  end
21
21
 
22
+ it "is true if the ref is HEAD" do
23
+ expect(cache).to receive(:exist?).and_return true
24
+ expect(subject.sync_cache?('HEAD')).to eq true
25
+ end
26
+
22
27
  it "is true if the ref is unresolvable" do
23
28
  expect(cache).to receive(:exist?).and_return true
24
29
  expect(cache).to receive(:ref_type).with('0.9.x').and_return(:unknown)