From 1765f4f0b4a09b4cb4b107a0d024099bac9de437 Mon Sep 17 00:00:00 2001 From: gbrodman Date: Mon, 26 Aug 2024 16:25:31 -0400 Subject: [PATCH] Allow skip of emailing/uploading for activity reports (#2538) This will help us if/when we need to run the report generation multiple times, or for past dates and we don't want to send extra emails or upload any extra reports to ICANN. --- .../reporting/icann/IcannReportingModule.java | 8 +++ .../icann/IcannReportingStagingAction.java | 54 ++++++++++++------- .../IcannReportingStagingActionTest.java | 30 +++++++++++ 3 files changed, 74 insertions(+), 18 deletions(-) diff --git a/core/src/main/java/google/registry/reporting/icann/IcannReportingModule.java b/core/src/main/java/google/registry/reporting/icann/IcannReportingModule.java index 2792d39fe..3c79303e0 100644 --- a/core/src/main/java/google/registry/reporting/icann/IcannReportingModule.java +++ b/core/src/main/java/google/registry/reporting/icann/IcannReportingModule.java @@ -14,6 +14,7 @@ package google.registry.reporting.icann; +import static google.registry.request.RequestParameters.extractOptionalBooleanParameter; import static google.registry.request.RequestParameters.extractOptionalParameter; import static google.registry.request.RequestParameters.extractRequiredParameter; import static google.registry.request.RequestParameters.extractSetOfEnumParameters; @@ -42,6 +43,7 @@ public final class IcannReportingModule { static final String PARAM_SUBDIR = "subdir"; static final String PARAM_REPORT_TYPES = "reportTypes"; + static final String PARAM_SHOULD_UPLOAD = "shouldUpload"; static final String ICANN_REPORTING_DATA_SET = "icannReportingDataSet"; static final String MANIFEST_FILE_NAME = "MANIFEST.txt"; @@ -76,6 +78,12 @@ public final class IcannReportingModule { return reportTypes.isEmpty() ? ImmutableSet.copyOf(ReportType.values()) : reportTypes; } + @Provides + @Parameter(PARAM_SHOULD_UPLOAD) + static boolean provideShouldUpload(HttpServletRequest req) { + return extractOptionalBooleanParameter(req, PARAM_SHOULD_UPLOAD).orElse(true); + } + /** * Constructs a BigqueryConnection with default settings. * diff --git a/core/src/main/java/google/registry/reporting/icann/IcannReportingStagingAction.java b/core/src/main/java/google/registry/reporting/icann/IcannReportingStagingAction.java index 60fa9ffe1..b091de469 100644 --- a/core/src/main/java/google/registry/reporting/icann/IcannReportingStagingAction.java +++ b/core/src/main/java/google/registry/reporting/icann/IcannReportingStagingAction.java @@ -16,6 +16,7 @@ package google.registry.reporting.icann; import static com.google.common.base.Throwables.getRootCause; import static google.registry.reporting.icann.IcannReportingModule.PARAM_REPORT_TYPES; +import static google.registry.reporting.icann.IcannReportingModule.PARAM_SHOULD_UPLOAD; import static google.registry.reporting.icann.IcannReportingModule.PARAM_SUBDIR; import static google.registry.request.Action.Method.POST; import static jakarta.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; @@ -30,6 +31,7 @@ import google.registry.batch.CloudTasksUtils; import google.registry.bigquery.BigqueryJobFailureException; import google.registry.config.RegistryConfig.Config; import google.registry.groups.GmailClient; +import google.registry.reporting.ReportingModule; import google.registry.reporting.icann.IcannReportingModule.ReportType; import google.registry.request.Action; import google.registry.request.Action.Service; @@ -79,6 +81,15 @@ public final class IcannReportingStagingAction implements Runnable { @Inject YearMonth yearMonth; @Inject @Parameter(PARAM_SUBDIR) Optional overrideSubdir; @Inject @Parameter(PARAM_REPORT_TYPES) ImmutableSet reportTypes; + + @Inject + @Parameter(ReportingModule.SEND_EMAIL) + boolean sendEmail; + + @Inject + @Parameter(PARAM_SHOULD_UPLOAD) + boolean shouldUpload; + @Inject IcannReportingStager stager; @Inject Retrier retrier; @Inject Response response; @@ -106,28 +117,35 @@ public final class IcannReportingStagingAction implements Runnable { stager.createAndUploadManifest(subdir, manifestedFiles); logger.atInfo().log("Completed staging %d report files.", manifestedFiles.size()); - gmailClient.sendEmail( - EmailMessage.newBuilder() - .setSubject("ICANN Monthly report staging summary [SUCCESS]") - .setBody( - String.format( - "Completed staging the following %d ICANN reports:\n%s", - manifestedFiles.size(), Joiner.on('\n').join(manifestedFiles))) - .addRecipient(recipient) - .build()); - + if (sendEmail) { + gmailClient.sendEmail( + EmailMessage.newBuilder() + .setSubject("ICANN Monthly report staging summary [SUCCESS]") + .setBody( + String.format( + "Completed staging the following %d ICANN reports:\n%s", + manifestedFiles.size(), Joiner.on('\n').join(manifestedFiles))) + .addRecipient(recipient) + .build()); + } else { + logger.atInfo().log("Would have sent staging report summary to %s", recipient); + } response.setStatus(SC_OK); response.setContentType(MediaType.PLAIN_TEXT_UTF_8); response.setPayload("Completed staging action."); - logger.atInfo().log("Enqueueing report upload."); - cloudTasksUtils.enqueue( - CRON_QUEUE, - cloudTasksUtils.createPostTaskWithDelay( - IcannReportingUploadAction.PATH, - Service.BACKEND, - null, - Duration.standardMinutes(2))); + if (shouldUpload) { + logger.atInfo().log("Enqueueing report upload."); + cloudTasksUtils.enqueue( + CRON_QUEUE, + cloudTasksUtils.createPostTaskWithDelay( + IcannReportingUploadAction.PATH, + Service.BACKEND, + null, + Duration.standardMinutes(2))); + } else { + logger.atInfo().log("Would have enqueued report upload"); + } return null; }, BigqueryJobFailureException.class); diff --git a/core/src/test/java/google/registry/reporting/icann/IcannReportingStagingActionTest.java b/core/src/test/java/google/registry/reporting/icann/IcannReportingStagingActionTest.java index c23388ea3..b78c844d8 100644 --- a/core/src/test/java/google/registry/reporting/icann/IcannReportingStagingActionTest.java +++ b/core/src/test/java/google/registry/reporting/icann/IcannReportingStagingActionTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import com.google.cloud.tasks.v2.HttpMethod; @@ -60,6 +61,8 @@ class IcannReportingStagingActionTest { action.yearMonth = yearMonth; action.overrideSubdir = Optional.of(subdir); action.reportTypes = ImmutableSet.of(ReportType.ACTIVITY, ReportType.TRANSACTIONS); + action.sendEmail = true; + action.shouldUpload = true; action.response = response; action.stager = stager; action.retrier = new Retrier(new FakeSleeper(new FakeClock()), 3); @@ -154,6 +157,33 @@ class IcannReportingStagingActionTest { cloudTasksHelper.assertNoTasksEnqueued("retryable-cron-tasks"); } + @Test + void testSkipsEmail() throws Exception { + action.sendEmail = false; + action.run(); + verify(stager).stageReports(yearMonth, subdir, ReportType.ACTIVITY); + verify(stager).stageReports(yearMonth, subdir, ReportType.TRANSACTIONS); + verify(stager).createAndUploadManifest(subdir, ImmutableList.of("a", "b", "c", "d")); + verifyNoInteractions(action.gmailClient); + assertUploadTaskEnqueued(); + } + + @Test + void testSkipsUpload() throws Exception { + action.shouldUpload = false; + action.run(); + verify(stager).stageReports(yearMonth, subdir, ReportType.ACTIVITY); + verify(stager).stageReports(yearMonth, subdir, ReportType.TRANSACTIONS); + verify(stager).createAndUploadManifest(subdir, ImmutableList.of("a", "b", "c", "d")); + verify(action.gmailClient) + .sendEmail( + EmailMessage.create( + "ICANN Monthly report staging summary [SUCCESS]", + "Completed staging the following 4 ICANN reports:\na\nb\nc\nd", + new InternetAddress("recipient@example.com"))); + cloudTasksHelper.assertNoTasksEnqueued("retryable-cron-tasks"); + } + @Test void testEmptySubDir_returnsDefaultSubdir() { action.overrideSubdir = Optional.empty();