Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FI-2532: Add feature flag to toggle using HL7 validator wrapper #497

Merged
merged 3 commits into from
Mar 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,13 @@ G10_VALIDATOR_URL=http://validator_service:4567
G10_FHIR_RESOURCE_VALIDATOR_URL=http://hl7_validator_service:3500
REDIS_URL=redis://redis:6379/0

USE_HL7_RESOURCE_VALIDATOR=false
# To use the HL7 validator wrapper instead of the inferno validator wrapper, set the above to true,
# and uncomment the relevant settings in the following files:
# - docker-compose.yml -- "hl7_validator_service" section at the bottom
# - docker-compose.background.yml -- "hl7_validator_service" section at the bottom
# - nginx.background.conf -- "location /hl7validatorapi/" section at the bottom

# Full path to a custom JWKS json file, will use lib/onc_certification_g10_test_kit/bulk_data_jwks.json if left blank
# G10_BULK_DATA_JWKS=

Expand Down
39 changes: 21 additions & 18 deletions config/nginx.background.conf
Original file line number Diff line number Diff line change
Expand Up @@ -68,22 +68,7 @@ http {
# proxy_pass http://fhir_validator_app;
# }

# location /validatorapi/ {
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $http_host;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Forwarded-Port $server_port;
# proxy_redirect off;
# proxy_set_header Connection '';
# proxy_http_version 1.1;
# chunked_transfer_encoding off;
# proxy_buffering off;
# proxy_cache off;

# proxy_pass http://validator_service:4567/;
# }

location /hl7validatorapi/ {
location /validatorapi/ {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
Expand All @@ -94,9 +79,27 @@ http {
chunked_transfer_encoding off;
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 600s;

proxy_pass http://hl7_validator_service:3500/;
proxy_pass http://validator_service:4567/;
}


# To enable the HL7 Validator Wrapper, both the section below and
# the section in docker-compose.background.yml need to be uncommented
# location /hl7validatorapi/ {
# proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# proxy_set_header Host $http_host;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Forwarded-Port $server_port;
# proxy_redirect off;
# proxy_set_header Connection '';
# proxy_http_version 1.1;
# chunked_transfer_encoding off;
# proxy_buffering off;
# proxy_cache off;
# proxy_read_timeout 600s;
#
# proxy_pass http://hl7_validator_service:3500/;
# }
}
}
38 changes: 19 additions & 19 deletions docker-compose.background.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
version: '3'
services:
# validator_service:
# image: infernocommunity/fhir-validator-service:v2.3.2
# environment:
# - DISABLE_TX= true
# - DISPLAY_ISSUES_ARE_WARNINGS=true
# volumes:
# - ./lib/onc_certification_g10_test_kit/igs:/home/igs
validator_service:
image: infernocommunity/fhir-validator-service:v2.3.2
environment:
- DISABLE_TX= true
- DISPLAY_ISSUES_ARE_WARNINGS=true
volumes:
- ./lib/onc_certification_g10_test_kit/igs:/home/igs
# fhir_validator_app:
# image: infernocommunity/fhir-validator-app
# depends_on:
Expand All @@ -28,15 +28,15 @@ services:
volumes:
- ./data/redis:/data
command: redis-server --appendonly yes
hl7_validator_service:
# image: markiantorno/validator-wrapper
# If running on the MITRE network, comment out the "image" line above
# and uncomment the "build" section below
build:
context: .
dockerfile: Dockerfile.fhir_resource_validator
volumes:
- ./lib/onc_certification_g10_test_kit/igs:/home/igs
# To let the service share your local FHIR package cache,
# uncomment the below line
# - ~/.fhir:/home/ktor/.fhir
# hl7_validator_service:
# image: markiantorno/validator-wrapper
# # If running on the MITRE network, comment out the "image" line above
# # and uncomment the "build" section below
# # build:
# # context: .
# # dockerfile: Dockerfile.fhir_resource_validator
# volumes:
# - ./lib/onc_certification_g10_test_kit/igs:/home/igs
# # To let the service share your local FHIR package cache,
# # uncomment the below line
# # - ~/.fhir:/home/ktor/.fhir
20 changes: 10 additions & 10 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ services:
volumes:
- ./data:/opt/inferno/data
depends_on:
- hl7_validator_service
# - validator_service
# - hl7_validator_service
- validator_service
worker:
build:
context: ./
Expand All @@ -16,10 +16,10 @@ services:
command: bundle exec sidekiq -r ./worker.rb
depends_on:
- redis
# validator_service:
# extends:
# file: docker-compose.background.yml
# service: validator_service
validator_service:
extends:
file: docker-compose.background.yml
service: validator_service
# fhir_validator_app:
# extends:
# file: docker-compose.background.yml
Expand All @@ -34,7 +34,7 @@ services:
extends:
file: docker-compose.background.yml
service: redis
hl7_validator_service:
extends:
file: docker-compose.background.yml
service: hl7_validator_service
# hl7_validator_service:
# extends:
# file: docker-compose.background.yml
# service: hl7_validator_service
48 changes: 31 additions & 17 deletions lib/onc_certification_g10_test_kit.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ class G10CertificationSuite < Inferno::TestSuite
].freeze

