cookbook-client 0.1.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/spec/spec.opts ADDED
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --format specdoc
3
+ --loadby mtime
4
+ --reverse
@@ -0,0 +1,6 @@
1
+ $TESTING=true
2
+ $:.push File.join(File.dirname(__FILE__), '..', 'lib')
3
+
4
+ require 'chef/cookbook_client'
5
+ require 'chef/remote_cookbook'
6
+ require 'chef/streaming_cookbook_uploader'
@@ -0,0 +1,240 @@
1
+ #
2
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
3
+ # Copyright:: Copyright (c) 2009 Opscode, Inc.
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
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
+ require File.expand_path(File.join(File.dirname(__FILE__), "..", "spec_helper"))
20
+
21
+ describe "Spoon" do
22
+ LIST_RESPONSE_1 = {
23
+ 'cookbook' => 'http://cookbook_uri1',
24
+ 'cookbook_maintainer' => 'the_maintainer1',
25
+ 'cookbook_name' => 'The Name 1',
26
+ 'cookbook_description' => 'The Description 1',
27
+ }
28
+ LIST_RESPONSE_2 = {
29
+ 'cookbook' => 'http://cookbook_uri2',
30
+ 'cookbook_maintainer' => 'the_maintainer2',
31
+ 'cookbook_name' => 'The Name 2',
32
+ 'cookbook_description' => 'The Description 2',
33
+ }
34
+
35
+ before(:each) do
36
+ @mock_rest_client = mock('Opscode::REST')
37
+ Opscode::REST.stub!(:new).and_return(@mock_rest_client)
38
+
39
+ @cookbook_client = Chef::CookbookClient.new('hostname')
40
+ end
41
+
42
+ describe "parsing" do
43
+ it "should parse the json response hash from list-style queries" do
44
+ json_hash = {
45
+ 'cookbook' => 'http://cookbook_uri',
46
+ 'cookbook_maintainer' => 'the_maintainer',
47
+ 'cookbook_name' => 'The Name',
48
+ 'cookbook_description' => 'The Description',
49
+ }
50
+ res = Chef::RemoteCookbook.from_json_list(json_hash)
51
+ res.uri.should == 'http://cookbook_uri'
52
+ res.maintainer.should == 'the_maintainer'
53
+ res.name.should == 'The Name'
54
+ res.description.should == 'The Description'
55
+ end
56
+
57
+ it "should make a valid url" do
58
+ uri = @cookbook_client.make_uri('api/v1/cookbooks', {'arg1' => 'val1', 'arg2' => 'val2', 'arg?' => 'val&'})
59
+
60
+ uri.should == 'http://hostname/api/v1/cookbooks?arg%3F=val%26&arg1=val1&arg2=val2'
61
+ end
62
+ end
63
+
64
+ describe "API calls" do
65
+ it "should make a list request and properly handle the result" do
66
+ expected_uri = 'http://hostname/api/v1/cookbooks?items=999999'
67
+
68
+ json_result = {
69
+ 'items' => [ LIST_RESPONSE_1, LIST_RESPONSE_2 ]
70
+ }
71
+
72
+ @mock_rest_client.should_receive(:get).with(expected_uri).once.and_return(json_result)
73
+ res = @cookbook_client.do_list
74
+ res.length.should == 2
75
+
76
+ first_res = res[0]
77
+ first_res.uri.should == 'http://cookbook_uri1'
78
+ first_res.maintainer.should == 'the_maintainer1'
79
+ first_res.name.should == 'The Name 1'
80
+ first_res.description.should == 'The Description 1'
81
+
82
+ second_res = res[1]
83
+ second_res.uri.should == 'http://cookbook_uri2'
84
+ second_res.maintainer.should == 'the_maintainer2'
85
+ second_res.name.should == 'The Name 2'
86
+ second_res.description.should == 'The Description 2'
87
+ end
88
+
89
+ it "should make a search request" do
90
+ expected_uri = 'http://hostname/api/v1/search?q=test+term'
91
+
92
+ json_result = {
93
+ 'items' => [ LIST_RESPONSE_1, LIST_RESPONSE_2 ]
94
+ }
95
+
96
+ @mock_rest_client.should_receive(:get).with(expected_uri).once.and_return(json_result)
97
+ res = @cookbook_client.do_search('test term')
98
+ res.length.should == 2
99
+ end
100
+
101
+ it "should throw an exception if items isn't an array" do
102
+ json_result = {} # no 'items' there
103
+ @mock_rest_client.should_receive(:get).and_return(json_result)
104
+ proc { @cookbook_client.do_list }.should raise_error(Exception)
105
+
106
+ json_result = {
107
+ 'items' => {} # should be an Array
108
+ }
109
+ @mock_rest_client.should_receive(:get).and_return(json_result)
110
+ proc { @cookbook_client.do_list }.should raise_error(Exception)
111
+ end
112
+
113
+ it "should make a details request and properly handle the result" do
114
+ expected_cookbook_uri = 'http://hostname/api/v1/cookbooks/example'
115
+ expected_version1_uri = 'http://hostname/api/v1/cookbooks/example/0_7_0'
116
+ expected_version2_uri = 'http://hostname/api/v1/cookbooks/example/0_8_0'
117
+ json_result_cookbook = {
118
+ 'name' => 'Example',
119
+ 'maintainer' => 'timh',
120
+ 'description' => 'A Description',
121
+ 'versions' => [
122
+ expected_version1_uri,
123
+ expected_version2_uri,
124
+ ],
125
+ 'latest_version' => expected_version1_uri,
126
+ }
127
+ json_result_version1 = { 'file' => '/files/example-0.7.0.tar.gz' }
128
+ json_result_version2 = { 'file' => '/files/example-0.8.0.tar.gz' }
129
+
130
+ @mock_rest_client.should_receive(:get).with(expected_cookbook_uri).and_return(json_result_cookbook)
131
+ @mock_rest_client.should_receive(:get).with(expected_version1_uri).and_return(json_result_version1)
132
+ @mock_rest_client.should_receive(:get).with(expected_version2_uri).and_return(json_result_version2)
133
+
134
+ res = @cookbook_client.do_details 'example'
135
+ res.name.should == 'Example'
136
+ res.maintainer.should == 'timh'
137
+ res.description.should == 'A Description'
138
+ res.versions.length.should == 2
139
+
140
+ version1 = res.versions[0]
141
+ version1.should == res.latest_version
142
+ version1.version.should == '0.7.0'
143
+ version1.tarball_uri.should == 'http://hostname/files/example-0.7.0.tar.gz'
144
+
145
+ version2 = res.versions[1]
146
+ version2.version.should == '0.8.0'
147
+ version2.tarball_uri.should == 'http://hostname/files/example-0.8.0.tar.gz'
148
+ end
149
+ end
150
+
151
+ describe "download API" do
152
+ def setup_download_test
153
+ # Download starts out the same as details, because it calls do_details as its
154
+ # first step, to gather information about the cookbook.
155
+ expected_cookbook_uri = 'http://hostname/api/v1/cookbooks/example'
156
+ expected_version1_uri = 'http://hostname/api/v1/cookbooks/example/0_7_0'
157
+ expected_version2_uri = 'http://hostname/api/v1/cookbooks/example/0_8_0'
158
+ json_result_cookbook = {
159
+ 'name' => 'Example',
160
+ 'maintainer' => 'timh',
161
+ 'description' => 'A Description',
162
+ 'versions' => [
163
+ expected_version1_uri,
164
+ expected_version2_uri,
165
+ ],
166
+ 'latest_version' => expected_version1_uri,
167
+ }
168
+ json_result_version1 = { 'file' => '/files/example-0.7.0.tar.gz' }
169
+ json_result_version2 = { 'file' => 'https://https-example.org/https-files/example-0.8.0.tar.gz' }
170
+
171
+ @mock_rest_client.should_receive(:get).with(expected_cookbook_uri).and_return(json_result_cookbook)
172
+ @mock_rest_client.should_receive(:get).with(expected_version1_uri).and_return(json_result_version1)
173
+ @mock_rest_client.should_receive(:get).with(expected_version2_uri).and_return(json_result_version2)
174
+ end
175
+
176
+ it "should download a tarball via HTTP" do
177
+ setup_download_test
178
+
179
+ mock_http = mock('Net::HTTP')
180
+ mock_response = mock('Net::HTTPResponse')
181
+ Net::HTTP.stub!(:new).with('hostname', 80).and_return(mock_http)
182
+
183
+ mock_http.should_receive(:request_get).with('/files/example-0.7.0.tar.gz').and_return(mock_response)
184
+ mock_response.should_receive(:body).and_return('contents')
185
+
186
+ mock_file = mock("File")
187
+ File.stub!(:open).and_return(mock_file)
188
+ mock_file.should_receive(:write).with('contents')
189
+ mock_file.should_receive(:close)
190
+
191
+ @cookbook_client.do_download 'example'
192
+ end
193
+
194
+ it "should download a versioned tarball via HTTPS" do
195
+ setup_download_test
196
+
197
+ mock_http = mock('Net::HTTP')
198
+ mock_response = mock('Net::HTTPResponse')
199
+ Net::HTTP.stub!(:new).with('https-example.org', 443).and_return(mock_http)
200
+
201
+ mock_http.should_receive(:use_ssl=).with(true)
202
+ mock_http.should_receive(:verify_mode=)
203
+ mock_http.should_receive(:request_get).with('/https-files/example-0.8.0.tar.gz').and_return(mock_response)
204
+ mock_response.should_receive(:body).and_return('contents')
205
+
206
+ mock_file = mock("File")
207
+ File.stub!(:open).and_return(mock_file)
208
+ mock_file.should_receive(:write).with('contents')
209
+ mock_file.should_receive(:close)
210
+
211
+ @cookbook_client.do_download 'example', '0.8.0'
212
+ end
213
+
214
+ it "should throw an exception when a non-existant version is requested" do
215
+ setup_download_test
216
+
217
+ proc { @cookbook_client.do_download 'example', '2.0.0' }.should raise_error(Exception)
218
+ end
219
+
220
+ end
221
+
222
+ describe "RemoteCookbookVersion" do
223
+ it "should handle relative tarball paths" do
224
+ cookbook_version = Chef::RemoteCookbookVersion.new('http://hostname/api/v1/cookbooks/example/0_7_0')
225
+ cookbook_version.set_from_json_hash('hostname', { 'file' => '/server/path_to/example-0.7.0.tar.gz' })
226
+
227
+ cookbook_version.tarball_uri.should == 'http://hostname/server/path_to/example-0.7.0.tar.gz'
228
+ end
229
+
230
+ it "should handle absolute tarball paths" do
231
+ cookbook_version = Chef::RemoteCookbookVersion.new('http://hostname/api/v1/cookbooks/example/0_7_0')
232
+ cookbook_version.set_from_json_hash('hostname', { 'file' => 'http://other_server/path_to/example-0.7.0.tar.gz' })
233
+
234
+ cookbook_version.tarball_uri.should == 'http://other_server/path_to/example-0.7.0.tar.gz'
235
+ end
236
+ end
237
+
238
+ end
239
+
240
+
metadata ADDED
@@ -0,0 +1,93 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cookbook-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Opscode, Inc.
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-09 00:00:00 -08:00
13
+ default_executable: spoon
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: mixlib-authentication
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description:
26
+ email: info@opscode.com
27
+ executables:
28
+ - spoon
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - NOTICE
35
+ - Rakefile
36
+ - VERSION
37
+ - bin/spoon
38
+ - cookbook-client.gemspec
39
+ - lib/chef/cookbook_client.rb
40
+ - lib/chef/remote_cookbook.rb
41
+ - lib/chef/streaming_cookbook_uploader.rb
42
+ - spec/spec.opts
43
+ - spec/spec_helper.rb
44
+ - spec/spoon/spoon_spec.rb
45
+ has_rdoc: true
46
+ homepage: http://www.opscode.com
47
+ licenses: []
48
+
49
+ post_install_message:
50
+ rdoc_options:
51
+ - --charset=UTF-8
52
+ require_paths:
53
+ - lib
54
+ required_ruby_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ required_rubygems_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ requirements: []
67
+
68
+ rubyforge_project:
69
+ rubygems_version: 1.3.5
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: A command-line tool for interacting with the Cookbook Community Site, cookbooks.opscode.com
73
+ test_files:
74
+ - spec/spec_helper.rb
75
+ - spec/spoon/spoon_spec.rb
76
+ - examples/couchdb/metadata.rb
77
+ - examples/couchdb/recipes/default.rb
78
+ - examples/couchdb2/metadata.rb
79
+ - examples/couchdb2/recipes/default.rb
80
+ - examples/couchdb3/metadata.rb
81
+ - examples/couchdb3/recipes/default.rb
82
+ - examples/couchdb4/metadata.rb
83
+ - examples/couchdb4/recipes/default.rb
84
+ - examples/couchdb5/metadata.rb
85
+ - examples/couchdb5/recipes/default.rb
86
+ - examples/rest-delete.rb
87
+ - examples/test-auth-against-erlang.rb
88
+ - examples/test-hash-find.rb
89
+ - examples/test-ssl.rb
90
+ - examples/test-using-restclient-multipart.rb
91
+ - examples/test_signature_verification.rb
92
+ - examples/testrestoc.rb
93
+ - examples/upload-using-cw_multipart.rb