diff --git a/.gitignore b/.gitignore index 844ff2d825..9f56b19cfd 100644 --- a/.gitignore +++ b/.gitignore @@ -278,4 +278,5 @@ ready-for-integration.sh update-pr.sh /chpl/chpl-api/e2e/env/*.postman_environment.json newman/ +/Servers Servers/ diff --git a/chpl/chpl-api/src/main/java/gov/healthit/chpl/web/controller/OnDemandUrlCheckerController.java b/chpl/chpl-api/src/main/java/gov/healthit/chpl/web/controller/OnDemandUrlCheckerController.java new file mode 100644 index 0000000000..5f002c7de3 --- /dev/null +++ b/chpl/chpl-api/src/main/java/gov/healthit/chpl/web/controller/OnDemandUrlCheckerController.java @@ -0,0 +1,46 @@ +package gov.healthit.chpl.web.controller; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RestController; + +import com.datadog.api.client.ApiException; + +import gov.healthit.chpl.datadog.OnDemandUrlCheckerManager; +import gov.healthit.chpl.datadog.OnDemandUrlCheckerResponse; +import gov.healthit.chpl.datadog.OnDemandUrlRequest; +import gov.healthit.chpl.exception.ValidationException; +import gov.healthit.chpl.util.SwaggerSecurityRequirement; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.security.SecurityRequirement; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Tag(name = "urls", description = "") +@RestController +@RequestMapping("/urls") +public class OnDemandUrlCheckerController { + + private OnDemandUrlCheckerManager onDemandUrlCheckerManager; + + @Autowired + public OnDemandUrlCheckerController(OnDemandUrlCheckerManager onDemandUrlCheckerManager) { + this.onDemandUrlCheckerManager = onDemandUrlCheckerManager; + } + + @Operation(summary = "Validates a URL. Three checks are performed: 1) HTTP Status code is 200, 2) Response time is less than 30 seconds, and 3) Response body is not empty.", + description = "Security Restrictions: chpl-admin, chpl-onc, or chpl-onc-acb", + security = { + @SecurityRequirement(name = SwaggerSecurityRequirement.API_KEY), + @SecurityRequirement(name = SwaggerSecurityRequirement.BEARER) + }) + @RequestMapping(value = "/validate", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE, produces = "application/json; charset=utf-8") + public OnDemandUrlCheckerResponse checkUrl(@RequestBody OnDemandUrlRequest url) throws InterruptedException, ApiException, ValidationException { + return onDemandUrlCheckerManager.checkUrl(url.getUrl()); + } + +} diff --git a/chpl/chpl-resources/src/main/resources/errors.properties b/chpl/chpl-resources/src/main/resources/errors.properties index c9dbbe6263..a1ce2768c1 100644 --- a/chpl/chpl-resources/src/main/resources/errors.properties +++ b/chpl/chpl-resources/src/main/resources/errors.properties @@ -649,6 +649,8 @@ listing.realWorldTesting.eligibilityYearNotUpdatable=Real World Eligibility Year listing.svap.url.invalid=SVAP Notice URL is not a well formed URL. +onDemandUrlTest.invalidUrl=URL to test is not a well formed URL. + job.missingRequiredData=%s must be specified for every job. job.doesNotExist=The job with ID %s does not exist. job.exists=A job with ID %s already exists. diff --git a/chpl/chpl-service/pom.xml b/chpl/chpl-service/pom.xml index c42a0084b2..5290e30f04 100644 --- a/chpl/chpl-service/pom.xml +++ b/chpl/chpl-service/pom.xml @@ -383,7 +383,7 @@ provided - + org.springframework.boot @@ -419,6 +419,13 @@ 0.4.0 + + + dev.failsafe + failsafe + 3.3.2 + + org.junit.jupiter diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerAssertionResult.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerAssertionResult.java new file mode 100644 index 0000000000..b5a3e1cccf --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerAssertionResult.java @@ -0,0 +1,11 @@ +package gov.healthit.chpl.datadog; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class OnDemandUrlCheckerAssertionResult { + private Boolean passed; + private String actualValue; +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerManager.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerManager.java new file mode 100644 index 0000000000..522f721668 --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerManager.java @@ -0,0 +1,202 @@ +package gov.healthit.chpl.datadog; + +import java.time.Duration; +import java.util.List; +import java.util.Map; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.stereotype.Component; + +import com.datadog.api.client.ApiException; +import com.datadog.api.client.v1.model.SyntheticsAPITest; +import com.datadog.api.client.v1.model.SyntheticsAPITestResultFull; +import com.datadog.api.client.v1.model.SyntheticsApiTestFailureCode; +import com.datadog.api.client.v1.model.SyntheticsGetAPITestLatestResultsResponse; +import com.datadog.api.client.v1.model.SyntheticsTriggerBody; +import com.datadog.api.client.v1.model.SyntheticsTriggerTest; + +import dev.failsafe.Failsafe; +import dev.failsafe.RetryPolicy; +import gov.healthit.chpl.exception.ValidationException; +import gov.healthit.chpl.scheduler.job.urluptime.DatadogSyntheticsTestResultService; +import gov.healthit.chpl.scheduler.job.urluptime.DatadogSyntheticsTestService; +import gov.healthit.chpl.util.ErrorMessageUtil; +import gov.healthit.chpl.util.ValidationUtils; +import lombok.extern.log4j.Log4j2; + +@Log4j2 +@Component +public class OnDemandUrlCheckerManager { + public static final Long TEMP_DEVELOPER_ID = -99L; + private static final Integer MAX_ATTEMPTS = 45; + private static final Integer MAX_SECONDS = 45; + private static final String ASSERTION_RESULTS_KEY = "assertionResults"; + private static final String TYPE_KEY = "type"; + private static final String ACTUAL_KEY = "actual"; + private static final String VALID_KEY = "valid"; + private static final String TYPE_VALUE_STATUS_CODE = "statusCode"; + private static final String TYPE_VALUE_BODY = "body"; + private static final String TYPE_VALUE_RESPONSE_TIME = "responseTime"; + + private List errorsToIgnore = List.of("BODY_TOO_LARGE_TO_PROCESS"); + + private DatadogSyntheticsTestService datadogSyntheticsTestService; + private DatadogSyntheticsTestResultService datadogSyntheticsTestResultService; + private ValidationUtils validationUtils; + private ErrorMessageUtil errorMessageUtil; + + @Autowired + public OnDemandUrlCheckerManager(DatadogSyntheticsTestService datadogSyntheticsTestService, DatadogSyntheticsTestResultService datadogSyntheticsTestResultService, + ValidationUtils validationUtils, ErrorMessageUtil errorMessageUtil) { + this.datadogSyntheticsTestService = datadogSyntheticsTestService; + this.datadogSyntheticsTestResultService = datadogSyntheticsTestResultService; + this.validationUtils = validationUtils; + this.errorMessageUtil = errorMessageUtil; + } + + @PreAuthorize("@permissions.hasAccess(T(gov.healthit.chpl.permissions.Permissions).URL_CHECKER, " + + "T(gov.healthit.chpl.permissions.domains.UrlCheckerDomainPermissions).CHECK)") + public OnDemandUrlCheckerResponse checkUrl(String url) throws ApiException, ValidationException { + SyntheticsAPITest test = null; + validateUrlWellFormed(url); + try { + test = createTest(url); + triggerTest(test); + SyntheticsGetAPITestLatestResultsResponse result = awaitTestResults(test); + OnDemandUrlCheckerResponse response = analyzeTestResults(result, test); + return response; + } finally { + try { + LOGGER.info("Completed On Demand URL Check"); + if (test != null) { + LOGGER.info("Deleting On Demand URL Check: {}", test.getPublicId()); + datadogSyntheticsTestService.deleteSyntheticsTests(List.of(test.getPublicId())); + LOGGER.info("Deleted On Demand URL Check: {}", test.getPublicId()); + } + } catch (Exception e) { + LOGGER.error("Failed to delete On Demand URL Check", e); + } + + } + } + + private void validateUrlWellFormed(String url) throws ValidationException { + if (!validationUtils.isWellFormedUrl(url)) { + throw new ValidationException(errorMessageUtil.getMessage("onDemandUrlTest.invalidUrl")); + } + } + + private SyntheticsAPITest createTest(String url) { + LOGGER.info("Creating On Demand URL Check for: {}", url); + var x = datadogSyntheticsTestService.createSyntheticsTest(url, List.of(TEMP_DEVELOPER_ID)); + LOGGER.info("Created On Demand URL Check: {}", x.getPublicId()); + return x; + } + + private void triggerTest(SyntheticsAPITest test) throws ApiException { + LOGGER.info("Triggering On Demand URL Check"); + SyntheticsTriggerBody body = new SyntheticsTriggerBody() + .tests(List.of(new SyntheticsTriggerTest().publicId(test.getPublicId()))); + + datadogSyntheticsTestService.getApiProvider().getApiInstance().triggerTests(body); + } + + private SyntheticsGetAPITestLatestResultsResponse awaitTestResults(SyntheticsAPITest test) throws ApiException { + LOGGER.info("Awaiting On Demand URL Check"); + RetryPolicy retryPolicy = RetryPolicy.builder() + .withMaxAttempts(MAX_ATTEMPTS) + .withDelay(Duration.ofSeconds(1)) + .withMaxDuration(Duration.ofSeconds(MAX_SECONDS)) + .onRetry(e -> LOGGER.info("Failure #{}. Retrying.", e.getAttemptCount())) + .onSuccess(e -> LOGGER.info("Success #{}.", e.getAttemptCount())) + .handleResultIf(res -> res == null || res.getResults().size() == 0) + .build(); + + return Failsafe.with(retryPolicy) + .get(() -> datadogSyntheticsTestResultService.getSyntheticsTestResults(test.getPublicId())); + } + + private OnDemandUrlCheckerResponse analyzeTestResults(SyntheticsGetAPITestLatestResultsResponse result, SyntheticsAPITest test) throws ApiException { + SyntheticsAPITestResultFull fullTestResults = null; + OnDemandUrlCheckerResponse response = null; + if (result != null + && result.getResults().size() > 0) { + fullTestResults = datadogSyntheticsTestResultService.getDetailedTestResult(test.getPublicId(), result.getResults().get(0).getResultId()); + response = convertToResponse(test.getConfig().getRequest().getUrl(), fullTestResults); + if (fullTestResults.getResult().getFailure() != null + && isErrorIgnorable(fullTestResults.getResult().getFailure().getCode())) { + response.setPassed(true); + response.setErrorMessage(""); + } else { + response.setPassed(result.getResults().get(0).getResult().getPassed()); + if (!result.getResults().get(0).getResult().getPassed()) { + response.setErrorMessage(fullTestResults.getResult().getFailure().getMessage()); + } + } + } else { + throw new ApiException("No results found for test " + test.getPublicId()); + } + return response; + } + + private OnDemandUrlCheckerResponse convertToResponse(String url, SyntheticsAPITestResultFull fullTestResults) { + if (doAdditionalPropertiesExist(fullTestResults)) { + if (fullTestResults.getResult().getFailure() != null + && isErrorIgnorable(fullTestResults.getResult().getFailure().getCode())) { + return OnDemandUrlCheckerResponse.builder() + .httpResponseAssertion(OnDemandUrlCheckerAssertionResult.builder().passed(true).actualValue("").build()) + .responseTimeAssertion(OnDemandUrlCheckerAssertionResult.builder().passed(true).actualValue("").build()) + .bodyNotEmptyAssertion(OnDemandUrlCheckerAssertionResult.builder().passed(true).actualValue("").build()) + .url(url) + .build(); + } + return OnDemandUrlCheckerResponse.builder() + .httpResponseAssertion(getAssertionResult(fullTestResults.getResult().getAdditionalProperties(), TYPE_VALUE_STATUS_CODE)) + .responseTimeAssertion(getAssertionResult(fullTestResults.getResult().getAdditionalProperties(), TYPE_VALUE_RESPONSE_TIME)) + .bodyNotEmptyAssertion(getAssertionResult(fullTestResults.getResult().getAdditionalProperties(), TYPE_VALUE_BODY)) + .url(url) + .build(); + } else { + return OnDemandUrlCheckerResponse.builder() + .url(url) + .build(); + } + } + + private OnDemandUrlCheckerAssertionResult getAssertionResult(Map results, String value) { + if (results.containsKey(ASSERTION_RESULTS_KEY) + && results.get(ASSERTION_RESULTS_KEY) instanceof List) { + + return ((List) results.get(ASSERTION_RESULTS_KEY)).stream() + .filter(map -> map instanceof Map) + .filter(map -> ((Map) map).containsKey(TYPE_KEY) + && ((Map) map).containsKey(VALID_KEY) + && ((String) ((Map) map).get(TYPE_KEY)).equals(value)) + + .findAny() + .map(map -> OnDemandUrlCheckerAssertionResult.builder() + .passed((Boolean) ((Map) map).get(VALID_KEY)) + .actualValue(((Map) map).containsKey(ACTUAL_KEY) ? ((Map) map).get(ACTUAL_KEY).toString() : "") + .build()) + .orElse(OnDemandUrlCheckerAssertionResult.builder() + .passed(false) + .actualValue("Unknown") + .build()); + } + return null; + } + + private Boolean doAdditionalPropertiesExist(SyntheticsAPITestResultFull fullTestResults) { + return fullTestResults.getResult().getAdditionalProperties().containsKey(ASSERTION_RESULTS_KEY) + && fullTestResults.getResult().getAdditionalProperties().get(ASSERTION_RESULTS_KEY) instanceof List; + } + + private boolean isErrorIgnorable(SyntheticsApiTestFailureCode errorCode) { + return errorsToIgnore.stream() + .filter(code -> code.equals(errorCode.getValue())) + .findAny() + .isPresent(); + } + +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerResponse.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerResponse.java new file mode 100644 index 0000000000..1fd973b2d9 --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlCheckerResponse.java @@ -0,0 +1,15 @@ +package gov.healthit.chpl.datadog; + +import lombok.Builder; +import lombok.Data; + +@Data +@Builder +public class OnDemandUrlCheckerResponse { + private String url; + private String errorMessage; + private Boolean passed; + private OnDemandUrlCheckerAssertionResult responseTimeAssertion; + private OnDemandUrlCheckerAssertionResult bodyNotEmptyAssertion; + private OnDemandUrlCheckerAssertionResult httpResponseAssertion; +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlRequest.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlRequest.java new file mode 100644 index 0000000000..3d0c0b7ccc --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/datadog/OnDemandUrlRequest.java @@ -0,0 +1,18 @@ +package gov.healthit.chpl.datadog; + +import java.io.Serializable; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class OnDemandUrlRequest implements Serializable { + private static final long serialVersionUID = -3009297190983937267L; + + private String url; +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/Permissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/Permissions.java index f766a307c1..9b0eddcb16 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/Permissions.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/Permissions.java @@ -39,6 +39,7 @@ import gov.healthit.chpl.permissions.domains.TestToolDomainPermissions; import gov.healthit.chpl.permissions.domains.TestingLabDomainPermissions; import gov.healthit.chpl.permissions.domains.UcdProcessDomainPermissions; +import gov.healthit.chpl.permissions.domains.UrlCheckerDomainPermissions; import gov.healthit.chpl.permissions.domains.UserPermissionsDomainPermissions; @Component @@ -79,6 +80,7 @@ public class Permissions { public static final String STANDARD = "STANDARD"; public static final String CODE_SET = "CODE_SET"; public static final String API_KEY = "API_KEY"; + public static final String URL_CHECKER = "URL_CHECKER"; private Map domainPermissions = new HashMap(); @@ -116,7 +118,8 @@ public Permissions(CertificationResultsDomainPermissions certificationResultsDom FunctionalityTestedDomainPermissions functionalityTestedDomainPermissions, StandardDomainPermissions standardDomainPermissions, CodeSetDomainPermissions codeSetPermissions, - ApiKeyDomainPermissions apiKeyPermissions) { + ApiKeyDomainPermissions apiKeyPermissions, + UrlCheckerDomainPermissions urlCheckerDomainPermissions) { domainPermissions.put(ACCESSIBILITY_STANDARD, accessibilityStandardDomainPermissions); domainPermissions.put(ACTIVITY, activityDomainPermissions); @@ -151,6 +154,7 @@ public Permissions(CertificationResultsDomainPermissions certificationResultsDom domainPermissions.put(UCD_PROCESS, ucdProcessDomainPermissions); domainPermissions.put(USER_PERMISSIONS, userPermissionsDomainPermissions); domainPermissions.put(API_KEY, apiKeyPermissions); + domainPermissions.put(URL_CHECKER, urlCheckerDomainPermissions); } public boolean hasAccess(final String domain, final String action) { diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/UrlCheckerDomainPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/UrlCheckerDomainPermissions.java new file mode 100644 index 0000000000..c06f4690aa --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/UrlCheckerDomainPermissions.java @@ -0,0 +1,18 @@ +package gov.healthit.chpl.permissions.domains; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.stereotype.Component; + +import gov.healthit.chpl.permissions.domains.testinglab.urlchecker.CheckActionPermissions; + +@Component +public class UrlCheckerDomainPermissions extends DomainPermissions { + public static final String CHECK = "CHECK"; + + @Autowired + public UrlCheckerDomainPermissions( + @Qualifier("urlCheckerCheckActionPermissions") CheckActionPermissions checkActionPermissions) { + getActionPermissions().put(CHECK, checkActionPermissions); + } +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testinglab/urlchecker/CheckActionPermissions.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testinglab/urlchecker/CheckActionPermissions.java new file mode 100644 index 0000000000..ab7109085d --- /dev/null +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/permissions/domains/testinglab/urlchecker/CheckActionPermissions.java @@ -0,0 +1,21 @@ +package gov.healthit.chpl.permissions.domains.testinglab.urlchecker; + +import org.springframework.stereotype.Component; + +import gov.healthit.chpl.permissions.domains.ActionPermissions; + +@Component("urlCheckerCheckActionPermissions") +public class CheckActionPermissions extends ActionPermissions { + + @Override + public boolean hasAccess() { + return getResourcePermissions().isUserRoleAdmin() + || getResourcePermissions().isUserRoleOnc() + || getResourcePermissions().isUserRoleAcbAdmin(); + } + + @Override + public boolean hasAccess(Object obj) { + return false; + } +} diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestResultService.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestResultService.java index aeb79db028..a4bd8a5a53 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestResultService.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestResultService.java @@ -24,7 +24,6 @@ public class DatadogSyntheticsTestResultService { private DatadogSyntheticsTestApiProvider apiProvider; - @Autowired public DatadogSyntheticsTestResultService(DatadogSyntheticsTestApiProvider apiProvider) { this.apiProvider = apiProvider; @@ -58,6 +57,15 @@ public List getSyntheticsTestResults(String public return testResults; } + public SyntheticsGetAPITestLatestResultsResponse getSyntheticsTestResults(String publicTestKey) { + try { + return apiProvider.getApiInstance().getAPITestLatestResults(publicTestKey); + } catch (ApiException e) { + LOGGER.error("Could not retrieve results for test key: {}", publicTestKey, e); + return null; + } + } + public SyntheticsAPITestResultFull getDetailedTestResult(String publicTestKey, String resultId) { try { return apiProvider.getApiInstance().getAPITestResult(publicTestKey, resultId); diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestService.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestService.java index befdbe58fa..98ff6d0209 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestService.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogSyntheticsTestService.java @@ -38,7 +38,6 @@ public class DatadogSyntheticsTestService { private static final Long SECONDS_IN_A_MINUTE = 60L; private DatadogSyntheticsTestApiProvider apiProvider; - private Boolean datadogIsReadOnly; private String datadogTestStartTime; private String datadogTestEndTime; private Long datadogCheckEveryMinutes; @@ -46,14 +45,12 @@ public class DatadogSyntheticsTestService { private String datadogTestLocation; public DatadogSyntheticsTestService(DatadogSyntheticsTestApiProvider apiProvider, - @Value("${datadog.syntheticsTest.readOnly}") Boolean datadogIsReadOnly, @Value("${datadog.syntheticsTest.startTime}") String datadogTestStartTime, @Value("${datadog.syntheticsTest.endTime}") String datadogTestEndTime, @Value("${datadog.syntheticsTest.checkEveryMinutes}") Long datadogCheckEveryMinutes, @Value("${datadog.syntheticsTest.timeout}") Integer datadogTestTimeout, @Value("${datadog.syntheticsTest.location}") String datadogTestLocation) { this.apiProvider = apiProvider; - this.datadogIsReadOnly = datadogIsReadOnly; this.datadogTestStartTime = datadogTestStartTime; this.datadogTestEndTime = datadogTestEndTime; this.datadogCheckEveryMinutes = datadogCheckEveryMinutes; @@ -61,7 +58,7 @@ public DatadogSyntheticsTestService(DatadogSyntheticsTestApiProvider apiProvider this.datadogTestLocation = datadogTestLocation; } - protected DatadogSyntheticsTestApiProvider getApiProvider() { + public DatadogSyntheticsTestApiProvider getApiProvider() { return apiProvider; } @@ -86,12 +83,7 @@ public SyntheticsAPITest getSyntheticsTest(String publicId) { public void deleteSyntheticsTests(List publicIds) { try { - if (datadogIsReadOnly) { - LOGGER.info("Not deleting from datadog (due to environment setting) with Public Ids: {}", publicIds); - } else { - apiProvider.getApiInstance().deleteTests(new SyntheticsDeleteTestsPayload().publicIds(publicIds)); - } - + apiProvider.getApiInstance().deleteTests(new SyntheticsDeleteTestsPayload().publicIds(publicIds)); } catch (ApiException e) { LOGGER.error("Could not delete Synthetic Tests from Datadog: {}", publicIds, e); } @@ -114,8 +106,8 @@ public SyntheticsAPITest createSyntheticsTest(String url, List developerId .target(NOT_EMPTY_REGEX) .type(SyntheticsAssertionType.BODY)))) .request(new SyntheticsTestRequest() - .url(url) - .method(HTTP_METHOD_GET))) + .url(url) + .method(HTTP_METHOD_GET))) .options(new SyntheticsTestOptions() .httpVersion(SyntheticsTestOptionsHTTPVersion.ANY) .minFailureDuration(0L) @@ -150,13 +142,8 @@ public SyntheticsAPITest createSyntheticsTest(String url, List developerId .tags(developerIdsToTags(developerIds)); try { - if (datadogIsReadOnly) { - LOGGER.info("Not updating datadog (due to environment setting) with Developers: {} and URL: {}", developerIds, url); - return body; - } else { - LOGGER.info("Adding Synthetics Test for URL: {}, with Developers: {}", url, developerIds); - return apiProvider.getApiInstance().createSyntheticsAPITest(body); - } + LOGGER.info("Adding Synthetics Test for URL: {}, with Developers: {}", url, developerIds); + return apiProvider.getApiInstance().createSyntheticsAPITest(body); } catch (ApiException e) { LOGGER.error("Could not create Synthetics Test for URL: {}", url, e); return null; @@ -174,11 +161,7 @@ public void setApplicableDevelopersForTest(String syntheticsApiTestPublicId, Lis .path("/tags") .value(test.getTags())); try { - if (datadogIsReadOnly) { - LOGGER.info("Not adding Developer(s) (due to environment setting) to existing Synthetics Test {}", developerIds); - } else { - apiProvider.getApiInstance().patchTest(syntheticsApiTestPublicId, body); - } + apiProvider.getApiInstance().patchTest(syntheticsApiTestPublicId, body); } catch (ApiException e) { LOGGER.error("Could not add Developer(s) to existing Synthetics Test {}", developerIds, e); } diff --git a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogUrlUptimeSynchonizer.java b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogUrlUptimeSynchonizer.java index 11480bfd8e..fef186f3d0 100644 --- a/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogUrlUptimeSynchonizer.java +++ b/chpl/chpl-service/src/main/java/gov/healthit/chpl/scheduler/job/urluptime/DatadogUrlUptimeSynchonizer.java @@ -22,6 +22,7 @@ import com.datadog.api.client.v1.model.SyntheticsApiTestFailureCode; import com.datadog.api.client.v1.model.SyntheticsTestDetails; +import gov.healthit.chpl.datadog.OnDemandUrlCheckerManager; import gov.healthit.chpl.domain.Developer; import lombok.extern.log4j.Log4j2; @@ -204,11 +205,14 @@ public static Predicate distinctByKey(Function keyExtr } private void addUrlUptimeMonitor(UrlUptimeMonitor urlUptimeMonitor) { - try { - LOGGER.info("Adding the following URL to url_uptime_monitor table: {}, {}", urlUptimeMonitor.getUrl(), urlUptimeMonitor.getDeveloper().getId()); - urlUptimeMonitorDAO.create(urlUptimeMonitor); - } catch (Exception e) { - LOGGER.error("Could not add the following URL to url_uptime_monitor table: {}", urlUptimeMonitor.getUrl(), e); + // Ignore monitors URL monitors with a developer of -99. These are from the On Demand Checker. + if (urlUptimeMonitor.getDeveloper().getId() != OnDemandUrlCheckerManager.TEMP_DEVELOPER_ID) { + try { + LOGGER.info("Adding the following URL to url_uptime_monitor table: {}, {}", urlUptimeMonitor.getUrl(), urlUptimeMonitor.getDeveloper().getId()); + urlUptimeMonitorDAO.create(urlUptimeMonitor); + } catch (Exception e) { + LOGGER.error("Could not add the following URL to url_uptime_monitor table: {}", urlUptimeMonitor.getUrl(), e); + } } }