diff --git a/java/google/registry/config/RegistryConfig.java b/java/google/registry/config/RegistryConfig.java index e4c734f89..21289bd92 100644 --- a/java/google/registry/config/RegistryConfig.java +++ b/java/google/registry/config/RegistryConfig.java @@ -590,6 +590,18 @@ public final class RegistryConfig { return "gs://" + billingBucket; } + /** + * Returns whether or not we should publish invoices to partners automatically by default. + * + * @see google.registry.reporting.billing.BillingModule + */ + @Provides + @Config("defaultShouldPublishInvoices") + public static boolean provideDefaultShouldPublishInvoices() { + // TODO(b/78278360): Make the default 'true' once we're done with SUNRISE. + return false; + } + /** * Returns the list of addresses that receive monthly invoicing emails. * diff --git a/java/google/registry/reporting/billing/BillingModule.java b/java/google/registry/reporting/billing/BillingModule.java index 610d3a6fc..d4a1889bf 100644 --- a/java/google/registry/reporting/billing/BillingModule.java +++ b/java/google/registry/reporting/billing/BillingModule.java @@ -14,6 +14,7 @@ package google.registry.reporting.billing; +import static google.registry.request.RequestParameters.extractOptionalBooleanParameter; import static google.registry.request.RequestParameters.extractRequiredParameter; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -43,6 +44,7 @@ public final class BillingModule { public static final String INVOICES_DIRECTORY = "invoices"; static final String PARAM_JOB_ID = "jobId"; + static final String PARAM_SHOULD_PUBLISH = "shouldPublish"; static final String BILLING_QUEUE = "billing"; static final String CRON_QUEUE = "retryable-cron-tasks"; @@ -56,6 +58,15 @@ public final class BillingModule { return extractRequiredParameter(req, PARAM_JOB_ID); } + @Provides + @Parameter(PARAM_SHOULD_PUBLISH) + static boolean provideShouldPublish( + HttpServletRequest req, + @Config("defaultShouldPublishInvoices") boolean defaultShouldPublishInvoices) { + return extractOptionalBooleanParameter(req, PARAM_SHOULD_PUBLISH) + .orElse(defaultShouldPublishInvoices); + } + @Provides @InvoiceDirectoryPrefix static String provideDirectoryPrefix(YearMonth yearMonth) { diff --git a/java/google/registry/reporting/billing/GenerateInvoicesAction.java b/java/google/registry/reporting/billing/GenerateInvoicesAction.java index f66d006dd..55e539520 100644 --- a/java/google/registry/reporting/billing/GenerateInvoicesAction.java +++ b/java/google/registry/reporting/billing/GenerateInvoicesAction.java @@ -15,6 +15,7 @@ package google.registry.reporting.billing; import static google.registry.reporting.ReportingModule.PARAM_YEAR_MONTH; +import static google.registry.reporting.billing.BillingModule.PARAM_SHOULD_PUBLISH; import static google.registry.request.Action.Method.POST; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_OK; @@ -29,6 +30,7 @@ import com.google.common.collect.ImmutableMap; import com.google.common.net.MediaType; import google.registry.config.RegistryConfig.Config; import google.registry.request.Action; +import google.registry.request.Parameter; import google.registry.request.Response; import google.registry.request.auth.Auth; import google.registry.util.FormattingLogger; @@ -55,6 +57,7 @@ public class GenerateInvoicesAction implements Runnable { private final String projectId; private final String beamBucketUrl; private final String invoiceTemplateUrl; + private final boolean shouldPublish; private final YearMonth yearMonth; private final Dataflow dataflow; private final Response response; @@ -65,6 +68,7 @@ public class GenerateInvoicesAction implements Runnable { @Config("projectId") String projectId, @Config("apacheBeamBucketUrl") String beamBucketUrl, @Config("invoiceTemplateUrl") String invoiceTemplateUrl, + @Parameter(PARAM_SHOULD_PUBLISH) boolean shouldPublish, YearMonth yearMonth, Dataflow dataflow, Response response, @@ -72,6 +76,7 @@ public class GenerateInvoicesAction implements Runnable { this.projectId = projectId; this.beamBucketUrl = beamBucketUrl; this.invoiceTemplateUrl = invoiceTemplateUrl; + this.shouldPublish = shouldPublish; this.yearMonth = yearMonth; this.dataflow = dataflow; this.response = response; @@ -99,7 +104,9 @@ public class GenerateInvoicesAction implements Runnable { .execute(); logger.infofmt("Got response: %s", launchResponse.getJob().toPrettyString()); String jobId = launchResponse.getJob().getId(); - enqueuePublishTask(jobId); + if (shouldPublish) { + enqueuePublishTask(jobId); + } } catch (IOException e) { logger.warning(e, "Template Launch failed"); emailUtils.sendAlertEmail(String.format("Template Launch failed due to %s", e.getMessage())); diff --git a/javatests/google/registry/reporting/billing/GenerateInvoicesActionTest.java b/javatests/google/registry/reporting/billing/GenerateInvoicesActionTest.java index f9bb7e0bb..16117b924 100644 --- a/javatests/google/registry/reporting/billing/GenerateInvoicesActionTest.java +++ b/javatests/google/registry/reporting/billing/GenerateInvoicesActionTest.java @@ -15,6 +15,7 @@ package google.registry.reporting.billing; import static com.google.common.truth.Truth.assertThat; +import static google.registry.testing.TaskQueueHelper.assertNoTasksEnqueued; import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; @@ -54,7 +55,7 @@ public class GenerateInvoicesActionTest { private Launch launch; private FakeResponse response; private BillingEmailUtils emailUtils; - private GenerateInvoicesAction action; + GenerateInvoicesAction action; @Before public void setUp() throws IOException { @@ -73,20 +74,20 @@ public class GenerateInvoicesActionTest { Job job = new Job(); job.setId("12345"); when(launch.execute()).thenReturn(new LaunchTemplateResponse().setJob(job)); + } + @Test + public void testLaunchTemplateJob_withPublish() throws Exception { action = new GenerateInvoicesAction( "test-project", "gs://test-project-beam", "gs://test-project-beam/templates/invoicing", + true, new YearMonth(2017, 10), dataflow, response, emailUtils); - } - - @Test - public void testLaunchTemplateJob() throws Exception { action.run(); LaunchTemplateParameters expectedParams = new LaunchTemplateParameters() @@ -110,9 +111,47 @@ public class GenerateInvoicesActionTest { assertTasksEnqueued("billing", matcher); } + @Test + public void testLaunchTemplateJob_withoutPublish() throws Exception { + action = + new GenerateInvoicesAction( + "test-project", + "gs://test-project-beam", + "gs://test-project-beam/templates/invoicing", + false, + new YearMonth(2017, 10), + dataflow, + response, + emailUtils); + action.run(); + LaunchTemplateParameters expectedParams = + new LaunchTemplateParameters() + .setJobName("invoicing-2017-10") + .setEnvironment( + new RuntimeEnvironment() + .setZone("us-east1-c") + .setTempLocation("gs://test-project-beam/temporary")) + .setParameters(ImmutableMap.of("yearMonth", "2017-10")); + verify(templates).launch("test-project", expectedParams); + verify(launch).setGcsPath("gs://test-project-beam/templates/invoicing"); + assertThat(response.getStatus()).isEqualTo(200); + assertThat(response.getPayload()).isEqualTo("Launched dataflow template."); + assertNoTasksEnqueued(); + } + @Test public void testCaughtIOException() throws IOException { when(launch.execute()).thenThrow(new IOException("expected")); + action = + new GenerateInvoicesAction( + "test-project", + "gs://test-project-beam", + "gs://test-project-beam/templates/invoicing", + true, + new YearMonth(2017, 10), + dataflow, + response, + emailUtils); action.run(); assertThat(response.getStatus()).isEqualTo(500); assertThat(response.getPayload()).isEqualTo("Template launch failed: expected");