puppet-library 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -15,98 +15,13 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
- class Array
19
- def deep_merge
20
- inject({}) do |merged, map|
21
- merged.deep_merge(map)
22
- end
23
- end
24
- end
25
-
26
- class Hash
27
- def deep_merge(other)
28
- merge(other) do |key, old_val, new_val|
29
- if old_val.instance_of? Array
30
- old_val + new_val
31
- else
32
- new_val
33
- end
34
- end
35
- end
36
- end
37
-
38
- module PuppetLibrary
18
+ module PuppetLibrary::Forge
39
19
  class ModuleNotFound < Exception
40
20
  end
41
21
 
42
- class Forge
43
- class Config
44
- def initialize(module_repo)
45
- @module_repo = module_repo
46
- end
47
-
48
- def module_repo(repo)
49
- @module_repo.add_repo repo
50
- end
51
- end
52
-
53
- def self.configure(&config_block)
54
- module_repo = ModuleRepo::Multi.new
55
- yield(Config.new(module_repo))
56
- Forge.new(module_repo)
57
- end
58
-
59
- def initialize(module_repo)
60
- @repo = module_repo
61
- end
62
-
63
- def get_module_metadata(author, name)
64
- modules = get_metadata(author, name)
65
-
66
- raise ModuleNotFound if modules.empty?
67
-
68
- module_infos = modules.map { |m| m.to_info }
69
- module_infos.deep_merge
70
- end
71
-
72
- def get_module_metadata_with_dependencies(author, name, version)
73
- raise ModuleNotFound if get_metadata(author, name).empty?
74
-
75
- full_name = "#{author}/#{name}"
76
- versions = collect_dependencies_versions(full_name)
77
- return versions if version.nil?
78
-
79
- versions[full_name] = versions[full_name].select do |v|
80
- v["version"].start_with?(version)
81
- end
82
-
83
- dependencies = versions[full_name].map do |v|
84
- v["dependencies"].map {|(name, spec)| name}
85
- end.flatten
86
- versions = Hash[versions.select do |name, info|
87
- name == full_name || dependencies.include?(name)
88
- end]
89
- return versions
90
- end
91
-
92
- def collect_dependencies_versions(module_full_name, metadata = {})
93
- author, module_name = module_full_name.split "/"
94
- module_versions = get_metadata(author, module_name)
95
- metadata[module_full_name] = module_versions.map {|v| v.to_version }
96
-
97
- dependencies = module_versions.map {|v| v.dependency_names }.flatten
98
- dependencies.each do |dependency|
99
- collect_dependencies_versions(dependency, metadata) unless metadata.include? dependency
100
- end
101
- return metadata
102
- end
103
-
104
- def get_module_buffer(author, name, version)
105
- @repo.get_module(author, name, version) or raise ModuleNotFound
106
- end
107
-
108
- def get_metadata(author, module_name)
109
- @repo.get_metadata(author, module_name).map {|metadata| ModuleMetadata.new(metadata)}
110
- end
111
- end
22
+ require 'puppet_library/forge/abstract'
23
+ require 'puppet_library/forge/directory'
24
+ require 'puppet_library/forge/multi'
25
+ require 'puppet_library/forge/proxy'
26
+ require 'puppet_library/forge/search_result'
112
27
  end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module PuppetLibrary::Http::Cache
19
+ require 'puppet_library/http/cache/in_memory'
20
+ require 'puppet_library/http/cache/noop'
21
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module PuppetLibrary::Http
19
+ require 'puppet_library/http/cache'
20
+ require 'puppet_library/http/http_client'
21
+ require 'puppet_library/http/url'
22
+ end
@@ -16,9 +16,8 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  require 'rack'
19
- require 'puppet_library/forge'
20
- require 'puppet_library/module_repo/directory'
21
- require 'puppet_library/module_repo/multi'
19
+ require 'puppet_library/forge/directory'
20
+ require 'puppet_library/forge/multi'
22
21
 
23
22
  module PuppetLibrary
24
23
  class PuppetLibrary
@@ -54,12 +53,12 @@ module PuppetLibrary
54
53
  options[:hostname] = hostname
55
54
  end
56
55
 
57
- options[:repositories] = []
56
+ options[:forges] = []
58
57
  opts.on("-m", "--module-dir [DIR]", "Directory containing the modules (can be specified multiple times. Defaults to './modules')") do |module_dir|
59
- options[:repositories] << [ModuleRepo::Directory, module_dir]
58
+ options[:forges] << [Forge::Directory, module_dir]
60
59
  end
61
60
  opts.on("-x", "--proxy [URL]", "Remote forge to proxy (can be specified multiple times)") do |url|
62
- options[:repositories] << [ModuleRepo::Proxy, url]
61
+ options[:forges] << [Forge::Proxy, url]
63
62
  end
