r10k 1.4.2 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (244) hide show
  1. data/.travis.yml +2 -0
  2. data/CHANGELOG.mkd +192 -0
  3. data/CONTRIBUTING.mkd +3 -3
  4. data/Gemfile +4 -0
  5. data/README.mkd +13 -6
  6. data/doc/dynamic-environments/configuration.mkd +77 -8
  7. data/doc/dynamic-environments/git-environments.mkd +12 -2
  8. data/doc/dynamic-environments/quickstart.mkd +6 -0
  9. data/doc/faq.mkd +6 -6
  10. data/doc/git/cloning-and-mirroring.mkd +60 -0
  11. data/doc/git/providers.mkd +68 -0
  12. data/integration/Gemfile +3 -0
  13. data/integration/README.mkd +29 -0
  14. data/integration/configs/README.mkd +7 -0
  15. data/integration/configs/pe/centos-6-64mda +25 -0
  16. data/integration/configs/pe/centos-7-64mda +25 -0
  17. data/integration/configs/pe/debian-6-64mda +25 -0
  18. data/integration/configs/pe/debian-7-64mda +25 -0
  19. data/integration/configs/pe/redhat-6-64mda +25 -0
  20. data/integration/configs/pe/redhat-7-64mda +25 -0
  21. data/integration/configs/pe/sles-11-64mda +25 -0
  22. data/integration/configs/pe/ubuntu-1004-64mda +25 -0
  23. data/integration/configs/pe/ubuntu-1204-64mda +25 -0
  24. data/integration/configs/pe/ubuntu-1404-64mda +25 -0
  25. data/integration/files/README.mkd +4 -0
  26. data/integration/files/hiera.yaml +8 -0
  27. data/integration/files/modules/helloworld/manifests/init.pp +3 -0
  28. data/integration/files/modules/hieratest/manifests/init.pp +3 -0
  29. data/integration/files/modules/unicode/files/pretend_unicode +1 -0
  30. data/integration/files/modules/unicode/manifests/init.pp +6 -0
  31. data/integration/files/pre-suite/prod_env.config +3 -0
  32. data/integration/files/r10k_conf.yaml.erb +9 -0
  33. data/integration/lib/README.mkd +4 -0
  34. data/integration/lib/git_utils.rb +205 -0
  35. data/integration/lib/master_manipulator.rb +205 -0
  36. data/integration/lib/r10k_utils.rb +166 -0
  37. data/integration/manifests/README.mkd +4 -0
  38. data/integration/pre-suite/00_pe_install.rb +4 -0
  39. data/integration/pre-suite/01_git_config.rb +59 -0
  40. data/integration/pre-suite/02_pe_r10k.rb +60 -0
  41. data/integration/pre-suite/03_test_utils.rb +17 -0
  42. data/integration/pre-suite/README.mkd +5 -0
  43. data/integration/test_run_scripts/README.mkd +5 -0
  44. data/integration/test_run_scripts/all_tests-rugged-pe-centos6.sh +20 -0
  45. data/integration/test_run_scripts/all_tests-rugged-pe-rhel7.sh +20 -0
  46. data/integration/test_run_scripts/all_tests-rugged-pe-sles11.sh +20 -0
  47. data/integration/test_run_scripts/all_tests-rugged-pe-ubuntu1204.sh +20 -0
  48. data/integration/test_run_scripts/all_tests-rugged-pe-ubuntu1404.sh +20 -0
  49. data/integration/test_run_scripts/all_tests-shellgit-pe-centos6.sh +20 -0
  50. data/integration/test_run_scripts/all_tests-shellgit-pe-rhel7.sh +20 -0
  51. data/integration/test_run_scripts/all_tests-shellgit-pe-sles11.sh +20 -0
  52. data/integration/test_run_scripts/all_tests-shellgit-pe-ubuntu1204.sh +20 -0
  53. data/integration/test_run_scripts/all_tests-shellgit-pe-ubuntu1404.sh +20 -0
  54. data/integration/test_run_scripts/basic_functionality/all_tests-pe-centos6.sh +20 -0
  55. data/integration/test_run_scripts/command_line/all_tests-pe-centos6.sh +20 -0
  56. data/integration/test_run_scripts/git_source/all_tests-pe-centos6.sh +20 -0
  57. data/integration/test_run_scripts/user_scenario/basic_workflow/all_tests-pe-centos6.sh +20 -0
  58. data/integration/test_run_scripts/user_scenario/complex_workflow/all_tests-pe-centos6.sh +20 -0
  59. data/integration/tests/README.mkd +4 -0
  60. data/integration/tests/basic_functionality/negative/neg_deploy_with_invalid_r10k_yaml.rb +46 -0
  61. data/integration/tests/basic_functionality/negative/neg_deploy_with_missing_r10k_yaml.rb +27 -0
  62. data/integration/tests/command_line/deploy_env_without_mod_update.rb +75 -0
  63. data/integration/tests/command_line/negative/neg_deploy_env_with_module_update.rb +76 -0
  64. data/integration/tests/command_line/negative/neg_invalid_cli_dep_flag.rb +22 -0
  65. data/integration/tests/command_line/negative/neg_invalid_cli_env_flag.rb +22 -0
  66. data/integration/tests/command_line/negative/neg_invalid_cmd_line_arg.rb +24 -0
  67. data/integration/tests/git_source/git_source_git.rb +123 -0
  68. data/integration/tests/git_source/git_source_ssh.rb +84 -0
  69. data/integration/tests/git_source/git_source_submodule.rb +69 -0
  70. data/integration/tests/git_source/negative/neg_git_broken_remote.rb +37 -0
  71. data/integration/tests/git_source/negative/neg_git_unauthorized_https.rb +45 -0
  72. data/integration/tests/git_source/negative/neg_git_unauthorized_ssh.rb +72 -0
  73. data/integration/tests/git_source/negative/neg_git_unicode_branch.rb +34 -0
  74. data/integration/tests/user_scenario/basic_workflow/multi_env_1000_branches.rb +66 -0
  75. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module.rb +110 -0
  76. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module_static.rb +113 -0
  77. data/integration/tests/user_scenario/basic_workflow/multi_env_hiera.rb +93 -0
  78. data/integration/tests/user_scenario/basic_workflow/multi_env_multi_source.rb +132 -0
  79. data/integration/tests/user_scenario/basic_workflow/multi_source_custom_forge_git_module.rb +160 -0
  80. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_basedir.rb +45 -0
  81. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_forge_module.rb +43 -0
  82. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module.rb +40 -0
  83. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module_ref.rb +42 -0
  84. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_remote.rb +44 -0
  85. data/integration/tests/user_scenario/basic_workflow/negative/neg_branch_name_collision.rb +63 -0
  86. data/integration/tests/user_scenario/basic_workflow/negative/neg_disk_full.rb +73 -0
  87. data/integration/tests/user_scenario/basic_workflow/negative/neg_duplicate_module_names.rb +45 -0
  88. data/integration/tests/user_scenario/basic_workflow/negative/neg_inaccessible_forge.rb +51 -0
  89. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_env_name.rb +33 -0
  90. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_puppet_file.rb +35 -0
  91. data/integration/tests/user_scenario/basic_workflow/negative/neg_module_specified_at_deleted_release.rb +44 -0
  92. data/integration/tests/user_scenario/basic_workflow/negative/neg_read_only.rb +57 -0
  93. data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +44 -0
  94. data/integration/tests/user_scenario/basic_workflow/single_env_10000_files.rb +73 -0
  95. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_git_module.rb +103 -0
  96. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_module.rb +80 -0
  97. data/integration/tests/user_scenario/basic_workflow/single_env_custom_module.rb +48 -0
  98. data/integration/tests/user_scenario/basic_workflow/single_env_large_files.rb +73 -0
  99. data/integration/tests/user_scenario/basic_workflow/single_env_module_already_installed.rb +81 -0
  100. data/integration/tests/user_scenario/basic_workflow/single_env_module_last_release_deleted.rb +67 -0
  101. data/integration/tests/user_scenario/basic_workflow/single_env_non-existent_base_dir.rb +93 -0
  102. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +92 -0
  103. data/integration/tests/user_scenario/basic_workflow/single_env_switch_forge_git_module.rb +116 -0
  104. data/integration/tests/user_scenario/basic_workflow/single_env_unicode_paths.rb +59 -0
  105. data/integration/tests/user_scenario/basic_workflow/single_env_upgrade_forge_mod_revert_change.rb +165 -0
  106. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +162 -0
  107. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +110 -0
  108. data/lib/r10k/action/cri_runner.rb +10 -13
  109. data/lib/r10k/cli.rb +3 -8
  110. data/lib/r10k/cli/version.rb +10 -1
  111. data/lib/r10k/deployment/config.rb +26 -6
  112. data/lib/r10k/deployment/config/loader.rb +38 -29
  113. data/lib/r10k/deployment/source.rb +2 -4
  114. data/lib/r10k/environment/git.rb +10 -19
  115. data/lib/r10k/environment/name.rb +86 -0
  116. data/lib/r10k/errors.rb +8 -5
  117. data/lib/r10k/feature.rb +35 -0
  118. data/lib/r10k/feature/collection.rb +23 -0
  119. data/lib/r10k/features.rb +18 -0
  120. data/lib/r10k/git.rb +106 -12
  121. data/lib/r10k/git/alternates.rb +2 -2
  122. data/lib/r10k/git/cache.rb +43 -26
  123. data/lib/r10k/git/errors.rb +12 -6
  124. data/lib/r10k/git/head.rb +3 -0
  125. data/lib/r10k/git/ref.rb +3 -0
  126. data/lib/r10k/git/remote_head.rb +6 -0
  127. data/lib/r10k/git/repository.rb +6 -0
  128. data/lib/r10k/git/rugged.rb +17 -0
  129. data/lib/r10k/git/rugged/bare_repository.rb +86 -0
  130. data/lib/r10k/git/rugged/base_repository.rb +90 -0
  131. data/lib/r10k/git/rugged/cache.rb +11 -0
  132. data/lib/r10k/git/rugged/thin_repository.rb +72 -0
  133. data/lib/r10k/git/rugged/working_repository.rb +99 -0
  134. data/lib/r10k/git/shellgit.rb +9 -0
  135. data/lib/r10k/git/shellgit/bare_repository.rb +29 -0
  136. data/lib/r10k/git/shellgit/base_repository.rb +102 -0
  137. data/lib/r10k/git/shellgit/cache.rb +11 -0
  138. data/lib/r10k/git/shellgit/thin_repository.rb +56 -0
  139. data/lib/r10k/git/shellgit/working_repository.rb +73 -0
  140. data/lib/r10k/git/stateful_repository.rb +80 -0
  141. data/lib/r10k/git/tag.rb +3 -0
  142. data/lib/r10k/git/working_dir.rb +15 -2
  143. data/lib/r10k/logging.rb +73 -36
  144. data/lib/r10k/logging/terminaloutputter.rb +36 -0
  145. data/lib/r10k/module/forge.rb +10 -9
  146. data/lib/r10k/module/git.rb +14 -44
  147. data/lib/r10k/module/metadata_file.rb +31 -0
  148. data/lib/r10k/module/svn.rb +0 -1
  149. data/lib/r10k/module_repository/forge.rb +20 -7
  150. data/lib/r10k/puppetfile.rb +1 -1
  151. data/lib/r10k/settings/container.rb +6 -0
  152. data/lib/r10k/settings/mixin.rb +9 -0
  153. data/lib/r10k/source.rb +2 -3
  154. data/lib/r10k/source/base.rb +5 -5
  155. data/lib/r10k/source/git.rb +11 -86
  156. data/lib/r10k/source/svn.rb +8 -52
  157. data/lib/r10k/util/basedir.rb +4 -4
  158. data/lib/r10k/util/commands.rb +31 -0
  159. data/lib/r10k/util/exec_env.rb +36 -0
  160. data/lib/r10k/util/platform.rb +4 -0
  161. data/lib/r10k/util/purgeable.rb +2 -2
  162. data/lib/r10k/util/subprocess.rb +3 -7
  163. data/lib/r10k/util/subprocess/runner.rb +3 -28
  164. data/lib/r10k/util/subprocess/runner/posix.rb +103 -0
  165. data/lib/r10k/util/subprocess/runner/pump.rb +59 -0
  166. data/lib/r10k/util/subprocess/{windows/runner.rb → runner/windows.rb} +2 -11
  167. data/lib/r10k/util/symbolize_keys.rb +31 -0
  168. data/lib/r10k/version.rb +1 -1
  169. data/lib/shared/puppet/module_tool/metadata.rb +197 -0
  170. data/r10k.gemspec +7 -5
  171. data/spec/fixtures/integration/git/puppet-boolean-bare.tar +0 -0
  172. data/spec/fixtures/module/forge/bad_module/metadata.json +1 -0
  173. data/spec/fixtures/unit/util/subprocess/posix/runner/no-execute.sh +3 -0
  174. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/and_the_expected_version_is_latest/can_fetch_all_versions_of_a_given_module.yml +171 -26
  175. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/and_the_expected_version_is_latest/can_fetch_the_latest_version_of_a_given_module.yml +171 -26
  176. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/and_the_expected_version_is_latest/ignores_deleted_releases.yml +190 -0
  177. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/it_handles_errors_from_forgeapi_puppetlabs_com/raises_an_error_for_a_non-existant_module.yml +34 -0
  178. data/spec/fixtures/vcr/cassettes/R10K_Module_Forge/and_the_expected_version_is_latest/sets_the_expected_version_based_on_the_latest_forge_version.yml +87 -26
  179. data/spec/integration/git/rugged/bare_repository_spec.rb +13 -0
  180. data/spec/integration/git/rugged/thin_repository_spec.rb +14 -0
  181. data/spec/integration/git/rugged/working_repository_spec.rb +13 -0
  182. data/spec/integration/git/shellgit/bare_repository_spec.rb +13 -0
  183. data/spec/integration/git/shellgit/thin_repository_spec.rb +14 -0
  184. data/spec/integration/git/shellgit/working_repository_spec.rb +13 -0
  185. data/spec/integration/git/stateful_repository_spec.rb +104 -0
  186. data/spec/matchers/match_realpath.rb +18 -0
  187. data/spec/shared-contexts/git-fixtures.rb +55 -0
  188. data/spec/shared-examples/git-repository.rb +38 -0
  189. data/spec/shared-examples/git/bare_repository.rb +70 -0
  190. data/spec/shared-examples/git/thin_repository.rb +26 -0
  191. data/spec/shared-examples/git/working_repository.rb +115 -0
  192. data/spec/shared-examples/subprocess-runner.rb +83 -0
  193. data/spec/spec_helper.rb +13 -9
  194. data/spec/unit/action/cri_runner_spec.rb +0 -6
  195. data/spec/unit/action/puppetfile/{cri_action_spec.rb → cri_runner_spec.rb} +0 -0
  196. data/spec/unit/deployment/config/loader_spec.rb +48 -0
  197. data/spec/unit/deployment/config_spec.rb +49 -0
  198. data/spec/unit/environment/git_spec.rb +5 -39
  199. data/spec/unit/environment/name_spec.rb +135 -0
  200. data/spec/unit/feature_spec.rb +50 -0
  201. data/spec/unit/git/alternates_spec.rb +1 -1
  202. data/spec/unit/git/cache_spec.rb +32 -19
  203. data/spec/unit/git/commit_spec.rb +1 -0
  204. data/spec/unit/git/head_spec.rb +1 -6
  205. data/spec/unit/git/ref_spec.rb +0 -23
  206. data/spec/unit/git/rugged/cache_spec.rb +26 -0
  207. data/spec/unit/git/shellgit/cache_spec.rb +27 -0
  208. data/spec/unit/git/stateful_repository_spec.rb +43 -0
  209. data/spec/unit/git/tag_spec.rb +1 -0
  210. data/spec/unit/git/working_dir_spec.rb +1 -0
  211. data/spec/unit/git_spec.rb +74 -0
  212. data/spec/unit/logging/terminaloutputter_spec.rb +53 -0
  213. data/spec/unit/logging_spec.rb +68 -0
  214. data/spec/unit/module/forge_spec.rb +7 -38
  215. data/spec/unit/module/git_spec.rb +7 -38
  216. data/spec/unit/module/metadata_file_spec.rb +69 -0
  217. data/spec/unit/module/svn_spec.rb +0 -4
  218. data/spec/unit/module_repository/forge_spec.rb +22 -1
  219. data/spec/unit/puppet/module_tool/metadata_spec.rb +301 -0
  220. data/spec/unit/settings/container_spec.rb +17 -0
  221. data/spec/unit/source/git_spec.rb +0 -123
  222. data/spec/unit/source/svn_spec.rb +66 -0
  223. data/spec/unit/util/commands_spec.rb +61 -0
  224. data/spec/unit/util/exec_env_spec.rb +56 -0
  225. data/spec/unit/util/subprocess/runner/posix_spec.rb +7 -0
  226. data/spec/unit/util/subprocess/runner/pump_spec.rb +79 -0
  227. data/spec/unit/util/subprocess_spec.rb +3 -2
  228. data/spec/unit/util/symbolize_keys_spec.rb +51 -0
  229. metadata +226 -45
  230. data/lib/r10k/execution.rb +0 -47
  231. data/lib/r10k/module/metadata.rb +0 -47
  232. data/lib/r10k/util/core_ext/hash_ext.rb +0 -19
  233. data/lib/r10k/util/subprocess/io.rb +0 -7
  234. data/lib/r10k/util/subprocess/posix.rb +0 -4
  235. data/lib/r10k/util/subprocess/posix/io.rb +0 -7
  236. data/lib/r10k/util/subprocess/posix/runner.rb +0 -140
  237. data/lib/r10k/util/subprocess/windows.rb +0 -4
  238. data/lib/r10k/util/subprocess/windows/io.rb +0 -6
  239. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions.yml +0 -42
  240. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions/can_fetch_all_versions_of_a_given_module.yml +0 -42
  241. data/spec/fixtures/vcr/cassettes/R10K_ModuleRepository_Forge/looking_up_versions/can_fetch_the_latest_version_of_a_given_module.yml +0 -42
  242. data/spec/unit/deployment/source_spec.rb +0 -24
  243. data/spec/unit/module/metadata_spec.rb +0 -68
  244. data/spec/unit/util/core_ext/hash_ext_spec.rb +0 -63
