inferno_core 0.4.37 → 0.4.38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/inferno/apps/cli/console.rb +3 -0
- data/lib/inferno/apps/cli/main.rb +2 -0
- data/lib/inferno/apps/cli/migration.rb +2 -2
- data/lib/inferno/apps/cli/templates/.env.development +1 -1
- data/lib/inferno/apps/cli/templates/.env.production +1 -1
- data/lib/inferno/apps/cli/templates/.env.test +1 -1
- data/lib/inferno/apps/cli/templates/config/nginx.background.conf.tt +16 -0
- data/lib/inferno/apps/cli/templates/config/nginx.conf.tt +16 -0
- data/lib/inferno/apps/cli/templates/docker-compose.background.yml.tt +11 -0
- data/lib/inferno/apps/cli/templates/docker-compose.yml.tt +4 -0
- data/lib/inferno/apps/cli/templates/lib/%library_name%/igs/README.md +21 -0
- data/lib/inferno/apps/cli/templates/lib/%library_name%.rb.tt +7 -2
- data/lib/inferno/apps/cli/templates/spec/%library_name%/patient_group_spec.rb.tt +25 -6
- data/lib/inferno/config/boot/sidekiq.rb +5 -0
- data/lib/inferno/config/boot/validator.rb +2 -0
- data/lib/inferno/dsl/resume_test_route.rb +59 -20
- data/lib/inferno/dsl/runnable.rb +1 -1
- data/lib/inferno/dsl/suite_endpoint.rb +1 -1
- data/lib/inferno/jobs/invoke_validator_session.rb +1 -0
- data/lib/inferno/public/bundle.js +2 -2
- data/lib/inferno/version.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e2af0569e09addd1d815e42110f9813a875037b66a67871af0441a149b38c818
|
4
|
+
data.tar.gz: 4b526226bac3009548c7e70b75b59dc77e9c800700eed13e13846d30cbc79161
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c0ab492c234d9a19ee06cca497a1e9714238bd1b7b0a2765b3647a49e0f3125a7a3b3f73e025e9741ec71b67c695d78258480d22aaf8974f8002b0354a0c0bdc
|
7
|
+
data.tar.gz: 241271ec1ef24731b06446dd442485fb8053f43504e3948a29077e26358b6b515102f41671336577c54b6705cb3858b7c59e0ac53819eadde5243ea98c16f8b2
|
@@ -11,6 +11,7 @@ module Inferno
|
|
11
11
|
class Main < Thor
|
12
12
|
desc 'console', 'Start an interactive console session with Inferno'
|
13
13
|
def console
|
14
|
+
Migration.new.run(Logger::INFO)
|
14
15
|
Console.new.run
|
15
16
|
end
|
16
17
|
|
@@ -25,6 +26,7 @@ module Inferno
|
|
25
26
|
type: :boolean,
|
26
27
|
desc: 'Automatically restart Inferno when a file is changed.'
|
27
28
|
def start
|
29
|
+
Migration.new.run(Logger::INFO)
|
28
30
|
command = 'foreman start --env=/dev/null'
|
29
31
|
if `gem list -i foreman`.chomp == 'false'
|
30
32
|
puts "You must install foreman with 'gem install foreman' prior to running Inferno."
|
@@ -3,9 +3,9 @@ require_relative '../../utils/migration'
|
|
3
3
|
module Inferno
|
4
4
|
module CLI
|
5
5
|
class Migration
|
6
|
-
def run
|
6
|
+
def run(log_level = Logger::DEBUG)
|
7
7
|
Inferno::Application.start(:logging)
|
8
|
-
Inferno::Application['logger'].level =
|
8
|
+
Inferno::Application['logger'].level = log_level
|
9
9
|
|
10
10
|
Utils::Migration.new.run
|
11
11
|
end
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
1
|
+
FHIR_RESOURCE_VALIDATOR_URL=http://localhost/hl7validatorapi
|
2
2
|
REDIS_URL=redis://localhost:6379/0
|
@@ -1,2 +1,2 @@
|
|
1
1
|
REDIS_URL=redis://redis:6379/0
|
2
|
-
|
2
|
+
FHIR_RESOURCE_VALIDATOR_URL=http://hl7_validator_service:3500
|
@@ -1,2 +1,2 @@
|
|
1
|
-
|
1
|
+
FHIR_RESOURCE_VALIDATOR_URL=https://example.com/validatorapi
|
2
2
|
ASYNC_JOBS=false
|
@@ -82,5 +82,21 @@ http {
|
|
82
82
|
|
83
83
|
proxy_pass http://validator_service:4567/;
|
84
84
|
}
|
85
|
+
|
86
|
+
location /hl7validatorapi/ {
|
87
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
88
|
+
proxy_set_header Host $http_host;
|
89
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
90
|
+
proxy_set_header X-Forwarded-Port $server_port;
|
91
|
+
proxy_redirect off;
|
92
|
+
proxy_set_header Connection '';
|
93
|
+
proxy_http_version 1.1;
|
94
|
+
chunked_transfer_encoding off;
|
95
|
+
proxy_buffering off;
|
96
|
+
proxy_cache off;
|
97
|
+
proxy_read_timeout 600s;
|
98
|
+
|
99
|
+
proxy_pass http://hl7_validator_service:3500/;
|
100
|
+
}
|
85
101
|
}
|
86
102
|
}
|
@@ -97,5 +97,21 @@ http {
|
|
97
97
|
|
98
98
|
proxy_pass http://validator_service:4567/;
|
99
99
|
}
|
100
|
+
|
101
|
+
location /hl7validatorapi/ {
|
102
|
+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
103
|
+
proxy_set_header Host $http_host;
|
104
|
+
proxy_set_header X-Forwarded-Proto $scheme;
|
105
|
+
proxy_set_header X-Forwarded-Port $server_port;
|
106
|
+
proxy_redirect off;
|
107
|
+
proxy_set_header Connection '';
|
108
|
+
proxy_http_version 1.1;
|
109
|
+
chunked_transfer_encoding off;
|
110
|
+
proxy_buffering off;
|
111
|
+
proxy_cache off;
|
112
|
+
proxy_read_timeout 600s;
|
113
|
+
|
114
|
+
proxy_pass http://hl7_validator_service:3500/;
|
115
|
+
}
|
100
116
|
}
|
101
117
|
}
|
@@ -1,5 +1,16 @@
|
|
1
1
|
version: '3'
|
2
2
|
services:
|
3
|
+
hl7_validator_service:
|
4
|
+
image: infernocommunity/inferno-resource-validator
|
5
|
+
environment:
|
6
|
+
# Defines how long validator sessions last if unused, in minutes:
|
7
|
+
# Negative values mean sessions never expire, 0 means sessions immediately expire
|
8
|
+
SESSION_CACHE_DURATION: -1
|
9
|
+
volumes:
|
10
|
+
- ./<%= ig_path %>:/app/igs
|
11
|
+
# To let the service share your local FHIR package cache,
|
12
|
+
# uncomment the below line
|
13
|
+
# - ~/.fhir:/home/ktor/.fhir
|
3
14
|
validator_service:
|
4
15
|
image: infernocommunity/fhir-validator-service
|
5
16
|
# Update this path to match your directory structure
|
@@ -15,6 +15,10 @@ services:
|
|
15
15
|
command: bundle exec sidekiq -r ./worker.rb
|
16
16
|
depends_on:
|
17
17
|
- redis
|
18
|
+
hl7_validator_service:
|
19
|
+
extends:
|
20
|
+
file: docker-compose.background.yml
|
21
|
+
service: hl7_validator_service
|
18
22
|
validator_service:
|
19
23
|
extends:
|
20
24
|
file: docker-compose.background.yml
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Note on this IGs folder
|
2
|
+
|
3
|
+
There are three reasons why it would be necessary to put an IG package.tgz in this folder. If none of these apply, you do not need to put any files here, or can consider removing any existing files to make it clear they are unused.
|
4
|
+
|
5
|
+
## 1. Generated Test Suites
|
6
|
+
Some test kits use a "generator" to automatically generate the contents of a test suite for an IG. The IG files are required every time the test suites need to be regenerated. Examples of test kits that use this approach are the US Core Test Kit and CARIN IG for Blue Button® Test Kit.
|
7
|
+
|
8
|
+
|
9
|
+
## 2. Non-published IG
|
10
|
+
If your IG, or the specific version of the IG you want to test against, is not published, then the validator service needs to load the IG from file in order to be able to validate resources with it. The IG must be referenced in the `fhir_resource_validator` block in the test suite definition by filename, ie:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
fhir_resource_validator do
|
14
|
+
igs 'igs/filename.tgz'
|
15
|
+
|
16
|
+
...
|
17
|
+
end
|
18
|
+
```
|
19
|
+
|
20
|
+
## 3. Inferno Validator UI
|
21
|
+
The Inferno Validator UI is configured to auto-load any IGs present in the igs folder and include them in all validations. In general, the Inferno team is currently leaving IGs in this folder even if not otherwise necessary to make it easy to re-enable the validator UI.
|
@@ -22,8 +22,13 @@ module <%= module_name %>
|
|
22
22
|
end
|
23
23
|
|
24
24
|
# All FHIR validation requsets will use this FHIR validator
|
25
|
-
|
26
|
-
|
25
|
+
fhir_resource_validator do
|
26
|
+
# igs 'identifier#version' # Use this method for published IGs/versions
|
27
|
+
# igs 'igs/filename.tgz' # Use this otherwise
|
28
|
+
|
29
|
+
exclude_message do |message|
|
30
|
+
message.message.match?(/\A\S+: \S+: URL value '.*' does not resolve/)
|
31
|
+
end
|
27
32
|
end
|
28
33
|
|
29
34
|
# Tests and TestGroups can be defined inline
|
@@ -4,7 +4,26 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
4
4
|
let(:session_data_repo) { Inferno::Repositories::SessionData.new }
|
5
5
|
let(:test_session) { repo_create(:test_session, test_suite_id: '<%= test_suite_id %>') }
|
6
6
|
let(:url) { 'http://example.com/fhir' }
|
7
|
-
let(:
|
7
|
+
let(:success_outcome) do
|
8
|
+
{
|
9
|
+
outcomes: [{
|
10
|
+
issues: []
|
11
|
+
}],
|
12
|
+
sessionId: ''
|
13
|
+
}
|
14
|
+
end
|
15
|
+
let(:error_outcome) do
|
16
|
+
{
|
17
|
+
outcomes: [{
|
18
|
+
issues: [{
|
19
|
+
location: 'Patient.identifier[0]',
|
20
|
+
message: 'Identifier.system must be an absolute reference, not a local reference',
|
21
|
+
level: 'ERROR'
|
22
|
+
}]
|
23
|
+
}],
|
24
|
+
sessionId: ''
|
25
|
+
}
|
26
|
+
end
|
8
27
|
|
9
28
|
def run(runnable, inputs = {})
|
10
29
|
test_run_params = { test_session_id: test_session.id }.merge(runnable.reference_hash)
|
@@ -67,9 +86,9 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
67
86
|
let(:test) { group.tests.last }
|
68
87
|
|
69
88
|
it 'passes if the resource is valid' do
|
70
|
-
stub_request(:post, "#{ENV.fetch('
|
89
|
+
stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate")
|
71
90
|
.with(query: hash_including({}))
|
72
|
-
.to_return(status: 200, body:
|
91
|
+
.to_return(status: 200, body: success_outcome.to_json)
|
73
92
|
|
74
93
|
resource = FHIR::Patient.new
|
75
94
|
repo_create(
|
@@ -79,13 +98,13 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
79
98
|
response_body: resource.to_json
|
80
99
|
)
|
81
100
|
|
82
|
-
result = run(test)
|
101
|
+
result = run(test, url: url)
|
83
102
|
|
84
103
|
expect(result.result).to eq('pass')
|
85
104
|
end
|
86
105
|
|
87
106
|
it 'fails if the resource is not valid' do
|
88
|
-
stub_request(:post, "#{ENV.fetch('
|
107
|
+
stub_request(:post, "#{ENV.fetch('FHIR_RESOURCE_VALIDATOR_URL')}/validate")
|
89
108
|
.with(query: hash_including({}))
|
90
109
|
.to_return(status: 200, body: error_outcome.to_json)
|
91
110
|
|
@@ -97,7 +116,7 @@ RSpec.describe <%= module_name %>::PatientGroup do
|
|
97
116
|
response_body: resource.to_json
|
98
117
|
)
|
99
118
|
|
100
|
-
result = run(test)
|
119
|
+
result = run(test, url: url)
|
101
120
|
|
102
121
|
expect(result.result).to eq('fail')
|
103
122
|
end
|
@@ -5,6 +5,11 @@ Inferno::Application.register_provider(:sidekiq) do
|
|
5
5
|
if Inferno::Application['async_jobs']
|
6
6
|
Sidekiq.configure_server do |config|
|
7
7
|
config.redis = { url: ENV.fetch('REDIS_URL', 'redis://127.0.0.1:6379/0') }
|
8
|
+
|
9
|
+
config.capsule('validator_sessions') do |cap|
|
10
|
+
cap.concurrency = ENV.fetch('VALIDATOR_SESSIONS_CONCURRENCY', '1').to_i
|
11
|
+
cap.queues = ['validator_sessions']
|
12
|
+
end
|
8
13
|
end
|
9
14
|
end
|
10
15
|
end
|
@@ -8,6 +8,8 @@ Inferno::Application.register_provider(:validator) do
|
|
8
8
|
|
9
9
|
next if ENV['APP_ENV'] == 'test'
|
10
10
|
|
11
|
+
next if ENV.fetch('INITIALIZE_VALIDATOR_SESSIONS', 'true').casecmp?('false')
|
12
|
+
|
11
13
|
Inferno::Repositories::TestSuites.new.all.each do |suite|
|
12
14
|
suite.fhir_validators.each do |name, validators|
|
13
15
|
validators.each_with_index do |validator, index|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require 'hanami/controller'
|
2
2
|
|
3
3
|
module Inferno
|
4
4
|
module DSL
|
@@ -6,47 +6,58 @@ module Inferno
|
|
6
6
|
# an incoming request.
|
7
7
|
# @private
|
8
8
|
# @see Inferno::DSL::Runnable#resume_test_route
|
9
|
-
class ResumeTestRoute <
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
9
|
+
class ResumeTestRoute < Hanami::Action
|
10
|
+
include Import[
|
11
|
+
requests_repo: 'inferno.repositories.requests',
|
12
|
+
results_repo: 'inferno.repositories.results',
|
13
|
+
test_runs_repo: 'inferno.repositories.test_runs',
|
14
|
+
tests_repo: 'inferno.repositories.tests'
|
15
|
+
]
|
16
|
+
|
17
|
+
def self.call(...)
|
18
|
+
new.call(...)
|
15
19
|
end
|
16
20
|
|
17
21
|
# @private
|
18
|
-
def
|
19
|
-
|
22
|
+
def test_run_identifier_block
|
23
|
+
self.class.singleton_class.instance_variable_get(:@test_run_identifier_block)
|
20
24
|
end
|
21
25
|
|
22
26
|
# @private
|
23
27
|
def tags
|
24
|
-
self.class.singleton_class.instance_variable_get(:@tags)
|
28
|
+
self.class.singleton_class.instance_variable_get(:@tags)
|
25
29
|
end
|
26
30
|
|
27
31
|
# @private
|
28
|
-
def
|
29
|
-
|
32
|
+
def result
|
33
|
+
self.class.singleton_class.instance_variable_get(:@result)
|
30
34
|
end
|
31
35
|
|
32
36
|
# @private
|
33
|
-
def
|
34
|
-
|
37
|
+
def find_test_run(test_run_identifier)
|
38
|
+
test_runs_repo.find_latest_waiting_by_identifier(test_run_identifier)
|
35
39
|
end
|
36
40
|
|
37
41
|
# @private
|
38
|
-
def
|
39
|
-
|
42
|
+
def find_waiting_result(test_run)
|
43
|
+
results_repo.find_waiting_result(test_run_id: test_run.id)
|
40
44
|
end
|
41
45
|
|
42
46
|
# @private
|
43
|
-
def
|
44
|
-
|
47
|
+
def update_result(waiting_result)
|
48
|
+
results_repo.update_result(waiting_result.id, result)
|
45
49
|
end
|
46
50
|
|
47
51
|
# @private
|
48
|
-
def
|
49
|
-
|
52
|
+
def persist_request(request, test_run, waiting_result, test)
|
53
|
+
requests_repo.create(
|
54
|
+
request.to_hash.merge(
|
55
|
+
test_session_id: test_run.test_session_id,
|
56
|
+
result_id: waiting_result.id,
|
57
|
+
name: test.config.request_name(test.incoming_request_name),
|
58
|
+
tags:
|
59
|
+
)
|
60
|
+
)
|
50
61
|
end
|
51
62
|
|
52
63
|
# @private
|
@@ -54,10 +65,38 @@ module Inferno
|
|
54
65
|
"#{Application['base_url']}/test_sessions/#{test_run.test_session_id}##{resume_ui_at_id(test_run, test)}"
|
55
66
|
end
|
56
67
|
|
68
|
+
# @private
|
69
|
+
def find_test(waiting_result)
|
70
|
+
tests_repo.find(waiting_result.test_id)
|
71
|
+
end
|
72
|
+
|
57
73
|
# @private
|
58
74
|
def resume_ui_at_id(test_run, test)
|
59
75
|
test_run.test_suite_id || test_run.test_group_id || test.parent.id
|
60
76
|
end
|
77
|
+
|
78
|
+
# @private
|
79
|
+
def handle(req, res)
|
80
|
+
request = Inferno::Entities::Request.from_hanami_request(req)
|
81
|
+
|
82
|
+
test_run_identifier = instance_exec(request, &test_run_identifier_block)
|
83
|
+
|
84
|
+
test_run = find_test_run(test_run_identifier)
|
85
|
+
|
86
|
+
halt 500, "Unable to find test run with identifier '#{test_run_identifier}'." if test_run.nil?
|
87
|
+
|
88
|
+
test_runs_repo.mark_as_no_longer_waiting(test_run.id)
|
89
|
+
|
90
|
+
waiting_result = find_waiting_result(test_run)
|
91
|
+
test = find_test(waiting_result)
|
92
|
+
|
93
|
+
update_result(waiting_result)
|
94
|
+
persist_request(request, test_run, waiting_result, test)
|
95
|
+
|
96
|
+
Jobs.perform(Jobs::ResumeTestRun, test_run.id)
|
97
|
+
|
98
|
+
res.redirect_to redirect_route(test_run, test)
|
99
|
+
end
|
61
100
|
end
|
62
101
|
end
|
63
102
|
end
|
data/lib/inferno/dsl/runnable.rb
CHANGED
@@ -343,7 +343,7 @@ module Inferno
|
|
343
343
|
route_class = Class.new(ResumeTestRoute) do |klass|
|
344
344
|
klass.singleton_class.instance_variable_set(:@test_run_identifier_block, block)
|
345
345
|
klass.singleton_class.instance_variable_set(:@tags, tags)
|
346
|
-
klass.singleton_class.instance_variable_set(:@
|
346
|
+
klass.singleton_class.instance_variable_set(:@result, result)
|
347
347
|
end
|
348
348
|
|
349
349
|
route(method, path, route_class)
|