hs-pact-mock_service 3.9.2
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/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
|