64
63
  end
65
64
  begin
@@ -72,14 +71,14 @@ module PuppetLibrary
72
71
  end
73
72
 
74
73
  def build_server(options)
75
- if options[:repositories].empty?
76
- options[:repositories] << [ ModuleRepo::Proxy, "http://forge.puppetlabs.com" ]
74
+ if options[:forges].empty?
75
+ options[:forges] << [ Forge::Proxy, "http://forge.puppetlabs.com" ]
77
76
  end
78
77
 
79
78
  Server.set_up do |server|
80
- options[:repositories].each do |(repo_type, config)|
81
- subrepo = repo_type.new(config)
82
- server.module_repo subrepo
79
+ options[:forges].each do |(forge_type, config)|
80
+ subforge = forge_type.new(config)
81
+ server.forge subforge
83
82
  end
84
83
  end
85
84
  end
@@ -91,9 +90,9 @@ module PuppetLibrary
91
90
  @log.puts " |- Port: #{options[:port]}"
92
91
  @log.puts " |- Host: #{options[:hostname]}"
93
92
  @log.puts " |- Server: #{options[:server]}"
94
- @log.puts " `- Repositories:"
95
- options[:repositories].each do |(repo_type, config)|
96
- @log.puts " - #{repo_type}: #{config}"
93
+ @log.puts " `- Forges:"
94
+ options[:forges].each do |(forge_type, config)|
95
+ @log.puts " - #{forge_type}: #{config}"
97
96
  end
98
97
  end
99
98
 
@@ -17,14 +17,24 @@
17
17
 
18
18
  require 'sinatra/base'
19
19
 
20
- require 'puppet_library/forge'
21
- require 'puppet_library/module_metadata'
22
- require 'puppet_library/module_repo/multi'
20
+ require 'puppet_library/forge/multi'
23
21
 
24
22
  module PuppetLibrary
25
23
  class Server < Sinatra::Base
24
+ class Config
25
+ def initialize(forge)
26
+ @forge = forge
27
+ end
28
+
29
+ def forge(forge)
30
+ @forge.add_forge forge
31
+ end
32
+ end
33
+
26
34
  def self.set_up(&config_block)
27
- Server.new(Forge.configure(&config_block))
35
+ forge = Forge::Multi.new
36
+ yield(Config.new(forge))
37
+ Server.new(forge)
28
38
  end
29
39
 
30
40
  def initialize(forge)
@@ -36,13 +46,18 @@ module PuppetLibrary
36
46
  enable :logging
37
47
  end
38
48
 
49
+ get "/modules.json" do
50
+ search_term = params[:q]
51
+ @forge.search_modules(search_term).to_json
52
+ end
53
+
39
54
  get "/:author/:module.json" do
40
55
  author = params[:author]
41
56
  module_name = params[:module]
42
57
 
43
58
  begin
44
59
  @forge.get_module_metadata(author, module_name).to_json
45
- rescue ModuleNotFound
60
+ rescue Forge::ModuleNotFound
46
61
  status 410
47
62
  {"error" => "Could not find module \"#{module_name}\""}.to_json
48
63
  end
@@ -53,7 +68,7 @@ module PuppetLibrary
53
68
  version = params[:version]
54
69
  begin
55
70
  @forge.get_module_metadata_with_dependencies(author, module_name, version).to_json
56
- rescue ModuleNotFound
71
+ rescue Forge::ModuleNotFound
57
72
  status 410
58
73
  {"error" => "Module #{author}/#{module_name} not found"}.to_json
59
74
  end
@@ -70,7 +85,7 @@ module PuppetLibrary
70
85
  @forge.get_module_buffer(author, name, version).tap do
71
86
  attachment "#{author}-#{name}-#{version}.tar.gz"
72
87
  end
73
- rescue ModuleNotFound
88
+ rescue Forge::ModuleNotFound
74
89
  status 404
75
90
  end
76
91
  end
@@ -30,6 +30,31 @@ class Array
30
30
  !is_duplicate
31
31
  end
32
32
  end
33
+
34
+ def version_sort_by
35
+ sort_by do |element|
36
+ version = yield(element)
37
+ Gem::Version.new(version)
38
+ end
39
+ end
40
+
41
+ def deep_merge
42
+ inject({}) do |merged, map|
43
+ merged.deep_merge(map)
44
+ end
45
+ end
46
+ end
47
+
48
+ class Hash
49
+ def deep_merge(other)
50
+ merge(other) do |key, old_val, new_val|
51
+ if old_val.instance_of? Array
52
+ old_val + new_val
53
+ else
54
+ new_val
55
+ end
56
+ end
57
+ end
33
58
  end
34
59
 
35
60
  class Gem::Package::TarReader