ERROR_FILTERS = [
/\A\S+: \S+: Unknown Code/,
/\A\S+: \S+: Unknown [Cc]ode/,
/\A\S+: \S+: None of the codings provided are in the value set/,
/\A\S+: \S+: The code provided \(\S*\) is not in the value set/,
/\A\S+: \S+: The Coding provided \(\S*\) is not in the value set/,
Expand All @@ -72,35 +72,39 @@ class G10CertificationSuite < Inferno::TestSuite
/\A\S+: \S+: URL value '.*' does not resolve/
].freeze

[
G10Options::US_CORE_3_REQUIREMENT,
G10Options::US_CORE_4_REQUIREMENT,
G10Options::US_CORE_5_REQUIREMENT,
G10Options::US_CORE_6_REQUIREMENT
def self.setup_validator(us_core_version_requirement) # rubocop:disable Metrics/CyclomaticComplexity
validator_method = if Feature.use_hl7_resource_validator?
method(:fhir_resource_validator)
else
method(:validator)
end

validator_method.call :default, required_suite_options: us_core_version_requirement do
if Feature.use_hl7_resource_validator?
url ENV.fetch('G10_FHIR_RESOURCE_VALIDATOR_URL', 'http://hl7_validator_service:3500')

cli_context do
txServer nil
displayWarnings true
disableDefaultResourceFetcher true
end

].each do |us_core_version_requirement|
fhir_resource_validator :default, required_suite_options: us_core_version_requirement do
url ENV.fetch('G10_FHIR_RESOURCE_VALIDATOR_URL', 'http://hl7_validator_service:3500')
us_core_version_num = G10Options::US_CORE_VERSION_NUMBERS[us_core_version_requirement[:us_core_version]]

cli_context do
txServer nil
displayWarnings true
disableDefaultResourceFetcher true
igs("hl7.fhir.us.core##{us_core_version_num}")
else
url ENV.fetch('G10_VALIDATOR_URL', 'http://validator_service:4567')
end

us_core_message_filters =
case (us_core_version_requirement[:us_core_version])
when G10Options::US_CORE_3
igs('hl7.fhir.us.core#3.1.1')
USCoreTestKit::USCoreV311::USCoreTestSuite::VALIDATION_MESSAGE_FILTERS
when G10Options::US_CORE_4
igs('hl7.fhir.us.core#4.0.0')
USCoreTestKit::USCoreV400::USCoreTestSuite::VALIDATION_MESSAGE_FILTERS
when G10Options::US_CORE_5
igs('hl7.fhir.us.core#5.0.1')
USCoreTestKit::USCoreV501::USCoreTestSuite::VALIDATION_MESSAGE_FILTERS
when G10Options::US_CORE_6
igs('hl7.fhir.us.core#6.1.0')
USCoreTestKit::USCoreV610::USCoreTestSuite::VALIDATION_MESSAGE_FILTERS
end

Expand Down Expand Up @@ -159,6 +163,16 @@ class G10CertificationSuite < Inferno::TestSuite
end
end

[
G10Options::US_CORE_3_REQUIREMENT,
G10Options::US_CORE_4_REQUIREMENT,
G10Options::US_CORE_5_REQUIREMENT,
G10Options::US_CORE_6_REQUIREMENT

].each do |us_core_version_requirement|
setup_validator(us_core_version_requirement)
end

