hs-pact-mock_service 3.9.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +494 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +22 -0
- data/README.md +137 -0
- data/bin/pact-mock-service +3 -0
- data/bin/pact-stub-service +3 -0
- data/lib/pact/consumer/mock_service/cors_origin_header_middleware.rb +31 -0
- data/lib/pact/consumer/mock_service/error_handler.rb +31 -0
- data/lib/pact/consumer/mock_service/rack_request_helper.rb +65 -0
- data/lib/pact/consumer/mock_service/set_location.rb +28 -0
- data/lib/pact/consumer/server.rb +111 -0
- data/lib/pact/consumer_contract/consumer_contract_decorator.rb +53 -0
- data/lib/pact/consumer_contract/consumer_contract_writer.rb +181 -0
- data/lib/pact/consumer_contract/interaction_decorator.rb +40 -0
- data/lib/pact/consumer_contract/request_decorator.rb +88 -0
- data/lib/pact/consumer_contract/response_decorator.rb +47 -0
- data/lib/pact/mock_service/app.rb +85 -0
- data/lib/pact/mock_service/app_manager.rb +156 -0
- data/lib/pact/mock_service/cli/custom_thor.rb +74 -0
- data/lib/pact/mock_service/cli/pidfile.rb +99 -0
- data/lib/pact/mock_service/cli.rb +213 -0
- data/lib/pact/mock_service/client.rb +79 -0
- data/lib/pact/mock_service/control_server/app.rb +42 -0
- data/lib/pact/mock_service/control_server/delegator.rb +44 -0
- data/lib/pact/mock_service/control_server/index.rb +25 -0
- data/lib/pact/mock_service/control_server/mock_service_creator.rb +32 -0
- data/lib/pact/mock_service/control_server/mock_services.rb +26 -0
- data/lib/pact/mock_service/control_server/require_pacticipant_headers.rb +20 -0
- data/lib/pact/mock_service/control_server/run.rb +73 -0
- data/lib/pact/mock_service/errors.rb +9 -0
- data/lib/pact/mock_service/interaction_decorator.rb +49 -0
- data/lib/pact/mock_service/interactions/actual_interactions.rb +36 -0
- data/lib/pact/mock_service/interactions/candidate_interactions.rb +15 -0
- data/lib/pact/mock_service/interactions/expected_interactions.rb +18 -0
- data/lib/pact/mock_service/interactions/interaction_diff_message.rb +45 -0
- data/lib/pact/mock_service/interactions/interaction_mismatch.rb +74 -0
- data/lib/pact/mock_service/interactions/interactions_filter.rb +66 -0
- data/lib/pact/mock_service/interactions/verification.rb +52 -0
- data/lib/pact/mock_service/interactions/verified_interactions.rb +20 -0
- data/lib/pact/mock_service/logger.rb +40 -0
- data/lib/pact/mock_service/request_decorator.rb +36 -0
- data/lib/pact/mock_service/request_handlers/base_administration_request_handler.rb +42 -0
- data/lib/pact/mock_service/request_handlers/base_request_handler.rb +30 -0
- data/lib/pact/mock_service/request_handlers/index_get.rb +23 -0
- data/lib/pact/mock_service/request_handlers/interaction_delete.rb +38 -0
- data/lib/pact/mock_service/request_handlers/interaction_post.rb +43 -0
- data/lib/pact/mock_service/request_handlers/interaction_replay.rb +191 -0
- data/lib/pact/mock_service/request_handlers/interactions_put.rb +44 -0
- data/lib/pact/mock_service/request_handlers/log_get.rb +27 -0
- data/lib/pact/mock_service/request_handlers/missing_interactions_get.rb +33 -0
- data/lib/pact/mock_service/request_handlers/options.rb +64 -0
- data/lib/pact/mock_service/request_handlers/pact_post.rb +38 -0
- data/lib/pact/mock_service/request_handlers/session_delete.rb +32 -0
- data/lib/pact/mock_service/request_handlers/verification_get.rb +74 -0
- data/lib/pact/mock_service/request_handlers.rb +42 -0
- data/lib/pact/mock_service/response_decorator.rb +31 -0
- data/lib/pact/mock_service/run.rb +125 -0
- data/lib/pact/mock_service/server/respawn.rb +20 -0
- data/lib/pact/mock_service/server/spawn.rb +37 -0
- data/lib/pact/mock_service/server/wait_for_server_up.rb +44 -0
- data/lib/pact/mock_service/server/webrick_request_monkeypatch.rb +15 -0
- data/lib/pact/mock_service/session.rb +96 -0
- data/lib/pact/mock_service/spawn.rb +86 -0
- data/lib/pact/mock_service/version.rb +5 -0
- data/lib/pact/mock_service.rb +2 -0
- data/lib/pact/stub_service/cli.rb +71 -0
- data/lib/pact/support/expand_file_list.rb +26 -0
- metadata +399 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require 'pact/mock_service/logger'
|
5
|
+
require 'pact/consumer/mock_service/cors_origin_header_middleware'
|
6
|
+
require 'pact/mock_service/request_handlers'
|
7
|
+
require 'pact/consumer/mock_service/error_handler'
|
8
|
+
require 'pact/mock_service/session'
|
9
|
+
|
10
|
+
module Pact
|
11
|
+
module MockService
|
12
|
+
|
13
|
+
def self.new *args
|
14
|
+
App.new(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
class App
|
18
|
+
def initialize options = {}
|
19
|
+
logger = Logger.from_options(options)
|
20
|
+
@options = options
|
21
|
+
stubbing = options[:stub_pactfile_paths] && options[:stub_pactfile_paths].any?
|
22
|
+
@name = options.fetch(:name, "MockService")
|
23
|
+
@session = Session.new(options.merge(logger: logger, warn_on_too_many_interactions: !stubbing))
|
24
|
+
setup_stub(options[:stub_pactfile_paths]) if stubbing
|
25
|
+
request_handlers = RequestHandlers.new(@name, logger, @session, options)
|
26
|
+
@app = Rack::Builder.app do
|
27
|
+
use Pact::Consumer::MockService::ErrorHandler, logger
|
28
|
+
use Pact::Consumer::CorsOriginHeaderMiddleware, options[:cors_enabled]
|
29
|
+
run request_handlers
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def call env
|
34
|
+
@app.call env
|
35
|
+
end
|
36
|
+
|
37
|
+
def shutdown
|
38
|
+
write_pact_if_configured
|
39
|
+
end
|
40
|
+
|
41
|
+
def setup_stub stub_pactfile_paths
|
42
|
+
interactions = stub_pactfile_paths.collect do | pactfile_path |
|
43
|
+
$stdout.puts "INFO: Loading interactions from #{pactfile_path}"
|
44
|
+
hash_interactions = JSON.parse(Pact::PactFile.read(pactfile_path, pactfile_options))['interactions']
|
45
|
+
hash_interactions.collect { | hash | Interaction.from_hash(hash) }
|
46
|
+
end.flatten
|
47
|
+
@session.set_expected_interactions interactions
|
48
|
+
end
|
49
|
+
|
50
|
+
def write_pact_if_configured
|
51
|
+
consumer_contract_writer = ConsumerContractWriter.new(@session.consumer_contract_details, StdoutLogger.new)
|
52
|
+
if consumer_contract_writer.can_write? && !@session.pact_written?
|
53
|
+
$stdout.puts "INFO: Writing pact before shutting down"
|
54
|
+
consumer_contract_writer.write
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
"#{@name} #{super.to_s}"
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def pactfile_options
|
65
|
+
{
|
66
|
+
:token => broker_token,
|
67
|
+
:username => @options[:broker_username],
|
68
|
+
:password => @options[:broker_password],
|
69
|
+
}
|
70
|
+
end
|
71
|
+
|
72
|
+
def broker_token
|
73
|
+
@options[:broker_token] || ENV['PACT_BROKER_TOKEN']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Can't write to a file in a TRAP, might deadlock
|
78
|
+
# Not sure why we can still write to the pact file though
|
79
|
+
class StdoutLogger
|
80
|
+
def info message
|
81
|
+
$stdout.puts "\n#{message}"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'pact/logging'
|
4
|
+
require 'pact/consumer/server'
|
5
|
+
require 'singleton'
|
6
|
+
require 'pact/mock_service/app'
|
7
|
+
|
8
|
+
module Pact
|
9
|
+
module MockService
|
10
|
+
class AppManager
|
11
|
+
|
12
|
+
include Pact::Logging
|
13
|
+
|
14
|
+
include Singleton
|
15
|
+
|
16
|
+
def initialize
|
17
|
+
@apps_spawned = false
|
18
|
+
@app_registrations = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def register_mock_service_for(name, url, options = {})
|
22
|
+
uri = URI(url)
|
23
|
+
raise "Currently only http is supported" unless uri.scheme == 'http'
|
24
|
+
uri.port = nil if options[:find_available_port]
|
25
|
+
|
26
|
+
app = Pact::MockService.new(
|
27
|
+
name: name,
|
28
|
+
log_file: create_log_file(name),
|
29
|
+
pact_dir: pact_dir,
|
30
|
+
pact_specification_version: options.fetch(:pact_specification_version)
|
31
|
+
)
|
32
|
+
register(app, uri.host, uri.port)
|
33
|
+
end
|
34
|
+
|
35
|
+
def register(app, host, port = nil)
|
36
|
+
if port
|
37
|
+
existing = existing_app_on_host_and_port(host, port)
|
38
|
+
raise "Port #{port} is already being used by #{existing}" if existing and not existing == app
|
39
|
+
end
|
40
|
+
app_registration = register_app(app, host, port)
|
41
|
+
app_registration.spawn
|
42
|
+
app_registration.port
|
43
|
+
end
|
44
|
+
|
45
|
+
def urls_of_mock_services
|
46
|
+
app_registrations.find_all(&:is_a_mock_service?).collect{ |ar| "http://#{ar.host}:#{ar.port}" }
|
47
|
+
end
|
48
|
+
|
49
|
+
def kill_all
|
50
|
+
app_registrations.find_all(&:spawned?).collect(&:kill)
|
51
|
+
@apps_spawned = false
|
52
|
+
end
|
53
|
+
|
54
|
+
def clear_all
|
55
|
+
kill_all
|
56
|
+
@app_registrations = []
|
57
|
+
end
|
58
|
+
|
59
|
+
def spawn_all
|
60
|
+
app_registrations.find_all(&:not_spawned?).collect(&:spawn)
|
61
|
+
@apps_spawned = true
|
62
|
+
end
|
63
|
+
|
64
|
+
def app_registered_on?(port)
|
65
|
+
app_registrations.any? { |app_registration| app_registration.port == port }
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def existing_app_on_host_and_port(host, port)
|
71
|
+
app_registration = registration_on_host_and_port(host, port)
|
72
|
+
app_registration ? app_registration.app : nil
|
73
|
+
end
|
74
|
+
|
75
|
+
def registration_on_host_and_port(host, port)
|
76
|
+
@app_registrations.find { |app_registration| app_registration.port == port && app_registration.host == host }
|
77
|
+
end
|
78
|
+
|
79
|
+
def pact_dir
|
80
|
+
Pact.configuration.pact_dir
|
81
|
+
end
|
82
|
+
|
83
|
+
def create_log_file(service_name)
|
84
|
+
FileUtils::mkdir_p(Pact.configuration.log_dir)
|
85
|
+
log = File.open(log_file_path(service_name), 'w')
|
86
|
+
log.sync = true
|
87
|
+
log
|
88
|
+
end
|
89
|
+
|
90
|
+
def log_file_path(service_name)
|
91
|
+
File.join(Pact.configuration.log_dir, "#{log_file_name(service_name)}.log")
|
92
|
+
end
|
93
|
+
|
94
|
+
def log_file_name(service_name)
|
95
|
+
lower_case_name = service_name.downcase.gsub(/\s+/, '_')
|
96
|
+
if lower_case_name.include?('_service')
|
97
|
+
lower_case_name.gsub('_service', '_mock_service')
|
98
|
+
else
|
99
|
+
lower_case_name + '_mock_service'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def app_registrations
|
104
|
+
@app_registrations
|
105
|
+
end
|
106
|
+
|
107
|
+
def register_app(app, host, port)
|
108
|
+
app_registration = AppRegistration.new(app: app, host: host, port: port)
|
109
|
+
app_registrations << app_registration
|
110
|
+
app_registration
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
class AppRegistration
|
115
|
+
include Pact::Logging
|
116
|
+
attr_accessor :host, :port, :app
|
117
|
+
|
118
|
+
def initialize(opts)
|
119
|
+
@max_wait = 10
|
120
|
+
@port = opts[:port]
|
121
|
+
@host = opts[:host]
|
122
|
+
@app = opts[:app]
|
123
|
+
@spawned = false
|
124
|
+
end
|
125
|
+
|
126
|
+
def kill
|
127
|
+
logger.debug "Supposed to be stopping"
|
128
|
+
@spawned = false
|
129
|
+
end
|
130
|
+
|
131
|
+
def not_spawned?
|
132
|
+
!spawned?
|
133
|
+
end
|
134
|
+
|
135
|
+
def spawned?
|
136
|
+
@spawned
|
137
|
+
end
|
138
|
+
|
139
|
+
def is_a_mock_service?
|
140
|
+
app.is_a?(Pact::MockService::App)
|
141
|
+
end
|
142
|
+
|
143
|
+
def to_s
|
144
|
+
"#{app} on port #{port}"
|
145
|
+
end
|
146
|
+
|
147
|
+
def spawn
|
148
|
+
logger.info "Starting app #{self}..."
|
149
|
+
@server = Pact::Server.new(app, host, port).boot
|
150
|
+
@port = @server.port
|
151
|
+
@spawned = true
|
152
|
+
logger.info "Started on port #{port}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module MockService
|
5
|
+
class CLI < Thor
|
6
|
+
##
|
7
|
+
# Custom Thor task allows the following:
|
8
|
+
#
|
9
|
+
# `script arg1 arg2` to be interpreted as `script <default_task> arg1 arg2`
|
10
|
+
# `--option 1 --option 2` to be interpreted as `--option 1 2` (the standard Thor format for multiple value options)
|
11
|
+
# `script --help` to display the help for the default task instead of the command list
|
12
|
+
#
|
13
|
+
class CustomThor < ::Thor
|
14
|
+
def self.exit_on_failure? # Thor 1.0 deprecation guard
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
no_commands do
|
19
|
+
def self.start given_args = ARGV, config = {}
|
20
|
+
super(massage_args(given_args))
|
21
|
+
end
|
22
|
+
|
23
|
+
def help *args
|
24
|
+
if args.empty?
|
25
|
+
super(self.class.default_task)
|
26
|
+
else
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.massage_args argv
|
32
|
+
prepend_default_task_name(turn_muliple_tag_options_into_array(argv))
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.prepend_default_task_name argv
|
36
|
+
if known_first_arguments.include?(argv[0])
|
37
|
+
argv
|
38
|
+
else
|
39
|
+
[default_command] + argv
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# other task names, help, and the help shortcuts
|
44
|
+
def self.known_first_arguments
|
45
|
+
@known_first_arguments ||= tasks.keys + ::Thor::HELP_MAPPINGS + ['help']
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.turn_muliple_tag_options_into_array argv
|
49
|
+
new_argv = []
|
50
|
+
opt_name = nil
|
51
|
+
argv.each_with_index do | arg, i |
|
52
|
+
if arg.start_with?('-')
|
53
|
+
opt_name = arg
|
54
|
+
existing = new_argv.find { | a | a.first == opt_name }
|
55
|
+
if !existing
|
56
|
+
new_argv << [arg]
|
57
|
+
end
|
58
|
+
else
|
59
|
+
if opt_name
|
60
|
+
existing = new_argv.find { | a | a.first == opt_name }
|
61
|
+
existing << arg
|
62
|
+
opt_name = nil
|
63
|
+
else
|
64
|
+
new_argv << [arg]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
new_argv.flatten
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module MockService
|
5
|
+
class CLI < Thor
|
6
|
+
def self.exit_on_failure? # Thor 1.0 deprecation guard
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
class Pidfile
|
11
|
+
attr_accessor :pid_dir, :name, :pid
|
12
|
+
|
13
|
+
def initialize options
|
14
|
+
@pid_dir = options[:pid_dir] || 'tmp/pids'
|
15
|
+
@name = options[:name] || default_name
|
16
|
+
@pid = options[:pid] || Process.pid
|
17
|
+
end
|
18
|
+
|
19
|
+
def file_exists?
|
20
|
+
File.exist?(pidfile_path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def process_running?
|
24
|
+
process_exists? pid_from_file
|
25
|
+
end
|
26
|
+
|
27
|
+
def pidfile_path
|
28
|
+
File.join(pid_dir, name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def pid_from_file
|
32
|
+
File.read(pidfile_path).to_i
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_name
|
36
|
+
File.basename($0, File.extname($0)) + ".pid"
|
37
|
+
end
|
38
|
+
|
39
|
+
def process_exists? pid
|
40
|
+
Process.kill 0, pid
|
41
|
+
true
|
42
|
+
rescue Errno::ESRCH
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def file_exists_and_process_running?
|
47
|
+
file_exists? && process_running?
|
48
|
+
end
|
49
|
+
|
50
|
+
def can_start?
|
51
|
+
if file_exists? && process_running?
|
52
|
+
$stderr.puts "Server already running."
|
53
|
+
false
|
54
|
+
elsif file_exists?
|
55
|
+
$stderr.puts "WARN: PID file #{pidfile_path} already exists, but process is not running. Overwriting pidfile."
|
56
|
+
true
|
57
|
+
else
|
58
|
+
true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def write
|
63
|
+
FileUtils.mkdir_p pid_dir
|
64
|
+
File.open(pidfile_path, "w") { |file| file << pid }
|
65
|
+
end
|
66
|
+
|
67
|
+
def delete
|
68
|
+
FileUtils.rm pidfile_path
|
69
|
+
end
|
70
|
+
|
71
|
+
def waitpid
|
72
|
+
tries = 0
|
73
|
+
sleep_time = 0.1
|
74
|
+
while process_running? && tries < 100
|
75
|
+
sleep sleep_time
|
76
|
+
tries += 1
|
77
|
+
end
|
78
|
+
raise "Process #{pid_from_file} not stopped after {100 * sleep_time} seconds." if process_running?
|
79
|
+
end
|
80
|
+
|
81
|
+
def kill_process
|
82
|
+
if file_exists?
|
83
|
+
begin
|
84
|
+
`ps -ef | grep pact`
|
85
|
+
Process.kill 2, pid_from_file
|
86
|
+
waitpid
|
87
|
+
delete
|
88
|
+
rescue Errno::ESRCH
|
89
|
+
$stderr.puts "Process in PID file #{pidfile_path} not running. Deleting PID file."
|
90
|
+
delete
|
91
|
+
end
|
92
|
+
else
|
93
|
+
$stderr.puts "No PID file found at #{pidfile_path}, server probably not running. Use `ps -ef | grep pact` if you suspect the process is still running."
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,213 @@
|
|
1
|
+
require 'thor'
|
2
|
+
|
3
|
+
module Pact
|
4
|
+
module MockService
|
5
|
+
class CLI < Thor
|
6
|
+
def self.exit_on_failure? # Thor 1.0 deprecation guard
|
7
|
+
false
|
8
|
+
end
|
9
|
+
|
10
|
+
PACT_FILE_WRITE_MODE_DESC = "`overwrite` or `merge`. Use `merge` when running multiple mock service instances in parallel for the same consumer/provider pair." +
|
11
|
+
" Ensure the pact file is deleted before running tests when using this option so that interactions deleted from the code are not maintained in the file."
|
12
|
+
|
13
|
+
desc 'service', "Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown (INT)."
|
14
|
+
method_option :consumer, desc: "Consumer name"
|
15
|
+
method_option :provider, desc: "Provider name"
|
16
|
+
method_option :port, aliases: "-p", desc: "Port on which to run the service"
|
17
|
+
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
18
|
+
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written"
|
19
|
+
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
20
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
21
|
+
method_option :log, aliases: "-l", desc: "File to which to log output"
|
22
|
+
method_option :log_level, desc: "Log level. Options are DEBUG INFO WARN ERROR", default: "DEBUG"
|
23
|
+
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
24
|
+
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
25
|
+
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
26
|
+
method_option :sslkey, desc: "Specify the path to the SSL key to use when running the service over HTTPS"
|
27
|
+
method_option :monkeypatch, hide: true
|
28
|
+
|
29
|
+
def service
|
30
|
+
require_common_dependencies
|
31
|
+
require 'pact/mock_service/run'
|
32
|
+
Run.(options)
|
33
|
+
end
|
34
|
+
|
35
|
+
desc 'control', "Run a Pact mock service control server."
|
36
|
+
method_option :port, aliases: "-p", desc: "Port on which to run the service"
|
37
|
+
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
38
|
+
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written"
|
39
|
+
method_option :log_dir, aliases: "-l", desc: "File to which to log output"
|
40
|
+
method_option :log_level, desc: "Log level. Options are DEBUG INFO WARN ERROR", default: "DEBUG"
|
41
|
+
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
42
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
43
|
+
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
44
|
+
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
45
|
+
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
46
|
+
method_option :sslkey, desc: "Specify the path to the SSL key to use when running the service over HTTPS"
|
47
|
+
|
48
|
+
def control
|
49
|
+
require_common_dependencies
|
50
|
+
require 'pact/mock_service/control_server/run'
|
51
|
+
ControlServer::Run.(options)
|
52
|
+
end
|
53
|
+
|
54
|
+
desc 'start', "Start a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown (INT)."
|
55
|
+
method_option :consumer, desc: "Consumer name"
|
56
|
+
method_option :provider, desc: "Provider name"
|
57
|
+
method_option :port, aliases: "-p", default: '1234', desc: "Port on which to run the service"
|
58
|
+
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
59
|
+
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written"
|
60
|
+
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
61
|
+
method_option :pid_dir, desc: "PID dir", default: 'tmp/pids'
|
62
|
+
method_option :log, aliases: "-l", desc: "File to which to log output"
|
63
|
+
method_option :log_level, desc: "Log level. Options are DEBUG INFO WARN ERROR", default: "DEBUG"
|
64
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
65
|
+
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
66
|
+
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
67
|
+
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
68
|
+
method_option :sslkey, desc: "Specify the path to the SSL key to use when running the service over HTTPS"
|
69
|
+
method_option :monkeypatch, hide: true
|
70
|
+
|
71
|
+
def start
|
72
|
+
require_common_dependencies
|
73
|
+
start_server(mock_service_pidfile) do
|
74
|
+
service
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
desc 'stop', "Stop a Pact mock service"
|
79
|
+
method_option :port, aliases: "-p", desc: "Port of the service to stop", default: '1234', required: true
|
80
|
+
method_option :pid_dir, desc: "PID dir, defaults to tmp/pids", default: "tmp/pids"
|
81
|
+
|
82
|
+
def stop
|
83
|
+
require_common_dependencies
|
84
|
+
mock_service_pidfile.kill_process
|
85
|
+
end
|
86
|
+
|
87
|
+
desc 'restart', "Start or restart a mock service. If the consumer, provider and pact-dir options are provided, the pact will be written automatically on shutdown (INT)."
|
88
|
+
method_option :consumer, desc: "Consumer name"
|
89
|
+
method_option :provider, desc: "Provider name"
|
90
|
+
method_option :port, aliases: "-p", default: '1234', desc: "Port on which to run the service"
|
91
|
+
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
92
|
+
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written"
|
93
|
+
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
94
|
+
method_option :pid_dir, desc: "PID dir", default: 'tmp/pids'
|
95
|
+
method_option :log, aliases: "-l", desc: "File to which to log output"
|
96
|
+
method_option :log_level, desc: "Log level. Options are DEBUG INFO WARN ERROR", default: "DEBUG"
|
97
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
98
|
+
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
99
|
+
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
100
|
+
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
101
|
+
method_option :sslkey, desc: "Specify the path to the SSL key to use when running the service over HTTPS"
|
102
|
+
|
103
|
+
def restart
|
104
|
+
require_common_dependencies
|
105
|
+
restart_server(mock_service_pidfile) do
|
106
|
+
service
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
desc 'control-start', "Start a Pact mock service control server."
|
111
|
+
method_option :port, aliases: "-p", desc: "Port on which to run the service", default: '1234'
|
112
|
+
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
113
|
+
method_option :log_dir, aliases: "-l", desc: "File to which to log output", default: "log"
|
114
|
+
method_option :log_level, desc: "Log level. Options are DEBUG INFO WARN ERROR", default: "DEBUG"
|
115
|
+
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
116
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact", default: '2'
|
117
|
+
method_option :pid_dir, desc: "PID dir", default: "tmp/pids"
|
118
|
+
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
119
|
+
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
120
|
+
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
121
|
+
method_option :sslkey, desc: "Specify the path to the SSL key to use when running the service over HTTPS"
|
122
|
+
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written", default: "."
|
123
|
+
|
124
|
+
def control_start
|
125
|
+
require_common_dependencies
|
126
|
+
start_server(control_server_pidfile) do
|
127
|
+
control
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
desc 'control-stop', "Stop a Pact mock service control server."
|
132
|
+
method_option :port, aliases: "-p", desc: "Port of control server to stop", default: "1234"
|
133
|
+
method_option :pid_dir, desc: "PID dir, defaults to tmp/pids", default: "tmp/pids"
|
134
|
+
|
135
|
+
def control_stop
|
136
|
+
require_common_dependencies
|
137
|
+
control_server_pidfile.kill_process
|
138
|
+
end
|
139
|
+
|
140
|
+
desc 'control-restart', "Start a Pact mock service control server."
|
141
|
+
method_option :port, aliases: "-p", desc: "Port on which to run the service", default: '1234'
|
142
|
+
method_option :host, aliases: "-h", desc: "Host on which to bind the service", default: 'localhost'
|
143
|
+
method_option :log_dir, aliases: "-l", desc: "File to which to log output", default: "log"
|
144
|
+
method_option :log_level, desc: "Log level. Options are DEBUG INFO WARN ERROR", default: "DEBUG"
|
145
|
+
method_option :pact_dir, aliases: "-d", desc: "Directory to which the pacts will be written", default: "."
|
146
|
+
method_option :pact_file_write_mode, aliases: "-m", desc: PACT_FILE_WRITE_MODE_DESC, type: :string, default: 'overwrite'
|
147
|
+
method_option :pact_specification_version, aliases: "-i", desc: "The pact specification version to use when writing the pact. Note that only versions 1 and 2 are currently supported.", default: '2'
|
148
|
+
method_option :pid_dir, desc: "PID dir", default: "tmp/pids"
|
149
|
+
method_option :cors, aliases: "-o", desc: "Support browser security in tests by responding to OPTIONS requests and adding CORS headers to mocked responses"
|
150
|
+
method_option :ssl, desc: "Use a self-signed SSL cert to run the service over HTTPS", type: :boolean, default: false
|
151
|
+
method_option :sslcert, desc: "Specify the path to the SSL cert to use when running the service over HTTPS"
|
152
|
+
method_option :sslkey, desc: "Specify the path to the SSL key to use when running the service over HTTPS"
|
153
|
+
|
154
|
+
def control_restart
|
155
|
+
require_common_dependencies
|
156
|
+
restart_server(control_server_pidfile) do
|
157
|
+
control
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
desc 'version', "Show the pact-mock-service gem version"
|
162
|
+
|
163
|
+
def version
|
164
|
+
require 'pact/mock_service/version.rb'
|
165
|
+
puts Pact::MockService::VERSION
|
166
|
+
end
|
167
|
+
|
168
|
+
default_task :service
|
169
|
+
|
170
|
+
no_commands do
|
171
|
+
|
172
|
+
def require_common_dependencies
|
173
|
+
require 'webrick/https'
|
174
|
+
require 'rack/handler/webrick'
|
175
|
+
require 'fileutils'
|
176
|
+
require 'pact/mock_service/server/wait_for_server_up'
|
177
|
+
require 'pact/mock_service/cli/pidfile'
|
178
|
+
require 'socket'
|
179
|
+
end
|
180
|
+
|
181
|
+
def control_server_pidfile
|
182
|
+
Pidfile.new(pid_dir: options[:pid_dir], name: control_pidfile_name)
|
183
|
+
end
|
184
|
+
|
185
|
+
def mock_service_pidfile
|
186
|
+
Pidfile.new(pid_dir: options[:pid_dir], name: mock_service_pidfile_name)
|
187
|
+
end
|
188
|
+
|
189
|
+
def mock_service_pidfile_name
|
190
|
+
"mock-service-#{options[:port]}.pid"
|
191
|
+
end
|
192
|
+
|
193
|
+
def control_pidfile_name
|
194
|
+
"mock-service-control-#{options[:port]}.pid"
|
195
|
+
end
|
196
|
+
|
197
|
+
def start_server pidfile
|
198
|
+
require 'pact/mock_service/server/spawn'
|
199
|
+
Pact::MockService::Server::Spawn.(pidfile, options[:host], options[:port], options[:ssl]) do
|
200
|
+
yield
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def restart_server pidfile
|
205
|
+
require 'pact/mock_service/server/respawn'
|
206
|
+
Pact::MockService::Server::Respawn.(pidfile, options[:host], options[:port], options[:ssl]) do
|
207
|
+
yield
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|