inferno_core 0.4.43 → 0.5.0

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 (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/inferno/apps/cli/execute/console_outputter.rb +152 -0
  3. data/lib/inferno/apps/cli/execute.rb +269 -0
  4. data/lib/inferno/apps/cli/main.rb +73 -4
  5. data/lib/inferno/apps/cli/templates/.env.development +2 -1
  6. data/lib/inferno/apps/cli/templates/.env.production +2 -1
  7. data/lib/inferno/apps/cli/templates/.env.test +1 -0
  8. data/lib/inferno/apps/cli/templates/.gitignore +1 -0
  9. data/lib/inferno/apps/cli/templates/config/nginx.background.conf.tt +15 -0
  10. data/lib/inferno/apps/cli/templates/docker-compose.background.yml.tt +5 -0
  11. data/lib/inferno/apps/cli/templates/docker-compose.yml.tt +4 -0
  12. data/lib/inferno/apps/cli.rb +0 -1
  13. data/lib/inferno/apps/web/controllers/test_runs/create.rb +7 -32
  14. data/lib/inferno/apps/web/serializers/serializer.rb +3 -0
  15. data/lib/inferno/config/boot/executor.rb +14 -0
  16. data/lib/inferno/dsl/auth_info.rb +77 -72
  17. data/lib/inferno/dsl/fhir_client_builder.rb +2 -2
  18. data/lib/inferno/dsl/fhir_resource_validation.rb +4 -0
  19. data/lib/inferno/dsl/http_client_builder.rb +2 -2
  20. data/lib/inferno/dsl/links.rb +100 -0
  21. data/lib/inferno/dsl/runnable.rb +6 -1
  22. data/lib/inferno/entities/has_runnable.rb +1 -1
  23. data/lib/inferno/entities/request.rb +2 -2
  24. data/lib/inferno/entities/test.rb +4 -4
  25. data/lib/inferno/entities/test_group.rb +2 -2
  26. data/lib/inferno/entities/test_suite.rb +2 -24
  27. data/lib/inferno/exceptions.rb +12 -0
  28. data/lib/inferno/ext/fhir_models.rb +3 -3
  29. data/lib/inferno/jobs.rb +4 -4
  30. data/lib/inferno/public/237.bundle.js +1 -0
  31. data/lib/inferno/public/assets.json +1 -1
  32. data/lib/inferno/public/bundle.js +42 -63
  33. data/lib/inferno/public/bundle.js.LICENSE.txt +5 -33
  34. data/lib/inferno/repositories/in_memory_repository.rb +5 -8
  35. data/lib/inferno/repositories/repository.rb +1 -1
  36. data/lib/inferno/result_summarizer.rb +1 -1
  37. data/lib/inferno/test_runner.rb +2 -2
  38. data/lib/inferno/utils/middleware/request_logger.rb +1 -1
  39. data/lib/inferno/utils/persist_inputs.rb +30 -0
  40. data/lib/inferno/utils/preset_template_generator.rb +1 -1
  41. data/lib/inferno/utils/verify_runnable.rb +15 -0
  42. data/lib/inferno/version.rb +1 -1
  43. data/spec/factories/result.rb +4 -0
  44. data/spec/fixtures/basic_test_group.rb +2 -1
  45. data/spec/fixtures/run_as_group_test_group.rb +11 -0
  46. metadata +24 -171
  47. data/lib/inferno/public/175.bundle.js +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '09f9e6a4ff6df2749650a972de54dbf8e693de38469c3ac8cb781ee99cbf6ce4'
4
- data.tar.gz: 2153922e52c9207e092526b7a0bedaca8b9333530c4c2e41515083001ba09097
3
+ metadata.gz: 5c6ddae6726754b2036409f6765ffd3746e88a2238226655905332ac9083a907
4
+ data.tar.gz: a7f8fe7d9eedd5213bd9d825fc32075b00abf69953c29ab550c45b66fc0147b6
5
5
  SHA512:
6
- metadata.gz: fe29bbefe0208e36c4e9919dba3292f35779f1c9d8e9810e98b03837ef73b3538bf19bd752e659733da7bc6b646a190249a7017b44ff45a679e29b2faa3d91fe
7
- data.tar.gz: 8b43e4f565366c80930ab4150c1c1a493fc8fe8551295851ef49eef213e42a185521abd62438e5a0514f51463968bf24e84824aa72c9ef20f5880a65b5145cb1
6
+ metadata.gz: bfbb7ef6d15895b029349446501d739b7e676cff8e0ea369c1f781ee29151187eaba602f4485cee34a19c9a492d1cdbe2e4db3454db5f33a8f7b578586c53685
7
+ data.tar.gz: 14cb75b1bbaa2dcca319348f9914cf2af5d40d36a23ab7de3d212e43555466dc5f7c6d1af9a570fcca977e16353df80bc76f891616b32f0d91a593cfb9378730
@@ -0,0 +1,152 @@
1
+ require 'pastel'
2
+ require_relative '../../web/serializers/test_run'
3
+ require_relative '../../web/serializers/result'
4
+
5
+ module Inferno
6
+ module CLI
7
+ class Execute
8
+ # @private
9
+ class ConsoleOutputter
10
+ COLOR = Pastel.new
11
+ CHECKMARK = "\u2713".freeze
12
+ BAR = ('=' * 80).freeze
13
+
14
+ def print_start_message(options)
15
+ puts ''
16
+ puts BAR
17
+ puts "Testing #{options[:suite]}"
18
+ verbose_puts options, "Running Groups #{options[:groups]}" unless options[:groups].blank?
19
+ verbose_puts options, "Running Tests #{options[:tests]}" unless options[:tests].blank?
20
+ verbose_puts options, "Running Entities #{options[:short_ids]}" unless options[:short_ids].blank?
21
+ puts BAR
22
+ end
23
+
24
+ def print_around_run(_options)
25
+ puts 'Running tests. This may take a while...'
26
+ # TODO: spinner/progress bar
27
+ yield
28
+ end
29
+
30
+ def print_results(options, results)
31
+ verbose_print_json_results(options, results)
32
+
33
+ puts BAR
34
+ puts 'Test Results:'
35
+ puts BAR
36
+ results.each do |result|
37
+ print format_tag(result), ': ', format_result(result), "\n"
38
+ verbose_puts(options, "\tsummary: ", result.result_message)
39
+ verbose_puts(options, "\tmessages: ", format_messages(result))
40
+ verbose_puts(options, "\trequests: ", format_requests(result))
41
+ verbose_puts(options, "\tinputs: ", format_inputs(result))
42
+ verbose_puts(options, "\toutputs: ", format_outputs(result))
43
+ end
44
+ puts BAR
45
+ end
46
+
47
+ def print_end_message(options); end
48
+
49
+ def print_error(options, exception)
50
+ puts COLOR.red "Error: #{exception.full_message}"
51
+ verbose_print(options, exception.backtrace&.join('\n'))
52
+ end
53
+
54
+ # private
55
+
56
+ def verbose_print(options, *args)
57
+ print(COLOR.dim(*args)) if options[:verbose]
58
+ end
59
+
60
+ def verbose_puts(options, *args)
61
+ args.push("\n")
62
+ verbose_print(options, *args)
63
+ end
64
+
65
+ def format_tag(result)
66
+ if result.runnable.respond_to?(:short_id)
67
+ "#{result.runnable.short_id} #{format_tag_suffix(result)}"
68
+ else
69
+ format_tag_suffix(result)
70
+ end
71
+ end
72
+
73
+ def format_tag_suffix(result)
74
+ result.runnable.short_title.presence || result.runnable.title.presence || result.runnable.id
75
+ end
76
+
77
+ def format_messages(result)
78
+ result.messages.map do |message|
79
+ "\n\t\t#{message.type}: #{message.message}"
80
+ end.join
81
+ end
82
+
83
+ def format_requests(result)
84
+ result.requests.map do |req_res|
85
+ "\n\t\t#{req_res.status} #{req_res.verb.upcase} #{req_res.url}"
86
+ end.join
87
+ end
88
+
89
+ def format_session_data(result, attr)
90
+ json = result.send(attr)
91
+ return '' if json.nil?
92
+
93
+ JSON.parse(json).map do |hash|
94
+ "\n\t\t#{hash['name']}: #{hash['value']}"
95
+ end.join
96
+ end
97
+
98
+ def format_inputs(result)
99
+ format_session_data(result, :input_json)
100
+ end
101
+
102
+ def format_outputs(result)
103
+ format_session_data(result, :output_json)
104
+ end
105
+
106
+ def format_result(result) # rubocop:disable Metrics/CyclomaticComplexity
107
+ case result.result
108
+ when 'pass'
109
+ COLOR.bold.green(CHECKMARK, ' pass')
110
+ when 'fail'
111
+ COLOR.bold.red 'X fail'
112
+ when 'skip'
113
+ COLOR.yellow '* skip'
114
+ when 'omit'
115
+ COLOR.blue '* omit'
116
+ when 'error'
117
+ COLOR.magenta 'X error'
118
+ when 'wait'
119
+ COLOR.bold '. wait'
120
+ when 'cancel'
121
+ COLOR.red 'X cancel'
122
+ when 'running'
123
+ COLOR.bold '- running'
124
+ else
125
+ raise StandardError.new, "Unrecognized result #{result.result}"
126
+ end
127
+ end
128
+
129
+ def verbose_print_json_results(options, results)
130
+ verbose_puts(options, BAR)
131
+ verbose_puts(options, 'JSON Test Results:')
132
+ verbose_puts(options, BAR)
133
+ verbose_puts(options, serialize(results))
134
+ verbose_puts(options, BAR)
135
+ end
136
+
137
+ def serialize(entity)
138
+ case entity.class.to_s
139
+ when 'Array'
140
+ JSON.pretty_generate(entity.map { |item| JSON.parse serialize(item) })
141
+ when lambda { |x|
142
+ defined?(x.constantize) && defined?("Inferno::Web::Serializers::#{x.split('::').last}".constantize)
143
+ }
144
+ "Inferno::Web::Serializers::#{entity.class.to_s.split('::').last}".constantize.render(entity)
145
+ else
146
+ raise StandardError, "CLI does not know how to serialize #{entity.class}"
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,269 @@
1
+ require 'pastel'
2
+ require 'active_support'
3
+ require_relative '../../utils/verify_runnable'
4
+ require_relative '../../utils/persist_inputs'
5
+ require_relative 'execute/console_outputter'
6
+ require_relative '../../result_summarizer'
7
+
8
+ module Inferno
9
+ module CLI
10
+ class Execute
11
+ include ::Inferno::Utils::VerifyRunnable
12
+ include ::Inferno::Utils::PersistInputs
13
+
14
+ attr_accessor :options
15
+
16
+ def self.suppress_output
17
+ begin
18
+ original_stdout = $stdout.clone
19
+ $stdout.reopen(File.new(File::NULL, 'w+'))
20
+ retval = yield
21
+ ensure
22
+ $stdout.reopen(original_stdout)
23
+ end
24
+ retval
25
+ end
26
+
27
+ def self.boot_full_inferno
28
+ ENV['NO_DB'] = 'false'
29
+
30
+ # Inferno boot flow triggers migration and logger outputs it
31
+ Inferno::CLI::Execute.suppress_output { require_relative '../../../inferno' }
32
+
33
+ Inferno::Application.start(:executor)
34
+ end
35
+
36
+ def run(options)
37
+ print_help_and_exit if options[:help]
38
+
39
+ self.options = options
40
+
41
+ outputter.print_start_message(options)
42
+
43
+ results = []
44
+ outputter.print_around_run(options) do
45
+ if all_selected_groups_and_tests.empty?
46
+ test_run = create_test_run(suite)
47
+ run_one(suite, test_run)
48
+
49
+ results = test_runs_repo.results_for_test_run(test_run.id)
50
+ results = sort_results(results)
51
+ else
52
+ all_selected_groups_and_tests.each do |runnable|
53
+ test_run = create_test_run(runnable)
54
+ run_one(runnable, test_run)
55
+
56
+ results += sort_results(test_runs_repo.results_for_test_run(test_run.id))
57
+ end
58
+ end
59
+ end
60
+
61
+ # User may enter duplicate runnables, in which case this prevents a bug of extraneous results
62
+ results.uniq!(&:id)
63
+
64
+ outputter.print_results(options, results)
65
+ outputter.print_end_message(options)
66
+
67
+ # TODO: respect customized rollups
68
+ exit(0) if Inferno::ResultSummarizer.new(results).summarize == 'pass'
69
+
70
+ # exit(1) is for Thor failures
71
+ # exit(2) is for shell builtin failures
72
+ exit(3)
73
+ rescue Sequel::ValidationFailed => e
74
+ print_error_and_exit(e, 4)
75
+ rescue Sequel::ForeignKeyConstraintViolation => e
76
+ print_error_and_exit(e, 5)
77
+ rescue Inferno::Exceptions::RequiredInputsNotFound => e
78
+ print_error_and_exit(e, 6)
79
+ rescue Inferno::Exceptions::NotUserRunnableException => e
80
+ print_error_and_exit(e, 7)
81
+ rescue StandardError => e
82
+ print_error_and_exit(e, 8)
83
+ end
84
+
85
+ def print_help_and_exit
86
+ puts `NO_DB=true bundle exec inferno help execute`
87
+ exit(0)
88
+ end
89
+
90
+ def outputter
91
+ # TODO: swap outputter based on options
92
+ @outputter ||= Inferno::CLI::Execute::ConsoleOutputter.new
93
+ end
94
+
95
+ def all_selected_groups_and_tests
96
+ @all_selected_groups_and_tests ||= runnables_by_short_id + groups + tests
97
+ end
98
+
99
+ def run_one(runnable, test_run)
100
+ verify_runnable(
101
+ runnable,
102
+ thor_hash_to_inputs_array(options[:inputs]),
103
+ test_session.suite_options
104
+ )
105
+
106
+ persist_inputs(session_data_repo, create_params(test_session, suite), test_run)
107
+
108
+ dispatch_job(test_run)
109
+ end
110
+
111
+ def suite
112
+ @suite ||= Inferno::Repositories::TestSuites.new.find(options[:suite])
113
+
114
+ raise StandardError, "Test suite #{options[:suite]} not found" if @suite.nil?
115
+
116
+ @suite
117
+ end
118
+
119
+ def test_runs_repo
120
+ @test_runs_repo ||= Inferno::Repositories::TestRuns.new
121
+ end
122
+
123
+ def create_test_run(runnable)
124
+ test_runs_repo.create(
125
+ create_params(test_session, runnable).merge({ status: 'queued' })
126
+ )
127
+ end
128
+
129
+ def results_repo
130
+ @results_repo ||= Inferno::Repositories::Results.new
131
+ end
132
+
133
+ def test_groups_repo
134
+ @test_groups_repo ||= Inferno::Repositories::TestGroups.new
135
+ end
136
+
137
+ def tests_repo
138
+ @tests_repo ||= Inferno::Repositories::Tests.new
139
+ end
140
+
141
+ def test_sessions_repo
142
+ @test_sessions_repo ||= Inferno::Repositories::TestSessions.new
143
+ end
144
+
145
+ def session_data_repo
146
+ @session_data_repo ||= Inferno::Repositories::SessionData.new
147
+ end
148
+
149
+ def test_session
150
+ @test_session ||= test_sessions_repo.create({
151
+ test_suite_id: suite.id,
152
+ suite_options: thor_hash_to_suite_options_array(
153
+ options[:suite_options]
154
+ )
155
+ })
156
+ end
157
+
158
+ def create_params(test_session, runnable)
159
+ {
160
+ test_session_id: test_session.id,
161
+ runnable_id_key(runnable) => runnable.id,
162
+ inputs: thor_hash_to_inputs_array(options[:inputs])
163
+ }
164
+ end
165
+
166
+ def dispatch_job(test_run)
167
+ # TODO: move suppression to outputter? better suppression?
168
+ if options[:verbose]
169
+ Jobs.perform(Jobs::ExecuteTestRun, test_run.id, force_synchronous: true)
170
+ else
171
+ Inferno::CLI::Execute.suppress_output do
172
+ Jobs.perform(Jobs::ExecuteTestRun, test_run.id, force_synchronous: true)
173
+ end
174
+ end
175
+ end
176
+
177
+ def runnables_by_short_id
178
+ return [] if options[:short_ids].blank?
179
+
180
+ @runnables_by_short_id ||= options[:short_ids]&.map { |short_id| find_by_short_id(:group_or_test, short_id) }
181
+ end
182
+
183
+ def groups
184
+ return [] if options[:groups].blank?
185
+
186
+ @groups ||= options[:groups]&.map { |short_id| find_by_short_id(:group, short_id) }
187
+ end
188
+
189
+ def tests
190
+ return [] if options[:tests].blank?
191
+
192
+ @tests ||= options[:tests]&.map { |short_id| find_by_short_id(:test, short_id) }
193
+ end
194
+
195
+ def find_by_short_id(repo_symbol, short_id)
196
+ repo_symbol_to_array(repo_symbol).each do |repo|
197
+ repo.all.each do |entity|
198
+ return entity if short_id == entity.short_id && suite.id == entity.suite.id
199
+ end
200
+ end
201
+ raise StandardError, "#{repo_symbol.to_s.humanize} #{short_id} not found."
202
+ end
203
+
204
+ def repo_symbol_to_array(repo_symbol)
205
+ case repo_symbol
206
+ when :group
207
+ [test_groups_repo]
208
+ when :test
209
+ [tests_repo]
210
+ when :group_or_test
211
+ [test_groups_repo, tests_repo]
212
+ else
213
+ raise StandardError, "Unrecognized repo_symbol #{repo_symbol} for `find_by_short_id`"
214
+ end
215
+ end
216
+
217
+ def thor_hash_to_suite_options_array(hash = {})
218
+ hash.to_a.map { |pair| Inferno::DSL::SuiteOption.new({ id: pair[0], value: pair[1] }) }
219
+ end
220
+
221
+ def thor_hash_to_inputs_array(hash = {})
222
+ hash.to_a.map { |pair| { name: pair[0], value: pair[1] } }
223
+ end
224
+
225
+ def print_error_and_exit(err, code)
226
+ outputter.print_error(options || {}, err)
227
+ rescue StandardError => e
228
+ puts "Caught exception #{e} while printing exception #{err}. Exiting."
229
+ ensure
230
+ exit(code)
231
+ end
232
+
233
+ def runnable_type(runnable)
234
+ if runnable < Inferno::TestSuite
235
+ :suite
236
+ elsif runnable < Inferno::TestGroup
237
+ :group
238
+ elsif runnable < Inferno::Test
239
+ :test
240
+ else
241
+ raise StandardError, "Unidentified runnable #{runnable}"
242
+ end
243
+ end
244
+
245
+ def runnable_id_key(runnable)
246
+ case runnable_type(runnable)
247
+ when :suite
248
+ :test_suite_id
249
+ when :group
250
+ :test_group_id
251
+ else
252
+ :test_id
253
+ end
254
+ end
255
+
256
+ def sort_results(results)
257
+ results.sort do |result, other|
258
+ if result.runnable < Inferno::TestSuite
259
+ -1
260
+ elsif other.runnable < Inferno::TestSuite
261
+ 1
262
+ else
263
+ result.runnable.short_id <=> other.runnable.short_id
264
+ end
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end
@@ -5,6 +5,7 @@ require_relative 'suite'
5
5
  require_relative 'suites'
6
6
  require_relative 'new'
7
7
  require_relative '../../version'
8
+ require_relative 'execute'
8
9
 
9
10
  module Inferno
10
11
  module CLI
@@ -65,18 +66,86 @@ module Inferno
65
66
  puts "Inferno Core v#{Inferno::VERSION}"
66
67
  end
67
68
 
69
+ EXECUTE_HELP = <<~END_OF_HELP.freeze
70
+ Run Inferno tests in the command line. Exits with 0 only if test entity passes.
71
+ Must be run with test kit as working directory.
72
+
73
+ You must have background services running: `bundle exec inferno services start`
74
+
75
+ You can view suite ids with: `bundle exec inferno suites`
76
+
77
+ Examples:
78
+
79
+ (These examples only work from within the inferno_core directory).
80
+
81
+ `bundle exec inferno execute --suite dev_validator \
82
+ --inputs "url:https://hapi.fhir.org/baseR4" \
83
+ patient_id:1234321`
84
+ => Outputs test results
85
+
86
+ `bundle exec inferno execute --suite dev_validator \
87
+ --inputs "url:https://hapi.fhir.org/baseR4" \
88
+ patient_id:1234321 \
89
+ --tests 1.01 1.02`
90
+ => Run specific tests from suite
91
+ END_OF_HELP
92
+ desc 'execute', 'Run Inferno tests in command line'
93
+ long_desc EXECUTE_HELP, wrap: false
94
+ option :suite,
95
+ aliases: ['-s'],
96
+ type: :string,
97
+ desc: 'Test suite id to run or to select groups and tests from',
98
+ banner: 'id'
99
+ option :suite_options,
100
+ aliases: ['-u'], # NOTE: -o will be for outputter
101
+ type: :hash,
102
+ desc: 'Suite options'
103
+ option :groups,
104
+ aliases: ['-g'],
105
+ type: :array,
106
+ desc: 'Series of test group short ids (AKA sequence number) to run, requires suite'
107
+ option :tests,
108
+ aliases: ['-t'],
109
+ type: :array,
110
+ desc: 'Series of test short ids (AKA sequence number) to run, requires suite'
111
+ option :short_ids,
112
+ aliases: ['-r'],
113
+ type: :array,
114
+ desc: 'Series of test or group short ids (AKA sequence number) to run, requires suite'
115
+ option :inputs,
116
+ aliases: ['-i'],
117
+ type: :hash,
118
+ desc: 'Inputs (i.e: --inputs=foo:bar goo:baz)'
119
+ option :verbose,
120
+ aliases: ['-v'],
121
+ type: :boolean,
122
+ default: false,
123
+ desc: 'Output additional information for debugging'
124
+ option :help,
125
+ aliases: ['-h'],
126
+ type: :boolean,
127
+ default: false,
128
+ desc: 'Display this message'
129
+ def execute
130
+ Execute.boot_full_inferno
131
+ Execute.new.run(options)
132
+ end
133
+
134
+ # https://github.com/rails/thor/issues/244 - Make Thor exit(1) on Errors/Exceptions
135
+ def self.exit_on_failure?
136
+ true
137
+ end
138
+
68
139
  private
69
140
 
70
141
  # https://github.com/rubocop/rubocop/issues/12571 - still affects Ruby 3.1 upto Rubocop 1.63
71
- # rubocop:disable Naming/BlockForwarding
72
- def without_bundler(&block)
142
+ def without_bundler(&)
73
143
  if defined?(Bundler) && ENV['BUNDLE_GEMFILE']
74
- Bundler.with_unbundled_env(&block)
144
+ Bundler.with_unbundled_env(&)
75
145
  else
76
146
  yield
77
147
  end
78
148
  end
79
- # rubocop:enable Naming/BlockForwarding
80
149
  end
81
150
  end
82
151
  end
@@ -1,2 +1,3 @@
1
1
  FHIR_RESOURCE_VALIDATOR_URL=http://localhost/hl7validatorapi
2
- REDIS_URL=redis://localhost:6379/0
2
+ REDIS_URL=redis://localhost:6379/0
3
+ FHIRPATH_URL=http://localhost/fhirpath
@@ -1,2 +1,3 @@
1
1
  REDIS_URL=redis://redis:6379/0
2
- FHIR_RESOURCE_VALIDATOR_URL=http://hl7_validator_service:3500
2
+ FHIR_RESOURCE_VALIDATOR_URL=http://hl7_validator_service:3500
3
+ FHIRPATH_URL=http://fhirpath:6789
@@ -1,2 +1,3 @@
1
1
  FHIR_RESOURCE_VALIDATOR_URL=https://example.com/validatorapi
2
2
  ASYNC_JOBS=false
3
+ FHIRPATH_URL=https://example.com/fhirpath
@@ -12,6 +12,7 @@
12
12
  .settings/org.eclipse.wst.jsdt.ui.superType.container
13
13
  .settings/org.eclipse.wst.jsdt.ui.superType.name
14
14
  .idea
15
+ *.gem
15
16
 
16
17
  /coverage
17
18
  /spec/examples.txt
@@ -98,5 +98,20 @@ http {
98
98
 
99
99
  proxy_pass http://hl7_validator_service:3500/;
100
100
  }
101
+
102
+ location /fhirpath/ {
103
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
104
+ proxy_set_header Host $http_host;
105
+ proxy_set_header X-Forwarded-Proto $scheme;
106
+ proxy_set_header X-Forwarded-Port $server_port;
107
+ proxy_redirect off;
108
+ proxy_set_header Connection '';
109
+ proxy_http_version 1.1;
110
+ chunked_transfer_encoding off;
111
+ proxy_buffering off;
112
+ proxy_cache off;
113
+
114
+ proxy_pass http://fhirpath:6789/;
115
+ }
101
116
  }
