puppet-library 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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