beaker-http 0.0.1
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.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/README.md +17 -0
- data/Rakefile +17 -0
- data/acceptance/tests/puppetserver_requests.rb +33 -0
- data/beaker-http.gemspec +36 -0
- data/lib/beaker-http/dsl/web_helpers.rb +62 -0
- data/lib/beaker-http/helpers/puppet_helpers.rb +49 -0
- data/lib/beaker-http/http.rb +93 -0
- data/lib/beaker-http/middleware/response/faraday_beaker_logger.rb +55 -0
- data/lib/beaker-http/version.rb +7 -0
- data/lib/beaker-http.rb +10 -0
- data/spec/beaker-http/dsl/web_helpers_spec.rb +151 -0
- data/spec/beaker-http/http_spec.rb +80 -0
- data/spec/beaker-http/middleware/response/faraday_beaker_logger_spec.rb +49 -0
- data/spec/spec_helper.rb +10 -0
- metadata +223 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 126ad20369072bad14cd0f1c540ebf2c5c09c8c8
|
4
|
+
data.tar.gz: 627779ca603f73a147d893dd8fef723b48082d28
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 149ac40c2ad28e4dd28d96cd27dfa0661b94018f1735139712ed655c969c179a8e0589339d7dc13f1c3ce137949eba67e98fe304185b829e356487fd291ccb85
|
7
|
+
data.tar.gz: da4fac3b62401bbabe3400c336701e76329dc2bb700fb5f802d1be66f38bdcdc93dd41839b2919a4eb37a429b403ebac4d4fec74ce0db9c7ef1cec76c7f65272
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# beaker-http
|
2
|
+
|
3
|
+
This library is designed to assist in test scenarios where http requests to a Beaker::Host
|
4
|
+
are required. It utilizes the Faraday library to generate requests, and the [Http](lib/beaker-http/http.rb)
|
5
|
+
class is designed to be subclassed into objects that are more targeted to specific http
|
6
|
+
services running on beaker hosts.
|
7
|
+
|
8
|
+
## spec testing
|
9
|
+
|
10
|
+
Spec tests all live under the `spec` folder. These are the default rake task, &
|
11
|
+
so can be run with a simple `bundle exec rake`, as well as being fully specified
|
12
|
+
by running `bundle exec rake test:spec:run` or using the `test:spec` task.
|
13
|
+
|
14
|
+
## acceptance testing
|
15
|
+
|
16
|
+
Acceptance testing will be added once the first few releases have been released.
|
17
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
|
3
|
+
namespace :test do
|
4
|
+
|
5
|
+
namespace :spec do
|
6
|
+
|
7
|
+
desc "Run spec tests"
|
8
|
+
RSpec::Core::RakeTask.new(:run) do |t|
|
9
|
+
t.rspec_opts = ['--color']
|
10
|
+
t.pattern = 'spec/'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
task 'test:spec' => 'test:spec:run'
|
16
|
+
task :test => 'test:spec'
|
17
|
+
task :default => :test
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'beaker-http'
|
2
|
+
|
3
|
+
test_name 'Ensure that requests can be built out to the puppetserver' do
|
4
|
+
|
5
|
+
step 'install latest released puppet agent' do
|
6
|
+
install_puppet_agent_on(hosts)
|
7
|
+
end
|
8
|
+
|
9
|
+
step 'install the latest puppet-server on the master' do
|
10
|
+
install_package(master, 'puppetserver')
|
11
|
+
on master, 'service puppetserver start'
|
12
|
+
end
|
13
|
+
|
14
|
+
step 'generate a new beaker http connection object'
|
15
|
+
http_connection = generate_new_http_connection(master)
|
16
|
+
|
17
|
+
step 'configure the connection to connect to the master port' do
|
18
|
+
http_connection.url_prefix.port = 8140
|
19
|
+
end
|
20
|
+
|
21
|
+
step 'call the environments endpoint on the puppetserver' do
|
22
|
+
response = http_connection.get('/puppet/v3/environments')
|
23
|
+
assert_equal(200, response.status)
|
24
|
+
end
|
25
|
+
|
26
|
+
step 'call the environments endpoint with the #https_request method' do
|
27
|
+
response = http_request("https://#{master.hostname}:8140/puppet/v3/environments",
|
28
|
+
:get,
|
29
|
+
http_connection.ssl['client_cert'],
|
30
|
+
http_connection.ssl['client_key'])
|
31
|
+
assert_equal(200, response.status)
|
32
|
+
end
|
33
|
+
end
|
data/beaker-http.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'beaker-http/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "beaker-http"
|
8
|
+
spec.version = Beaker::Http::Version::STRING
|
9
|
+
spec.authors = ["Puppet"]
|
10
|
+
spec.email = ["qe@puppet.com"]
|
11
|
+
spec.summary = %q{Puppet testing tool}
|
12
|
+
spec.description = %q{Puppet testing tool coupled with Beaker}
|
13
|
+
spec.homepage = "https://github.com/puppetlabs/beaker-http"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
#Development dependencies
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
22
|
+
spec.add_development_dependency 'pry', '~> 0.9.12'
|
23
|
+
spec.add_development_dependency 'rake'
|
24
|
+
spec.add_development_dependency 'rspec', '>= 3.0.0'
|
25
|
+
|
26
|
+
#Documentation dependencies
|
27
|
+
spec.add_development_dependency 'yard', '~> 0'
|
28
|
+
spec.add_development_dependency 'markdown', '~> 0'
|
29
|
+
spec.add_development_dependency 'activesupport', '4.2.6'
|
30
|
+
|
31
|
+
#Run time dependencies
|
32
|
+
spec.add_runtime_dependency 'json', '~> 1.8'
|
33
|
+
spec.add_runtime_dependency 'beaker', '~> 3.0'
|
34
|
+
spec.add_runtime_dependency 'faraday', '~> 0.9', '>= 0.9.1'
|
35
|
+
spec.add_runtime_dependency 'faraday_middleware', '~> 0.9'
|
36
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Beaker::DSL::Helpers::WebHelpers
|
2
|
+
|
3
|
+
# Generates a new http connection object, using the ever-present options hash to
|
4
|
+
# configure the connection.
|
5
|
+
#
|
6
|
+
# @param host [Beaker::Host optional] supply a SUT host object; will use puppet on host
|
7
|
+
# to configure certs, and use the options in the host object instead of the global.
|
8
|
+
# @return [Beaker::Http::Connection] an object wrapping the Faraday::Connection object.
|
9
|
+
def generate_new_http_connection(host = nil)
|
10
|
+
if host
|
11
|
+
raise ArgumentError.new "host must be Beaker::Host, not #{host.class}" if !host.is_a?(Beaker::Host)
|
12
|
+
connection = Beaker::Http::Connection.new(host.options)
|
13
|
+
connection.configure_private_key_and_cert_with_puppet(host)
|
14
|
+
connection
|
15
|
+
else
|
16
|
+
Beaker::Http::Connection.new(options)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Make a single http request and discard the http connection object. Returns a Faraday::Response
|
21
|
+
# object that can be introspected for all response information.
|
22
|
+
#
|
23
|
+
# @param url [String] String that will be parsed into a URI object.
|
24
|
+
# @param request_method [Symbol] Represents any valid http verb.
|
25
|
+
# @param cert [OpenSSL::X509::Certificate] Certifcate for authentication.
|
26
|
+
# @param key [OpenSSL::PKey::RSA] Private Key for authentication.
|
27
|
+
# @param body [String, Hash] For requests that can send a body. Strings are sent unformatted and
|
28
|
+
# Hashes are JSON.parsed by the Faraday Middleware.
|
29
|
+
# @param [Hash] options Hash of options extra options for the request
|
30
|
+
# @option options [Boolean] :read_timeout How long to wait before closing the connection.
|
31
|
+
# @return [Faraday::Response]
|
32
|
+
def http_request(url, request_method, cert=nil, key=nil, body=nil, options={})
|
33
|
+
connection = generate_new_http_connection
|
34
|
+
|
35
|
+
|
36
|
+
connection.url_prefix = URI.parse(url)
|
37
|
+
|
38
|
+
if cert
|
39
|
+
if cert.is_a?(OpenSSL::X509::Certificate)
|
40
|
+
connection.ssl['client_cert'] = cert
|
41
|
+
else
|
42
|
+
raise TypeError, "cert must be an OpenSSL::X509::Certificate object, not #{cert.class}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
if key
|
47
|
+
if key.is_a?(OpenSSL::PKey::RSA)
|
48
|
+
connection.ssl['client_key'] = key
|
49
|
+
else
|
50
|
+
raise TypeError, "key must be an OpenSSL::PKey:RSA object, not #{key.class}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# ewwww
|
55
|
+
connection.ssl[:verify] = false
|
56
|
+
|
57
|
+
connection.connection.options.timeout = options[:read_timeout] if options[:read_timeout]
|
58
|
+
|
59
|
+
response = connection.send(request_method) { |conn| conn.body = body }
|
60
|
+
response
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Http
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
# Given a Beaker::Host object, introspect the host for the CA cert and save it to
|
6
|
+
# the coordinator's filesystem.
|
7
|
+
# @param host[Beaker::Host] host to ssh into and find the CA cert
|
8
|
+
# @return [String] File path to the CA cert saved on the coordinator
|
9
|
+
def get_host_cacert(host)
|
10
|
+
cacert_on_host= host.puppet['localcacert']
|
11
|
+
# puppet may not have laid down the cacert yet, so check to make sure
|
12
|
+
# the file exists
|
13
|
+
host.execute("test -f #{cacert_on_host}")
|
14
|
+
ca_cert = host.execute("cat #{cacert_on_host}", :silent => true)
|
15
|
+
cert_dir = Dir.mktmpdir("pe_certs")
|
16
|
+
ca_cert_file = File.join(cert_dir, "cacert.pem")
|
17
|
+
File.open(ca_cert_file, "w+") do |f|
|
18
|
+
f.write(ca_cert)
|
19
|
+
end
|
20
|
+
ca_cert_file
|
21
|
+
end
|
22
|
+
|
23
|
+
# Given a Beaker::Host object, introspect the host for the private key and save it to
|
24
|
+
# the coordinator's filesystem.
|
25
|
+
# @param host[Beaker::Host] host to ssh into and find the private key
|
26
|
+
# @return [String] A String of the private key
|
27
|
+
def get_host_private_key(host)
|
28
|
+
private_key = host.puppet['hostprivkey']
|
29
|
+
# puppet may not have laid down the private_key yet, so check to make sure
|
30
|
+
# the file exists
|
31
|
+
host.execute("test -f #{private_key}")
|
32
|
+
host.execute("cat #{private_key}", :silent => true)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Given a Beaker::Host object, introspect the host for the host cert and save it to
|
36
|
+
# the coordinator's filesystem.
|
37
|
+
# @param host[Beaker::Host] host to ssh into and find the host cert
|
38
|
+
# @return [String] A String of the host cert
|
39
|
+
def get_host_cert(host)
|
40
|
+
hostcert = host.puppet['hostcert']
|
41
|
+
# puppet may not have laid down the hostcert yet, so check to make sure
|
42
|
+
# the file exists
|
43
|
+
host.execute("test -f #{hostcert}")
|
44
|
+
host.execute("cat #{hostcert}", :silent => true)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Http
|
3
|
+
|
4
|
+
# == Beaker::Http::Connection object instantiation examples
|
5
|
+
# These examples are for using the Connection object directly. If you are trying to use
|
6
|
+
# this from within a test, consider using the
|
7
|
+
# {Beaker::DSL::Helpers::WebHelpers DSL constructors} instead.
|
8
|
+
# @see Beaker::DSL::Helpers::WebHelpers
|
9
|
+
class Connection
|
10
|
+
include Beaker::Http::Helpers
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
attr_reader :connection
|
14
|
+
|
15
|
+
# Beaker::Http::Connection objects can be instantiated with object that
|
16
|
+
# utilizes a object for easier setup during testing.
|
17
|
+
#
|
18
|
+
# @param [Hash] options Typically the global options provided by Beaker.
|
19
|
+
# @option options [Beaker::Logger] :logger
|
20
|
+
# @option options [Boolean] :log_http_bodies
|
21
|
+
def initialize(options)
|
22
|
+
@connection = create_default_connection(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def_delegators :connection, :get, :post, :put, :delete, :head, :patch, :url_prefix, :url_prefix=, :ssl
|
26
|
+
|
27
|
+
def create_default_connection(options)
|
28
|
+
Faraday.new do |conn|
|
29
|
+
conn.request :json
|
30
|
+
|
31
|
+
conn.response :follow_redirects
|
32
|
+
conn.response :raise_error
|
33
|
+
conn.response :json, :content_type => /\bjson$/
|
34
|
+
|
35
|
+
# We can supply a third argument, a Hash with key of :bodies set to true or false,
|
36
|
+
# to configure whether or not to log http bodies in requests and responses.
|
37
|
+
# However, to uncomplicate things, we will just use the default
|
38
|
+
# set in the middleware and not allow the http log level to be set
|
39
|
+
# independently of the beaker log level. If we find that we should allow setting
|
40
|
+
# of http bodies independent of the beaker log level, we should expose that setting
|
41
|
+
# here.
|
42
|
+
conn.response :faraday_beaker_logger, options[:logger]
|
43
|
+
|
44
|
+
conn.adapter :net_http
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# If you would like to run tests that expect 400 or even 500 responses,
|
49
|
+
# apply this method to remove the <tt>:raise_error</tt> middleware.
|
50
|
+
def remove_error_checking
|
51
|
+
connection.builder.delete(Faraday::Response::RaiseError)
|
52
|
+
nil
|
53
|
+
end
|
54
|
+
|
55
|
+
def set_cacert(ca_file)
|
56
|
+
ssl['ca_file'] = ca_file
|
57
|
+
url_prefix.scheme = 'https'
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_client_key(client_key)
|
61
|
+
ssl['client_key'] = client_key
|
62
|
+
end
|
63
|
+
|
64
|
+
def set_client_cert(client_cert)
|
65
|
+
ssl['client_cert'] = client_cert
|
66
|
+
end
|
67
|
+
|
68
|
+
# Use this method if you are connecting as a user to the system; it will
|
69
|
+
# provide the correct SSL context but not provide authentication.
|
70
|
+
def configure_cacert_with_puppet(host)
|
71
|
+
set_cacert(get_host_cacert(host))
|
72
|
+
connection.host = host.hostname
|
73
|
+
nil
|
74
|
+
end
|
75
|
+
|
76
|
+
# Use this method if you want to connect to the system using certificate
|
77
|
+
# based authentication. This method will provide the ssl context and use
|
78
|
+
# the private key and cert from the host provided for authentication.
|
79
|
+
def configure_private_key_and_cert_with_puppet(host)
|
80
|
+
configure_cacert_with_puppet(host)
|
81
|
+
|
82
|
+
client_key_raw = get_host_private_key(host)
|
83
|
+
client_cert_raw = get_host_cert(host)
|
84
|
+
|
85
|
+
ssl['client_key'] = OpenSSL::PKey.read(client_key_raw)
|
86
|
+
ssl['client_cert'] = OpenSSL::X509::Certificate.new(client_cert_raw)
|
87
|
+
|
88
|
+
nil
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Http
|
3
|
+
class FaradayBeakerLogger < Faraday::Response::Middleware
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
DEFAULT_OPTIONS = { :bodies => true }
|
7
|
+
|
8
|
+
def initialize(app, logger, options = {} )
|
9
|
+
super(app)
|
10
|
+
@logger = logger
|
11
|
+
@options = DEFAULT_OPTIONS.merge(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
def_delegators :@logger, :trace, :debug, :info, :notify, :warn
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
@start_time = Time.now
|
18
|
+
info "#{env.method.upcase}: #{env.url.to_s}"
|
19
|
+
debug "REQUEST HEADERS:\n#{dump_headers env.request_headers}"
|
20
|
+
debug "REQUEST BODY:\n#{dump_body env[:body]}" if env[:body] && log_body?(:request)
|
21
|
+
super
|
22
|
+
end
|
23
|
+
|
24
|
+
def on_complete(env)
|
25
|
+
info "RESPONSE CODE: #{env.status.to_s}"
|
26
|
+
debug "ELAPSED TIME: #{Time.now - @start_time}"
|
27
|
+
debug "RESPONSE HEADERS:\n#{dump_headers env.response_headers}"
|
28
|
+
debug "RESPONSE BODY:\n#{dump_body env[:body]}" if env[:body] && log_body?(:response)
|
29
|
+
end
|
30
|
+
private
|
31
|
+
|
32
|
+
def dump_headers(headers)
|
33
|
+
headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def dump_body(body)
|
37
|
+
if body.respond_to?(:to_str)
|
38
|
+
body.to_str
|
39
|
+
else
|
40
|
+
pretty_inspect(body)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def log_body?(type)
|
45
|
+
case @options[:bodies]
|
46
|
+
when Hash then @options[:bodies][type]
|
47
|
+
else @options[:bodies]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
Faraday::Response.register_middleware :faraday_beaker_logger => lambda { Beaker::Http::FaradayBeakerLogger }
|
data/lib/beaker-http.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
require 'beaker'
|
6
|
+
|
7
|
+
require 'beaker-http/helpers/puppet_helpers'
|
8
|
+
require 'beaker-http/dsl/web_helpers'
|
9
|
+
require "beaker-http/http"
|
10
|
+
require 'beaker-http/middleware/response/faraday_beaker_logger'
|
@@ -0,0 +1,151 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class ClassMixedWithDSLWebHelpers
|
4
|
+
include Beaker::DSL::Helpers
|
5
|
+
|
6
|
+
attr_accessor :options
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@options = { logger: Beaker::Logger.new }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ClassMixedWithDSLWebHelpers do
|
14
|
+
|
15
|
+
describe '#generate_new_http_connection' do
|
16
|
+
|
17
|
+
it 'raises an argument error if a non Beaker::Host is supplied' do
|
18
|
+
expect{subject.generate_new_http_connection(Object.new)}.to raise_error(ArgumentError)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'raises no errors when no argument is supplied' do
|
22
|
+
expect{subject.generate_new_http_connection}.to_not raise_error
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'when passed a beaker host' do
|
26
|
+
unixhost = { roles: ['test_role'],
|
27
|
+
'platform' => 'debian-7-x86_64' }
|
28
|
+
let(:host) { Beaker::Host.create('test.com', unixhost, {}) }
|
29
|
+
let(:mock_options) { {:logger => Beaker::Logger.new} }
|
30
|
+
let(:mock_connection) {double('connection')}
|
31
|
+
|
32
|
+
it 'configures the connection object' do
|
33
|
+
expect(mock_connection).to receive(:configure_private_key_and_cert_with_puppet).with(host)
|
34
|
+
expect(Beaker::Http::Connection).to receive(:new).with(mock_options).and_return(mock_connection)
|
35
|
+
allow(host).to receive(:options).and_return(mock_options)
|
36
|
+
expect{subject.generate_new_http_connection(host)}.to_not raise_error
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
describe '#http_request' do
|
43
|
+
let (:url) {"http://wwww.test.com"}
|
44
|
+
let (:request_method) { :get }
|
45
|
+
let (:mock_response) {double('reponse')}
|
46
|
+
let (:mock_connection) { subject.generate_new_http_connection }
|
47
|
+
let (:read_timeout) {double('read_timeout')}
|
48
|
+
|
49
|
+
it 'sends a GET request to the url with the minimum required params' do
|
50
|
+
expect(mock_connection).to receive(:get).and_return(mock_response)
|
51
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
52
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
53
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
54
|
+
expect(subject.http_request(url, request_method)).to eq(mock_response)
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'send a DELETE request to the url with the minimum required params' do
|
58
|
+
let (:request_method) { :delete }
|
59
|
+
it 'sends a DELETE request to the url with the minimum required params' do
|
60
|
+
expect(mock_connection).to receive(:delete).and_return(mock_response)
|
61
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
62
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
63
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
64
|
+
expect(subject.http_request(url, request_method)).to eq(mock_response)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when the request_method is POST' do
|
69
|
+
let (:request_method) { :post }
|
70
|
+
let (:body) {double('body')}
|
71
|
+
let (:conn) { double('conn') }
|
72
|
+
|
73
|
+
it 'sends a body along in the request' do
|
74
|
+
expect(conn).to receive(:body=).with(body)
|
75
|
+
expect(mock_connection).to receive(:post).and_yield(conn).and_return(mock_response)
|
76
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
77
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
78
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
79
|
+
expect(subject.http_request(url, request_method, nil, nil, body, {})).to eq(mock_response)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
context 'when the request_method is PUT' do
|
85
|
+
let (:request_method) { :put }
|
86
|
+
let (:body) {double('body')}
|
87
|
+
let (:conn) { double('conn') }
|
88
|
+
|
89
|
+
it 'sends a body along in the request' do
|
90
|
+
expect(conn).to receive(:body=).with(body)
|
91
|
+
expect(mock_connection).to receive(:put).and_yield(conn).and_return(mock_response)
|
92
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
93
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
94
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
95
|
+
expect(subject.http_request(url, request_method, nil, nil, body, {})).to eq(mock_response)
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'can set the timeout from the options hash passed in' do
|
101
|
+
expect(mock_connection).to receive(:get).and_return(mock_response)
|
102
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
103
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
104
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
105
|
+
expect(subject.http_request(url, request_method, nil, nil, nil, :read_timeout => read_timeout)).to eq(mock_response)
|
106
|
+
expect(mock_connection.connection.options.timeout).to eq(read_timeout)
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'with a key and cert provided' do
|
110
|
+
let (:key) {'key'}
|
111
|
+
let (:cert) {'cert'}
|
112
|
+
it 'checks to ensure they are valid types and then adds them to the request' do
|
113
|
+
|
114
|
+
expect(mock_connection).to receive(:get).and_return(mock_response)
|
115
|
+
expect(key).to receive(:is_a?).with(OpenSSL::PKey::RSA).and_return(true)
|
116
|
+
expect(cert).to receive(:is_a?).with(OpenSSL::X509::Certificate).and_return(true)
|
117
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
118
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
119
|
+
|
120
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
121
|
+
|
122
|
+
expect(subject.http_request(url, request_method, cert, key)).to eq(mock_response)
|
123
|
+
expect(mock_connection.ssl['client_key']).to eq(key)
|
124
|
+
expect(mock_connection.ssl['client_cert']).to eq(cert)
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'errors when an invalid key is provided' do
|
128
|
+
expect(mock_connection).to_not receive(:get)
|
129
|
+
expect(key).to receive(:is_a?).with(OpenSSL::PKey::RSA).and_call_original
|
130
|
+
expect(cert).to receive(:is_a?).with(OpenSSL::X509::Certificate).and_return(true)
|
131
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
132
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
133
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
134
|
+
expect{subject.http_request(url, request_method, cert, key)}.to raise_error(TypeError)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'errors when an invalid cert is provided' do
|
138
|
+
expect(mock_connection).to_not receive(:get)
|
139
|
+
expect(key).to_not receive(:is_a?).with(OpenSSL::PKey::RSA)
|
140
|
+
expect(cert).to receive(:is_a?).with(OpenSSL::X509::Certificate).and_call_original
|
141
|
+
expect(URI).to receive(:parse).with(url).and_call_original
|
142
|
+
expect(mock_connection).to receive(:url_prefix=).and_call_original
|
143
|
+
expect(subject).to receive(:generate_new_http_connection).and_return(mock_connection)
|
144
|
+
expect{subject.http_request(url, request_method, cert, key)}.to raise_error(TypeError)
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Beaker
|
4
|
+
module Http
|
5
|
+
describe Connection do
|
6
|
+
|
7
|
+
let(:options) {{ :logger => Beaker::Logger.new}}
|
8
|
+
|
9
|
+
subject { Connection.new( options ) }
|
10
|
+
|
11
|
+
context 'with a beaker logger in the options passed in ' do
|
12
|
+
|
13
|
+
it 'does not raise errors' do
|
14
|
+
expect {subject}.to_not raise_error
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'sets a Faraday object as the instance connection object' do
|
18
|
+
expect(subject.connection).to be_instance_of(Faraday::Connection)
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'sets the middleware stack' do
|
22
|
+
expect(subject.connection.builder.handlers).to eq(HttpHelpers::DEFAULT_MIDDLEWARE_STACK)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'routes all http verbs to the connection object' do
|
26
|
+
http_verbs = [:get, :post, :put, :delete, :head, :patch]
|
27
|
+
|
28
|
+
http_verbs.each do |verb|
|
29
|
+
expect(subject.connection).to receive(verb)
|
30
|
+
subject.send(verb)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'routes other useful methods to the connection object' do
|
35
|
+
useful_methods = [:url_prefix, :url_prefix=, :ssl]
|
36
|
+
|
37
|
+
useful_methods.each do |method|
|
38
|
+
expect(subject.connection).to receive(method)
|
39
|
+
subject.send(method)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#remove_error_checking' do
|
44
|
+
it 'removes the faraday middleware raising errors on 4xx and 5xx requests' do
|
45
|
+
subject.remove_error_checking
|
46
|
+
expect(subject.connection.builder.handlers).not_to include(Faraday::Response::RaiseError)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with a beaker host passed in' do
|
51
|
+
unixhost = { roles: ['test_role'],
|
52
|
+
'platform' => 'debian-7-x86_64' }
|
53
|
+
let(:host) { Beaker::Host.create('test.com', unixhost, {}) }
|
54
|
+
|
55
|
+
describe '#configure_cacert_with_puppet'
|
56
|
+
it 'adds a ca_cert to the connection and changes the scheme to https' do
|
57
|
+
allow(subject).to receive(:get_host_cacert).with(host).and_return('ca_file')
|
58
|
+
subject.configure_cacert_with_puppet(host)
|
59
|
+
expect(subject.connection.ssl['ca_file']).to eq('ca_file')
|
60
|
+
expect(subject.connection.scheme).to eq('https')
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#configure_private_key_and_cert_with_puppet'
|
64
|
+
it 'calls #configure_cacert_only_with_puppet and adds the host private key and cert' do
|
65
|
+
allow(subject).to receive(:configure_cacert_with_puppet)
|
66
|
+
allow(subject).to receive(:get_host_private_key).with(host).and_return('private_key')
|
67
|
+
allow(subject).to receive(:get_host_cert).with(host).and_return('host_cert')
|
68
|
+
|
69
|
+
allow(OpenSSL::PKey).to receive(:read).with('private_key').and_return('ssl_private_key')
|
70
|
+
allow(OpenSSL::X509::Certificate).to receive(:new).with('host_cert').and_return('ssl_host_cert')
|
71
|
+
|
72
|
+
subject.configure_private_key_and_cert_with_puppet(host)
|
73
|
+
expect(subject.connection.ssl['client_key']).to eq('ssl_private_key')
|
74
|
+
expect(subject.connection.ssl['client_cert']).to eq('ssl_host_cert')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Beaker::Http::FaradayBeakerLogger do
|
4
|
+
|
5
|
+
let(:conn) { Faraday.new(:url => 'http://test.com/path') }
|
6
|
+
let (:logger) { Beaker::Logger.new }
|
7
|
+
|
8
|
+
context 'with log bodies turned off' do
|
9
|
+
|
10
|
+
before do
|
11
|
+
conn.builder.insert(0, Beaker::Http::FaradayBeakerLogger, logger, :bodies => false)
|
12
|
+
conn.adapter :test do |stub|
|
13
|
+
stub.get('/path') {[200, {}, 'success']}
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'sends info and debug requests to the logger' do
|
18
|
+
expect(logger).to receive(:info).with('GET: http://test.com/path').once
|
19
|
+
expect(logger).to receive(:info).with(/RESPONSE CODE: 200/).once
|
20
|
+
expect(logger).to receive(:debug).with(/ELAPSED TIME:/).once
|
21
|
+
expect(logger).to receive(:debug).with(/REQUEST HEADERS:/).once
|
22
|
+
expect(logger).to receive(:debug).with(/RESPONSE HEADERS:/).once
|
23
|
+
expect(logger).to_not receive(:debug).with(/RESPONSE BODY:/)
|
24
|
+
expect(logger).to_not receive(:debug).with(/REQUEST BODY:/)
|
25
|
+
conn.get
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context 'with log bodies turned on' do
|
30
|
+
|
31
|
+
before do
|
32
|
+
conn.builder.insert(0, Beaker::Http::FaradayBeakerLogger, logger, :bodies => true)
|
33
|
+
conn.adapter :test do |stub|
|
34
|
+
stub.post('/path') {[201, {}, 'success']}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'sends extra debug requests to the logger' do
|
39
|
+
expect(logger).to receive(:info).with('POST: http://test.com/path').once
|
40
|
+
expect(logger).to receive(:info).with(/RESPONSE CODE: 201/).once
|
41
|
+
expect(logger).to receive(:debug).with(/ELAPSED TIME:/).once
|
42
|
+
expect(logger).to receive(:debug).with(/RESPONSE BODY:\nsuccess/).once
|
43
|
+
expect(logger).to receive(:debug).with(/REQUEST BODY:\nBODY MOVIN'/).once
|
44
|
+
expect(logger).to receive(:debug).with(/REQUEST HEADERS:/).once
|
45
|
+
expect(logger).to receive(:debug).with(/RESPONSE HEADERS:/).once
|
46
|
+
conn.post() { |connection| connection.body = "BODY MOVIN'" }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'beaker-http'
|
2
|
+
|
3
|
+
module HttpHelpers
|
4
|
+
DEFAULT_MIDDLEWARE_STACK = [FaradayMiddleware::EncodeJson,
|
5
|
+
FaradayMiddleware::FollowRedirects,
|
6
|
+
Faraday::Response::RaiseError,
|
7
|
+
FaradayMiddleware::ParseJson,
|
8
|
+
Beaker::Http::FaradayBeakerLogger,
|
9
|
+
Faraday::Adapter::NetHttp]
|
10
|
+
end
|
metadata
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: beaker-http
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Puppet
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-10-25 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.6'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.9.12
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.9.12
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.0.0
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 3.0.0
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: yard
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: markdown
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activesupport
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 4.2.6
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: 4.2.6
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: json
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '1.8'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '1.8'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: beaker
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: faraday
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.9'
|
146
|
+
- - ">="
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: 0.9.1
|
149
|
+
type: :runtime
|
150
|
+
prerelease: false
|
151
|
+
version_requirements: !ruby/object:Gem::Requirement
|
152
|
+
requirements:
|
153
|
+
- - "~>"
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0.9'
|
156
|
+
- - ">="
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: 0.9.1
|
159
|
+
- !ruby/object:Gem::Dependency
|
160
|
+
name: faraday_middleware
|
161
|
+
requirement: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - "~>"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0.9'
|
166
|
+
type: :runtime
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - "~>"
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: '0.9'
|
173
|
+
description: Puppet testing tool coupled with Beaker
|
174
|
+
email:
|
175
|
+
- qe@puppet.com
|
176
|
+
executables: []
|
177
|
+
extensions: []
|
178
|
+
extra_rdoc_files: []
|
179
|
+
files:
|
180
|
+
- Gemfile
|
181
|
+
- README.md
|
182
|
+
- Rakefile
|
183
|
+
- acceptance/tests/puppetserver_requests.rb
|
184
|
+
- beaker-http.gemspec
|
185
|
+
- lib/beaker-http.rb
|
186
|
+
- lib/beaker-http/dsl/web_helpers.rb
|
187
|
+
- lib/beaker-http/helpers/puppet_helpers.rb
|
188
|
+
- lib/beaker-http/http.rb
|
189
|
+
- lib/beaker-http/middleware/response/faraday_beaker_logger.rb
|
190
|
+
- lib/beaker-http/version.rb
|
191
|
+
- spec/beaker-http/dsl/web_helpers_spec.rb
|
192
|
+
- spec/beaker-http/http_spec.rb
|
193
|
+
- spec/beaker-http/middleware/response/faraday_beaker_logger_spec.rb
|
194
|
+
- spec/spec_helper.rb
|
195
|
+
homepage: https://github.com/puppetlabs/beaker-http
|
196
|
+
licenses: []
|
197
|
+
metadata: {}
|
198
|
+
post_install_message:
|
199
|
+
rdoc_options: []
|
200
|
+
require_paths:
|
201
|
+
- lib
|
202
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
203
|
+
requirements:
|
204
|
+
- - ">="
|
205
|
+
- !ruby/object:Gem::Version
|
206
|
+
version: '0'
|
207
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
208
|
+
requirements:
|
209
|
+
- - ">="
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
212
|
+
requirements: []
|
213
|
+
rubyforge_project:
|
214
|
+
rubygems_version: 2.5.1
|
215
|
+
signing_key:
|
216
|
+
specification_version: 4
|
217
|
+
summary: Puppet testing tool
|
218
|
+
test_files:
|
219
|
+
- spec/beaker-http/dsl/web_helpers_spec.rb
|
220
|
+
- spec/beaker-http/http_spec.rb
|
221
|
+
- spec/beaker-http/middleware/response/faraday_beaker_logger_spec.rb
|
222
|
+
- spec/spec_helper.rb
|
223
|
+
has_rdoc:
|