102
117
  }
@@ -23,6 +23,10 @@ services:
23
23
  environment:
24
24
  EXTERNAL_VALIDATOR_URL: http://localhost/validatorapi
25
25
  VALIDATOR_BASE_PATH: /validator
26
+ fhirpath:
27
+ image: infernocommunity/fhirpath-service
28
+ ports:
29
+ - "6789:6789"
26
30
  nginx:
27
31
  image: nginx
28
32
  volumes:
@@ -32,6 +36,7 @@ services:
32
36
  command: [nginx, '-g', 'daemon off;']
33
37
  depends_on:
34
38
  - fhir_validator_app
39
+ - fhirpath
35
40
  redis:
36
41
  image: redis
37
42
  ports:
@@ -27,6 +27,10 @@ services:
27
27
  extends:
28
28
  file: docker-compose.background.yml
29
29
  service: fhir_validator_app
30
+ fhirpath:
31
+ extends:
32
+ file: docker-compose.background.yml
33
+ service: fhirpath
30
34
  nginx:
31
35
  extends:
32
36
  file: docker-compose.background.yml
@@ -1,5 +1,4 @@
1
1
  require 'thor'
2
-
3
2
  require_relative 'cli/main'
4
3
 
5
4
  module Inferno
@@ -1,8 +1,14 @@
1
+ require_relative '../../../../utils/verify_runnable'
2
+ require_relative '../../../../utils/persist_inputs'
3
+
1
4
  module Inferno
