diff --git a/build.gradle b/build.gradle index d6bdf0946..b30b2668c 100644 --- a/build.gradle +++ b/build.gradle @@ -347,6 +347,7 @@ subprojects { def services = [':services:default', ':services:backend', + ':services:bsa', ':services:tools', ':services:pubapi'] diff --git a/core/src/main/java/google/registry/bsa/PlaceholderAction.java b/core/src/main/java/google/registry/bsa/PlaceholderAction.java new file mode 100644 index 000000000..6b8427a68 --- /dev/null +++ b/core/src/main/java/google/registry/bsa/PlaceholderAction.java @@ -0,0 +1,45 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.bsa; + +import static javax.servlet.http.HttpServletResponse.SC_OK; + +import google.registry.request.Action; +import google.registry.request.Action.Service; +import google.registry.request.Response; +import google.registry.request.auth.Auth; +import javax.inject.Inject; + +@Action( + service = Service.BSA, + path = PlaceholderAction.PATH, + method = Action.Method.GET, + auth = Auth.AUTH_API_ADMIN) +public class PlaceholderAction implements Runnable { + private final Response response; + + static final String PATH = "/_dr/task/bsaDownload"; + + @Inject + public PlaceholderAction(Response response) { + this.response = response; + } + + @Override + public void run() { + response.setStatus(SC_OK); + response.setPayload("Hello World"); + } +} diff --git a/core/src/main/java/google/registry/config/RegistryConfig.java b/core/src/main/java/google/registry/config/RegistryConfig.java index 0a2ec5e25..38e8e73c4 100644 --- a/core/src/main/java/google/registry/config/RegistryConfig.java +++ b/core/src/main/java/google/registry/config/RegistryConfig.java @@ -1458,6 +1458,15 @@ public final class RegistryConfig { return makeUrl(CONFIG_SETTINGS.get().gcpProject.backendServiceUrl); } + /** + * Returns the address of the Nomulus app bsa HTTP server. + * + *

This is used by the {@code nomulus} tool to connect to the App Engine remote API. + */ + public static URL getBsaServer() { + return makeUrl(CONFIG_SETTINGS.get().gcpProject.bsaServiceUrl); + } + /** * Returns the address of the Nomulus app tools HTTP server. * diff --git a/core/src/main/java/google/registry/config/RegistryConfigSettings.java b/core/src/main/java/google/registry/config/RegistryConfigSettings.java index 4d7f07ee4..c2544801b 100644 --- a/core/src/main/java/google/registry/config/RegistryConfigSettings.java +++ b/core/src/main/java/google/registry/config/RegistryConfigSettings.java @@ -53,6 +53,7 @@ public class RegistryConfigSettings { public boolean isLocal; public String defaultServiceUrl; public String backendServiceUrl; + public String bsaServiceUrl; public String toolsServiceUrl; public String pubapiServiceUrl; } diff --git a/core/src/main/java/google/registry/config/files/default-config.yaml b/core/src/main/java/google/registry/config/files/default-config.yaml index 401683b0a..57c87a66b 100644 --- a/core/src/main/java/google/registry/config/files/default-config.yaml +++ b/core/src/main/java/google/registry/config/files/default-config.yaml @@ -20,9 +20,11 @@ gcpProject: # URLs of the services for the project. defaultServiceUrl: https://default.example.com backendServiceUrl: https://backend.example.com + bsaServiceUrl: https://bsa.example.com toolsServiceUrl: https://tools.example.com pubapiServiceUrl: https://pubapi.example.com + gSuite: # Publicly accessible domain name of the running G Suite instance. domainName: domain-registry.example diff --git a/core/src/main/java/google/registry/env/alpha/backend/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/alpha/backend/WEB-INF/appengine-web.xml index b81832e6f..260b79ab5 100644 --- a/core/src/main/java/google/registry/env/alpha/backend/WEB-INF/appengine-web.xml +++ b/core/src/main/java/google/registry/env/alpha/backend/WEB-INF/appengine-web.xml @@ -18,13 +18,6 @@ value="alpha"/> - - - - projects/domain-registry-alpha/locations/us-central1/connectors/appengine-connector - all-traffic - - diff --git a/core/src/main/java/google/registry/env/alpha/bsa/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/alpha/bsa/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..816b688fb --- /dev/null +++ b/core/src/main/java/google/registry/env/alpha/bsa/WEB-INF/appengine-web.xml @@ -0,0 +1,31 @@ + + + + java17 + bsa + true + true + B4 + + 100 + 10m + + + + + + + + + + + projects/domain-registry-alpha/locations/us-central1/connectors/appengine-connector + all-traffic + + + + + + diff --git a/core/src/main/java/google/registry/env/common/META-INF/application.xml b/core/src/main/java/google/registry/env/common/META-INF/application.xml index 80d8baf00..212039d73 100644 --- a/core/src/main/java/google/registry/env/common/META-INF/application.xml +++ b/core/src/main/java/google/registry/env/common/META-INF/application.xml @@ -31,6 +31,12 @@ encoding="UTF-8"?> backend + + + bsa + bsa + + tools diff --git a/core/src/main/java/google/registry/env/common/bsa/WEB-INF/logging.properties b/core/src/main/java/google/registry/env/common/bsa/WEB-INF/logging.properties new file mode 100644 index 000000000..487bddee4 --- /dev/null +++ b/core/src/main/java/google/registry/env/common/bsa/WEB-INF/logging.properties @@ -0,0 +1,17 @@ +# A default java.util.logging configuration. +# (All App Engine logging is through java.util.logging by default). +# +# To use this configuration, copy it into your application's WEB-INF +# folder and add the following to your appengine-web.xml: +# +# +# +# +# + +# Set the default logging level for all loggers to INFO. +.level = INFO + +# Turn off logging in Hibernate classes for misleading ERROR-level logs +org.hibernate.engine.jdbc.batch.internal.BatchingBatch.level=OFF +org.hibernate.engine.jdbc.spi.SqlExceptionHelper.level=OFF diff --git a/core/src/main/java/google/registry/env/common/bsa/WEB-INF/web.xml b/core/src/main/java/google/registry/env/common/bsa/WEB-INF/web.xml new file mode 100644 index 000000000..d344908e6 --- /dev/null +++ b/core/src/main/java/google/registry/env/common/bsa/WEB-INF/web.xml @@ -0,0 +1,70 @@ + + + + + + + BsaServlet + bsa-servlet + google.registry.module.bsa.BsaServlet + 1 + + + + + backend-servlet + /_dr/task/bsa + + + + + + Internal + + Admin-only internal section. Requests for paths covered by the URL patterns below will be + checked for a logged-in user account that's allowed to access the AppEngine admin console + (NOTE: this includes Editor/Viewer permissions in addition to Owner and the new IAM + App Engine Admin role. See https://cloud.google.com/appengine/docs/java/access-control + specifically the "Access handlers that have a login:admin restriction" line.) + + TODO(b/28219927): lift some of these restrictions so that we can allow OAuth authentication + for endpoints that need to be accessed by open-source automated processes. + + + + /_ah/* + + + /registrar* + + + /assets/sources/* + + + + admin + + + + + CONFIDENTIAL + + + + + + + Secure + + Require encryption for all paths. http URLs will be redirected to https. + + /* + + + CONFIDENTIAL + + + diff --git a/core/src/main/java/google/registry/env/crash/backend/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/crash/backend/WEB-INF/appengine-web.xml index 8374a6ddd..66a7c22fa 100644 --- a/core/src/main/java/google/registry/env/crash/backend/WEB-INF/appengine-web.xml +++ b/core/src/main/java/google/registry/env/crash/backend/WEB-INF/appengine-web.xml @@ -18,12 +18,6 @@ value="crash"/> - - - projects/domain-registry-crash/locations/us-central1/connectors/appengine-connector - all-traffic - - diff --git a/core/src/main/java/google/registry/env/crash/bsa/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/crash/bsa/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..866b0392f --- /dev/null +++ b/core/src/main/java/google/registry/env/crash/bsa/WEB-INF/appengine-web.xml @@ -0,0 +1,30 @@ + + + + java17 + bsa + true + true + B4 + + 10 + 10m + + + + + + + + + + projects/domain-registry-crash/locations/us-central1/connectors/appengine-connector + all-traffic + + + + + + diff --git a/core/src/main/java/google/registry/env/local/bsa/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/local/bsa/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..9945fe536 --- /dev/null +++ b/core/src/main/java/google/registry/env/local/bsa/WEB-INF/appengine-web.xml @@ -0,0 +1,28 @@ + + + + java17 + bsa + true + true + B4 + + 10 + 10m + + + + + + + + + + + + + + diff --git a/core/src/main/java/google/registry/env/production/bsa/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/production/bsa/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..37b811b89 --- /dev/null +++ b/core/src/main/java/google/registry/env/production/bsa/WEB-INF/appengine-web.xml @@ -0,0 +1,30 @@ + + + + java8 + bsa + + true + true + B4_1G + + 100 + 10m + + + + + + + + + + + + + + + + diff --git a/core/src/main/java/google/registry/env/qa/backend/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/qa/backend/WEB-INF/appengine-web.xml index a9b00fa06..0f78e0339 100644 --- a/core/src/main/java/google/registry/env/qa/backend/WEB-INF/appengine-web.xml +++ b/core/src/main/java/google/registry/env/qa/backend/WEB-INF/appengine-web.xml @@ -22,12 +22,6 @@ - - - projects/domain-registry-qa/locations/us-central1/connectors/appengine-connector - all-traffic - - diff --git a/core/src/main/java/google/registry/env/qa/bsa/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/qa/bsa/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..6dc8eeea3 --- /dev/null +++ b/core/src/main/java/google/registry/env/qa/bsa/WEB-INF/appengine-web.xml @@ -0,0 +1,35 @@ + + + + java17 + bsa + true + true + B4 + + 10 + 10m + + + + + + + + + + + + + + projects/domain-registry-qa/locations/us-central1/connectors/appengine-connector + all-traffic + + + + + + + diff --git a/core/src/main/java/google/registry/env/sandbox/backend/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/sandbox/backend/WEB-INF/appengine-web.xml index cec30d9dc..65d0e73e7 100644 --- a/core/src/main/java/google/registry/env/sandbox/backend/WEB-INF/appengine-web.xml +++ b/core/src/main/java/google/registry/env/sandbox/backend/WEB-INF/appengine-web.xml @@ -23,12 +23,6 @@ - - - projects/domain-registry-sandbox/locations/us-central1/connectors/appengine-connector - all-traffic - - diff --git a/core/src/main/java/google/registry/env/sandbox/bsa/WEB-INF/appengine-web.xml b/core/src/main/java/google/registry/env/sandbox/bsa/WEB-INF/appengine-web.xml new file mode 100644 index 000000000..755b14045 --- /dev/null +++ b/core/src/main/java/google/registry/env/sandbox/bsa/WEB-INF/appengine-web.xml @@ -0,0 +1,36 @@ + + + + java8 + bsa + + true + true + B4 + + 100 + 10m + + + + + + + + + + + + + + projects/domain-registry-sandbox/locations/us-central1/connectors/appengine-connector + all-traffic + + + + + + + diff --git a/core/src/main/java/google/registry/module/bsa/BsaComponent.java b/core/src/main/java/google/registry/module/bsa/BsaComponent.java new file mode 100644 index 000000000..ab95a0e0d --- /dev/null +++ b/core/src/main/java/google/registry/module/bsa/BsaComponent.java @@ -0,0 +1,46 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.module.bsa; + +import com.google.monitoring.metrics.MetricReporter; +import dagger.Component; +import dagger.Lazy; +import google.registry.config.CredentialModule; +import google.registry.config.RegistryConfig.ConfigModule; +import google.registry.module.bsa.BsaRequestComponent.BsaRequestComponentModule; +import google.registry.monitoring.whitebox.StackdriverModule; +import google.registry.request.Modules.GsonModule; +import google.registry.request.Modules.UserServiceModule; +import google.registry.request.auth.AuthModule; +import google.registry.util.UtilsModule; +import javax.inject.Singleton; + +@Singleton +@Component( + modules = { + AuthModule.class, + UtilsModule.class, + UserServiceModule.class, + GsonModule.class, + ConfigModule.class, + StackdriverModule.class, + CredentialModule.class, + BsaRequestComponentModule.class + }) +interface BsaComponent { + BsaRequestHandler requestHandler(); + + Lazy metricReporter(); +} diff --git a/core/src/main/java/google/registry/module/bsa/BsaRequestComponent.java b/core/src/main/java/google/registry/module/bsa/BsaRequestComponent.java new file mode 100644 index 000000000..42d050ee1 --- /dev/null +++ b/core/src/main/java/google/registry/module/bsa/BsaRequestComponent.java @@ -0,0 +1,45 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.module.bsa; + +import dagger.Module; +import dagger.Subcomponent; +import google.registry.bsa.PlaceholderAction; +import google.registry.request.RequestComponentBuilder; +import google.registry.request.RequestModule; +import google.registry.request.RequestScope; + +@RequestScope +@Subcomponent( + modules = { + RequestModule.class, + }) +interface BsaRequestComponent { + + PlaceholderAction bsaAction(); + + @Subcomponent.Builder + abstract class Builder implements RequestComponentBuilder { + + @Override + public abstract Builder requestModule(RequestModule requestModule); + + @Override + public abstract BsaRequestComponent build(); + } + + @Module(subcomponents = BsaRequestComponent.class) + class BsaRequestComponentModule {} +} diff --git a/core/src/main/java/google/registry/module/bsa/BsaRequestHandler.java b/core/src/main/java/google/registry/module/bsa/BsaRequestHandler.java new file mode 100644 index 000000000..50e4e380b --- /dev/null +++ b/core/src/main/java/google/registry/module/bsa/BsaRequestHandler.java @@ -0,0 +1,29 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.module.bsa; + +import google.registry.request.RequestHandler; +import google.registry.request.auth.RequestAuthenticator; +import javax.inject.Inject; +import javax.inject.Provider; + +public class BsaRequestHandler extends RequestHandler { + @Inject + public BsaRequestHandler( + Provider componentBuilderProvider, + RequestAuthenticator requestAuthenticator) { + super(componentBuilderProvider, requestAuthenticator); + } +} diff --git a/core/src/main/java/google/registry/module/bsa/BsaServlet.java b/core/src/main/java/google/registry/module/bsa/BsaServlet.java new file mode 100644 index 000000000..279e37c20 --- /dev/null +++ b/core/src/main/java/google/registry/module/bsa/BsaServlet.java @@ -0,0 +1,30 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.module.bsa; + +import com.google.monitoring.metrics.MetricReporter; +import dagger.Lazy; +import google.registry.module.ServletBase; + +public final class BsaServlet extends ServletBase { + + private static final BsaComponent component = DaggerBsaComponent.create(); + private static final BsaRequestHandler requestHandler = component.requestHandler(); + private static final Lazy metricReporter = component.metricReporter(); + + public BsaServlet() { + super(requestHandler, metricReporter); + } +} diff --git a/core/src/main/java/google/registry/module/bsa/package-info.java b/core/src/main/java/google/registry/module/bsa/package-info.java new file mode 100644 index 000000000..2a1c8cd61 --- /dev/null +++ b/core/src/main/java/google/registry/module/bsa/package-info.java @@ -0,0 +1,16 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +@javax.annotation.ParametersAreNonnullByDefault +package google.registry.module.bsa; diff --git a/core/src/main/java/google/registry/request/Action.java b/core/src/main/java/google/registry/request/Action.java index fa475486f..6ae95bd41 100644 --- a/core/src/main/java/google/registry/request/Action.java +++ b/core/src/main/java/google/registry/request/Action.java @@ -30,11 +30,13 @@ public @interface Action { /** App Engine services supported by the request processor. */ enum Service { + BSA("bsa"), DEFAULT("default"), TOOLS("tools"), BACKEND("backend"), PUBAPI("pubapi"); + private final String serviceId; Service(String serviceId) { diff --git a/core/src/main/java/google/registry/tools/ServiceConnection.java b/core/src/main/java/google/registry/tools/ServiceConnection.java index d7c5104a6..8ba86926e 100644 --- a/core/src/main/java/google/registry/tools/ServiceConnection.java +++ b/core/src/main/java/google/registry/tools/ServiceConnection.java @@ -170,6 +170,8 @@ public class ServiceConnection { return RegistryConfig.getToolsServer(); case BACKEND: return RegistryConfig.getBackendServer(); + case BSA: + return RegistryConfig.getBsaServer(); case PUBAPI: return RegistryConfig.getPubapiServer(); } diff --git a/core/src/test/java/google/registry/module/bsa/BsaServletTest.java b/core/src/test/java/google/registry/module/bsa/BsaServletTest.java new file mode 100644 index 000000000..5d02b4238 --- /dev/null +++ b/core/src/test/java/google/registry/module/bsa/BsaServletTest.java @@ -0,0 +1,36 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package google.registry.module.bsa; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.jupiter.api.Test; + +class BsaServletTest { + private final HttpServletRequest req = mock(HttpServletRequest.class); + private final HttpServletResponse rsp = mock(HttpServletResponse.class); + + @Test + void testService_unknownPath_returnsNotFound() throws Exception { + when(req.getMethod()).thenReturn("GET"); + when(req.getRequestURI()).thenReturn("/lol"); + new BsaServlet().service(req, rsp); + verify(rsp).sendError(404); + } +} diff --git a/docs/architecture.md b/docs/architecture.md index 737d92997..cb654b6b3 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -66,6 +66,14 @@ sized to support not just the normal ongoing DNS load but also the load incurred by MapReduces, both scheduled (such as RDE) and on-demand (asynchronous contact/host deletion). +#### BSA service + +The bsa service is responsible for business logic behind Nomulus and BSA +functionality. Requests to the backend service are handled by the `BsaServlet`, +which provides all of the endpoints exposed in `BsaRequestComponent`. These +include tasks for downloading, processing and uploading BSA data. + + #### Tools service The tools service is responsible for servicing requests from the `nomulus` diff --git a/release/build_nomulus_for_env.sh b/release/build_nomulus_for_env.sh index e5733b9e7..3f3f4cfad 100755 --- a/release/build_nomulus_for_env.sh +++ b/release/build_nomulus_for_env.sh @@ -46,7 +46,7 @@ else -PmavenUrl="${gcs_prefix}"/maven \ -PpluginsUrl="${gcs_prefix}"/plugins - for service in default pubapi backend tools + for service in default pubapi backend bsa tools do mv services/"${service}"/build/staged-app "${dest}/${service}" done diff --git a/release/cloudbuild-delete.yaml b/release/cloudbuild-delete.yaml index 1f3c55335..8ae7e9633 100644 --- a/release/cloudbuild-delete.yaml +++ b/release/cloudbuild-delete.yaml @@ -43,7 +43,7 @@ steps: gcloud auth activate-service-account --key-file=tool-credential.json - for service in default pubapi backend tools + for service in default pubapi backend bsa tools do for version in $(gcloud app versions list \ --filter="SERVICE:$service AND SERVING_STATUS:STOPPED" \ diff --git a/release/cloudbuild-deploy.yaml b/release/cloudbuild-deploy.yaml index 60bc66a9d..59394ef77 100644 --- a/release/cloudbuild-deploy.yaml +++ b/release/cloudbuild-deploy.yaml @@ -75,7 +75,7 @@ steps: gcloud app versions list \ --project $project_id --hide-no-traffic \ --format="csv[no-heading](SERVICE,VERSION.ID)" | \ - grep -e "^backend\|^default\|^pubapi\|^tools" |\ + grep -e "^backend\|^default\|^bsa\|^pubapi\|^tools" |\ while read line; do echo "${TAG_NAME},$line"; done | tee "$local_map" num_versions=$(cat "$local_map" | wc -l) if [ "$num_versions" -ne 4 ]; then diff --git a/settings.gradle b/settings.gradle index 224153982..308241f90 100644 --- a/settings.gradle +++ b/settings.gradle @@ -43,6 +43,7 @@ include 'proxy' include 'util' include 'services:default' include 'services:backend' +include 'services:bsa' include 'services:tools' include 'services:pubapi' include 'java8compatibility'