Implement connectivity check for Exoblaze and create dummy connectivity check for Blaze/Bazel.
The connectivity checks return a ConnectivityStatus, which is either ok, or contains a warning and whether the build should fail if this status is present.
This cl doesn't change behavior; it introduces the functionality without incorporating it.
RELNOTES: None.
PiperOrigin-RevId: 244869251
diff --git a/src/main/java/com/google/devtools/build/lib/network/ConnectivityModule.java b/src/main/java/com/google/devtools/build/lib/network/ConnectivityModule.java
new file mode 100644
index 0000000..21e0f5c
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/network/ConnectivityModule.java
@@ -0,0 +1,93 @@
+// Copyright 2019 The Bazel 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 com.google.devtools.build.lib.network;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.ImmutableList;
+import com.google.devtools.build.lib.network.ConnectivityStatus.Status;
+import com.google.devtools.build.lib.runtime.BlazeModule;
+import com.google.devtools.build.lib.runtime.Command;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.util.AbruptExitException;
+import com.google.devtools.common.options.Converters.DurationConverter;
+import com.google.devtools.common.options.Option;
+import com.google.devtools.common.options.OptionDocumentationCategory;
+import com.google.devtools.common.options.OptionEffectTag;
+import com.google.devtools.common.options.OptionsBase;
+import java.time.Duration;
+
+/** Stores network status for Bazel-adjacent services, usually remote build and BES. */
+public class ConnectivityModule extends BlazeModule implements ConnectivityStatusProvider {
+
+ /** Options that define the behavior of the Connectivity Modules. */
+ public static class ConnectivityOptions extends OptionsBase {
+ @Option(
+ name = "connectivity_check_frequency",
+ defaultValue = "5s",
+ documentationCategory = OptionDocumentationCategory.REMOTE,
+ effectTags = {OptionEffectTag.BAZEL_INTERNAL_CONFIGURATION},
+ converter = DurationConverter.class,
+ help =
+ "How often to perform a connectivity and reachability check for remote services "
+ + "(eg. 5s). 0 disables the check and assumes connectivity.")
+ public Duration cacheLifetime;
+ }
+
+ /**
+ * Attempts to retrieve and return the specified service's status from the cache, calculating it
+ * if it's not present in the cache.
+ *
+ * @param service the name of the service we want to determine connectivity status for
+ * @param cache a cache that stores the current connectivity status for each service
+ * @return the connectivity status for the specified service
+ */
+ protected ConnectivityStatus determineConnectivity(String service, Cache<String, Status> cache) {
+ return new ConnectivityStatus(Status.OK, /* serviceInfo= */ "");
+ }
+
+ private Duration cacheLifetime;
+ private Cache<String, Status> cache;
+
+ @Override
+ public Iterable<Class<? extends OptionsBase>> getCommandOptions(Command command) {
+ return "build".equals(command.name())
+ ? ImmutableList.of(ConnectivityOptions.class)
+ : ImmutableList.of();
+ }
+
+ @Override
+ public void beforeCommand(CommandEnvironment env) throws AbruptExitException {
+ ConnectivityOptions options = env.getOptions().getOptions(ConnectivityOptions.class);
+ if (options == null) {
+ return;
+ }
+ Duration newCacheLifetime = options.cacheLifetime;
+ // Initialize the cache if we haven't yet, or if the options have changed.
+ // TODO(steinman): Make this a LoadingCache where load() calls determineConnectivity().
+ if (cache == null || !newCacheLifetime.equals(cacheLifetime)) {
+ cache = CacheBuilder.newBuilder().expireAfterWrite(newCacheLifetime).build();
+ cacheLifetime = newCacheLifetime;
+ }
+ }
+
+ @Override
+ public ConnectivityStatus getStatus(String service) {
+ if (cacheLifetime.isZero()) {
+ return new ConnectivityStatus(Status.OK, /* serviceInfo= */ "");
+ }
+ return determineConnectivity(service, cache);
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/network/ConnectivityStatus.java b/src/main/java/com/google/devtools/build/lib/network/ConnectivityStatus.java
new file mode 100644
index 0000000..a0ee0ee
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/network/ConnectivityStatus.java
@@ -0,0 +1,55 @@
+// Copyright 2019 The Bazel 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 com.google.devtools.build.lib.network;
+
+/** Defines connectivity problem types and their short warning messages. */
+public final class ConnectivityStatus {
+ /** Enumerates common connectivity statuses and their generic short warnings. */
+ public enum Status {
+ NO_CREDENTIALS("No credentials."),
+ NO_NETWORK("No internet connection."),
+ NOT_REACHABLE("Service not reachable."),
+ OK("");
+
+ /** Generic warning associated with this status. */
+ public final String shortWarning;
+
+ Status(String shortWarning) {
+ this.shortWarning = shortWarning;
+ }
+ }
+
+ /** Service-specific information for this status. */
+ public String serviceInfo;
+
+ /** Generic category type for this status, which contains a generic warning. */
+ public final Status status;
+
+ /** Returns the complete formatted warning for this status. */
+ public String fullWarning() {
+ return status.shortWarning + " " + serviceInfo;
+ }
+
+ /**
+ * Constructs a connectivity status with a service-specific warning.
+ *
+ * @param serviceInfo service-specific information displayed or logged in addition to the status's
+ * short warning when this connectivityStatus is present.
+ */
+ public ConnectivityStatus(Status status, String serviceInfo) {
+ this.status = status;
+ this.serviceInfo = serviceInfo;
+ }
+}
diff --git a/src/main/java/com/google/devtools/build/lib/network/ConnectivityStatusProvider.java b/src/main/java/com/google/devtools/build/lib/network/ConnectivityStatusProvider.java
new file mode 100644
index 0000000..720aa9a
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/network/ConnectivityStatusProvider.java
@@ -0,0 +1,24 @@
+// Copyright 2019 The Bazel 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 com.google.devtools.build.lib.network;
+
+/**
+ * Interface that gives services (such as the BES or remote build) exposure to their corresponding
+ * {@link ConnectivityStatus}.
+ */
+public interface ConnectivityStatusProvider {
+ /** Returns the current connectivity status for a given service. */
+ ConnectivityStatus getStatus(String service);
+}