2
5
  module Web
3
6
  module Controllers
4
7
  module TestRuns
5
8
  class Create < Controller
9
+ include ::Inferno::Utils::VerifyRunnable
10
+ include ::Inferno::Utils::PersistInputs
11
+
6
12
  include Import[
7
13
  test_sessions_repo: 'inferno.repositories.test_sessions',
8
14
  session_data_repo: 'inferno.repositories.session_data',
@@ -11,37 +17,6 @@ module Inferno
11
17
 
12
18
  PARAMS = [:test_session_id, :test_suite_id, :test_group_id, :test_id].freeze
13
19
 
14
- def verify_runnable(runnable, inputs, selected_suite_options)
15
- missing_inputs = runnable&.missing_inputs(inputs, selected_suite_options)
16
- user_runnable = runnable&.user_runnable?
17
- raise Inferno::Exceptions::RequiredInputsNotFound, missing_inputs if missing_inputs&.any?
18
- raise Inferno::Exceptions::NotUserRunnableException unless user_runnable
19
- end
20
-
21
- def persist_inputs(params, test_run)
22
- available_inputs = test_run.runnable.available_inputs
23
- params[:inputs]&.each do |input_params|
24
- input =
25
- available_inputs
26
- .find { |_, runnable_input| runnable_input.name == input_params[:name] }
27
- &.last
28
-
29
- if input.nil?
30
- Inferno::Application['logger'].warn(
31
- "Unknown input `#{input_params[:name]}` for #{test_run.runnable.id}: #{test_run.runnable.title}"
32
- )
33
- next
34
- end
35
-
36
- session_data_repo.save(
37
- test_session_id: test_run.test_session_id,
38
- name: input.name,
39
- value: input_params[:value],
40
- type: input.type
41
- )
42
- end
43
- end
44
-
45
20
  def handle(req, res)
46
21
  test_session = test_sessions_repo.find(req.params[:test_session_id])
47
22
 
@@ -60,7 +35,7 @@ module Inferno
60
35
 
61
36
  res.body = serialize(test_run, suite_options: test_session.suite_options)
62
37
 
63
- persist_inputs(req.params, test_run)
38
+ persist_inputs(session_data_repo, req.params, test_run)
64
39
 
65
40
  Jobs.perform(Jobs::ExecuteTestRun, test_run.id)
66
41
  rescue Sequel::ValidationFailed, Sequel::ForeignKeyConstraintViolation,
@@ -1,3 +1,6 @@
1
+ require 'oj'
2
+ require 'blueprinter'
3
+
1
4
  module Inferno
2
5
  module Web
3
6
  module Serializers