@@ -16,5 +16,5 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  module PuppetLibrary
19
- VERSION = "0.2.0"
19
+ VERSION = "0.3.0"
20
20
  end
@@ -15,16 +15,11 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
- require 'puppet_library/version'
19
-
20
- require 'puppet_library/puppet_library'
21
- require 'puppet_library/server'
22
- require 'puppet_library/module_metadata'
23
- require 'puppet_library/http/http_client'
24
- require 'puppet_library/http/url'
25
- require 'puppet_library/http/cache/in_memory'
26
- require 'puppet_library/http/cache/noop'
27
- require 'puppet_library/module_repo/directory'
28
- require 'puppet_library/module_repo/multi'
29
- require 'puppet_library/module_repo/proxy'
30
- require 'puppet_library/util'
18
+ module PuppetLibrary
19
+ require 'puppet_library/forge'
20
+ require 'puppet_library/http'
21
+ require 'puppet_library/puppet_library'
22
+ require 'puppet_library/server'
23
+ require 'puppet_library/util'
24
+ require 'puppet_library/version'
25
+ end
@@ -49,4 +49,11 @@ Gem::Specification.new do |spec|
49
49
  spec.add_development_dependency "rake"
50
50
  spec.add_development_dependency "rspec"
51
51
  spec.add_development_dependency "simplecov"
52
+
53
+ # Guard has dependencies that don't work with Ruby < 1.9
54
+ unless RUBY_VERSION.start_with? "1.8"
55
+ spec.add_development_dependency "guard"
56
+ spec.add_development_dependency "guard-rspec"
57
+ spec.add_development_dependency "terminal-notifier-guard"
58
+ end
52
59
  end
@@ -17,9 +17,9 @@
17
17
 
18
18
  require 'spec_helper'
19
19
 
20
- module PuppetLibrary
21
- describe Forge do
22
- let(:forge) { Forge.new(module_repo) }
20
+ module PuppetLibrary::Forge
21
+ describe Abstract do
22
+ let(:forge) { Abstract.new(module_repo) }
23
23
  let(:module_repo) { double('module_repo') }
24
24
 
25
25
  describe "#get_module_buffer" do
@@ -44,6 +44,123 @@ module PuppetLibrary
44
44
  end
45
45
  end
46
46
 
