From 2102af6d2d66e4e48a8ef92f7f2bcdcc8f95c21d Mon Sep 17 00:00:00 2001 From: Justin Campbell Date: Fri, 21 Nov 2014 15:28:43 -0500 Subject: [PATCH] Ensure path is passed through to API middleware --- lib/stacker_bee/client.rb | 4 +- lib/stacker_bee/middleware/cloud_stack_api.rb | 3 +- .../raises_a_helpful_exception.yml | 33 ++++++++ .../refuses_to_connect.yml | 77 +++++++++++++++++++ .../raises_a_client_error.yml | 47 +++++++++++ spec/integration/request_spec.rb | 11 ++- .../middleware/cloud_stack_api_spec.rb | 17 +--- 7 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/raises_a_helpful_exception.yml create mode 100644 spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/refuses_to_connect.yml create mode 100644 spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/with_a_nonexistant_path/raises_a_client_error.yml diff --git a/lib/stacker_bee/client.rb b/lib/stacker_bee/client.rb index 27bad20..1c9ffc4 100644 --- a/lib/stacker_bee/client.rb +++ b/lib/stacker_bee/client.rb @@ -38,7 +38,9 @@ def middlewares builder.use Middleware::EndpointNormalizer, api: self.class.api builder.use Middleware::RemoveEmptyStrings - builder.use Middleware::CloudStackAPI, api_key: configuration.api_key + builder.use Middleware::CloudStackAPI, + api_key: configuration.api_key, + url: configuration.url configuration.middlewares.call builder diff --git a/lib/stacker_bee/middleware/cloud_stack_api.rb b/lib/stacker_bee/middleware/cloud_stack_api.rb index 75c15f2..295fce7 100644 --- a/lib/stacker_bee/middleware/cloud_stack_api.rb +++ b/lib/stacker_bee/middleware/cloud_stack_api.rb @@ -2,7 +2,6 @@ module StackerBee module Middleware class CloudStackAPI < Base RESPONSE_TYPE = 'json' - DEFAULT_PATH = '/client/api/' def before(env) env.request.params.merge!( @@ -10,7 +9,7 @@ def before(env) command: env.request.endpoint_name, response: RESPONSE_TYPE ) - env.request.path ||= DEFAULT_PATH + env.request.path ||= URI.parse(url).path end end end diff --git a/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/raises_a_helpful_exception.yml b/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/raises_a_helpful_exception.yml new file mode 100644 index 0000000..33eda1a --- /dev/null +++ b/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/raises_a_helpful_exception.yml @@ -0,0 +1,33 @@ +--- +http_interactions: +- request: + method: get + uri: ?apiKey=&command=listAccounts&response=json&signature=oftBcJm8kFc%2Buxul8pAL2%2Bh0bdU= + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - Faraday v0.8.9 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - '*/*' + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - text/javascript; charset=UTF-8 + Content-Length: + - '1727' + Server: + - Jetty(6.1.26) + body: + encoding: UTF-8 + string: '{ "listaccountsresponse" : { "count":1 ,"account" : [ {"id":"b32dc958-b904-11e3-b3f0-080027079e3d","name":"admin","accounttype":1,"domainid":"b32db4c2-b904-11e3-b3f0-080027079e3d","domain":"ROOT","vmlimit":"Unlimited","vmtotal":0,"vmavailable":"Unlimited","iplimit":"Unlimited","iptotal":0,"ipavailable":"Unlimited","volumelimit":"Unlimited","volumetotal":0,"volumeavailable":"Unlimited","snapshotlimit":"Unlimited","snapshottotal":0,"snapshotavailable":"Unlimited","templatelimit":"Unlimited","templatetotal":0,"templateavailable":"Unlimited","projectlimit":"Unlimited","projecttotal":0,"projectavailable":"Unlimited","networklimit":"Unlimited","networktotal":0,"networkavailable":"Unlimited","vpclimit":"Unlimited","vpctotal":0,"vpcavailable":"Unlimited","cpulimit":"Unlimited","cputotal":0,"cpuavailable":"Unlimited","memorylimit":"Unlimited","memorytotal":0,"memoryavailable":"Unlimited","primarystoragelimit":"Unlimited","primarystoragetotal":0,"primarystorageavailable":"Unlimited","secondarystoragelimit":"Unlimited","secondarystoragetotal":0,"secondarystorageavailable":"Unlimited","state":"enabled","user":[{"id":"b32e02b0-b904-11e3-b3f0-080027079e3d","username":"admin","firstname":"Admin","lastname":"User","email":"admin@mailprovider.com","created":"2014-03-31T18:45:58+0000","state":"enabled","account":"admin","accounttype":1,"domainid":"b32db4c2-b904-11e3-b3f0-080027079e3d","domain":"ROOT","apikey":"","secretkey":"","accountid":"b32dc958-b904-11e3-b3f0-080027079e3d","iscallerchilddomain":false,"isdefault":true}],"isdefault":true} + ] } }' + http_version: + recorded_at: Fri, 21 Nov 2014 19:49:56 GMT +recorded_with: VCR 2.9.3 diff --git a/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/refuses_to_connect.yml b/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/refuses_to_connect.yml new file mode 100644 index 0000000..9d0a1bd --- /dev/null +++ b/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/given_an_nonexistant_path/refuses_to_connect.yml @@ -0,0 +1,77 @@ +--- +http_interactions: +- request: + method: get + uri: ?apiKey=&command=listAccounts&response=json&signature=oftBcJm8kFc%2Buxul8pAL2%2Bh0bdU= + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - Faraday v0.8.9 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - '*/*' + response: + status: + code: 200 + message: OK + headers: + Content-Type: + - text/javascript; charset=UTF-8 + Content-Length: + - '1727' + Server: + - Jetty(6.1.26) + body: + encoding: UTF-8 + string: '{ "listaccountsresponse" : { "count":1 ,"account" : [ {"id":"b32dc958-b904-11e3-b3f0-080027079e3d","name":"admin","accounttype":1,"domainid":"b32db4c2-b904-11e3-b3f0-080027079e3d","domain":"ROOT","vmlimit":"Unlimited","vmtotal":0,"vmavailable":"Unlimited","iplimit":"Unlimited","iptotal":0,"ipavailable":"Unlimited","volumelimit":"Unlimited","volumetotal":0,"volumeavailable":"Unlimited","snapshotlimit":"Unlimited","snapshottotal":0,"snapshotavailable":"Unlimited","templatelimit":"Unlimited","templatetotal":0,"templateavailable":"Unlimited","projectlimit":"Unlimited","projecttotal":0,"projectavailable":"Unlimited","networklimit":"Unlimited","networktotal":0,"networkavailable":"Unlimited","vpclimit":"Unlimited","vpctotal":0,"vpcavailable":"Unlimited","cpulimit":"Unlimited","cputotal":0,"cpuavailable":"Unlimited","memorylimit":"Unlimited","memorytotal":0,"memoryavailable":"Unlimited","primarystoragelimit":"Unlimited","primarystoragetotal":0,"primarystorageavailable":"Unlimited","secondarystoragelimit":"Unlimited","secondarystoragetotal":0,"secondarystorageavailable":"Unlimited","state":"enabled","user":[{"id":"b32e02b0-b904-11e3-b3f0-080027079e3d","username":"admin","firstname":"Admin","lastname":"User","email":"admin@mailprovider.com","created":"2014-03-31T18:45:58+0000","state":"enabled","account":"admin","accounttype":1,"domainid":"b32db4c2-b904-11e3-b3f0-080027079e3d","domain":"ROOT","apikey":"","secretkey":"","accountid":"b32dc958-b904-11e3-b3f0-080027079e3d","iscallerchilddomain":false,"isdefault":true}],"isdefault":true} + ] } }' + http_version: + recorded_at: Fri, 21 Nov 2014 20:16:07 GMT +- request: + method: get + uri: /not/a/real/endpoint?apiKey=&command=listAccounts&response=json&signature=oftBcJm8kFc%2Buxul8pAL2%2Bh0bdU= + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - Faraday v0.8.9 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - '*/*' + response: + status: + code: 404 + message: Not Found + headers: + Cache-Control: + - must-revalidate,no-cache,no-store + Content-Type: + - text/html; charset=iso-8859-1 + Content-Length: + - '1287' + Server: + - Jetty(6.1.26) + body: + encoding: UTF-8 + string: "\n\n\nError 404 NOT_FOUND\n\n\n