@@ -47,19 +47,8 @@ describe R10K::Module::Forge do
47
47
  end
48
48
  end
49
49
 
50
- describe "fetching the current version" do
51
- subject { described_class.new('branan/eight_hundred', '/moduledir', '8.0.0') }
52
-
53
- it "reads the metadata before returning the version from the metadata" do
54
- metadata = subject.metadata
55
- expect(metadata).to receive(:read)
56
- expect(metadata).to receive(:version).and_return(R10K::SemVer.new('1.2.3'))
57
- expect(subject.current_version).to eq(R10K::SemVer.new('1.2.3'))
58
- end
59
- end
60
-
61
50
  describe "properties" do
62
- subject { described_class.new('branan/eight_hundred', '/moduledir', '8.0.0') }
51
+ subject { described_class.new('branan/eight_hundred', fixture_modulepath, '8.0.0') }
63
52
 
64
53
  it "sets the module type to :forge" do
65
54
  expect(subject.properties).to include(:type => :forge)
@@ -85,8 +74,6 @@ describe R10K::Module::Forge do
85
74
 
86
75
  subject { described_class.new('branan/eight_hundred', fixture_modulepath, '8.0.0') }
87
76
 
88
- before { allow(R10K::Module::Metadata).to receive(:new).and_return metadata }
89
-
90
77
  describe "and the module is in sync" do
