r10k 2.0.3 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (198) hide show
  1. checksums.yaml +8 -8
  2. data/CHANGELOG.mkd +150 -0
  3. data/README.mkd +10 -1
  4. data/doc/dynamic-environments/configuration.mkd +31 -0
  5. data/doc/dynamic-environments/quickstart.mkd +33 -79
  6. data/doc/faq.mkd +67 -0
  7. data/doc/git/providers.mkd +37 -0
  8. data/doc/puppetfile.mkd +73 -0
  9. data/integration/lib/r10k_utils.rb +47 -2
  10. data/integration/pre-suite/01_git_config.rb +9 -8
  11. data/integration/pre-suite/02_pe_r10k.rb +5 -8
  12. data/integration/scripts/setup_r10k_env_centos5.sh +1 -1
  13. data/integration/scripts/setup_r10k_env_centos6.sh +1 -1
  14. data/integration/scripts/setup_r10k_env_rhel7.sh +1 -1
  15. data/integration/scripts/setup_r10k_env_sles11.sh +1 -1
  16. data/integration/scripts/setup_r10k_env_sles12.sh +1 -1
  17. data/integration/scripts/setup_r10k_env_ubuntu1004.sh +1 -1
  18. data/integration/scripts/setup_r10k_env_ubuntu1204.sh +1 -1
  19. data/integration/scripts/setup_r10k_env_ubuntu1404.sh +1 -1
  20. data/integration/test_run_scripts/all_tests-rugged-pe-centos6.sh +1 -1
  21. data/integration/test_run_scripts/all_tests-rugged-pe-rhel7.sh +1 -1
  22. data/integration/test_run_scripts/all_tests-rugged-pe-sles11.sh +1 -1
  23. data/integration/test_run_scripts/all_tests-rugged-pe-ubuntu1204.sh +1 -1
  24. data/integration/test_run_scripts/all_tests-rugged-pe-ubuntu1404.sh +1 -1
  25. data/integration/test_run_scripts/all_tests-shellgit-pe-centos6.sh +1 -1
  26. data/integration/test_run_scripts/all_tests-shellgit-pe-rhel7.sh +1 -1
  27. data/integration/test_run_scripts/all_tests-shellgit-pe-sles11.sh +1 -1
  28. data/integration/test_run_scripts/all_tests-shellgit-pe-ubuntu1204.sh +1 -1
  29. data/integration/test_run_scripts/all_tests-shellgit-pe-ubuntu1404.sh +1 -1
  30. data/integration/test_run_scripts/basic_functionality/all_tests-pe-centos6.sh +1 -1
  31. data/integration/test_run_scripts/command_line/all_tests-pe-centos6.sh +1 -1
  32. data/integration/test_run_scripts/git_source/all_tests-pe-centos6.sh +1 -1
  33. data/integration/test_run_scripts/user_scenario/basic_workflow/all_tests-pe-centos6.sh +1 -1
  34. data/integration/test_run_scripts/user_scenario/complex_workflow/all_tests-pe-centos6.sh +1 -1
  35. data/integration/tests/basic_functionality/install_pe_only_module_with_puppetfile.rb +83 -0
  36. data/integration/tests/basic_functionality/negative/attempt_to_install_peonly_module_without_license.rb +71 -0
  37. data/integration/tests/basic_functionality/negative/neg_deploy_with_invalid_r10k_yaml.rb +7 -2
  38. data/integration/tests/basic_functionality/negative/neg_deploy_with_missing_r10k_yaml.rb +3 -2
  39. data/integration/tests/basic_functionality/negative/neg_invalid_git_provider.rb +3 -2
  40. data/integration/tests/basic_functionality/negative/negative_bad_proxy.rb +56 -0
  41. data/integration/tests/basic_functionality/proxy_specified_in_configuration.rb +103 -0
  42. data/integration/tests/basic_functionality/proxy_with_puppetfile.rb +61 -0
  43. data/integration/tests/basic_functionality/rugged_git_provider_with_ssh.rb +2 -1
  44. data/integration/tests/basic_functionality/rugged_git_provider_without_ssh.rb +2 -1
  45. data/integration/tests/command_line/deploy_env_without_mod_update.rb +3 -2
  46. data/integration/tests/command_line/negative/neg_deploy_env_with_module_update.rb +3 -2
  47. data/integration/tests/command_line/negative/neg_invalid_cli_dep_flag.rb +2 -1
  48. data/integration/tests/command_line/negative/neg_invalid_cli_env_flag.rb +2 -1
  49. data/integration/tests/command_line/negative/neg_invalid_cmd_line_arg.rb +3 -4
  50. data/integration/tests/git_source/git_source_git.rb +7 -2
  51. data/integration/tests/git_source/git_source_ssh.rb +3 -2
  52. data/integration/tests/git_source/git_source_submodule.rb +2 -1
  53. data/integration/tests/git_source/negative/neg_git_broken_remote.rb +2 -1
  54. data/integration/tests/git_source/negative/neg_git_unauthorized_https.rb +2 -1
  55. data/integration/tests/git_source/negative/neg_git_unauthorized_ssh.rb +2 -1
  56. data/integration/tests/git_source/negative/neg_git_unicode_branch.rb +2 -1
  57. data/integration/tests/user_scenario/basic_workflow/multi_env_1000_branches.rb +3 -3
  58. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module.rb +2 -1
  59. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module_static.rb +9 -5
  60. data/integration/tests/user_scenario/basic_workflow/multi_env_hiera.rb +9 -2
  61. data/integration/tests/user_scenario/basic_workflow/multi_env_multi_source.rb +2 -1
  62. data/integration/tests/user_scenario/basic_workflow/multi_source_custom_forge_git_module.rb +2 -1
  63. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_basedir.rb +2 -1
  64. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_forge_module.rb +7 -2
  65. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module.rb +3 -4
  66. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_module_ref.rb +2 -1
  67. data/integration/tests/user_scenario/basic_workflow/negative/neg_bad_git_remote.rb +2 -1
  68. data/integration/tests/user_scenario/basic_workflow/negative/neg_branch_name_collision.rb +2 -1
  69. data/integration/tests/user_scenario/basic_workflow/negative/neg_disk_full.rb +2 -1
  70. data/integration/tests/user_scenario/basic_workflow/negative/neg_duplicate_module_names.rb +10 -4
  71. data/integration/tests/user_scenario/basic_workflow/negative/neg_inaccessible_forge.rb +9 -2
  72. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_env_name.rb +2 -1
  73. data/integration/tests/user_scenario/basic_workflow/negative/neg_invalid_puppet_file.rb +2 -1
  74. data/integration/tests/user_scenario/basic_workflow/negative/neg_module_specified_at_deleted_release.rb +7 -2
  75. data/integration/tests/user_scenario/basic_workflow/negative/neg_read_only.rb +2 -1
  76. data/integration/tests/user_scenario/basic_workflow/negative/neg_specify_deleted_forge_module.rb +9 -2
  77. data/integration/tests/user_scenario/basic_workflow/single_env_10000_files.rb +2 -1
  78. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_git_module.rb +2 -1
  79. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_module.rb +2 -1
  80. data/integration/tests/user_scenario/basic_workflow/single_env_custom_module.rb +2 -1
  81. data/integration/tests/user_scenario/basic_workflow/single_env_large_files.rb +2 -1
  82. data/integration/tests/user_scenario/basic_workflow/single_env_module_already_installed.rb +2 -1
  83. data/integration/tests/user_scenario/basic_workflow/single_env_module_last_release_deleted.rb +2 -1
  84. data/integration/tests/user_scenario/basic_workflow/single_env_non-existent_base_dir.rb +2 -1
  85. data/integration/tests/user_scenario/basic_workflow/single_env_purge_unmanaged_modules.rb +3 -2
  86. data/integration/tests/user_scenario/basic_workflow/single_env_switch_forge_git_module.rb +3 -2
  87. data/integration/tests/user_scenario/basic_workflow/single_env_unicode_paths.rb +2 -1
  88. data/integration/tests/user_scenario/basic_workflow/single_env_upgrade_forge_mod_revert_change.rb +4 -3
  89. data/integration/tests/user_scenario/complex_workflow/multi_env_add_change_remove.rb +3 -2
  90. data/integration/tests/user_scenario/complex_workflow/multi_env_remove_re-add.rb +4 -3
  91. data/integration/tests/user_scenario/complex_workflow/multi_env_unamanaged.rb +3 -2
  92. data/integration/tests/user_scenario/complex_workflow/single_env_git_module_update.rb +3 -2
  93. data/lib/r10k/action/base.rb +31 -0
  94. data/lib/r10k/action/deploy/deploy_helpers.rb +34 -0
  95. data/lib/r10k/action/deploy/display.rb +57 -75
  96. data/lib/r10k/action/deploy/environment.rb +52 -15
  97. data/lib/r10k/action/deploy/module.rb +13 -18
  98. data/lib/r10k/action/puppetfile/check.rb +8 -18
  99. data/lib/r10k/action/puppetfile/install.rb +13 -27
  100. data/lib/r10k/action/puppetfile/purge.rb +8 -17
  101. data/lib/r10k/action/runner.rb +39 -3
  102. data/lib/r10k/cli.rb +1 -3
  103. data/lib/r10k/cli/deploy.rb +3 -1
  104. data/lib/r10k/cli/puppetfile.rb +2 -2
  105. data/lib/r10k/deployment.rb +8 -6
  106. data/lib/r10k/deployment/config.rb +18 -65
  107. data/lib/r10k/environment/base.rb +19 -0
  108. data/lib/r10k/environment/git.rb +9 -0
  109. data/lib/r10k/environment/svn.rb +9 -0
  110. data/lib/r10k/forge/module_release.rb +21 -14
  111. data/lib/r10k/git.rb +6 -0
  112. data/lib/r10k/git/alternates.rb +20 -6
  113. data/lib/r10k/git/cache.rb +1 -1
  114. data/lib/r10k/git/rugged/bare_repository.rb +5 -0
  115. data/lib/r10k/git/rugged/base_repository.rb +6 -20
  116. data/lib/r10k/git/rugged/credentials.rb +66 -0
  117. data/lib/r10k/git/rugged/thin_repository.rb +16 -11
  118. data/lib/r10k/git/rugged/working_repository.rb +15 -7
  119. data/lib/r10k/git/shellgit/bare_repository.rb +9 -4
  120. data/lib/r10k/git/shellgit/thin_repository.rb +8 -10
  121. data/lib/r10k/git/stateful_repository.rb +1 -1
  122. data/lib/r10k/initializers.rb +55 -0
  123. data/lib/r10k/module.rb +1 -0
  124. data/lib/r10k/module/base.rb +3 -2
  125. data/lib/r10k/module/forge.rb +14 -6
  126. data/lib/r10k/module/local.rb +36 -0
  127. data/lib/r10k/module/metadata_file.rb +2 -2
  128. data/lib/r10k/puppetfile.rb +1 -1
  129. data/lib/r10k/settings.rb +86 -0
  130. data/lib/r10k/settings/collection.rb +118 -0
  131. data/lib/r10k/settings/definition.rb +112 -0
  132. data/lib/r10k/settings/enum_definition.rb +22 -0
  133. data/lib/r10k/settings/loader.rb +96 -0
  134. data/lib/r10k/settings/uri_definition.rb +19 -0
  135. data/lib/r10k/util/subprocess/runner/windows.rb +4 -4
  136. data/lib/r10k/version.rb +1 -1
  137. data/r10k.gemspec +2 -3
  138. data/spec/fixtures/unit/puppetfile/argument-error/Puppetfile +1 -0
  139. data/spec/fixtures/unit/util/subprocess/{posix/runner → runner}/no-execute.sh +0 -0
  140. data/spec/integration/git/rugged/thin_repository_spec.rb +2 -2
  141. data/spec/integration/git/rugged/working_repository_spec.rb +9 -0
  142. data/spec/integration/git/shellgit/thin_repository_spec.rb +2 -2
  143. data/spec/integration/git/stateful_repository_spec.rb +1 -1
  144. data/spec/r10k-mocks/mock_config.rb +10 -13
  145. data/spec/r10k-mocks/mock_env.rb +8 -0
  146. data/spec/shared-examples/deploy-actions.rb +69 -0
  147. data/spec/shared-examples/puppetfile-action.rb +17 -0
  148. data/spec/unit/action/cri_runner_spec.rb +3 -1
  149. data/spec/unit/action/deploy/deploy_helpers_spec.rb +38 -0
  150. data/spec/unit/action/deploy/display_spec.rb +31 -0
  151. data/spec/unit/action/deploy/environment_spec.rb +56 -0
  152. data/spec/unit/action/deploy/module_spec.rb +17 -0
  153. data/spec/unit/action/puppetfile/check_spec.rb +26 -0
  154. data/spec/unit/action/puppetfile/install_spec.rb +68 -0
  155. data/spec/unit/action/puppetfile/purge_spec.rb +19 -0
  156. data/spec/unit/action/runner_spec.rb +10 -9
  157. data/spec/unit/deployment/config_spec.rb +20 -44
  158. data/spec/unit/deployment_spec.rb +1 -1
  159. data/spec/unit/environment/git_spec.rb +20 -0
  160. data/spec/unit/environment/svn_spec.rb +20 -0
  161. data/spec/unit/forge/module_release_spec.rb +6 -3
  162. data/spec/unit/git/alternates_spec.rb +38 -12
  163. data/spec/unit/git/cache_spec.rb +4 -0
  164. data/spec/unit/git/rugged/credentials_spec.rb +74 -0
  165. data/spec/unit/initializers_spec.rb +68 -0
  166. data/spec/unit/module/base_spec.rb +2 -2
  167. data/spec/unit/module/forge_spec.rb +11 -3
  168. data/spec/unit/module/metadata_file_spec.rb +0 -1
  169. data/spec/unit/puppetfile_spec.rb +11 -0
  170. data/spec/unit/settings/collection_spec.rb +122 -0
  171. data/spec/unit/settings/definition_spec.rb +78 -0
  172. data/spec/unit/settings/enum_definition_spec.rb +20 -0
  173. data/spec/unit/{deployment/config → settings}/loader_spec.rb +50 -2
  174. data/spec/unit/settings/uri_definition_spec.rb +23 -0
  175. data/spec/unit/settings_spec.rb +151 -0
  176. data/spec/unit/util/subprocess/runner/posix_spec.rb +1 -1
  177. data/spec/unit/util/subprocess/runner/windows_spec.rb +7 -0
  178. metadata +53 -90
  179. data/lib/r10k/deployment/config/loader.rb +0 -59
  180. data/lib/shared/puppet/module_tool/metadata.rb +0 -197
  181. data/lib/shared/puppet_forge/connection.rb +0 -64
  182. data/lib/shared/puppet_forge/connection/connection_failure.rb +0 -26
  183. data/lib/shared/puppet_forge/error.rb +0 -41
  184. data/lib/shared/puppet_forge/tar.rb +0 -10
  185. data/lib/shared/puppet_forge/tar/mini.rb +0 -81
  186. data/lib/shared/puppet_forge/unpacker.rb +0 -68
  187. data/lib/shared/puppet_forge/v3.rb +0 -13
  188. data/lib/shared/puppet_forge/v3/module.rb +0 -69
  189. data/lib/shared/puppet_forge/v3/module_release.rb +0 -85
  190. data/lib/shared/puppet_forge/version.rb +0 -3
  191. data/spec/unit/puppet/module_tool/metadata_spec.rb +0 -301
  192. data/spec/unit/puppet_forge/connection/connection_failure_spec.rb +0 -28
  193. data/spec/unit/puppet_forge/connection_spec.rb +0 -41
  194. data/spec/unit/puppet_forge/tar/mini_spec.rb +0 -87
  195. data/spec/unit/puppet_forge/tar_spec.rb +0 -9
  196. data/spec/unit/puppet_forge/unpacker_spec.rb +0 -59
  197. data/spec/unit/puppet_forge/v3/module_release_spec.rb +0 -83
  198. data/spec/unit/puppet_forge/v3/module_spec.rb +0 -75