47
+ describe "#search_modules" do
48
+ before do
49
+ all_metadata = [{
50
+ "name"=>"puppetlabs-apache",
51
+ "version"=>"0.10.0",
52
+ "source"=>"git://github.com/puppetlabs/puppetlabs-apache.git",
53
+ "author"=>"puppetlabs",
54
+ "license"=>"Apache 2.0",
55
+ "summary"=>"Puppet module for Apache",
56
+ "description"=>"Module for Apache configuration",
57
+ "project_page"=>"https://github.com/puppetlabs/puppetlabs-apache"
58
+ },{
59
+ "name"=>"dodgybrothers-ntp",
60
+ "version"=>"1.0.0",
61
+ "source"=>"git://github.com/dodgybrothers/puppet-ntp.git",
62
+ "author"=>"dodgybrothers",
63
+ "license"=>"Apache 2.0",
64
+ "summary"=>"Puppet module for NTP",
65
+ "description"=>"Module for NTP configuration",
66
+ "project_page"=>"https://github.com/dodgybrothers/puppet-ntp"
67
+ }]
68
+ allow(module_repo).to receive(:get_all_metadata).and_return(all_metadata)
69
+ end
70
+
71
+ it "matches by name" do
72
+ search_results = forge.search_modules("apache")
73
+ expect(search_results).to eq [{
74
+ "author"=>"puppetlabs",
75
+ "full_name"=>"puppetlabs/apache",
76
+ "name"=>"apache",
77
+ "desc"=>"Puppet module for Apache",
78
+ "project_url"=>"https://github.com/puppetlabs/puppetlabs-apache",
79
+ "releases"=>[{"version"=>"0.10.0"}],
80
+ "version"=>"0.10.0",
81
+ "tag_list"=>["puppetlabs", "apache"]
82
+ }]
83
+ end
84
+
85
+ it "matches by author" do
86
+ search_results = forge.search_modules("dodgybrothers")
87
+ expect(search_results).to eq [{
88
+ "author"=>"dodgybrothers",
89
+ "full_name"=>"dodgybrothers/ntp",
90
+ "name"=>"ntp",
91
+ "desc"=>"Puppet module for NTP",
92
+ "project_url"=>"https://github.com/dodgybrothers/puppet-ntp",
93
+ "releases"=>[{"version"=>"1.0.0"}],
94
+ "version"=>"1.0.0",
95
+ "tag_list"=>["dodgybrothers", "ntp"]
96
+ }]
97
+ end
98
+
99
+ context "when multiple versions of a module exist" do
100
+ it "retuns merges the metadata, favoring the most recent one" do
101
+ all_metadata = [{
102
+ "name"=>"puppetlabs-apache",
103
+ "version"=>"0.10.0",
104
+ "source"=>"git://github.com/puppetlabs/puppetlabs-apache.git",
105
+ "author"=>"puppetlabs",
106
+ "license"=>"Apache 2.0",
107
+ "summary"=>"Puppet module for Apache",
108
+ "description"=>"Module for Apache configuration",
109
+ "project_page"=>"https://github.com/puppetlabs/puppetlabs-apache"
110
+ },{
111
+ "name"=>"puppetlabs-apache",
112
+ "version"=>"1.0.0",
113
+ "source"=>"git://github.com/puppetlabs/puppetlabs-apache-new.git",
114
+ "author"=>"puppetlabs",
115
+ "license"=>"GPL",
116
+ "summary"=>"New Puppet module for Apache",
117
+ "description"=>"New module for Apache configuration",
118
+ "project_page"=>"https://github.com/puppetlabs/puppetlabs-apache-new"
119
+ }]
120
+ expect(module_repo).to receive(:get_all_metadata).and_return(all_metadata)
121
+
122
+ search_results = forge.search_modules("apache")
123
+ expect(search_results).to eq [{
124
+ "author"=>"puppetlabs",
125
+ "full_name"=>"puppetlabs/apache",
126
+ "name"=>"apache",
127
+ "desc"=>"New Puppet module for Apache",
128
+ "project_url"=>"https://github.com/puppetlabs/puppetlabs-apache-new",
129
+ "releases"=>[{"version"=>"1.0.0"},{"version"=>"0.10.0"}],
130
+ "version"=>"1.0.0",
131
+ "tag_list"=>["puppetlabs", "apache"]
132
+ }]
133
+ end
134
+ end
135
+
136
+ context "with no query" do
137
+ it "retuns all metadata" do
138
+ search_results = forge.search_modules(nil)
139
+
140
+ search_results = search_results.sort_by {|r| r["name"]}
141
+ expect(search_results).to eq [{
142
+ "author"=>"puppetlabs",
143
+ "full_name"=>"puppetlabs/apache",
144
+ "name"=>"apache",
145
+ "desc"=>"Puppet module for Apache",
146
+ "project_url"=>"https://github.com/puppetlabs/puppetlabs-apache",
147
+ "releases"=>[{"version"=>"0.10.0"}],
148
+ "version"=>"0.10.0",
149
+ "tag_list"=>["puppetlabs", "apache"]
150
+ },{
151
+ "author"=>"dodgybrothers",
152
+ "full_name"=>"dodgybrothers/ntp",
153
+ "name"=>"ntp",
154
+ "desc"=>"Puppet module for NTP",
155
+ "project_url"=>"https://github.com/dodgybrothers/puppet-ntp",
156
+ "releases"=>[{"version"=>"1.0.0"}],
157
+ "version"=>"1.0.0",
158
+ "tag_list"=>["dodgybrothers", "ntp"]
159
+ }]
160
+ end
161
+ end
162
+ end
163
+
47
164
  describe "#get_module_metadata" do
48
165
  context "when no modules found" do
49
166
  it "raises an error" do
@@ -16,7 +16,7 @@
16
16
 
17
17
  require 'spec_helper'
18
18
 
19
- module PuppetLibrary::ModuleRepo
19
+ module PuppetLibrary::Forge
20
20
  describe Directory do
21
21
  include ModuleSpecHelper
22
22
  include FileUtils
@@ -55,6 +55,32 @@ module PuppetLibrary::ModuleRepo
55
55
  end
56
56
  end
57
57
 
58
+ describe "#get_all_metadata" do
59
+ context "when modules exist" do
60
+ before do
61
+ add_module("puppetlabs", "apache", "1.0.0")
62
+ add_module("puppetlabs", "apache", "2.0.0")
63
+ end
64
+
65
+ it "returns a the module archive as a file buffer" do
66
+ metadata = module_repo.get_all_metadata
67
+
68
+ v1 = metadata.find {|m| m["version"] == "1.0.0" }
69
+ v2 = metadata.find {|m| m["version"] == "2.0.0" }
70
+ expect(v1).not_to be_nil
71
+ expect(v2).not_to be_nil
72
+ end
73
+ end
74
+
75
+ context "when no modules exist" do
76
+ it "returns an empty array" do
77
+ result = module_repo.get_all_metadata
78
+
79
+ expect(result).to be_empty
80
+ end
81
+ end
82
+ end
83
+
58
84
  describe "#get_metadata" do
59
85
  context "when the module directory is empty" do
60
86
  it "returns an empty array" do