def self.jwks_json
bulk_data_jwks = JSON.parse(File.read(
ENV.fetch('G10_BULK_DATA_JWKS',
Expand Down
32 changes: 26 additions & 6 deletions lib/onc_certification_g10_test_kit/configuration_checker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

module ONCCertificationG10TestKit
class ConfigurationChecker
EXPECTED_VALIDATOR_VERSION = '"6.2.16-SNAPSHOT"'.freeze
EXPECTED_VALIDATOR_VERSION = '2.3.2'.freeze
EXPECTED_HL7_VALIDATOR_VERSION = '"6.2.16-SNAPSHOT"'.freeze

def configuration_messages
validator_version_message + terminology_messages + version_message
Expand All @@ -21,19 +22,38 @@ def validator_url
end

def validator_version_message
response = Faraday.get "#{validator_url}/validator/version"
version = response.body
if version == EXPECTED_VALIDATOR_VERSION
if Feature.use_hl7_resource_validator?
expected_validator_version = EXPECTED_HL7_VALIDATOR_VERSION
validator_version_url = "#{validator_url}/validator/version"
else
expected_validator_version = EXPECTED_VALIDATOR_VERSION
validator_version_url = "#{validator_url}/version"
end

response = Faraday.get validator_version_url
if response.body.starts_with? '{'
version_json = JSON.parse(response.body)
version = version_json['inferno-framework/fhir-validator-wrapper']
else
version = response.body
end

if version == expected_validator_version
[{
type: 'info',
message: "FHIR validator is the expected version `#{EXPECTED_VALIDATOR_VERSION}`"
message: "FHIR validator is the expected version `#{expected_validator_version}`"
}]
else
[{
type: 'error',
message: "Expected FHIR validator version `#{EXPECTED_VALIDATOR_VERSION}`, but found `#{version}`"
message: "Expected FHIR validator version `#{expected_validator_version}`, but found `#{version}`"
}]
end
rescue JSON::ParserError => e
[{
type: 'error',
message: "Unable to parse Validator version '`#{response.body}`'. Parser error: `#{e.message}`"
}]
rescue StandardError => e
[{
type: 'error',
Expand Down
9 changes: 4 additions & 5 deletions lib/onc_certification_g10_test_kit/feature.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
module ONCCertificationG10TestKit
module Feature
class << self # rubocop:disable Lint/EmptyClass
# This is how you can define feature flags to be used in the g10 test kit
# def us_core_v4?
# ENV.fetch('US_CORE_4_ENABLED', 'false')&.casecmp?('true')
# end
class << self
def use_hl7_resource_validator?
ENV.fetch('USE_HL7_RESOURCE_VALIDATOR', 'false')&.casecmp?('true')
end
end
end
end
7 changes: 7 additions & 0 deletions lib/onc_certification_g10_test_kit/g10_options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ module G10Options
US_CORE_5 = 'us_core_5'.freeze
US_CORE_6 = 'us_core_6'.freeze

US_CORE_VERSION_NUMBERS = {
US_CORE_3 => '3.1.1',
US_CORE_4 => '4.0.0',
US_CORE_5 => '5.0.1',
US_CORE_6 => '6.1.0'
}.freeze

BULK_DATA_1 = 'multi_patient_api_stu1'.freeze
BULK_DATA_2 = 'multi_patient_api_stu2'.freeze

Expand Down
42 changes: 42 additions & 0 deletions spec/fixtures/ValidationResponse-code-invalid-1.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"outcomes": [
{
"fileInfo": {
"fileName": "manually_entered_file.json",
"fileContent": "{\n \"resourceType\": \"Immunization\",\n \"subpotentReason\": [{\n \"coding\": [{\n \"system\": \"http://terminology.hl7.org/CodeSystem/immunization-subpotent-reason\",\n \"code\": \"partialdose\"\n }]\n }]\n}",
"fileType": "json"
},
"issues": [
{
"source": "TerminologyEngine",
"server": null,
"line": 3,
"col": 4,
"location": "Immunization.subpotentReason[0].coding[0].code",
"message": "Unknown code 'partialdose' in the CodeSystem 'http://terminology.hl7.org/CodeSystem/immunization-subpotent-reason' version '1.0.0'",
"messageId": null,
"type": "CODEINVALID",
"level": "ERROR",
"html": "Unknown code 'partialdose' in the CodeSystem 'http://terminology.hl7.org/CodeSystem/immunization-subpotent-reason' version '1.0.0'",
"locationLink": null,
"txLink": null,
"sliceHtml": null,
"sliceText": null,
"slicingHint": false,
"signpost": false,
"criticalSignpost": false,
"ruleDate": null,
"matched": false,
"ignorableError": false,
"invId": null,
"comment": null,
"sliceInfo": null,
"error": true,
"display": "ERROR: Immunization.subpotentReason[0].coding[0].code: Unknown code 'partialdose' in the CodeSystem 'http://terminology.hl7.org/CodeSystem/immunization-subpotent-reason' version '1.0.0'"
}
]
}
],
"sessionId": "f4af8f4f-15d0-44f3-8401-dc9f9014aeaf",
"validationTimes": {}
}
Loading