Skip to content

Commit

Permalink
FI-2532: Add feature flag to toggle using HL7 validator wrapper (#497)
Browse files Browse the repository at this point in the history
* FI-2532: add feature flag to switch between inferno validator and hl7 validator wrapper

* standardize name

* default hl7 validator to false and comment out its services
  • Loading branch information
dehall committed Mar 12, 2024
1 parent 7c56810 commit baa8ad2
Show file tree
Hide file tree
Showing 14 changed files with 403 additions and 118 deletions.
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

0 comments on commit baa8ad2

Please sign in to comment.