91
78
  before do
92
79
  allow(subject).to receive(:status).and_return :insync
@@ -184,13 +171,7 @@ describe R10K::Module::Forge do
184
171
 
185
172
  describe "determining the status" do
186
173
 
187
- let(:metadata) { double 'metadata', :version => R10K::SemVer.new('8.0.0'), :author => 'branan', :exist? => true, :read => nil }
188
-
189
- subject { described_class.new('branan/eight_hundred', '/moduledir', '8.0.0') }
190
-
191
- before do
192
- allow(R10K::Module::Metadata).to receive(:new).and_return metadata
193
- end
174
+ subject { described_class.new('branan/eight_hundred', fixture_modulepath, '8.0.0') }
194
175
 
195
176
  it "is :absent if the module directory is absent" do
196
177
  allow(subject).to receive(:exist?).and_return false
@@ -199,7 +180,7 @@ describe R10K::Module::Forge do
199
180
 
200
181
  it "is :mismatched if there is no module metadata" do
201
182
  allow(subject).to receive(:exist?).and_return true
202
- allow(metadata).to receive(:exist?).and_return false
183
+ allow(File).to receive(:exist?).and_return false
203
184
 
204
185
  expect(subject.status).to eq :mismatched
205
186
  end
@@ -207,7 +188,7 @@ describe R10K::Module::Forge do
207
188
  it "is :mismatched if the metadata author doesn't match the expected author" do
