community-zero 1.0.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.
- data/LICENSE +202 -0
- data/README.md +109 -0
- data/Rakefile +18 -0
- data/bin/community-zero +54 -0
- data/lib/community_zero.rb +31 -0
- data/lib/community_zero/chef.rb +20 -0
- data/lib/community_zero/chef/metadata.rb +49 -0
- data/lib/community_zero/endpoint.rb +112 -0
- data/lib/community_zero/endpoints/cookbook_endpoint.rb +68 -0
- data/lib/community_zero/endpoints/cookbook_versions_version_endpoint.rb +59 -0
- data/lib/community_zero/endpoints/cookbooks_endpoint.rb +102 -0
- data/lib/community_zero/endpoints/not_found_endpoint.rb +37 -0
- data/lib/community_zero/endpoints/search_endpoint.rb +44 -0
- data/lib/community_zero/error.rb +25 -0
- data/lib/community_zero/errors/rest_error.rb +30 -0
- data/lib/community_zero/object.rb +25 -0
- data/lib/community_zero/objects/cookbook.rb +99 -0
- data/lib/community_zero/request.rb +60 -0
- data/lib/community_zero/router.rb +55 -0
- data/lib/community_zero/server.rb +124 -0
- data/lib/community_zero/store.rb +149 -0
- data/lib/community_zero/version.rb +20 -0
- metadata +150 -0
@@ -0,0 +1,30 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Seth Vargo <sethvargo@gmail.com>
|
3
|
+
# Copyright 2013, Opscode, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module CommunityZero
|
19
|
+
# A general error for failed communicate with a REST API.
|
20
|
+
#
|
21
|
+
# @author Seth Vargo <sethvargo@gmail.com>
|
22
|
+
class RestError < Error
|
23
|
+
attr_reader :response_code, :error
|
24
|
+
|
25
|
+
def initialize(response_code, error)
|
26
|
+
@response_code = response_code
|
27
|
+
@error = error
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Seth Vargo <sethvargo@gmail.com>
|
3
|
+
# Copyright 2013, Opscode, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module CommunityZero
|
19
|
+
# The base class for objects.
|
20
|
+
#
|
21
|
+
# @author Seth Vargo <sethvargo@gmail.com>
|
22
|
+
class Object
|
23
|
+
require 'community_zero/objects/cookbook'
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Seth Vargo <sethvargo@gmail.com>
|
3
|
+
# Copyright 2013, Opscode, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module CommunityZero
|
19
|
+
# An object representation of a cookbook.
|
20
|
+
#
|
21
|
+
# @author Seth Vargo <sethvargo@gmail.com>
|
22
|
+
class Cookbook
|
23
|
+
class << self
|
24
|
+
# Create a cookbook object from a hash.
|
25
|
+
#
|
26
|
+
# @param [Hash] hash
|
27
|
+
# the hash from which to create the cookbook
|
28
|
+
def from_hash(hash)
|
29
|
+
new(hash)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Create a cookbook object from a hash and commit that object
|
33
|
+
# to memory.
|
34
|
+
#
|
35
|
+
# @param [Hash] hash
|
36
|
+
# the hash from which to create the cookbook
|
37
|
+
def create(hash)
|
38
|
+
new(hash).save
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Create a new cookbook from the given hash.
|
43
|
+
#
|
44
|
+
# @param [Hash] hash
|
45
|
+
# the hash from which to create the cookbook
|
46
|
+
def initialize(hash = {})
|
47
|
+
@average_rating = 3
|
48
|
+
hash.each { |k,v| instance_variable_set(:"@#{k}",v) }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Save this cookbook in the store.
|
52
|
+
def save
|
53
|
+
Store.update(self)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Delete this cookbook from the store.
|
57
|
+
def destroy
|
58
|
+
Store.remove(self)
|
59
|
+
end
|
60
|
+
|
61
|
+
# A list of all other versions of this cookbook.
|
62
|
+
#
|
63
|
+
# @return [Array<String>]
|
64
|
+
# the other verions
|
65
|
+
def versions
|
66
|
+
@versions ||= Store.versions(self)
|
67
|
+
end
|
68
|
+
|
69
|
+
# The latest (newest) version.
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
# the newest version
|
73
|
+
def latest_version
|
74
|
+
@latest_version ||= versions.last
|
75
|
+
end
|
76
|
+
|
77
|
+
# Dump this cookbook to a hash.
|
78
|
+
#
|
79
|
+
# @return [Hash]
|
80
|
+
# the hash representation of this cookbook
|
81
|
+
def to_hash
|
82
|
+
methods = instance_variables.map { |i| i.to_s.gsub('@', '') }
|
83
|
+
Hash[*methods.map { |m| [m, send(m.to_sym)] }.flatten]
|
84
|
+
end
|
85
|
+
|
86
|
+
def method_missing(m, *args, &block)
|
87
|
+
if m.to_s =~ /\=$/
|
88
|
+
value = args.size == 1 ? args[0] : args
|
89
|
+
instance_variable_set(:"@#{m.to_s.gsub('=', '')}", value)
|
90
|
+
else
|
91
|
+
instance_variable_get(:"@#{m}")
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def respond_to?(m, include_private = false)
|
96
|
+
instance_variables.map(&:to_s).include?("@#{m}")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Seth Vargo <sethvargo@gmail.com>
|
3
|
+
# Copyright 2013, Opscode, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module CommunityZero
|
19
|
+
# A singleton request.
|
20
|
+
#
|
21
|
+
# @author Seth Vargon <sethvargo@gmail.com>
|
22
|
+
class Request
|
23
|
+
attr_reader :env
|
24
|
+
|
25
|
+
def initialize(env)
|
26
|
+
@env = env
|
27
|
+
end
|
28
|
+
|
29
|
+
def base_uri
|
30
|
+
@base_uri ||= "#{env['rack.url_scheme']}://#{env['HTTP_HOST']}#{env['SCRIPT_NAME']}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def method
|
34
|
+
@env['REQUEST_METHOD']
|
35
|
+
end
|
36
|
+
|
37
|
+
def path
|
38
|
+
@path ||= env['PATH_INFO'].split('/').select { |part| part != "" }
|
39
|
+
end
|
40
|
+
|
41
|
+
def body=(body)
|
42
|
+
@body = body
|
43
|
+
end
|
44
|
+
|
45
|
+
def body
|
46
|
+
@body ||= env['rack.input'].read
|
47
|
+
end
|
48
|
+
|
49
|
+
def query_params
|
50
|
+
@query_params ||= begin
|
51
|
+
params = Rack::Request.new(env).GET
|
52
|
+
params.keys.each do |key|
|
53
|
+
params[key] = URI.unescape(params[key])
|
54
|
+
end
|
55
|
+
params
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Seth Vargo <sethvargo@gmail.com>
|
3
|
+
# Copyright 2013, Opscode, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module CommunityZero
|
19
|
+
# The router for the Community Server.
|
20
|
+
#
|
21
|
+
# @author Seth Vargo <sethvargo@gmail.com>
|
22
|
+
class Router
|
23
|
+
require 'community_zero/endpoint'
|
24
|
+
|
25
|
+
attr_reader :server, :routes
|
26
|
+
|
27
|
+
def initialize(server, *routes)
|
28
|
+
@server = server
|
29
|
+
@routes = routes.map do |route, endpoint|
|
30
|
+
pattern = Regexp.new("^#{route.gsub(/:[A-Za-z_]+/, '[^/]*')}$")
|
31
|
+
[pattern, endpoint]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def call(request)
|
36
|
+
begin
|
37
|
+
path = '/' + request.path.join('/')
|
38
|
+
find_endpoint(path).new(server).call(request)
|
39
|
+
rescue
|
40
|
+
[
|
41
|
+
500,
|
42
|
+
{ 'Content-Type' => 'text/plain' },
|
43
|
+
"Exception raised! #{$!.inspect}\n#{$!.backtrace.join("\n")}"
|
44
|
+
]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
def find_endpoint(path)
|
50
|
+
_, endpoint = routes.find { |route, endpoint| route.match(path) }
|
51
|
+
endpoint || NotFoundEndpoint
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Seth Vargo <sethvargo@gmail.com>
|
3
|
+
# Copyright 2013, Opscode, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module CommunityZero
|
19
|
+
# A single instance of the Community Server.
|
20
|
+
#
|
21
|
+
# @author Seth Vargo <sethvargo@gmail.com>
|
22
|
+
class Server
|
23
|
+
require 'community_zero'
|
24
|
+
|
25
|
+
DEFAULT_OPTIONS = {
|
26
|
+
:host => '0.0.0.0',
|
27
|
+
:port => 3000
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
# The list of options passed to the server.
|
31
|
+
#
|
32
|
+
# @return [Hash]
|
33
|
+
attr_reader :options
|
34
|
+
|
35
|
+
# Create a new Community site server.
|
36
|
+
#
|
37
|
+
# @param [Hash] options
|
38
|
+
# a list of options to pass in
|
39
|
+
#
|
40
|
+
# @option options [String] :host
|
41
|
+
# the host to listen on (default is 0.0.0.0)
|
42
|
+
# @option options [String, Fixnum] :port
|
43
|
+
# the port to listen on (default is 3000)
|
44
|
+
def initialize(options = {})
|
45
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Start the community server.
|
49
|
+
#
|
50
|
+
# @return [Thread]
|
51
|
+
# the thread the server is running in
|
52
|
+
def start
|
53
|
+
if options[:publish]
|
54
|
+
puts ">> Starting Community Zero (v#{CommunityZero::VERSION})..."
|
55
|
+
puts ">> Puma (v#{Puma::Const::PUMA_VERSION}) is listening at #{url}"
|
56
|
+
puts ">> Press CTRL+C to stop"
|
57
|
+
end
|
58
|
+
|
59
|
+
begin
|
60
|
+
thread = server.run.join
|
61
|
+
rescue Object, Interrupt
|
62
|
+
puts "\n>> Stopping Puma..." if options[:publish]
|
63
|
+
server.stop(true) if running?
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Determine if the server is currently running.
|
68
|
+
#
|
69
|
+
# @return [Boolean]
|
70
|
+
# true if the server is currently running, false otherwise
|
71
|
+
def running?
|
72
|
+
server && server.running?
|
73
|
+
end
|
74
|
+
|
75
|
+
# Returns the URL the server is listening on.
|
76
|
+
#
|
77
|
+
# @example
|
78
|
+
# server = CommunityZero.new
|
79
|
+
# server.url #=> http://0.0.0.0:3000
|
80
|
+
#
|
81
|
+
# @example
|
82
|
+
# server = CommunityZero.new(host: 'example.com', port: 80)
|
83
|
+
# server.url #=> http://example.com:80
|
84
|
+
def url
|
85
|
+
@url ||= "http://#{options[:host]}:#{options[:port]}"
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
# The Community Zero server.
|
90
|
+
#
|
91
|
+
# @return [Puma::Server]
|
92
|
+
# the actual server object
|
93
|
+
def server
|
94
|
+
return @server if @server
|
95
|
+
|
96
|
+
@server = Puma::Server.new(app, Puma::Events.new(STDERR, STDOUT))
|
97
|
+
@server.add_tcp_listener(options[:host], options[:port])
|
98
|
+
@server
|
99
|
+
end
|
100
|
+
|
101
|
+
# The actual application the server will respond to.
|
102
|
+
#
|
103
|
+
# @return []
|
104
|
+
def app
|
105
|
+
lambda do |env|
|
106
|
+
request = Request.new(env)
|
107
|
+
response = router.call(request)
|
108
|
+
|
109
|
+
response[-1] = Array(response[-1])
|
110
|
+
response
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def router
|
115
|
+
@router ||= Router.new(self,
|
116
|
+
['/search', SearchEndpoint],
|
117
|
+
['/cookbooks', CookbooksEndpoint],
|
118
|
+
['/cookbooks/:name', CookbookEndpoint],
|
119
|
+
['/cookbooks/:name/versions/:version', CookbookVersionsVersionEndpoint],
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2013, Seth Vargo <sethvargo@gmail.com>
|
3
|
+
# Copyright 2013, Opscode, Inc.
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module CommunityZero
|
19
|
+
# @author Seth Vargo <sethvargo@gmail.com>
|
20
|
+
module Store
|
21
|
+
extend self
|
22
|
+
|
23
|
+
# The number of cookbooks in the store.
|
24
|
+
#
|
25
|
+
# @return [Fixnum]
|
26
|
+
# the number of cookbooks in the store
|
27
|
+
def size
|
28
|
+
_cookbooks.keys.size
|
29
|
+
end
|
30
|
+
|
31
|
+
# The full array of cookbooks.
|
32
|
+
#
|
33
|
+
# @example
|
34
|
+
# [
|
35
|
+
# #<CommunityZero::Cookbook apache2>,
|
36
|
+
# #<CommunityZero::Cookbook apt>
|
37
|
+
# ]
|
38
|
+
#
|
39
|
+
# @return [Array<CommunityZero::Cookbook>]
|
40
|
+
# the list of cookbooks
|
41
|
+
def cookbooks
|
42
|
+
_cookbooks.map { |_,v| v[v.keys.first] }
|
43
|
+
end
|
44
|
+
|
45
|
+
# Query the installed cookbooks, returning those who's name matches the
|
46
|
+
# given query.
|
47
|
+
#
|
48
|
+
# @param [String] query
|
49
|
+
# the query parameter
|
50
|
+
#
|
51
|
+
# @return [Array<CommunityZero::Cookbook>]
|
52
|
+
# the list of cookbooks that match the given query
|
53
|
+
def search(query)
|
54
|
+
regex = Regexp.new(query, 'i')
|
55
|
+
_cookbooks.collect do |_, v|
|
56
|
+
v[v.keys.first] if regex.match(v[v.keys.first].name)
|
57
|
+
end.compact
|
58
|
+
end
|
59
|
+
|
60
|
+
# Delete all cookbooks in the store.
|
61
|
+
def destroy_all
|
62
|
+
@_cookbooks = nil
|
63
|
+
end
|
64
|
+
|
65
|
+
# Add the given cookbook to the cookbook store. This method's
|
66
|
+
# implementation prohibits duplicate cookbooks from entering the store.
|
67
|
+
#
|
68
|
+
# @param [CommunityZero::Cookbook] cookbook
|
69
|
+
# the cookbook to add
|
70
|
+
def add(cookbook)
|
71
|
+
cookbook = cookbook.dup
|
72
|
+
cookbook.created_at = Time.now
|
73
|
+
cookbook.updated_at = Time.now
|
74
|
+
|
75
|
+
entry = _cookbooks[cookbook.name] ||= {}
|
76
|
+
entry[cookbook.version] = cookbook
|
77
|
+
end
|
78
|
+
alias_method :update, :add
|
79
|
+
|
80
|
+
# Remove the cookbook from the store.
|
81
|
+
#
|
82
|
+
# @param [CommunityZero::Cookbook] cookbook
|
83
|
+
# the cookbook to remove
|
84
|
+
def remove(cookbook)
|
85
|
+
return unless has_cookbook?(cookbook.name, cookbook.version)
|
86
|
+
_cookbooks[cookbook.name].delete(cookbook.version)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Determine if the cookbook store contains a cookbook.
|
90
|
+
#
|
91
|
+
# @see {find} for the method signature and parameters
|
92
|
+
def has_cookbook?(name, version = nil)
|
93
|
+
!find(name, version).nil?
|
94
|
+
end
|
95
|
+
|
96
|
+
# Determine if the cookbook store contains a cookbook. If the version
|
97
|
+
# attribute is nil, this method will return the latest cookbook version by
|
98
|
+
# that name that exists. If the version is specified, this method will only
|
99
|
+
# return that specific version, or nil if that cookbook at that version
|
100
|
+
# exists.
|
101
|
+
#
|
102
|
+
# @param [String] name
|
103
|
+
# the name of the cookbook to find
|
104
|
+
# @param [String, nil] version
|
105
|
+
# the version of the cookbook to search
|
106
|
+
#
|
107
|
+
# @return [CommunityZero::Cookbook, nil]
|
108
|
+
# the cookbook in the store, or nil if one does not exist
|
109
|
+
def find(name, version = nil)
|
110
|
+
possibles = _cookbooks[name]
|
111
|
+
return nil if possibles.nil?
|
112
|
+
|
113
|
+
version ||= possibles.keys.sort.last
|
114
|
+
possibles[version]
|
115
|
+
end
|
116
|
+
|
117
|
+
# Return a list of all versions for the given cookbook.
|
118
|
+
#
|
119
|
+
# @param [String, CommunityZero::Cookbook] name
|
120
|
+
# the cookbook or name of the cookbook to get versions for
|
121
|
+
def versions(name)
|
122
|
+
name = name.respond_to?(:name) ? name.name : name
|
123
|
+
(_cookbooks[name] && _cookbooks[name].keys.sort) || []
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
# All the cookbooks in the store.
|
128
|
+
#
|
129
|
+
# @example
|
130
|
+
# {
|
131
|
+
# 'apache2' => {
|
132
|
+
# '1.0.0' => {
|
133
|
+
# 'license' => 'Apache 2.0',
|
134
|
+
# 'version' => '1.0.0',
|
135
|
+
# 'tarball_file_size' => 20949,
|
136
|
+
# 'file' => 'http://s3.amazonaws.com...',
|
137
|
+
# 'cookbook' => 'http://localhost:4000/apache2',
|
138
|
+
# 'average_rating' => nil
|
139
|
+
# }
|
140
|
+
# }
|
141
|
+
# }
|
142
|
+
#
|
143
|
+
# @return [Hash<String, Hash<String, CommunityZero::Cookbook>>]
|
144
|
+
def _cookbooks
|
145
|
+
@_cookbooks ||= {}
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
end
|