@@ -1,68 +0,0 @@
1
- require 'pathname'
2
- require 'shared/puppet_forge/error'
3
- require 'shared/puppet_forge/tar'
4
-
5
- module PuppetForge
6
- class Unpacker
7
- # Unpack a tar file into a specified directory
8
- #
9
- # @param filename [String] the file to unpack
10
- # @param target [String] the target directory to unpack into
11
- # @return [Hash{:symbol => Array<String>}] a hash with file-category keys pointing to lists of filenames.
12
- # The categories are :valid, :invalid and :symlink
13
- def self.unpack(filename, target, tmpdir)
14
- inst = self.new(filename, target, tmpdir)
15
- file_lists = inst.unpack
16
- inst.move_into(Pathname.new(target))
17
- file_lists
18
- end
19
-
20
- # Set the owner/group of the target directory to those of the source
21
- # Note: don't call this function on Microsoft Windows
22
- #
23
- # @param source [Pathname] source of the permissions
24
- # @param target [Pathname] target of the permissions change
25
- def self.harmonize_ownership(source, target)
26
- FileUtils.chown_R(source.stat.uid, source.stat.gid, target)
27
- end
28
-
29
- # @param filename [String] the file to unpack
30
- # @param target [String] the target directory to unpack into
31
- def initialize(filename, target, tmpdir)
32
- @filename = filename
33
- @target = target
34
- @tmpdir = tmpdir
35
- end
36
-
37
- # @api private
38
- def unpack
39
- begin
40
- PuppetForge::Tar.instance.unpack(@filename, @tmpdir)
41
- rescue PuppetForge::ExecutionFailure => e
42
- raise RuntimeError, "Could not extract contents of module archive: #{e.message}"
43
- end
44
- end
45
-
46
- # @api private
47
- def move_into(dir)
48
- dir.rmtree if dir.exist?
49
- FileUtils.mv(root_dir, dir)
50
- ensure
51
- FileUtils.rmtree(@tmpdir)
52
- end
53
-
54
- # @api private
55
- def root_dir
56
- return @root_dir if @root_dir
57
-
58
- # Grab the first directory containing a metadata.json file
59
- metadata_file = Dir["#{@tmpdir}/**/metadata.json"].sort_by(&:length)[0]
60
-
61
- if metadata_file
62
- @root_dir = Pathname.new(metadata_file).dirname
63
- else
64
- raise "No valid metadata.json found!"
65
- end
66
- end
67
- end
68
- end
@@ -1,13 +0,0 @@
1
- module PuppetForge
2
- module V3
3
- # Normalize a module name to use a hyphen as the separator between the
4
- # author and module.
5
- #
6
- # @example
7
- # PuppetForge::V3.normalize_name('my/module') #=> 'my-module'
8
- # PuppetForge::V3.normalize_name('my-module') #=> 'my-module'
9
- def self.normalize_name(name)
10
- name.tr('/', '-')
11
- end
12
- end
13
- end
@@ -1,69 +0,0 @@
1
- require 'shared/puppet_forge/v3'
2
- require 'shared/puppet_forge/v3/module_release'
3
- require 'shared/puppet_forge/connection'
4
- require 'shared/puppet_forge/error'
5
-
6
- module PuppetForge
7
- module V3
8
- # Represents metadata for a single Forge module and provides access to
9
- # the releases of a module.
10
- class Module
11
-
12
- include PuppetForge::Connection
13
-
14
- # @!attribute [r] full_name
15
- # @return [String] The hyphen separated full name of this module
16
- attr_reader :full_name
17
-
18
- # @param full_name [String] The name of this module, will be normalized to
19
- # a hyphen separated name.
20
- def initialize(full_name)
21
- @full_name = PuppetForge::V3.normalize_name(full_name)
22
- end
23
-
24
- # Get all released versions of this module
25
- #
26
- # @example
27
- # mod = PuppetForge::V3::Module.new('timmy-boolean')
28
- # mod.versions
29
- # #=> ["0.9.0-rc1", "0.9.0", "1.0.0", "1.0.1"]
30
- #
31
- # @return [Array<String>] All published versions of the given module
32
- def versions
33
- path = "/v3/modules/#{@full_name}"
34
- response = conn.get(path)
35
-
36
- releases = []
37
-
38
- response.body['releases'].each do |release|
39
- if !release['deleted_at']
40
- releases << release['version']
41
- end
42
- end
43
-
44
- releases.reverse
45
- rescue Faraday::ResourceNotFound => e
46
- raise PuppetForge::ModuleNotFound, "The module #{@full_name} does not exist on #{conn.url_prefix}.", e.backtrace
47
- end
48
-
49
- # Get all released versions of this module
50
- #
51
- # @example
52
- # mod = PuppetForge::V3::Module.new('timmy-boolean')
53
- # mod.latest_version
54
- # #=> "1.0.1"
55
- #
56
- # @return [String] The latest published version of the given module
57
- def latest_version
58
- versions.last
59
- end
60
-
61
- # Get a specific release of this module off of the forge.
62
- #
63
- # @return [ModuleRelease] a release object of the given version for this module.
64
- def release(version)
65
- PuppetForge::V3::ModuleRelease.new(@full_name, version).tap { |mr| mr.conn = conn }
66
- end
67
- end
68
- end
69
- end
@@ -1,85 +0,0 @@
1
- require 'shared/puppet_forge/v3'
2
- require 'shared/puppet_forge/connection'
3
- require 'shared/puppet_forge/error'
4
- require 'json'
5
-
6
- module PuppetForge
7
- module V3
8
- # Access metadata and downloads for a specific module release.
9
- class ModuleRelease
10
-
11
- include PuppetForge::Connection
12
-
13
- # @!attribute [r] full_name
14
- # @return [String] The hyphen delimited name of this module
15
- attr_reader :full_name
16
-
17
- # @!attribute [r] version
18
- # @return [String] The version of this module
19
- attr_reader :version
20
-
21
- # @param full_name [String] The name of the module, will be normalized
22
- # to a hyphen delimited name.
23
- # @param version [String]
24
- def initialize(full_name, version)
25
- @full_name = PuppetForge::V3.normalize_name(full_name)
26
- @version = version
27
- end
28
-
29
- # @return [Hash] The complete Forge response for this release.
30
- def data
31
- @data ||= conn.get(resource_url).body
32
- rescue Faraday::ResourceNotFound => e
33
- raise PuppetForge::ModuleReleaseNotFound, "The module release #{slug} does not exist on #{conn.url_prefix}.", e.backtrace
34
- end
35
-
36
- # @return [String] The unique identifier for this module release.
37
- def slug
38
- "#{full_name}-#{version}"
39
- end
40
-
41
- # Download this module release to the specified path.
42
- #
43
- # @param path [Pathname]
44
- # @return [void]
45
- def download(path)
46
- resp = conn.get(file_url)
47
- path.open('wb') { |fh| fh.write(resp.body) }
48
- rescue Faraday::ResourceNotFound => e
49
- raise PuppetForge::ModuleReleaseNotFound, "The module release #{slug} does not exist on #{conn.url_prefix}.", e.backtrace
50
- rescue Faraday::ClientError => e
51
- if e.response[:status] == 403
52
- raise PuppetForge::ModuleReleaseForbidden.from_response(e.response)
53
- else
54
- raise e
55
- end
56
- end
57
-
58
- # Verify that a downloaded module matches the checksum in the metadata for this release.
59
- #
60
- # @param path [Pathname]
61
- # @return [void]
62
- def verify(path)
63
- expected_md5 = data['file_md5']
64
- file_md5 = Digest::MD5.file(path).hexdigest
65
- if expected_md5 != file_md5
66
- raise ChecksumMismatch.new("Expected #{path} checksum to be #{expected_md5}, got #{file_md5}")
67
- end
68
- end
69
-
70
- private
71
-
72
- def file_url
73
- "/v3/files/#{slug}.tar.gz"
74
- end
75
-
76
- def resource_url
77
- "/v3/releases/#{slug}"
78
- end
79
-
80
- class ChecksumMismatch < StandardError
81
-
82
- end
83
- end
84
- end
85
- end
@@ -1,3 +0,0 @@
1
- module PuppetForge
2
- VERSION = '2.0.0.alpha'
3
- end
@@ -1,301 +0,0 @@
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