208
189
  allow(subject).to receive(:exist?).and_return true
209
190
 
210
- allow(metadata).to receive(:author).and_return 'blargh'
191
+ allow(subject.metadata).to receive(:full_module_name).and_return 'blargh-blargh'
211
192
 
212
193
  expect(subject.status).to eq :mismatched
213
194
  end
@@ -215,8 +196,7 @@ describe R10K::Module::Forge do
215
196
  it "is :outdated if the metadata version doesn't match the expected version" do
216
197
  allow(subject).to receive(:exist?).and_return true
217
198
 
218
- allow(metadata).to receive(:version).and_return R10K::SemVer.new('7.0.0')
219
-
199
+ allow(subject.metadata).to receive(:version).and_return '7.0.0'
220
200
  expect(subject.status).to eq :outdated
221
201
  end
222
202
 
@@ -228,22 +208,11 @@ describe R10K::Module::Forge do
228
208
  end
229
209
 
230
210
  describe "and the expected version is :latest", :vcr => true, :unless => (RUBY_VERSION == '1.8.7') do
231
- subject { described_class.new('branan/eight_hundred', '/moduledir', :latest) }
232
-
233
- let(:_metadata) do
234
- double('metadata',
235
- :version => R10K::SemVer.new('7.0.0'),
236
- :author => 'branan',
237
- :exist? => true,
238
- :read => nil)
239
- end
240
-
241
- before do
242
- allow(R10K::Module::Metadata).to receive(:new).and_return _metadata
243
- end
211
+ subject { described_class.new('branan/eight_hundred', fixture_modulepath, :latest) }
244
212
 