HTTP + ERROR: 404

\n

Problem accessing /not/a/real/endpoint. Reason:\n

+        \   NOT_FOUND

\n
Powered by Jetty://\n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n\n\n" + http_version: + recorded_at: Fri, 21 Nov 2014 20:20:21 GMT +recorded_with: VCR 2.9.3 diff --git a/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/with_a_nonexistant_path/raises_a_client_error.yml b/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/with_a_nonexistant_path/raises_a_client_error.yml new file mode 100644 index 0000000..1493480 --- /dev/null +++ b/spec/cassettes/A_response_to_a_request_sent_to_the_CloudStack_API/with_a_nonexistant_path/raises_a_client_error.yml @@ -0,0 +1,47 @@ +--- +http_interactions: +- request: + method: get + uri: /not/a/real/endpoint?apiKey=&command=listAccounts&response=json&signature=oftBcJm8kFc%2Buxul8pAL2%2Bh0bdU= + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - Faraday v0.8.9 + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + Accept: + - '*/*' + response: + status: + code: 404 + message: Not Found + headers: + Cache-Control: + - must-revalidate,no-cache,no-store + Content-Type: + - text/html; charset=iso-8859-1 + Content-Length: + - '1287' + Server: + - Jetty(6.1.26) + body: + encoding: UTF-8 + string: "\n\n\nError 404 NOT_FOUND\n\n\n

