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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +494 -0
  3. data/Gemfile +8 -0
  4. data/LICENSE.txt +22 -0
  5. data/README.md +137 -0
  6. data/bin/pact-mock-service +3 -0
  7. data/bin/pact-stub-service +3 -0
  8. data/lib/pact/consumer/mock_service/cors_origin_header_middleware.rb +31 -0
  9. data/lib/pact/consumer/mock_service/error_handler.rb +31 -0
  10. data/lib/pact/consumer/mock_service/rack_request_helper.rb +65 -0
  11. data/lib/pact/consumer/mock_service/set_location.rb +28 -0
  12. data/lib/pact/consumer/server.rb +111 -0
  13. data/lib/pact/consumer_contract/consumer_contract_decorator.rb +53 -0
  14. data/lib/pact/consumer_contract/consumer_contract_writer.rb +181 -0
  15. data/lib/pact/consumer_contract/interaction_decorator.rb +40 -0
  16. data/lib/pact/consumer_contract/request_decorator.rb +88 -0
  17. data/lib/pact/consumer_contract/response_decorator.rb +47 -0
  18. data/lib/pact/mock_service/app.rb +85 -0
  19. data/lib/pact/mock_service/app_manager.rb +156 -0
  20. data/lib/pact/mock_service/cli/custom_thor.rb +74 -0
  21. data/lib/pact/mock_service/cli/pidfile.rb +99 -0
  22. data/lib/pact/mock_service/cli.rb +213 -0
  23. data/lib/pact/mock_service/client.rb +79 -0
  24. data/lib/pact/mock_service/control_server/app.rb +42 -0
  25. data/lib/pact/mock_service/control_server/delegator.rb +44 -0
  26. data/lib/pact/mock_service/control_server/index.rb +25 -0
  27. data/lib/pact/mock_service/control_server/mock_service_creator.rb +32 -0
  28. data/lib/pact/mock_service/control_server/mock_services.rb +26 -0
  29. data/lib/pact/mock_service/control_server/require_pacticipant_headers.rb +20 -0
  30. data/lib/pact/mock_service/control_server/run.rb +73 -0
  31. data/lib/pact/mock_service/errors.rb +9 -0
  32. data/lib/pact/mock_service/interaction_decorator.rb +49 -0
  33. data/lib/pact/mock_service/interactions/actual_interactions.rb +36 -0
  34. data/lib/pact/mock_service/interactions/candidate_interactions.rb +15 -0
  35. data/lib/pact/mock_service/interactions/expected_interactions.rb +18 -0
  36. data/lib/pact/mock_service/interactions/interaction_diff_message.rb +45 -0
  37. data/lib/pact/mock_service/interactions/interaction_mismatch.rb +74 -0
  38. data/lib/pact/mock_service/interactions/interactions_filter.rb +66 -0
  39. data/lib/pact/mock_service/interactions/verification.rb +52 -0
  40. data/lib/pact/mock_service/interactions/verified_interactions.rb +20 -0
  41. data/lib/pact/mock_service/logger.rb +40 -0
  42. data/lib/pact/mock_service/request_decorator.rb +36 -0
  43. data/lib/pact/mock_service/request_handlers/base_administration_request_handler.rb +42 -0
  44. data/lib/pact/mock_service/request_handlers/base_request_handler.rb +30 -0
  45. data/lib/pact/mock_service/request_handlers/index_get.rb +23 -0
  46. data/lib/pact/mock_service/request_handlers/interaction_delete.rb +38 -0
  47. data/lib/pact/mock_service/request_handlers/interaction_post.rb +43 -0
  48. data/lib/pact/mock_service/request_handlers/interaction_replay.rb +191 -0
  49. data/lib/pact/mock_service/request_handlers/interactions_put.rb +44 -0
  50. data/lib/pact/mock_service/request_handlers/log_get.rb +27 -0
  51. data/lib/pact/mock_service/request_handlers/missing_interactions_get.rb +33 -0
  52. data/lib/pact/mock_service/request_handlers/options.rb +64 -0
  53. data/lib/pact/mock_service/request_handlers/pact_post.rb +38 -0
  54. data/lib/pact/mock_service/request_handlers/session_delete.rb +32 -0
  55. data/lib/pact/mock_service/request_handlers/verification_get.rb +74 -0
  56. data/lib/pact/mock_service/request_handlers.rb +42 -0
  57. data/lib/pact/mock_service/response_decorator.rb +31 -0
  58. data/lib/pact/mock_service/run.rb +125 -0
  59. data/lib/pact/mock_service/server/respawn.rb +20 -0
  60. data/lib/pact/mock_service/server/spawn.rb +37 -0
  61. data/lib/pact/mock_service/server/wait_for_server_up.rb +44 -0
  62. data/lib/pact/mock_service/server/webrick_request_monkeypatch.rb +15 -0
  63. data/lib/pact/mock_service/session.rb +96 -0
  64. data/lib/pact/mock_service/spawn.rb +86 -0
  65. data/lib/pact/mock_service/version.rb +5 -0
  66. data/lib/pact/mock_service.rb +2 -0
  67. data/lib/pact/stub_service/cli.rb +71 -0
  68. data/lib/pact/support/expand_file_list.rb +26 -0
  69. 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