245
213
  it "sets the expected version based on the latest forge version" do
246
214
  allow(subject).to receive(:exist?).and_return true
215
+ allow(subject.metadata).to receive(:version).and_return '7.0.0'
247
216
  expect(subject.status).to eq :outdated
248
217
  expect(subject.expected_version).to eq R10K::SemVer.new('8.0.0')
249
218
  end
@@ -63,20 +63,16 @@ describe R10K::Module::Git do
63
63
  end
64
64
 
65
65
  it "sets the expected version" do
66
- expect(subject.properties).to include(:expected => instance_of(R10K::Git::Ref))
66
+ expect(subject.properties).to include(:expected => 'master')
67
67
  end
68
68
 
69
69
  it "sets the actual version to the revision when the revision is available" do
70
- head = double('head')
71
- expect(subject.working_dir).to receive(:current).and_return(head)
72
- expect(head).to receive(:sha1).and_return('35d3517e67ceeb4b485b56d4a14d38fb95516c92')
70
+ expect(subject.repo).to receive(:head).and_return('35d3517e67ceeb4b485b56d4a14d38fb95516c92')
73
71
  expect(subject.properties).to include(:actual => '35d3517e67ceeb4b485b56d4a14d38fb95516c92')
74
72
  end
75
73
 
76
- it "sets the actual version (unresolvable) when the revision is unavailable" do
77
- head = double('head')
78
- expect(subject.working_dir).to receive(:current).and_return(head)
79
- expect(head).to receive(:sha1).and_raise(ArgumentError)
74
+ it "sets the actual version to (unresolvable) when the revision is unavailable" do
75
+ expect(subject.repo).to receive(:head).and_return(nil)
80
76
  expect(subject.properties).to include(:actual => '(unresolvable)')
81
77
  end
82
78
  end
@@ -92,36 +88,9 @@ describe R10K::Module::Git do
92
88
  )
93
89
  end
94
90
 
95
- it "is absent when the working dir is absent" do
96
- expect(subject.working_dir).to receive(:exist?).and_return false
97
- expect(subject.status).to eq :absent
98
- end
99
-
100
- it "is mismatched Then the working dir is not a git repository" do
101
- allow(subject.working_dir).to receive(:exist?).and_return true
102
- expect(subject.working_dir).to receive(:git?).and_return false
103
- expect(subject.status).to eq :mismatched
104
- end
105
-
106
- it "is mismatched when the expected remote does not match the actual remote" do
107
- allow(subject.working_dir).to receive(:exist?).and_return true
108
- expect(subject.working_dir).to receive(:git?).and_return true
109
- expect(subject.working_dir).to receive(:remote).and_return 'nope'
110
- expect(subject.status).to eq :mismatched
111
- end
112
-
113
- it "is outdated when the working dir is outdated" do
114
- allow(subject.working_dir).to receive(:exist?).and_return true
115
- expect(subject.working_dir).to receive(:git?).and_return true
116
- expect(subject.working_dir).to receive(:outdated?).and_return true
117
- expect(subject.status).to eq :outdated
118
- end
119
-
120
- it "is insync if all other conditions are satisfied" do
121
- allow(subject.working_dir).to receive(:exist?).and_return true
122
- expect(subject.working_dir).to receive(:git?).and_return true
123
- expect(subject.working_dir).to receive(:outdated?).and_return false
124
- expect(subject.status).to eq :insync
91
+ it "delegates to the repo" do
92
+ expect(subject.repo).to receive(:status).and_return :some_status
93
+ expect(subject.status).to eq(:some_status)
125
94
  end
126
95
  end
127
96
  end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+ require 'shared/puppet/module_tool/metadata'
