pact_broker 2.81.0 → 2.82.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/test.yml +1 -1
- data/CHANGELOG.md +30 -0
- data/DEVELOPER_SETUP.md +1 -1
- data/README.md +7 -5
- data/config.ru +3 -28
- data/db/migrations/20210722_add_index_to_triggered_webhooks_webhook_uuid.rb +7 -0
- data/db/migrations/20210810_set_allow_contract_modification.rb +17 -0
- data/docs/CONFIGURATION.md +398 -0
- data/docs/configuration.yml +320 -0
- data/example/Gemfile +4 -4
- data/example/README.md +15 -22
- data/example/config.ru +1 -24
- data/example/config/pact_broker.yml +9 -0
- data/example/config/puma.rb +3 -0
- data/lib/db.rb +1 -1
- data/lib/pact_broker/api/authorization/resource_access_policy.rb +68 -0
- data/lib/pact_broker/api/authorization/resource_access_rules.rb +40 -0
- data/lib/pact_broker/api/decorators/deployed_version_decorator.rb +2 -0
- data/lib/pact_broker/api/decorators/released_version_decorator.rb +2 -0
- data/lib/pact_broker/api/middleware/basic_auth.rb +63 -0
- data/lib/pact_broker/api/resources/pact.rb +15 -6
- data/lib/pact_broker/api/resources/tag.rb +1 -14
- data/lib/pact_broker/app.rb +52 -30
- data/lib/pact_broker/config/basic_auth_configuration.rb +38 -0
- data/lib/pact_broker/config/load.rb +21 -10
- data/lib/pact_broker/config/runtime_configuration.rb +188 -0
- data/lib/pact_broker/config/runtime_configuration_coercion_methods.rb +41 -0
- data/lib/pact_broker/config/runtime_configuration_database_methods.rb +119 -0
- data/lib/pact_broker/config/runtime_configuration_logging_methods.rb +61 -0
- data/lib/pact_broker/configuration.rb +67 -131
- data/lib/pact_broker/contracts/notice.rb +4 -0
- data/lib/pact_broker/contracts/service.rb +4 -4
- data/lib/pact_broker/db/models.rb +3 -0
- data/lib/pact_broker/db/validate_encoding.rb +0 -4
- data/lib/pact_broker/deployments/deployed_version.rb +8 -2
- data/lib/pact_broker/deployments/deployed_version_service.rb +13 -6
- data/lib/pact_broker/deployments/environment.rb +1 -1
- data/lib/pact_broker/deployments/released_version.rb +8 -0
- data/lib/pact_broker/deployments/released_version_service.rb +12 -0
- data/lib/pact_broker/doc/views/provider-pacts-for-verification.markdown +4 -0
- data/lib/pact_broker/domain/pacticipant.rb +17 -13
- data/lib/pact_broker/domain/verification.rb +4 -22
- data/lib/pact_broker/domain/version.rb +9 -5
- data/lib/pact_broker/domain/webhook.rb +4 -0
- data/lib/pact_broker/error.rb +1 -0
- data/lib/pact_broker/errors.rb +1 -1
- data/lib/pact_broker/feature_toggle.rb +3 -5
- data/lib/pact_broker/hash_refinements.rb +0 -1
- data/lib/pact_broker/index/service.rb +4 -6
- data/lib/pact_broker/initializers/database_connection.rb +80 -0
- data/lib/pact_broker/integrations/integration.rb +5 -0
- data/lib/pact_broker/integrations/service.rb +4 -2
- data/lib/pact_broker/locale/en.yml +1 -0
- data/lib/pact_broker/logging.rb +2 -1
- data/lib/pact_broker/matrix/integration.rb +1 -1
- data/lib/pact_broker/matrix/parse_can_i_deploy_query.rb +2 -2
- data/lib/pact_broker/matrix/quick_row.rb +10 -0
- data/lib/pact_broker/matrix/repository.rb +64 -3
- data/lib/pact_broker/metrics/service.rb +16 -13
- data/lib/pact_broker/pacticipants/repository.rb +4 -0
- data/lib/pact_broker/pacticipants/service.rb +9 -1
- data/lib/pact_broker/pacts/pact_publication.rb +10 -13
- data/lib/pact_broker/pacts/pact_publication_dataset_module.rb +6 -1
- data/lib/pact_broker/pacts/pact_publication_selector_dataset_module.rb +1 -2
- data/lib/pact_broker/pacts/pact_version.rb +25 -11
- data/lib/pact_broker/pacts/pacts_for_verification_repository.rb +54 -77
- data/lib/pact_broker/pacts/selected_pact.rb +1 -1
- data/lib/pact_broker/pacts/selector.rb +15 -2
- data/lib/pact_broker/pacts/selectors.rb +4 -0
- data/lib/pact_broker/pacts/service.rb +4 -0
- data/lib/pact_broker/repositories/scopes.rb +12 -1
- data/lib/pact_broker/string_refinements.rb +6 -0
- data/lib/pact_broker/tags/service.rb +8 -1
- data/lib/pact_broker/test/http_test_data_builder.rb +11 -5
- data/lib/pact_broker/ui/views/index/_css_and_js.haml +11 -9
- data/lib/pact_broker/ui/views/index/_pagination.haml +3 -1
- data/lib/pact_broker/ui/views/layouts/main.haml +5 -3
- data/lib/pact_broker/ui/views/matrix/show.haml +10 -8
- data/lib/pact_broker/verifications/required_verification.rb +28 -0
- data/lib/pact_broker/verifications/service.rb +49 -1
- data/lib/pact_broker/version.rb +1 -1
- data/lib/pact_broker/versions/repository.rb +15 -0
- data/lib/pact_broker/versions/service.rb +32 -2
- data/lib/pact_broker/webhooks/event_listener.rb +3 -0
- data/lib/pact_broker/webhooks/trigger_service.rb +30 -14
- data/lib/pact_broker/webhooks/triggered_webhook.rb +1 -0
- data/lib/pact_broker/webhooks/webhook.rb +2 -2
- data/lib/pact_broker/webhooks/webhook_event.rb +6 -1
- data/lib/semantic_logger/formatters/short.rb +29 -0
- data/pact_broker.gemspec +1 -0
- data/script/data/auto-create-things-for-tags.rb +19 -0
- data/script/data/contract-published-requiring-verification.rb +27 -0
- data/script/{reproduce-issue-expand-currently-deployed.rb → data/expand-currently-deployed.rb} +0 -0
- data/script/docs/generate-configuration-docs.rb +86 -0
- data/spec/features/get_latest_pact_badge_spec.rb +1 -0
- data/spec/features/get_matrix_badge_spec.rb +1 -0
- data/spec/features/publish_pact_spec.rb +21 -7
- data/spec/features/wip_pacts_spec.rb +1 -1
- data/spec/fixtures/approvals/matrix_integration_environment_spec.approved.json +62 -0
- data/spec/fixtures/approvals/matrix_integration_ignore_spec.approved.json +124 -0
- data/spec/fixtures/approvals/matrix_integration_spec.approved.json +173 -0
- data/spec/fixtures/approvals/publish_contract_no_branch.approved.json +9 -9
- data/spec/fixtures/approvals/publish_contract_nothing_exists.approved.json +7 -7
- data/spec/fixtures/approvals/publish_contract_nothing_exists_with_webhook.approved.json +5 -5
- data/spec/fixtures/approvals/publish_contract_verification_already_exists.approved.json +5 -5
- data/spec/lib/pact_broker/api/middleware/basic_auth_spec.rb +312 -0
- data/spec/lib/pact_broker/api/resources/tag_spec.rb +14 -39
- data/spec/lib/pact_broker/app_basic_auth_spec.rb +122 -0
- data/spec/lib/pact_broker/config/load_spec.rb +33 -6
- data/spec/lib/pact_broker/config/runtime_configuration_logging_methods_spec.rb +22 -0
- data/spec/lib/pact_broker/config/runtime_configuration_spec.rb +71 -0
- data/spec/lib/pact_broker/configuration_spec.rb +51 -25
- data/spec/lib/pact_broker/errors/error_logger_spec.rb +3 -0
- data/spec/lib/pact_broker/feature_toggle_spec.rb +18 -19
- data/spec/lib/pact_broker/matrix/integration_environment_spec.rb +12 -0
- data/spec/lib/pact_broker/matrix/integration_ignore_spec.rb +15 -3
- data/spec/lib/pact_broker/matrix/integration_spec.rb +47 -6
- data/spec/lib/pact_broker/matrix/parse_can_i_deploy_query_spec.rb +16 -1
- data/spec/lib/pact_broker/matrix/repository_dependency_spec.rb +0 -2
- data/spec/lib/pact_broker/matrix/repository_spec.rb +0 -2
- data/spec/lib/pact_broker/metrics/service_spec.rb +44 -0
- data/spec/lib/pact_broker/pacticipants/service_spec.rb +28 -5
- data/spec/lib/pact_broker/pacts/pact_publication_selector_dataset_module_spec.rb +25 -0
- data/spec/lib/pact_broker/pacts/pact_version_spec.rb +30 -1
- data/spec/lib/pact_broker/pacts/repository_find_for_verification_spec.rb +107 -20
- data/spec/lib/pact_broker/pacts/verifiable_pact_messages_spec.rb +1 -1
- data/spec/lib/pact_broker/tags/service_spec.rb +24 -8
- data/spec/lib/pact_broker/verifications/service_spec.rb +146 -0
- data/spec/lib/pact_broker/versions/repository_spec.rb +38 -2
- data/spec/lib/pact_broker/versions/service_spec.rb +93 -2
- data/spec/lib/pact_broker/webhooks/trigger_service_spec.rb +54 -2
- data/spec/lib/rack/pact_broker/invalid_uri_protection_spec.rb +3 -3
- data/spec/spec_helper.rb +2 -1
- data/spec/support/approvals.rb +29 -0
- metadata +52 -13
- data/example/basic_auth/Gemfile +0 -5
- data/example/basic_auth/Procfile +0 -1
- data/example/basic_auth/README.md +0 -43
- data/example/basic_auth/config.ru +0 -19
- data/example/example_data.sql +0 -19
- data/spec/lib/pact_broker/config/save_and_load_spec.rb +0 -25
- data/spec/lib/pact_broker/pacts/service_find_for_verification_spec.rb +0 -50
@@ -0,0 +1,38 @@
|
|
1
|
+
require "pact_broker/config/runtime_configuration_logging_methods"
|
2
|
+
require "pact_broker/string_refinements"
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Config
|
6
|
+
module RuntimeConfigurationBasicAuthMethods
|
7
|
+
using PactBroker::StringRefinements
|
8
|
+
|
9
|
+
def self.included(anyway_config)
|
10
|
+
anyway_config.class_eval do
|
11
|
+
attr_config(
|
12
|
+
basic_auth_enabled: false,
|
13
|
+
basic_auth_username: nil,
|
14
|
+
basic_auth_password: nil,
|
15
|
+
basic_auth_read_only_username: nil,
|
16
|
+
basic_auth_read_only_password: nil,
|
17
|
+
allow_public_read: false,
|
18
|
+
public_heartbeat: false
|
19
|
+
)
|
20
|
+
|
21
|
+
sensitive_values(:basic_auth_password, :basic_auth_read_only_password)
|
22
|
+
|
23
|
+
def basic_auth_credentials_provided?
|
24
|
+
basic_auth_username&.not_blank? && basic_auth_password&.not_blank?
|
25
|
+
end
|
26
|
+
|
27
|
+
def basic_auth_write_credentials
|
28
|
+
[basic_auth_username, basic_auth_password]
|
29
|
+
end
|
30
|
+
|
31
|
+
def basic_auth_read_credentials
|
32
|
+
[basic_auth_read_only_username, basic_auth_read_only_password]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -9,12 +9,12 @@ module PactBroker
|
|
9
9
|
|
10
10
|
include PactBroker::Logging
|
11
11
|
|
12
|
-
def self.call
|
13
|
-
new(
|
12
|
+
def self.call runtime_configuration
|
13
|
+
new(runtime_configuration).call
|
14
14
|
end
|
15
15
|
|
16
|
-
def initialize
|
17
|
-
@
|
16
|
+
def initialize runtime_configuration
|
17
|
+
@runtime_configuration = runtime_configuration
|
18
18
|
end
|
19
19
|
|
20
20
|
def call
|
@@ -25,18 +25,29 @@ module PactBroker
|
|
25
25
|
|
26
26
|
private
|
27
27
|
|
28
|
-
attr_reader :
|
28
|
+
attr_reader :runtime_configuration
|
29
29
|
|
30
30
|
def configuration_attribute_exists? setting
|
31
|
-
|
31
|
+
runtime_configuration.respond_to?("#{setting.name}=")
|
32
|
+
end
|
33
|
+
|
34
|
+
def unset_or_value_from_default? setting
|
35
|
+
setting_source(setting).nil? || setting_source(setting)[:type] == :defaults
|
36
|
+
end
|
37
|
+
|
38
|
+
def setting_source(setting)
|
39
|
+
runtime_configuration.to_source_trace.dig(setting.name, :source)
|
32
40
|
end
|
33
41
|
|
34
42
|
def set_value_on_configuration setting
|
35
|
-
if configuration_attribute_exists?
|
36
|
-
|
37
|
-
|
43
|
+
if configuration_attribute_exists?(setting)
|
44
|
+
if unset_or_value_from_default?(setting)
|
45
|
+
runtime_configuration.send("#{setting.name}=", setting.value_object)
|
46
|
+
else
|
47
|
+
logger.debug("Ignoring #{setting.name} configuration from database, as it has been set by another source #{setting_source(setting)}")
|
48
|
+
end
|
38
49
|
else
|
39
|
-
logger.warn("Could not load configuration setting \"#{setting.name}\" as there is no matching attribute on the
|
50
|
+
logger.warn("Could not load configuration setting \"#{setting.name}\" as there is no matching attribute on the #{runtime_configuration.class} class")
|
40
51
|
end
|
41
52
|
end
|
42
53
|
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
require "anyway_config"
|
2
|
+
require "pact_broker/config/runtime_configuration_logging_methods"
|
3
|
+
require "pact_broker/config/runtime_configuration_database_methods"
|
4
|
+
require "pact_broker/config/runtime_configuration_coercion_methods"
|
5
|
+
require "pact_broker/version"
|
6
|
+
require "pact_broker/config/basic_auth_configuration"
|
7
|
+
require "pact_broker/string_refinements"
|
8
|
+
require "pact_broker/hash_refinements"
|
9
|
+
require "pact_broker/error"
|
10
|
+
|
11
|
+
module PactBroker
|
12
|
+
module Config
|
13
|
+
class RuntimeConfiguration < Anyway::Config
|
14
|
+
using PactBroker::StringRefinements
|
15
|
+
using PactBroker::HashRefinements
|
16
|
+
include RuntimeConfigurationLoggingMethods
|
17
|
+
include RuntimeConfigurationCoercionMethods
|
18
|
+
|
19
|
+
include RuntimeConfigurationDatabaseMethods
|
20
|
+
include RuntimeConfigurationBasicAuthMethods
|
21
|
+
|
22
|
+
# logging attributes
|
23
|
+
attr_config(
|
24
|
+
log_dir: File.expand_path("./log"),
|
25
|
+
log_stream: :file,
|
26
|
+
log_level: :info,
|
27
|
+
log_format: nil,
|
28
|
+
warning_error_class_names: ["Sequel::ForeignKeyConstraintViolation"],
|
29
|
+
hide_pactflow_messages: false,
|
30
|
+
log_configuration_on_startup: true
|
31
|
+
)
|
32
|
+
|
33
|
+
on_load :validate_logging_attributes!
|
34
|
+
|
35
|
+
# webhook attributes
|
36
|
+
attr_config(
|
37
|
+
webhook_retry_schedule: [10, 60, 120, 300, 600, 1200], #10 sec, 1 min, 2 min, 5 min, 10 min, 20 min => 38 minutes
|
38
|
+
webhook_http_method_whitelist: ["POST"],
|
39
|
+
webhook_http_code_success: [200, 201, 202, 203, 204, 205, 206],
|
40
|
+
webhook_scheme_whitelist: ["https"],
|
41
|
+
webhook_host_whitelist: [],
|
42
|
+
disable_ssl_verification: false,
|
43
|
+
user_agent: "Pact Broker v#{PactBroker::VERSION}",
|
44
|
+
)
|
45
|
+
|
46
|
+
# resource attributes
|
47
|
+
attr_config(
|
48
|
+
port: 9292,
|
49
|
+
base_url: nil,
|
50
|
+
base_urls: [],
|
51
|
+
use_hal_browser: true,
|
52
|
+
enable_diagnostic_endpoints: true,
|
53
|
+
use_rack_protection: true,
|
54
|
+
badge_provider_mode: :redirect,
|
55
|
+
enable_public_badge_access: false,
|
56
|
+
shields_io_base_url: "https://img.shields.io",
|
57
|
+
use_case_sensitive_resource_names: true
|
58
|
+
)
|
59
|
+
|
60
|
+
# domain attributes
|
61
|
+
attr_config(
|
62
|
+
order_versions_by_date: true,
|
63
|
+
base_equality_only_on_content_that_affects_verification_results: true,
|
64
|
+
check_for_potential_duplicate_pacticipant_names: true,
|
65
|
+
create_deployed_versions_for_tags: true,
|
66
|
+
use_first_tag_as_branch: true,
|
67
|
+
use_first_tag_as_branch_time_limit: 10,
|
68
|
+
auto_detect_main_branch: true,
|
69
|
+
main_branch_candidates: ["develop", "main", "master"],
|
70
|
+
allow_dangerous_contract_modification: true,
|
71
|
+
semver_formats: ["%M.%m.%p%s%d", "%M.%m", "%M"],
|
72
|
+
seed_example_data: true,
|
73
|
+
features: []
|
74
|
+
)
|
75
|
+
|
76
|
+
def self.getter_and_setter_method_names
|
77
|
+
extra_methods = [
|
78
|
+
:warning_error_classes,
|
79
|
+
:database_configuration,
|
80
|
+
:basic_auth_credentials_provided?,
|
81
|
+
:basic_auth_write_credentials,
|
82
|
+
:basic_auth_read_credentials
|
83
|
+
]
|
84
|
+
config_attributes + config_attributes.collect{ |k| "#{k}=".to_sym } + extra_methods - [:base_url]
|
85
|
+
end
|
86
|
+
|
87
|
+
config_name :pact_broker
|
88
|
+
|
89
|
+
sensitive_values(:database_url, :database_password)
|
90
|
+
|
91
|
+
def log_level= log_level
|
92
|
+
super(log_level&.downcase&.to_sym)
|
93
|
+
end
|
94
|
+
|
95
|
+
def log_stream= log_stream
|
96
|
+
super(log_stream&.to_sym)
|
97
|
+
end
|
98
|
+
|
99
|
+
def log_format= log_format
|
100
|
+
super(log_format&.to_sym)
|
101
|
+
end
|
102
|
+
|
103
|
+
def custom_log_formatters= custom_log_formatters
|
104
|
+
super(custom_log_formatters&.symbolize_keys)
|
105
|
+
end
|
106
|
+
|
107
|
+
def base_url= base_url
|
108
|
+
super(value_to_string_array(base_url, "base_url"))
|
109
|
+
end
|
110
|
+
|
111
|
+
alias_method :original_base_url, :base_url
|
112
|
+
|
113
|
+
def base_url
|
114
|
+
raise NotImplementedError
|
115
|
+
end
|
116
|
+
|
117
|
+
def base_urls= base_urls
|
118
|
+
super(value_to_string_array(base_urls, "base_urls"))
|
119
|
+
end
|
120
|
+
|
121
|
+
def base_urls
|
122
|
+
(super + [*original_base_url]).uniq
|
123
|
+
end
|
124
|
+
|
125
|
+
def badge_provider_mode= badge_provider_mode
|
126
|
+
super(badge_provider_mode&.to_sym)
|
127
|
+
end
|
128
|
+
|
129
|
+
def warning_error_class_names= warning_error_class_names
|
130
|
+
super(value_to_string_array(warning_error_class_names, "warning_error_class_names"))
|
131
|
+
end
|
132
|
+
|
133
|
+
def semver_formats= semver_formats
|
134
|
+
super(value_to_string_array(semver_formats, "semver_formats"))
|
135
|
+
end
|
136
|
+
|
137
|
+
def webhook_retry_schedule= webhook_retry_schedule
|
138
|
+
super(value_to_integer_array(webhook_retry_schedule, "webhook_retry_schedule"))
|
139
|
+
end
|
140
|
+
|
141
|
+
def webhook_http_method_whitelist= webhook_http_method_whitelist
|
142
|
+
super(value_to_string_array(webhook_http_method_whitelist, "webhook_http_method_whitelist"))
|
143
|
+
end
|
144
|
+
|
145
|
+
def webhook_http_code_success= webhook_http_code_success
|
146
|
+
super(value_to_integer_array(webhook_http_code_success, "webhook_http_code_success"))
|
147
|
+
end
|
148
|
+
|
149
|
+
def webhook_scheme_whitelist= webhook_scheme_whitelist
|
150
|
+
super(value_to_string_array(webhook_scheme_whitelist, "webhook_scheme_whitelist"))
|
151
|
+
end
|
152
|
+
|
153
|
+
def webhook_host_whitelist= webhook_host_whitelist
|
154
|
+
super(value_to_string_array(webhook_host_whitelist, "webhook_host_whitelist"))
|
155
|
+
end
|
156
|
+
|
157
|
+
def features= features
|
158
|
+
super(value_to_string_array(features, "features").collect(&:downcase))
|
159
|
+
end
|
160
|
+
|
161
|
+
def warning_error_classes
|
162
|
+
warning_error_class_names.collect do | class_name |
|
163
|
+
begin
|
164
|
+
Object.const_get(class_name)
|
165
|
+
rescue NameError => e
|
166
|
+
puts("Class #{class_name} couldn't be loaded as a warning error class (#{e.class} - #{e.message}). Ignoring.")
|
167
|
+
nil
|
168
|
+
end
|
169
|
+
end.compact
|
170
|
+
end
|
171
|
+
|
172
|
+
def validate_logging_attributes!
|
173
|
+
valid_log_streams = [:file, :stdout]
|
174
|
+
unless valid_log_streams.include?(log_stream)
|
175
|
+
raise_validation_error("log_stream must be one of: #{valid_log_streams.join(", ")}")
|
176
|
+
end
|
177
|
+
|
178
|
+
if log_stream == :file && log_dir.blank?
|
179
|
+
raise_validation_error("Must specify log_dir if log_stream is set to file")
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def raise_validation_error(msg)
|
184
|
+
raise PactBroker::ConfigurationError, msg
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "pact_broker/config/space_delimited_string_list"
|
2
|
+
require "pact_broker/config/space_delimited_integer_list"
|
3
|
+
|
4
|
+
module PactBroker
|
5
|
+
module Config
|
6
|
+
module RuntimeConfigurationCoercionMethods
|
7
|
+
def value_to_string_array value, property_name
|
8
|
+
if value.is_a?(String)
|
9
|
+
PactBroker::Config::SpaceDelimitedStringList.parse(value)
|
10
|
+
elsif value.is_a?(Array)
|
11
|
+
# parse structured values to possible regexp
|
12
|
+
[*value].flat_map do | val |
|
13
|
+
if val.is_a?(String)
|
14
|
+
PactBroker::Config::SpaceDelimitedStringList.parse(val)
|
15
|
+
else
|
16
|
+
[val]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
elsif value
|
20
|
+
raise ConfigurationError.new("Pact Broker configuration property `#{property_name}` must be a space delimited String or an Array. Got: #{value.inspect}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private :value_to_string_array
|
25
|
+
|
26
|
+
def value_to_integer_array value, property_name
|
27
|
+
if value.is_a?(String)
|
28
|
+
PactBroker::Config::SpaceDelimitedIntegerList.parse(value)
|
29
|
+
elsif value.is_a?(Array)
|
30
|
+
value.collect { |v| v.to_i }
|
31
|
+
elsif value.is_a?(Integer)
|
32
|
+
[value]
|
33
|
+
elsif value
|
34
|
+
raise ConfigurationError.new("Pact Broker configuration property `#{property_name}` must be a space delimited String or an Array of Integers. Got: #{value.inspect}")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
private :value_to_integer_array
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module PactBroker
|
2
|
+
module Config
|
3
|
+
module RuntimeConfigurationDatabaseMethods
|
4
|
+
|
5
|
+
# rubocop: disable Metrics/MethodLength
|
6
|
+
# rubocop: disable Metrics/CyclomaticComplexity
|
7
|
+
def self.included(anyway_config)
|
8
|
+
anyway_config.class_eval do
|
9
|
+
|
10
|
+
attr_config(
|
11
|
+
database_adapter: "postgres",
|
12
|
+
database_username: nil,
|
13
|
+
database_password: nil,
|
14
|
+
database_name: nil,
|
15
|
+
database_host: nil,
|
16
|
+
database_port: nil,
|
17
|
+
database_url: nil,
|
18
|
+
database_sslmode: nil,
|
19
|
+
sql_log_level: :debug,
|
20
|
+
sql_log_warn_duration: 5,
|
21
|
+
database_max_connections: nil,
|
22
|
+
database_pool_timeout: 5,
|
23
|
+
database_connect_max_retries: 0,
|
24
|
+
auto_migrate_db: true,
|
25
|
+
auto_migrate_db_data: true,
|
26
|
+
allow_missing_migration_files: true,
|
27
|
+
validate_database_connection_config: true,
|
28
|
+
database_statement_timeout: 15,
|
29
|
+
metrics_sql_statement_timeout: 30,
|
30
|
+
database_connection_validation_timeout: -1
|
31
|
+
)
|
32
|
+
|
33
|
+
def database_configuration
|
34
|
+
database_credentials
|
35
|
+
.merge(
|
36
|
+
encoding: "utf8",
|
37
|
+
sslmode: database_sslmode,
|
38
|
+
sql_log_level: sql_log_level,
|
39
|
+
log_warn_duration: sql_log_warn_duration,
|
40
|
+
max_connections: database_max_connections,
|
41
|
+
pool_timeout: database_pool_timeout,
|
42
|
+
driver_options: driver_options,
|
43
|
+
connect_max_retries: database_connect_max_retries,
|
44
|
+
connection_validation_timeout: database_connection_validation_timeout
|
45
|
+
).compact
|
46
|
+
end
|
47
|
+
|
48
|
+
def database_connect_max_retries= database_connect_max_retries
|
49
|
+
super(database_connect_max_retries&.to_i)
|
50
|
+
end
|
51
|
+
|
52
|
+
def sql_log_level= sql_log_level
|
53
|
+
super(sql_log_level&.downcase&.to_sym)
|
54
|
+
end
|
55
|
+
|
56
|
+
def sql_log_warn_duration= sql_log_warn_duration
|
57
|
+
super(sql_log_warn_duration&.to_f)
|
58
|
+
end
|
59
|
+
|
60
|
+
def database_port= database_port
|
61
|
+
super(database_port&.to_i)
|
62
|
+
end
|
63
|
+
|
64
|
+
def metrics_sql_statement_timeout= metrics_sql_statement_timeout
|
65
|
+
super(metrics_sql_statement_timeout&.to_i)
|
66
|
+
end
|
67
|
+
|
68
|
+
def postgres?
|
69
|
+
database_credentials[:adapter] == "postgres"
|
70
|
+
end
|
71
|
+
private :postgres?
|
72
|
+
|
73
|
+
def driver_options
|
74
|
+
if postgres?
|
75
|
+
{ options: "-c statement_timeout=#{database_statement_timeout}s" }
|
76
|
+
end
|
77
|
+
end
|
78
|
+
private :driver_options
|
79
|
+
|
80
|
+
def database_credentials
|
81
|
+
if database_url
|
82
|
+
database_configuration_from_url
|
83
|
+
else
|
84
|
+
database_configuration_from_parts
|
85
|
+
end
|
86
|
+
end
|
87
|
+
private :database_credentials
|
88
|
+
|
89
|
+
def database_configuration_from_parts
|
90
|
+
{
|
91
|
+
adapter: database_adapter,
|
92
|
+
user: database_username,
|
93
|
+
password: database_password,
|
94
|
+
host: database_host,
|
95
|
+
database: database_name,
|
96
|
+
database_port: database_port
|
97
|
+
}.compact
|
98
|
+
end
|
99
|
+
private :database_credentials
|
100
|
+
|
101
|
+
def database_configuration_from_url
|
102
|
+
uri = URI(database_url)
|
103
|
+
{
|
104
|
+
adapter: uri.scheme,
|
105
|
+
user: uri.user,
|
106
|
+
password: uri.password,
|
107
|
+
host: uri.host,
|
108
|
+
database: uri.path.sub(/^\//, ""),
|
109
|
+
port: uri.port&.to_i,
|
110
|
+
}.compact
|
111
|
+
end
|
112
|
+
private :database_configuration_from_url
|
113
|
+
end
|
114
|
+
end
|
115
|
+
# rubocop: enable Metrics/MethodLength
|
116
|
+
# rubocop: enable Metrics/CyclomaticComplexity
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require "uri"
|
2
|
+
|
3
|
+
module PactBroker
|
4
|
+
module Config
|
5
|
+
module RuntimeConfigurationLoggingMethods
|
6
|
+
module ClassMethods
|
7
|
+
def sensitive_values(*values)
|
8
|
+
@sensitive_values ||= []
|
9
|
+
if values
|
10
|
+
@sensitive_values.concat([*values])
|
11
|
+
else
|
12
|
+
@sensitive_values
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def sensitive_value?(value)
|
17
|
+
sensitive_values.any? { |key| key == value || key == value.to_sym || key.kind_of?(Regexp) && key =~ value }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module InstanceMethods
|
22
|
+
def log_configuration(logger)
|
23
|
+
to_source_trace.sort_by { |key, _| key }.each { |key, value| log_config_inner(key, value, logger) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def log_config_inner(key, value, logger)
|
27
|
+
if !value.has_key? :value
|
28
|
+
value.sort_by { |inner_key, _| inner_key }.each { |inner_key, inner_value| log_config_inner("#{key}.#{inner_key}", inner_value, logger) }
|
29
|
+
elsif self.class.sensitive_value?(key)
|
30
|
+
logger.info "#{key}=#{redact(key, value[:value])} source=#{value[:source]}"
|
31
|
+
else
|
32
|
+
logger.info "#{key}=#{value[:value]} source=#{value[:source]}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
private :log_config_inner
|
36
|
+
|
37
|
+
def redact name, value
|
38
|
+
if value && name.to_s.end_with?("_url")
|
39
|
+
begin
|
40
|
+
uri = URI(value)
|
41
|
+
uri.password = "*****"
|
42
|
+
uri.to_s
|
43
|
+
rescue StandardError
|
44
|
+
"*****"
|
45
|
+
end
|
46
|
+
elsif !value.nil?
|
47
|
+
"*****"
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
private :redact
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.included(receiver)
|
56
|
+
receiver.extend ClassMethods
|
57
|
+
receiver.send :include, InstanceMethods
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|