HTTP + ERROR: 404

\n

Problem accessing /not/a/real/endpoint. Reason:\n

+        \   NOT_FOUND

\n
Powered by Jetty://\n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n + \ \n \n\n\n" + http_version: + recorded_at: Mon, 24 Nov 2014 16:10:28 GMT +recorded_with: VCR 2.9.3 diff --git a/spec/integration/request_spec.rb b/spec/integration/request_spec.rb index 0a4a7dc..9b024dc 100644 --- a/spec/integration/request_spec.rb +++ b/spec/integration/request_spec.rb @@ -3,7 +3,9 @@ describe 'A response to a request sent to the CloudStack API', :vcr do subject { client.list_accounts } - let(:url) { CONFIG['url'] } + let(:config_url) { CONFIG['url'] } + let(:uri) { URI.parse(config_url) } + let(:url) { uri.to_s } let(:config_hash) do { url: url, @@ -35,6 +37,13 @@ end end + context 'with a nonexistant path', :regression do + before { uri.path = '/not/a/real/endpoint' } + it 'raises a client error' do + expect { subject }.to raise_error(StackerBee::ClientError) + end + end + context 'trailing slash in URL', :regression do let(:url) { CONFIG['url'].gsub(/\/$/, '') + '/' } it 'makes request with trailing slash' do diff --git a/spec/units/stacker_bee/middleware/cloud_stack_api_spec.rb b/spec/units/stacker_bee/middleware/cloud_stack_api_spec.rb index 22872d7..b312b2c 100644 --- a/spec/units/stacker_bee/middleware/cloud_stack_api_spec.rb +++ b/spec/units/stacker_bee/middleware/cloud_stack_api_spec.rb @@ -1,12 +1,11 @@ describe StackerBee::Middleware::CloudStackAPI do let(:env) do StackerBee::Middleware::Environment.new( - endpoint_name: 'endpoint-name', - path: path + endpoint_name: 'endpoint-name' ) end - let(:middleware) { described_class.new(api_key: 'API-KEY', params: {}) } - let(:path) { nil } + let(:middleware) { described_class.new(api_key: 'API-KEY', url: url) } + let(:url) { 'http://localhost:1234/my/path' } before do middleware.before(env) @@ -15,15 +14,7 @@ describe 'request' do subject { env.request } - context 'when the path is not set' do - let(:path) { nil } - its(:path) { should == described_class::DEFAULT_PATH } - end - - context 'when the path is already set' do - let(:path) { 'already set' } - its(:path) { should == path } - end + its(:path) { should == '/my/path' } end describe 'params' do