3
+
4
+ describe R10K::Module::MetadataFile do
5
+
6
+ let(:path) { double 'pathname' }
7
+
8
+ subject(:metadata_file) { described_class.new(path) }
9
+
10
+ describe "determining if the metadata file exists" do
11
+ it "doesn't exist if the given path isn't a file" do
12
+ allow(path).to receive(:file?).and_return false
13
+ expect(metadata_file).to_not be_exist
14
+ end
15
+
16
+ it "doesn't exist if the given path is an unreadable file" do
17
+ allow(path).to receive(:file?).and_return true
18
+ allow(path).to receive(:readable?).and_return false
19
+
20
+ expect(metadata_file).to_not be_exist
21
+ end
22
+
23
+ it "exists if the given path exists and is readable" do
24
+ allow(path).to receive(:file?).and_return true
25
+ allow(path).to receive(:readable?).and_return true
26
+
27
+ expect(metadata_file).to be_exist
28
+ end
29
+ end
30
+
31
+ describe "parsing a metadata file" do
32
+ let(:fixture_path) do
33
+ fixture_path = Pathname.new(File.expand_path('spec/fixtures/module/forge/eight_hundred/metadata.json', PROJECT_ROOT))
34
+ end
35
+
36
+ before do
37
+ a_metadata_file = R10K::Module::MetadataFile.new(fixture_path)
38
+ @metadata = a_metadata_file.read
39
+ end
40
+
41
+ it "extracts the module name" do
42
+ expect(@metadata.name).to eq 'eight_hundred'
43
+ end
44
+
45
+ it "extracts the full module name" do
46
+ expect(@metadata.full_module_name).to eq 'branan-eight_hundred'
47
+ end
48
+
49
+ it "extracts the module author" do
50
+ expect(@metadata.author).to eq 'Branan Purvine-Riley'
51
+ end
52
+
53
+ it "extracts the module version" do
54
+ expect(@metadata.version).to eq '8.0.0'
55
+ end
56
+ end
57
+
58
+ describe "parsing an invalid metadata file" do
59
+ let(:fixture_path) do
60
+ fixture_path = Pathname.new(File.expand_path('spec/fixtures/module/forge/bad_module/metadata.json', PROJECT_ROOT))
61
+ end
62
+
63
+ it "raises an error" do
64
+ a_metadata_file = R10K::Module::MetadataFile.new(fixture_path)
65
+ expect {a_metadata_file.read}.to raise_error(R10K::Error, "Could not read metadata.json")
66
+ end
67
+ end
68
+
69
+ end
@@ -119,10 +119,6 @@ describe R10K::Module::SVN do
119
119
  end
120
120
  end
121
121
 
122
- describe "and the expected version is :latest" do
123
- it "sets the expected version based on the latest SVN revision"
124
- end
125
-
126
122
  describe "synchronizing" do
127
123
 
128
124
  subject { described_class.new('foo', '/moduledir', :svn => 'https://github.com/adrienthebo/r10k-fixture-repo', :rev => 123) }
@@ -6,7 +6,12 @@ describe R10K::ModuleRepository::Forge do
6
6
 
7
7
  it "uses the official forge by default" do
8
8
  forge = described_class.new
9
- expect(forge.forge).to eq 'forge.puppetlabs.com'
9
+ expect(forge.forge).to eq 'forgeapi.puppetlabs.com'
10
+ end
11
+
12
+ it "replaces old forge with forgeapi" do
13
+ forge = described_class.new(forge='forge.puppetlabs.com')
14
+ expect(forge.forge).to eq 'forgeapi.puppetlabs.com'
10
15
  end
11
16
 
12
17
  it "can use a private forge" do
@@ -28,5 +33,21 @@ describe R10K::ModuleRepository::Forge do
28
33
  it "can fetch the latest version of a given module" do
29
34
  expect(forge.latest_version('adrien/boolean')).to eq "1.0.1"
30
35
  end
36
+
37
+ it "ignores deleted releases" do
38
+ expect(forge.latest_version('r10ktesting/spotty')).to eq "0.3.0"
39
+ end
40
+ end
41
+
42
+ describe "it handles errors from forgeapi.puppetlabs.com", :vcr => true do
43
+ subject(:forge) { described_class.new }
44
+
45
+ before do
46
+ forge.conn.builder.insert_before(Faraday::Adapter::NetHttp, VCR::Middleware::Faraday)
47
+ end
48
+
49
+ it "raises an error for a non-existant module" do
50
+ expect { forge.versions('dne/dne') }.to raise_error(R10K::Error)
51
+ end
31
52
  end
32
53
  end
