community-zero 1.1.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -30
- data/Rakefile +15 -17
- data/bin/community-zero +10 -31
- data/lib/community_zero.rb +1 -2
- data/lib/community_zero/endpoint.rb +7 -9
- data/lib/community_zero/endpoints/cookbook_endpoint.rb +6 -6
- data/lib/community_zero/endpoints/cookbook_versions_version_endpoint.rb +3 -3
- data/lib/community_zero/endpoints/cookbooks_endpoint.rb +12 -8
- data/lib/community_zero/endpoints/search_endpoint.rb +1 -1
- data/lib/community_zero/{errors/rest_error.rb → errors.rb} +3 -1
- data/lib/community_zero/objects/cookbook.rb +0 -45
- data/lib/community_zero/router.rb +0 -2
- data/lib/community_zero/rspec.rb +59 -0
- data/lib/community_zero/server.rb +132 -98
- data/lib/community_zero/store.rb +9 -3
- data/lib/community_zero/version.rb +1 -1
- metadata +35 -34
- data/lib/community_zero/error.rb +0 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1435c42a58a4f5e005069db3566ebbfcd0af71b7
|
4
|
+
data.tar.gz: 2a5bfe36688097ef44601460e0ba82f6c7f7a810
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0b9baa73abd7875e2faff8ab2b81f198a3d3cc16c06d1c168cdc4dce84fb1d18707eae7f7a9b63ec9db63da770ecbdb1f1c45906a56769199eb55ad016b676ce
|
7
|
+
data.tar.gz: 1abbdab93b9fc8025d1dbbc33803d8baf0e9ede3ddf56f7dbf5c96c903af12baaa0633ab211396f63ba05ae6ae5f9899a8a3e88aa6f8a7299d2cff4bf3cd4073
|
data/README.md
CHANGED
@@ -38,41 +38,17 @@ Usage
|
|
38
38
|
The primary use is an in-memory fake Community site for testing. Here's a simple example:
|
39
39
|
|
40
40
|
```ruby
|
41
|
-
require 'community_zero/
|
42
|
-
server = CommunityZero::Server.new(port: 3000)
|
43
|
-
server.start
|
41
|
+
require 'community_zero/rspec'
|
44
42
|
```
|
45
43
|
|
46
|
-
This will create a server
|
47
|
-
|
48
|
-
```ruby
|
49
|
-
server.stop
|
50
|
-
```
|
51
|
-
|
52
|
-
This is great for debugging and logging requests, but you'll probably want
|
53
|
-
to run this in the background so you have full control of your thread.
|
54
|
-
|
55
|
-
To run Community Zero in the background, simply issue the `start_background` command:
|
56
|
-
|
57
|
-
```ruby
|
58
|
-
require 'community_zero/server'
|
59
|
-
server = CommunityZero::Server.new(port: 4000)
|
60
|
-
server.start_background
|
61
|
-
```
|
62
|
-
|
63
|
-
You can stop the server the same way:
|
64
|
-
|
65
|
-
```ruby
|
66
|
-
server.stop
|
67
|
-
```
|
44
|
+
This will create a server in the background and give you some nice hooks for accessing the data store to create and manipulate objects for testing. The best example tests are the cucumber tests packaged in the `features` directory.
|
68
45
|
|
69
46
|
Valid Options
|
70
47
|
-------------
|
71
48
|
You may currently pass the following options to the initializer:
|
72
49
|
|
73
|
-
- `host` - the host to run on
|
74
|
-
- `port` - the port to run on
|
75
|
-
- `debug` - run in debug mode to see all requests and responses (Default: false)
|
50
|
+
- `host` - the host to run on
|
51
|
+
- `port` - the port to run on
|
76
52
|
|
77
53
|
CLI (Command Line)
|
78
54
|
------------------
|
@@ -87,8 +63,7 @@ Run `community-zero --help` to see a list of the supported flags and options:
|
|
87
63
|
```text
|
88
64
|
Usage: community-zero [ARGS]
|
89
65
|
-H, --host HOST Host to bind to (default: 0.0.0.0)
|
90
|
-
-p, --port PORT Port to listen on
|
91
|
-
-d, --debug Show requests and debugging output
|
66
|
+
-p, --port PORT Port to listen on (default: 3389)
|
92
67
|
-h, --help Show this message
|
93
68
|
--version Show version
|
94
69
|
```
|
data/Rakefile
CHANGED
@@ -1,18 +1,16 @@
|
|
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
1
|
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
require 'cucumber/rake/task'
|
4
|
+
Cucumber::Rake::Task.new(:acceptance) do |t|
|
5
|
+
t.cucumber_opts = [].tap do |a|
|
6
|
+
a.push('--color')
|
7
|
+
a.push('--format progress')
|
8
|
+
a.push('--strict')
|
9
|
+
a.push('--tags ~@wip')
|
10
|
+
end.join(' ')
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'Run all tests'
|
14
|
+
task :test => [:acceptance]
|
15
|
+
|
16
|
+
task :default => [:test]
|
data/bin/community-zero
CHANGED
@@ -1,25 +1,12 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
#
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
-
#
|
12
|
-
# Unless required by applicable law or agreed to in writing, software
|
13
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
-
# See the License for the specific language governing permissions and
|
16
|
-
# limitations under the License.
|
17
|
-
#
|
18
|
-
|
19
|
-
$:.unshift(File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib')))
|
20
|
-
|
21
|
-
require 'community_zero/version'
|
22
|
-
require 'community_zero/server'
|
2
|
+
|
3
|
+
# Load paths are hard
|
4
|
+
$:.unshift(File.dirname(__FILE__) + '../lib')
|
5
|
+
|
6
|
+
# Trap interrupts to quit cleanly.
|
7
|
+
Signal.trap('INT') { exit 1 }
|
8
|
+
|
9
|
+
require 'community_zero'
|
23
10
|
require 'optparse'
|
24
11
|
|
25
12
|
options = { :publish => true }
|
@@ -27,22 +14,14 @@ options = { :publish => true }
|
|
27
14
|
OptionParser.new do |opts|
|
28
15
|
opts.banner = 'Usage: community-zero [ARGS]'
|
29
16
|
|
30
|
-
opts.on('-H', '--host HOST', 'Host to bind to (default:
|
17
|
+
opts.on('-H', '--host HOST', 'Host to bind to (default: 127.0.0.1)') do |value|
|
31
18
|
options[:host] = value
|
32
19
|
end
|
33
20
|
|
34
|
-
opts.on('-p', '--port PORT', Integer, 'Port to listen on (default:
|
21
|
+
opts.on('-p', '--port PORT', Integer, 'Port to listen on (default: 3389)') do |value|
|
35
22
|
options[:port] = value
|
36
23
|
end
|
37
24
|
|
38
|
-
opts.on('-s', '--socket SOCK', String, 'Unix socket path to listen on') do |value|
|
39
|
-
options[:socket] = value
|
40
|
-
end
|
41
|
-
|
42
|
-
opts.on('-l', '--log-level LEVEL', 'Set the output log level') do |value|
|
43
|
-
options[:log_level] = value
|
44
|
-
end
|
45
|
-
|
46
25
|
opts.on_tail('-h', '--help', 'Show this message') do
|
47
26
|
puts opts
|
48
27
|
exit
|
data/lib/community_zero.rb
CHANGED
@@ -16,13 +16,12 @@
|
|
16
16
|
#
|
17
17
|
|
18
18
|
require 'json'
|
19
|
-
require 'puma'
|
20
19
|
require 'timeout'
|
21
20
|
|
22
21
|
module CommunityZero
|
23
22
|
require_relative 'community_zero/chef'
|
24
23
|
require_relative 'community_zero/endpoint'
|
25
|
-
require_relative 'community_zero/
|
24
|
+
require_relative 'community_zero/errors'
|
26
25
|
require_relative 'community_zero/object'
|
27
26
|
require_relative 'community_zero/request'
|
28
27
|
require_relative 'community_zero/router'
|
@@ -38,6 +38,13 @@ module CommunityZero
|
|
38
38
|
@server = server
|
39
39
|
end
|
40
40
|
|
41
|
+
# The data store for these endpoints
|
42
|
+
#
|
43
|
+
# @return [CommunityZero::Store]
|
44
|
+
def store
|
45
|
+
server.store
|
46
|
+
end
|
47
|
+
|
41
48
|
# Generate the URL for the given cookbook.
|
42
49
|
#
|
43
50
|
# @param [CommunityZero::Cookbook] cookbook
|
@@ -79,15 +86,6 @@ module CommunityZero
|
|
79
86
|
]
|
80
87
|
end
|
81
88
|
|
82
|
-
# Must accept JSON
|
83
|
-
unless request.env['HTTP_ACCEPT'].to_s.split(';').include?('application/json')
|
84
|
-
return [
|
85
|
-
406,
|
86
|
-
{ 'Content-Type' => 'text/plain' },
|
87
|
-
'Must accept application/json'
|
88
|
-
]
|
89
|
-
end
|
90
|
-
|
91
89
|
begin
|
92
90
|
send(m, request)
|
93
91
|
rescue RestError => e
|
@@ -23,9 +23,9 @@ module CommunityZero
|
|
23
23
|
# GET /cookbooks/:name
|
24
24
|
def get(request)
|
25
25
|
name = request.path.last
|
26
|
-
cookbook =
|
26
|
+
cookbook = store.find(name)
|
27
27
|
|
28
|
-
if cookbook =
|
28
|
+
if cookbook = store.find(name)
|
29
29
|
respond({
|
30
30
|
'name' => cookbook.name,
|
31
31
|
'maintainer' => cookbook.maintainer,
|
@@ -33,8 +33,8 @@ module CommunityZero
|
|
33
33
|
'external_url' => cookbook.external_url,
|
34
34
|
'description' => cookbook.description,
|
35
35
|
'average_rating' => cookbook.average_rating,
|
36
|
-
'versions' =>
|
37
|
-
'latest_version' => version_url_for(cookbook,
|
36
|
+
'versions' => store.versions(cookbook).map { |i| version_url_for(cookbook, i) },
|
37
|
+
'latest_version' => version_url_for(cookbook, store.latest_version(cookbook)),
|
38
38
|
'created_at' => cookbook.created_at,
|
39
39
|
'updated_at' => cookbook.upadated_at,
|
40
40
|
})
|
@@ -52,8 +52,8 @@ module CommunityZero
|
|
52
52
|
def delete(request)
|
53
53
|
name = request.path.last
|
54
54
|
|
55
|
-
if cookbook =
|
56
|
-
cookbook
|
55
|
+
if cookbook = store.find(name)
|
56
|
+
store.remove(cookbook)
|
57
57
|
respond({})
|
58
58
|
else
|
59
59
|
respond(404,
|
@@ -23,7 +23,7 @@ module CommunityZero
|
|
23
23
|
def get(request)
|
24
24
|
name, version = request.path[1], request.path[-1].gsub('_', '.')
|
25
25
|
|
26
|
-
unless cookbook =
|
26
|
+
unless cookbook = store.find(name)
|
27
27
|
return respond(404,
|
28
28
|
{
|
29
29
|
'error_code' => 'NOT_FOUND',
|
@@ -32,8 +32,8 @@ module CommunityZero
|
|
32
32
|
)
|
33
33
|
end
|
34
34
|
|
35
|
-
version =
|
36
|
-
cookbook =
|
35
|
+
version = store.latest_version(cookbook) if version == 'latest'
|
36
|
+
cookbook = store.find(name, version)
|
37
37
|
respond(response_hash_for(cookbook))
|
38
38
|
end
|
39
39
|
|
@@ -27,7 +27,7 @@ module CommunityZero
|
|
27
27
|
def get(request)
|
28
28
|
start = Integer(request.query_params['start'] || 0)
|
29
29
|
items = Integer(request.query_params['items'] || 10)
|
30
|
-
cookbooks =
|
30
|
+
cookbooks = store.cookbooks[start...items] || []
|
31
31
|
|
32
32
|
respond({
|
33
33
|
'items' => cookbooks.collect { |cookbook|
|
@@ -38,7 +38,7 @@ module CommunityZero
|
|
38
38
|
'cookbook_maintainer' => cookbook.maintainer
|
39
39
|
}
|
40
40
|
},
|
41
|
-
'total' =>
|
41
|
+
'total' => store.size,
|
42
42
|
'start' => start.to_i,
|
43
43
|
})
|
44
44
|
end
|
@@ -51,7 +51,7 @@ module CommunityZero
|
|
51
51
|
|
52
52
|
metadata = Metadata.new(read_tarball(tarball))
|
53
53
|
|
54
|
-
if
|
54
|
+
if store.find(metadata.name, metadata.version)
|
55
55
|
respond(401,
|
56
56
|
{
|
57
57
|
'error_code' => 'ALREADY_EXISTS',
|
@@ -69,13 +69,17 @@ module CommunityZero
|
|
69
69
|
# @param [CommunityZero::Metadata] metadata
|
70
70
|
# the metadata to create the cookbook from
|
71
71
|
def create_cookbook(metadata, overrides = {})
|
72
|
-
Cookbook.
|
73
|
-
:name
|
74
|
-
:category
|
75
|
-
:maintainer
|
72
|
+
cookbook = Cookbook.new({
|
73
|
+
:name => metadata.name,
|
74
|
+
:category => nil,
|
75
|
+
:maintainer => metadata.maintainer,
|
76
76
|
:description => metadata.description,
|
77
|
-
:version
|
77
|
+
:version => metadata.version
|
78
78
|
}.merge(overrides))
|
79
|
+
|
80
|
+
store.add(cookbook)
|
81
|
+
|
82
|
+
cookbook
|
79
83
|
end
|
80
84
|
|
81
85
|
# Parse the metadata from the tarball.
|
@@ -25,7 +25,7 @@ module CommunityZero
|
|
25
25
|
q = request.query_params['q'].to_s
|
26
26
|
start = Integer(request.query_params['start'] || 0)
|
27
27
|
items = Integer(request.query_params['items'] || 10)
|
28
|
-
cookbooks =
|
28
|
+
cookbooks = store.search(q)[start...items] || []
|
29
29
|
|
30
30
|
respond({
|
31
31
|
'items' => cookbooks.collect { |cookbook|
|
@@ -16,9 +16,11 @@
|
|
16
16
|
#
|
17
17
|
|
18
18
|
module CommunityZero
|
19
|
-
#
|
19
|
+
# The base class for errors.
|
20
20
|
#
|
21
21
|
# @author Seth Vargo <sethvargo@gmail.com>
|
22
|
+
class Error < StandardError; end
|
23
|
+
|
22
24
|
class RestError < Error
|
23
25
|
attr_reader :response_code, :error
|
24
26
|
|
@@ -20,25 +20,6 @@ module CommunityZero
|
|
20
20
|
#
|
21
21
|
# @author Seth Vargo <sethvargo@gmail.com>
|
22
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
23
|
# Create a new cookbook from the given hash.
|
43
24
|
#
|
44
25
|
# @param [Hash] hash
|
@@ -48,32 +29,6 @@ module CommunityZero
|
|
48
29
|
hash.each { |k,v| instance_variable_set(:"@#{k}",v) }
|
49
30
|
end
|
50
31
|
|
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
32
|
# Dump this cookbook to a hash.
|
78
33
|
#
|
79
34
|
# @return [Hash]
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'singleton'
|
3
|
+
|
4
|
+
require 'community_zero/server'
|
5
|
+
|
6
|
+
module CommunityZero
|
7
|
+
class RSpec
|
8
|
+
undef :to_s, :inspect
|
9
|
+
|
10
|
+
def self.method_missing(m, *args, &block)
|
11
|
+
instance.send(m, *args, &block)
|
12
|
+
end
|
13
|
+
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
extend Forwardable
|
17
|
+
def_delegators :@server, :url, :running?, :stop, :reset!, :store, :to_s, :inspect
|
18
|
+
|
19
|
+
attr_reader :server
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@server = Server.new(port: 3389)
|
23
|
+
end
|
24
|
+
|
25
|
+
def start
|
26
|
+
unless @server.running?
|
27
|
+
@server.start_background
|
28
|
+
end
|
29
|
+
|
30
|
+
@server
|
31
|
+
end
|
32
|
+
|
33
|
+
def uri
|
34
|
+
@uri ||= URI.parse(url)
|
35
|
+
end
|
36
|
+
|
37
|
+
def get(path)
|
38
|
+
request = Net::HTTP::Get.new(path)
|
39
|
+
http.request(request)
|
40
|
+
end
|
41
|
+
|
42
|
+
def post(path, body)
|
43
|
+
request = Net::HTTP::Post.new(path)
|
44
|
+
request.set_form_data(body)
|
45
|
+
http.request(request)
|
46
|
+
end
|
47
|
+
|
48
|
+
def delete(path)
|
49
|
+
request = Net::HTTP::Delete.new(path)
|
50
|
+
http.request(request)
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def http
|
56
|
+
@http ||= Net::HTTP.new(uri.host, uri.port)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -15,23 +15,34 @@
|
|
15
15
|
# limitations under the License.
|
16
16
|
#
|
17
17
|
|
18
|
+
require 'open-uri'
|
19
|
+
require 'rack'
|
20
|
+
require 'webrick'
|
21
|
+
|
22
|
+
require 'community_zero'
|
23
|
+
|
18
24
|
module CommunityZero
|
19
25
|
# A single instance of the Community Server.
|
20
26
|
#
|
21
27
|
# @author Seth Vargo <sethvargo@gmail.com>
|
22
28
|
class Server
|
23
|
-
require_relative '../community_zero'
|
24
29
|
|
30
|
+
#
|
31
|
+
# Default options to populate
|
32
|
+
#
|
25
33
|
DEFAULT_OPTIONS = {
|
26
|
-
:host => '
|
27
|
-
:port =>
|
34
|
+
:host => '127.0.0.1',
|
35
|
+
:port => 3389,
|
28
36
|
}.freeze
|
29
37
|
|
38
|
+
#
|
30
39
|
# The list of options passed to the server.
|
31
40
|
#
|
32
41
|
# @return [Hash]
|
42
|
+
#
|
33
43
|
attr_reader :options
|
34
44
|
|
45
|
+
#
|
35
46
|
# Create a new Community site server.
|
36
47
|
#
|
37
48
|
# @param [Hash] options
|
@@ -40,145 +51,168 @@ module CommunityZero
|
|
40
51
|
# @option options [String] :host
|
41
52
|
# the host to listen on (default is 0.0.0.0)
|
42
53
|
# @option options [String, Fixnum] :port
|
43
|
-
# the port to listen on (default is
|
54
|
+
# the port to listen on (default is 3389)
|
55
|
+
#
|
44
56
|
def initialize(options = {})
|
45
57
|
@options = DEFAULT_OPTIONS.merge(options)
|
58
|
+
@options[:host] = "[#{@options[:host]}]" if @options[:host].include?(':')
|
59
|
+
@options.freeze
|
46
60
|
end
|
47
61
|
|
48
|
-
# Start the community server.
|
49
62
|
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
63
|
+
# The data store (by default, this is just a regular store)
|
64
|
+
#
|
65
|
+
def store
|
66
|
+
@store ||= Store.new
|
67
|
+
end
|
68
|
+
|
69
|
+
#
|
70
|
+
# The URL for this Community Zero server.
|
71
|
+
#
|
72
|
+
# @return [String]
|
73
|
+
#
|
74
|
+
def url
|
75
|
+
"http://#{@options[:host]}:#{@options[:port]}"
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Start a Community Zero server in the current thread. You can stop this
|
80
|
+
# server by canceling the current thread.
|
81
|
+
#
|
82
|
+
# @param [Boolean] publish
|
83
|
+
# publish the server information to STDOUT
|
84
|
+
#
|
85
|
+
# @return [nil]
|
86
|
+
# this method will block the main thread until interrupted
|
87
|
+
#
|
88
|
+
def start(publish = true)
|
89
|
+
if publish
|
90
|
+
puts <<-EOH.gsub(/^ {10}/, '')
|
91
|
+
>> Starting Community Zero (v#{CommunityZero::VERSION})...
|
92
|
+
>> WEBrick (v#{WEBrick::VERSION}) on Rack (v#{Rack.release}) is listening at #{url}
|
93
|
+
>> Press CTRL+C to stop
|
94
|
+
|
95
|
+
EOH
|
59
96
|
end
|
60
97
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
98
|
+
thread = start_background
|
99
|
+
|
100
|
+
%w[INT TERM].each do |signal|
|
101
|
+
Signal.trap(signal) do
|
102
|
+
puts "\n>> Stopping Community Zero..."
|
103
|
+
@server.shutdown
|
104
|
+
end
|
66
105
|
end
|
106
|
+
|
107
|
+
# Move the background process to the main thread
|
108
|
+
thread.join
|
67
109
|
end
|
68
110
|
|
69
|
-
#
|
70
|
-
#
|
111
|
+
#
|
112
|
+
# Start a Community Zero server in a forked process. This method returns
|
113
|
+
# the PID to the forked process.
|
71
114
|
#
|
72
115
|
# @param [Fixnum] wait
|
73
116
|
# the number of seconds to wait for the server to start
|
74
117
|
#
|
75
118
|
# @return [Thread]
|
76
|
-
# the thread the
|
119
|
+
# the thread the background process is running in
|
120
|
+
#
|
77
121
|
def start_background(wait = 5)
|
78
|
-
@
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
sleep(0.01) until running? || @server_error
|
89
|
-
raise @server_error if @server_error
|
90
|
-
end
|
91
|
-
|
122
|
+
@server = WEBrick::HTTPServer.new(
|
123
|
+
:BindAddress => @options[:host],
|
124
|
+
:Port => @options[:port],
|
125
|
+
:AccessLog => [],
|
126
|
+
:Logger => WEBrick::Log.new(StringIO.new, 7)
|
127
|
+
)
|
128
|
+
@server.mount('/', Rack::Handler::WEBrick, app)
|
129
|
+
|
130
|
+
@thread = Thread.new { @server.start }
|
131
|
+
@thread.abort_on_exception = true
|
92
132
|
@thread
|
93
133
|
end
|
94
134
|
|
95
|
-
#
|
135
|
+
#
|
136
|
+
# Boolean method to determine if the server is currently ready to accept
|
137
|
+
# requests. This method will attempt to make an HTTP request against the
|
138
|
+
# server. If this method returns true, you are safe to make a request.
|
96
139
|
#
|
97
140
|
# @return [Boolean]
|
98
|
-
# true if the server is
|
141
|
+
# true if the server is accepting requests, false otherwise
|
142
|
+
#
|
99
143
|
def running?
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
144
|
+
if @server.nil? || @server.status != :Running
|
145
|
+
return false
|
146
|
+
end
|
147
|
+
|
148
|
+
uri = URI.join(url, 'cookbooks')
|
149
|
+
headers = { 'Accept' => 'application/json' }
|
150
|
+
|
151
|
+
Timeout.timeout(0.1) { !open(uri, headers).nil? }
|
152
|
+
rescue SocketError, Errno::ECONNREFUSED, Timeout::Error
|
153
|
+
false
|
104
154
|
end
|
105
155
|
|
106
|
-
#
|
156
|
+
#
|
157
|
+
# Gracefully stop the Community Zero server.
|
107
158
|
#
|
108
159
|
# @param [Fixnum] wait
|
109
|
-
# the number of seconds to wait
|
160
|
+
# the number of seconds to wait before raising force-terminating the
|
161
|
+
# server
|
162
|
+
#
|
110
163
|
def stop(wait = 5)
|
164
|
+
Timeout.timeout(wait) do
|
165
|
+
@server.shutdown
|
166
|
+
@thread.join(wait) if @thread
|
167
|
+
end
|
168
|
+
rescue Timeout::Error
|
111
169
|
if @thread
|
112
|
-
|
113
|
-
|
114
|
-
server.stop(true)
|
170
|
+
$stderr.puts("Community Zero did not stop within #{wait} seconds! Killing...")
|
171
|
+
@thread.kill
|
115
172
|
end
|
116
|
-
rescue
|
117
|
-
$stderr.puts "Server did not stop within #{wait} seconds. Killing..."
|
118
|
-
@thread.kill if @thread
|
119
173
|
ensure
|
174
|
+
@server = nil
|
120
175
|
@thread = nil
|
121
176
|
end
|
122
177
|
|
123
178
|
# Clear out any existing entires and reset the server's contents to a
|
124
179
|
# clean state.
|
125
180
|
def reset!
|
126
|
-
|
181
|
+
store.destroy_all
|
127
182
|
end
|
128
183
|
|
129
|
-
|
130
|
-
|
131
|
-
# @example
|
132
|
-
# server = CommunityZero.new
|
133
|
-
# server.url #=> http://0.0.0.0:3000
|
134
|
-
#
|
135
|
-
# @example
|
136
|
-
# server = CommunityZero.new(host: 'example.com', port: 80)
|
137
|
-
# server.url #=> http://example.com:80
|
138
|
-
def url
|
139
|
-
@url ||= "http://#{options[:host]}:#{options[:port]}"
|
184
|
+
def to_s
|
185
|
+
"#<#{self.class} #{url}>"
|
140
186
|
end
|
141
187
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
# @return [Puma::Server]
|
146
|
-
# the actual server object
|
147
|
-
def server
|
148
|
-
return @server if @server
|
149
|
-
|
150
|
-
@server = Puma::Server.new(app, Puma::Events.new(STDERR, STDOUT))
|
151
|
-
|
152
|
-
if options[:socket]
|
153
|
-
@server.add_unix_listener(options[:socket])
|
154
|
-
else
|
155
|
-
@server.add_tcp_listener(options[:host], options[:port])
|
156
|
-
end
|
157
|
-
|
158
|
-
@server
|
159
|
-
end
|
188
|
+
def inspect
|
189
|
+
"#<#{self.class} @url=#{url.inspect}>"
|
190
|
+
end
|
160
191
|
|
161
|
-
|
162
|
-
#
|
163
|
-
# @return []
|
164
|
-
def app
|
165
|
-
lambda do |env|
|
166
|
-
request = Request.new(env)
|
167
|
-
response = router.call(request)
|
192
|
+
private
|
168
193
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
194
|
+
#
|
195
|
+
# The actual application the server will respond to.
|
196
|
+
#
|
197
|
+
# @return [RackApp]
|
198
|
+
#
|
199
|
+
def app
|
200
|
+
lambda do |env|
|
201
|
+
request = Request.new(env)
|
202
|
+
response = router.call(request)
|
173
203
|
|
174
|
-
|
175
|
-
|
176
|
-
['/search', SearchEndpoint],
|
177
|
-
['/cookbooks', CookbooksEndpoint],
|
178
|
-
['/cookbooks/:name', CookbookEndpoint],
|
179
|
-
['/cookbooks/:name/versions/:version', CookbookVersionsVersionEndpoint],
|
180
|
-
)
|
204
|
+
response[-1] = Array(response[-1])
|
205
|
+
response
|
181
206
|
end
|
207
|
+
end
|
182
208
|
|
209
|
+
def router
|
210
|
+
@router ||= Router.new(self,
|
211
|
+
['/search', SearchEndpoint],
|
212
|
+
['/cookbooks', CookbooksEndpoint],
|
213
|
+
['/cookbooks/:name', CookbookEndpoint],
|
214
|
+
['/cookbooks/:name/versions/:version', CookbookVersionsVersionEndpoint],
|
215
|
+
)
|
216
|
+
end
|
183
217
|
end
|
184
218
|
end
|
data/lib/community_zero/store.rb
CHANGED
@@ -17,9 +17,7 @@
|
|
17
17
|
|
18
18
|
module CommunityZero
|
19
19
|
# @author Seth Vargo <sethvargo@gmail.com>
|
20
|
-
|
21
|
-
extend self
|
22
|
-
|
20
|
+
class Store
|
23
21
|
# The number of cookbooks in the store.
|
24
22
|
#
|
25
23
|
# @return [Fixnum]
|
@@ -123,6 +121,14 @@ module CommunityZero
|
|
123
121
|
(_cookbooks[name] && _cookbooks[name].keys.sort) || []
|
124
122
|
end
|
125
123
|
|
124
|
+
# Return the latest version of the given cookbook.
|
125
|
+
#
|
126
|
+
# @param [String, CommunityZero::Cookbook] name
|
127
|
+
# the cookbook or name of the cookbook to get versions for
|
128
|
+
def latest_version(name)
|
129
|
+
versions(name).last
|
130
|
+
end
|
131
|
+
|
126
132
|
private
|
127
133
|
# All the cookbooks in the store.
|
128
134
|
#
|
metadata
CHANGED
@@ -1,85 +1,85 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: community-zero
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Seth Vargo
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: cucumber
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
type: :
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: json_spec
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - '>='
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - '>='
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: rack
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - '>='
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - '>='
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
54
|
+
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - '>='
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0
|
61
|
+
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - '>='
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
75
|
+
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
82
|
+
version: '0'
|
83
83
|
description: Self-contained, easy-setup, fast-start in-memory Chef Community Site
|
84
84
|
for testing.
|
85
85
|
email: sethvargo@gmail.com
|
@@ -91,27 +91,28 @@ files:
|
|
91
91
|
- LICENSE
|
92
92
|
- README.md
|
93
93
|
- Rakefile
|
94
|
-
-
|
94
|
+
- bin/community-zero
|
95
|
+
- lib/community_zero.rb
|
95
96
|
- lib/community_zero/chef.rb
|
97
|
+
- lib/community_zero/chef/metadata.rb
|
96
98
|
- lib/community_zero/endpoint.rb
|
97
99
|
- lib/community_zero/endpoints/cookbook_endpoint.rb
|
98
100
|
- lib/community_zero/endpoints/cookbook_versions_version_endpoint.rb
|
99
101
|
- lib/community_zero/endpoints/cookbooks_endpoint.rb
|
100
102
|
- lib/community_zero/endpoints/not_found_endpoint.rb
|
101
103
|
- lib/community_zero/endpoints/search_endpoint.rb
|
102
|
-
- lib/community_zero/
|
103
|
-
- lib/community_zero/errors/rest_error.rb
|
104
|
+
- lib/community_zero/errors.rb
|
104
105
|
- lib/community_zero/object.rb
|
105
106
|
- lib/community_zero/objects/cookbook.rb
|
106
107
|
- lib/community_zero/request.rb
|
107
108
|
- lib/community_zero/router.rb
|
109
|
+
- lib/community_zero/rspec.rb
|
108
110
|
- lib/community_zero/server.rb
|
109
111
|
- lib/community_zero/store.rb
|
110
112
|
- lib/community_zero/version.rb
|
111
|
-
- lib/community_zero.rb
|
112
|
-
- bin/community-zero
|
113
113
|
homepage: https://github.com/sethvargo/community-zero
|
114
|
-
licenses:
|
114
|
+
licenses:
|
115
|
+
- Apache 2.0
|
115
116
|
metadata: {}
|
116
117
|
post_install_message:
|
117
118
|
rdoc_options: []
|
@@ -129,7 +130,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
130
|
version: '0'
|
130
131
|
requirements: []
|
131
132
|
rubyforge_project:
|
132
|
-
rubygems_version: 2.0
|
133
|
+
rubygems_version: 2.2.0
|
133
134
|
signing_key:
|
134
135
|
specification_version: 4
|
135
136
|
summary: Self-contained, easy-setup, fast-start in-memory Chef Community Site for
|
data/lib/community_zero/error.rb
DELETED
@@ -1,25 +0,0 @@
|
|
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 errors.
|
20
|
-
#
|
21
|
-
# @author Seth Vargo <sethvargo@gmail.com>
|
22
|
-
class Error < StandardError; end
|
23
|
-
|
24
|
-
require_relative 'errors/rest_error'
|
25
|
-
end
|