@@ -0,0 +1,301 @@
1
+ require 'spec_helper'
2
+ require 'shared/puppet/module_tool/metadata'
3
+
4
+ describe Puppet::ModuleTool::Metadata do
5
+ let(:data) { {} }
6
+ let(:metadata) { Puppet::ModuleTool::Metadata.new }
7
+
8
+ describe 'property lookups' do
9
+ subject { metadata }
10
+
11
+ %w[ name version author summary license source project_page issues_url
12
+ dependencies dashed_name release_name description ].each do |prop|
13
+ describe "##{prop}" do
14
+ it "responds to the property" do
15
+ subject.send(prop)
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ describe "#update" do
22
+ subject { metadata.update(data) }
23
+
24
+ context "with a valid name" do
25
+ let(:data) { { 'name' => 'billgates-mymodule' } }
26
+
27
+ it "extracts the author name from the name field" do
28
+ expect(subject.to_hash['author']).to eq('billgates')
29
+ end
30
+
31
+ it "extracts a module name from the name field" do
32
+ expect(subject.module_name).to eq('mymodule')
33
+ end
34
+
35
+ context "and existing author" do
36
+ before { metadata.update('author' => 'foo') }
37
+
38
+ it "avoids overwriting the existing author" do
39
+ expect(subject.to_hash['author']).to eq('foo')
40
+ end
41
+ end
42
+ end
43
+
44
+ context "with a valid name and author" do
45
+ let(:data) { { 'name' => 'billgates-mymodule', 'author' => 'foo' } }
46
+
47
+ it "use the author name from the author field" do
48
+ expect(subject.to_hash['author']).to eq('foo')
49
+ end
50
+
51
+ context "and preexisting author" do
52
+ before { metadata.update('author' => 'bar') }
53
+
54
+ it "avoids overwriting the existing author" do
55
+ expect(subject.to_hash['author']).to eq('foo')
56
+ end
57
+ end
58
+ end
59
+
60
+ context "with an invalid name" do
61
+ context "(short module name)" do
62
+ let(:data) { { 'name' => 'mymodule' } }
63
+
64
+ it "raises an exception" do
65
+ expect { subject }.to raise_error(ArgumentError, "Invalid 'name' field in metadata.json: the field must be a namespaced module name")
66
+ end
67
+ end
68
+
69
+ context "(missing namespace)" do
70
+ let(:data) { { 'name' => '/mymodule' } }
71
+
72
+ it "raises an exception" do
73
+ expect { subject }.to raise_error(ArgumentError, "Invalid 'name' field in metadata.json: the field must be a namespaced module name")
74
+ end
75
+ end
76
+
77
+ context "(missing module name)" do
78
+ let(:data) { { 'name' => 'namespace/' } }
79
+
80
+ it "raises an exception" do
81
+ expect { subject }.to raise_error(ArgumentError, "Invalid 'name' field in metadata.json: the field must be a namespaced module name")
82
+ end
83
+ end
84
+
85
+ context "(invalid namespace)" do
86
+ let(:data) { { 'name' => "dolla'bill$-mymodule" } }
87
+
88
+ it "raises an exception" do
89
+ expect { subject }.to raise_error(ArgumentError, "Invalid 'name' field in metadata.json: the namespace contains non-alphanumeric characters")
90
+ end
91
+ end
92
+
93
+ context "(non-alphanumeric module name)" do
94
+ let(:data) { { 'name' => "dollabils-fivedolla'" } }
95
+
96
+ it "raises an exception" do
97
+ expect { subject }.to raise_error(ArgumentError, "Invalid 'name' field in metadata.json: the module name contains non-alphanumeric (or underscore) characters")
98
+ end
99
+ end
100
+
101
+ context "(module name starts with a number)" do
102
+ let(:data) { { 'name' => "dollabills-5dollars" } }
103
+
104
+ it "raises an exception" do
105
+ expect { subject }.to raise_error(ArgumentError, "Invalid 'name' field in metadata.json: the module name must begin with a letter")
106
+ end
107
+ end
108
+ end
109
+
110
+
111
+ context "with an invalid version" do
112
+ let(:data) { { 'version' => '3.0' } }
113
+
114
+ it "raises an exception" do
115
+ expect { subject }.to raise_error(ArgumentError, "Invalid 'version' field in metadata.json: version string cannot be parsed as a valid Semantic Version")
116
+ end
117
+ end
118
+
119
+ context "with a valid source" do
120
+ context "which is a GitHub URL" do
121
+ context "with a scheme" do
122
+ before { metadata.update('source' => 'https://github.com/billgates/amazingness') }
123
+
124
+ it "predicts a default project_page" do
125
+ expect(subject.to_hash['project_page']).to eq('https://github.com/billgates/amazingness')
126
+ end
127
+
128
+ it "predicts a default issues_url" do
129
+ expect(subject.to_hash['issues_url']).to eq('https://github.com/billgates/amazingness/issues')
130
+ end
131
+ end
132
+
133
+ context "without a scheme" do
134
+ before { metadata.update('source' => 'github.com/billgates/amazingness') }
135
+
136
+ it "predicts a default project_page" do
137
+ expect(subject.to_hash['project_page']).to eq('https://github.com/billgates/amazingness')
138
+ end
139
+
140
+ it "predicts a default issues_url" do
141
+ expect(subject.to_hash['issues_url']).to eq('https://github.com/billgates/amazingness/issues')
142
+ end
143
+ end
144
+ end
145
+
146
+ context "which is not a GitHub URL" do
147
+ before { metadata.update('source' => 'https://notgithub.com/billgates/amazingness') }
148
+
149
+ it "does not predict a default project_page" do
150
+ expect(subject.to_hash['project_page']).to be nil
151
+ end
152
+
153
+ it "does not predict a default issues_url" do
154
+ expect(subject.to_hash['issues_url']).to be nil
155
+ end
156
+ end
157
+
158
+ context "which is not a URL" do
159
+ before { metadata.update('source' => 'my brain') }
160
+
161
+ it "does not predict a default project_page" do
162
+ expect(subject.to_hash['project_page']).to be nil
163
+ end
164
+
165
+ it "does not predict a default issues_url" do
166
+ expect(subject.to_hash['issues_url']).to be nil
167
+ end
168
+ end
169
+
170
+ end
171
+
172
+ context "with a valid dependency", :pending => "dependency resolution is not yet in scope" do
173
+ let(:data) { {'dependencies' => [{'name' => 'puppetlabs-goodmodule'}] }}
174
+
175
+ it "adds the dependency" do
176
+ expect(subject.dependencies.size).to eq(1)
177
+ end
178
+ end
179
+
180
+ context "with a invalid dependency name" do
181
+ let(:data) { {'dependencies' => [{'name' => 'puppetlabsbadmodule'}] }}
182
+
183
+ it "raises an exception" do
184
+ expect { subject }.to raise_error(ArgumentError)
185
+ end
186
+ end
187
+
188
+ context "with a valid dependency version range", :pending => "dependency resolution is not yet in scope" do
189
+ let(:data) { {'dependencies' => [{'name' => 'puppetlabs-badmodule', 'version_requirement' => '>= 2.0.0'}] }}
190
+
191
+ it "adds the dependency" do
192
+ expect(subject.dependencies.size).to eq(1)
193
+ end
194
+ end
195
+
196
+ context "with a invalid version range" do
197
+ let(:data) { {'dependencies' => [{'name' => 'puppetlabsbadmodule', 'version_requirement' => '>= banana'}] }}
198
+
199
+ it "raises an exception" do
200
+ expect { subject }.to raise_error(ArgumentError)
201
+ end
202
+ end
203
+
204
+ context "with duplicate dependencies", :pending => "dependency resolution is not yet in scope" do
205
+ let(:data) { {'dependencies' => [{'name' => 'puppetlabs-dupmodule', 'version_requirement' => '1.0.0'},
206
+ {'name' => 'puppetlabs-dupmodule', 'version_requirement' => '0.0.1'}] }
207
+ }
208
+
209
+ it "raises an exception" do
210
+ expect { subject }.to raise_error(ArgumentError)
211
+ end
212
+ end
213
+
214
+ context "adding a duplicate dependency", :pending => "dependency resolution is not yet in scope" do
215
+ let(:data) { {'dependencies' => [{'name' => 'puppetlabs-origmodule', 'version_requirement' => '1.0.0'}] }}
216
+
217
+ it "with a different version raises an exception" do
218
+ metadata.add_dependency('puppetlabs-origmodule', '>= 0.0.1')
219
+ expect { subject }.to raise_error(ArgumentError)
220
+ end
221
+
222
+ it "with the same version does not add another dependency" do
223
+ metadata.add_dependency('puppetlabs-origmodule', '1.0.0')
224
+ expect(subject.dependencies.size).to eq(1)
225
+ end
226
+ end
227
+ end
228
+
229
+ describe '#dashed_name' do
230
+ it 'returns nil in the absence of a module name' do
231
+ expect(metadata.update('version' => '1.0.0').release_name).to be_nil
232
+ end
233
+
234
+ it 'returns a hyphenated string containing namespace and module name' do
235
+ data = metadata.update('name' => 'foo-bar')
236
+ expect(data.dashed_name).to eq('foo-bar')
237
+ end
238
+
239
+ it 'properly handles slash-separated names' do
240
+ data = metadata.update('name' => 'foo/bar')
241
+ expect(data.dashed_name).to eq('foo-bar')
242
+ end
243
+
244
+ it 'is unaffected by author name' do
245
+ data = metadata.update('name' => 'foo/bar', 'author' => 'me')
246
+ expect(data.dashed_name).to eq('foo-bar')
247
+ end
248
+ end
249
+
250
+ describe '#release_name' do
251
+ it 'returns nil in the absence of a module name' do
252
+ expect(metadata.update('version' => '1.0.0').release_name).to be_nil
253
+ end
254
+
255
+ it 'returns nil in the absence of a version' do
256
+ expect(metadata.update('name' => 'foo/bar').release_name).to be_nil
257
+ end
258
+
259
+ it 'returns a hyphenated string containing module name and version' do
260
+ data = metadata.update('name' => 'foo/bar', 'version' => '1.0.0')
261
+ expect(data.release_name).to eq('foo-bar-1.0.0')
262
+ end
263
+
264
+ it 'is unaffected by author name' do
265
+ data = metadata.update('name' => 'foo/bar', 'version' => '1.0.0', 'author' => 'me')
266
+ expect(data.release_name).to eq('foo-bar-1.0.0')
267
+ end
268
+ end
269
+
270
+ describe "#to_hash" do
271
+ subject { metadata.to_hash }
272
+
273
+ it "contains the default set of keys" do
274
+ expect(subject.keys.sort).to eq(%w[ name version author summary license source issues_url project_page dependencies ].sort)
275
+ end
276
+
277
+ describe "['license']" do
278
+ it "defaults to Apache 2" do
279
+ expect(subject['license']).to eq("Apache-2.0")
280
+ end
281
+ end
282
+
283
+ describe "['dependencies']" do
284
+ it "defaults to an empty set" do
285
+ expect(subject['dependencies']).to eq(Set.new)
286
+ end
287
+ end
288
+
289
+ context "when updated with non-default data" do
290
+ subject { metadata.update('license' => 'MIT', 'non-standard' => 'yup').to_hash }
291
+
292
+ it "overrides the defaults" do
293
+ expect(subject['license']).to eq('MIT')
294
+ end
295
+
296
+ it 'contains unanticipated values' do
297
+ expect(subject['non-standard']).to eq('yup')
298
+ end
299
+ end
300
+ end
301
+ end