mirror of
https://github.com/vacp2p/status-linea-besu.git
synced 2026-01-06 22:13:59 -05:00
remove k8s NAT method (#8289)
* remove k8s NAT method Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> * changelog - update pr number in changelog Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com> --------- Signed-off-by: Sally MacFarlane <macfarla.github@gmail.com>
This commit is contained in:
@@ -2,10 +2,10 @@
|
||||
|
||||
## Unreleased
|
||||
### Breaking Changes
|
||||
- k8s (KUBERNETES) Nat method is removed. Use docker or none instead. [#8289](https://github.com/hyperledger/besu/pull/8289)
|
||||
|
||||
### Upcoming Breaking Changes
|
||||
- `MetricSystem::createLabelledGauge` is deprecated and will be removed in a future release, replace it with `MetricSystem::createLabelledSuppliedGauge`
|
||||
- k8s (KUBERNETES) Nat method is now deprecated and will be removed in a future release. Use docker or none instead.
|
||||
- `--Xsnapsync-synchronizer-flat-db-healing-enabled` is deprecated, use `--Xbonsai-full-flat-db-enabled` instead.
|
||||
- `--Xbonsai-limit-trie-logs-enabled` is deprecated, use `--bonsai-limit-trie-logs-enabled` instead.
|
||||
- `--Xbonsai-trie-log-pruning-enabled` is deprecated, use `--bonsai-limit-trie-logs-enabled` instead.
|
||||
|
||||
@@ -118,8 +118,6 @@ import org.hyperledger.besu.nat.NatService;
|
||||
import org.hyperledger.besu.nat.core.NatManager;
|
||||
import org.hyperledger.besu.nat.docker.DockerDetector;
|
||||
import org.hyperledger.besu.nat.docker.DockerNatManager;
|
||||
import org.hyperledger.besu.nat.kubernetes.KubernetesDetector;
|
||||
import org.hyperledger.besu.nat.kubernetes.KubernetesNatManager;
|
||||
import org.hyperledger.besu.nat.upnp.UpnpNatManager;
|
||||
import org.hyperledger.besu.plugin.BesuPlugin;
|
||||
import org.hyperledger.besu.plugin.data.EnodeURL;
|
||||
@@ -170,7 +168,6 @@ public class RunnerBuilder {
|
||||
private String p2pListenInterface = NetworkUtility.INADDR_ANY;
|
||||
private int p2pListenPort;
|
||||
private NatMethod natMethod = NatMethod.AUTO;
|
||||
private String natManagerServiceName;
|
||||
private boolean natMethodFallbackEnabled;
|
||||
private EthNetworkConfig ethNetworkConfig;
|
||||
private EthstatsOptions ethstatsOptions;
|
||||
@@ -313,17 +310,6 @@ public class RunnerBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Nat manager service name.
|
||||
*
|
||||
* @param natManagerServiceName the nat manager service name
|
||||
* @return the runner builder
|
||||
*/
|
||||
public RunnerBuilder natManagerServiceName(final String natManagerServiceName) {
|
||||
this.natManagerServiceName = natManagerServiceName;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Nat method fallback.
|
||||
*
|
||||
@@ -1213,15 +1199,13 @@ public class RunnerBuilder {
|
||||
final NatMethod detectedNatMethod =
|
||||
Optional.of(natMethod)
|
||||
.filter(not(isEqual(NatMethod.AUTO)))
|
||||
.orElse(NatService.autoDetectNatMethod(new KubernetesDetector(), new DockerDetector()));
|
||||
.orElse(NatService.autoDetectNatMethod(new DockerDetector()));
|
||||
switch (detectedNatMethod) {
|
||||
case UPNP:
|
||||
return Optional.of(new UpnpNatManager());
|
||||
case DOCKER:
|
||||
return Optional.of(
|
||||
new DockerNatManager(p2pAdvertisedHost, p2pListenPort, jsonRpcConfiguration.getPort()));
|
||||
case KUBERNETES:
|
||||
return Optional.of(new KubernetesNatManager(natManagerServiceName));
|
||||
case NONE:
|
||||
default:
|
||||
return Optional.empty();
|
||||
|
||||
@@ -26,7 +26,6 @@ import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_
|
||||
import static org.hyperledger.besu.cli.util.CommandLineUtils.isOptionSet;
|
||||
import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
|
||||
import static org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService.EPHEMERAL_JWT_FILE;
|
||||
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
|
||||
|
||||
import org.hyperledger.besu.BesuInfo;
|
||||
import org.hyperledger.besu.Runner;
|
||||
@@ -1509,22 +1508,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
private void validateNatParams() {
|
||||
if (natMethod.equals(NatMethod.KUBERNETES)) {
|
||||
logger.warn("Kubernetes NAT method is deprecated. Please use Docker or UPNP");
|
||||
}
|
||||
if (!unstableNatOptions.getNatManagerServiceName().equals(DEFAULT_BESU_SERVICE_NAME_FILTER)) {
|
||||
logger.warn(
|
||||
"`--Xnat-kube-service-name` and Kubernetes NAT method are deprecated. Please use Docker or UPNP");
|
||||
}
|
||||
if (!(natMethod.equals(NatMethod.AUTO) || natMethod.equals(NatMethod.KUBERNETES))
|
||||
&& !unstableNatOptions
|
||||
.getNatManagerServiceName()
|
||||
.equals(DEFAULT_BESU_SERVICE_NAME_FILTER)) {
|
||||
throw new ParameterException(
|
||||
this.commandLine,
|
||||
"The `--Xnat-kube-service-name` parameter is only used in kubernetes mode. Either remove --Xnat-kube-service-name"
|
||||
+ " or select the KUBERNETES mode (via --nat--method=KUBERNETES)");
|
||||
}
|
||||
if (natMethod.equals(NatMethod.AUTO) && !unstableNatOptions.getNatMethodFallbackEnabled()) {
|
||||
throw new ParameterException(
|
||||
this.commandLine,
|
||||
@@ -2264,7 +2247,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
|
||||
.besuController(controller)
|
||||
.p2pEnabled(p2pEnabled)
|
||||
.natMethod(natMethod)
|
||||
.natManagerServiceName(unstableNatOptions.getNatManagerServiceName())
|
||||
.natMethodFallbackEnabled(unstableNatOptions.getNatMethodFallbackEnabled())
|
||||
.discoveryEnabled(peerDiscoveryEnabled)
|
||||
.ethNetworkConfig(ethNetworkConfig)
|
||||
|
||||
@@ -14,21 +14,11 @@
|
||||
*/
|
||||
package org.hyperledger.besu.cli.options;
|
||||
|
||||
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
|
||||
|
||||
import picocli.CommandLine;
|
||||
|
||||
/** The Nat Cli options. */
|
||||
public class NatOptions {
|
||||
|
||||
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
|
||||
@CommandLine.Option(
|
||||
hidden = true,
|
||||
names = {"--Xnat-kube-service-name"},
|
||||
description =
|
||||
"Specify the name of the service that will be used by the nat manager in Kubernetes. (default: ${DEFAULT-VALUE})")
|
||||
private String natManagerServiceName = DEFAULT_BESU_SERVICE_NAME_FILTER;
|
||||
|
||||
@CommandLine.Option(
|
||||
hidden = true,
|
||||
names = {"--Xnat-method-fallback-enabled"},
|
||||
@@ -49,15 +39,6 @@ public class NatOptions {
|
||||
return new NatOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets nat manager service name.
|
||||
*
|
||||
* @return the nat manager service name
|
||||
*/
|
||||
public String getNatManagerServiceName() {
|
||||
return natManagerServiceName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether nat method fallback is enabled.
|
||||
*
|
||||
|
||||
@@ -327,7 +327,6 @@ public abstract class CommandTestAbstract {
|
||||
when(mockRunnerBuilder.permissioningConfiguration(any())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.p2pEnabled(anyBoolean())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.natMethod(any())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.natManagerServiceName(any())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.natMethodFallbackEnabled(anyBoolean())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.jsonRpcConfiguration(any())).thenReturn(mockRunnerBuilder);
|
||||
when(mockRunnerBuilder.engineJsonRpcConfiguration(any())).thenReturn(mockRunnerBuilder);
|
||||
|
||||
@@ -16,7 +16,6 @@ package org.hyperledger.besu.cli;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
@@ -47,16 +46,6 @@ public class NatOptionsTest extends CommandTestAbstract {
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void natManagerPodNamePropertyDefaultIsBesu() {
|
||||
parseCommand();
|
||||
|
||||
verify(mockRunnerBuilder).natManagerServiceName(eq(DEFAULT_BESU_SERVICE_NAME_FILTER));
|
||||
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void natMethodOptionIsParsedCorrectly() {
|
||||
|
||||
@@ -75,52 +64,6 @@ public class NatOptionsTest extends CommandTestAbstract {
|
||||
parseCommand("--nat-method", "DOCKER");
|
||||
verify(mockRunnerBuilder).natMethod(eq(NatMethod.DOCKER));
|
||||
|
||||
parseCommand("--nat-method", "KUBERNETES");
|
||||
verify(mockRunnerBuilder).natMethod(eq(NatMethod.KUBERNETES));
|
||||
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void natManagerPodNamePropertyIsCorrectlyUpdated() {
|
||||
final String podName = "besu-updated";
|
||||
parseCommand("--Xnat-kube-service-name", podName);
|
||||
|
||||
verify(mockRunnerBuilder).natManagerServiceName(eq(podName));
|
||||
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void natManagerPodNameCannotBeUsedWithNatDockerMethod() {
|
||||
parseCommand("--nat-method", "DOCKER", "--Xnat-kube-service-name", "besu-updated");
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder);
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains(
|
||||
"The `--Xnat-kube-service-name` parameter is only used in kubernetes mode. Either remove --Xnat-kube-service-name or select the KUBERNETES mode (via --nat--method=KUBERNETES)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void natManagerPodNameCannotBeUsedWithNatNoneMethod() {
|
||||
parseCommand("--nat-method", "NONE", "--Xnat-kube-service-name", "besu-updated");
|
||||
Mockito.verifyNoInteractions(mockRunnerBuilder);
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains(
|
||||
"The `--Xnat-kube-service-name` parameter is only used in kubernetes mode. Either remove --Xnat-kube-service-name or select the KUBERNETES mode (via --nat--method=KUBERNETES)");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void natMethodFallbackEnabledPropertyIsCorrectlyUpdatedWithKubernetes() {
|
||||
|
||||
parseCommand("--nat-method", "KUBERNETES", "--Xnat-method-fallback-enabled", "false");
|
||||
verify(mockRunnerBuilder).natMethodFallbackEnabled(eq(false));
|
||||
parseCommand("--nat-method", "KUBERNETES", "--Xnat-method-fallback-enabled", "true");
|
||||
verify(mockRunnerBuilder).natMethodFallbackEnabled(eq(true));
|
||||
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
|
||||
}
|
||||
@@ -167,6 +110,6 @@ public class NatOptionsTest extends CommandTestAbstract {
|
||||
assertThat(commandOutput.toString(UTF_8)).isEmpty();
|
||||
assertThat(commandErrorOutput.toString(UTF_8))
|
||||
.contains(
|
||||
"Invalid value for option '--nat-method': expected one of [UPNP, UPNPP2PONLY, DOCKER, KUBERNETES, AUTO, NONE] (case-insensitive) but was 'invalid'");
|
||||
"Invalid value for option '--nat-method': expected one of [UPNP, UPNPP2PONLY, DOCKER, AUTO, NONE] (case-insensitive) but was 'invalid'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ security-module="localfile"
|
||||
identity="PegaSysEng"
|
||||
p2p-enabled=true
|
||||
nat-method="NONE"
|
||||
Xnat-kube-service-name="besu"
|
||||
Xnat-method-fallback-enabled=true
|
||||
discovery-enabled=false
|
||||
poa-discovery-retry-bootnodes=true
|
||||
|
||||
@@ -35,7 +35,6 @@ dependencies {
|
||||
implementation 'com.squareup.okhttp3:okhttp'
|
||||
implementation 'org.jupnp:org.jupnp'
|
||||
implementation 'org.jupnp:org.jupnp.support'
|
||||
implementation 'io.kubernetes:client-java'
|
||||
|
||||
// test dependencies.
|
||||
testImplementation project(path: ':ethereum:core', configuration: 'testArtifacts')
|
||||
|
||||
@@ -22,8 +22,6 @@ public enum NatMethod {
|
||||
UPNPP2PONLY,
|
||||
/** Docker nat method. */
|
||||
DOCKER,
|
||||
/** Kubernetes nat method. */
|
||||
KUBERNETES,
|
||||
/** Auto nat method. */
|
||||
AUTO,
|
||||
/** None nat method. */
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.nat.kubernetes;
|
||||
|
||||
import org.hyperledger.besu.nat.NatMethod;
|
||||
import org.hyperledger.besu.nat.core.NatMethodDetector;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Optional;
|
||||
|
||||
/** The Kubernetes detector. */
|
||||
public class KubernetesDetector implements NatMethodDetector {
|
||||
|
||||
// When a Pod runs on a Node, the kubelet adds a set of environment variables for each active
|
||||
// Service.
|
||||
// https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/#environment-variables
|
||||
private static final Optional<String> KUBERNETES_SERVICE_HOST =
|
||||
Optional.ofNullable(System.getenv("KUBERNETES_SERVICE_HOST"));
|
||||
private static final Path KUBERNETES_WATERMARK_FILE = Paths.get("var/run/secrets/kubernetes.io");
|
||||
|
||||
/** Default constructor */
|
||||
public KubernetesDetector() {}
|
||||
|
||||
@Override
|
||||
public Optional<NatMethod> detect() {
|
||||
return KUBERNETES_SERVICE_HOST
|
||||
.map(__ -> NatMethod.KUBERNETES)
|
||||
.or(
|
||||
() ->
|
||||
Files.exists(KUBERNETES_WATERMARK_FILE)
|
||||
? Optional.of(NatMethod.KUBERNETES)
|
||||
: Optional.empty());
|
||||
}
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.nat.kubernetes;
|
||||
|
||||
import org.hyperledger.besu.nat.NatMethod;
|
||||
import org.hyperledger.besu.nat.core.AbstractNatManager;
|
||||
import org.hyperledger.besu.nat.core.IpDetector;
|
||||
import org.hyperledger.besu.nat.core.domain.NatPortMapping;
|
||||
import org.hyperledger.besu.nat.core.domain.NatServiceType;
|
||||
import org.hyperledger.besu.nat.core.domain.NetworkProtocol;
|
||||
import org.hyperledger.besu.nat.core.exception.NatInitializationException;
|
||||
import org.hyperledger.besu.nat.kubernetes.service.KubernetesServiceType;
|
||||
import org.hyperledger.besu.nat.kubernetes.service.LoadBalancerBasedDetector;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import io.kubernetes.client.openapi.ApiClient;
|
||||
import io.kubernetes.client.openapi.Configuration;
|
||||
import io.kubernetes.client.openapi.apis.CoreV1Api;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.util.ClientBuilder;
|
||||
import io.kubernetes.client.util.KubeConfig;
|
||||
import io.kubernetes.client.util.authenticators.GCPAuthenticator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* This class describes the behavior of the Kubernetes NAT manager. Kubernetes Nat manager add
|
||||
* support for Kubernetes’s NAT implementation when Besu is being run from a Kubernetes cluster
|
||||
*/
|
||||
public class KubernetesNatManager extends AbstractNatManager {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(KubernetesNatManager.class);
|
||||
|
||||
/** The constant DEFAULT_BESU_SERVICE_NAME_FILTER. */
|
||||
public static final String DEFAULT_BESU_SERVICE_NAME_FILTER = "besu";
|
||||
|
||||
private String internalAdvertisedHost;
|
||||
private final String besuServiceNameFilter;
|
||||
private final List<NatPortMapping> forwardedPorts = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Instantiates a new Kubernetes nat manager.
|
||||
*
|
||||
* @param besuServiceNameFilter the besu service name filter
|
||||
*/
|
||||
public KubernetesNatManager(final String besuServiceNameFilter) {
|
||||
super(NatMethod.KUBERNETES);
|
||||
this.besuServiceNameFilter = besuServiceNameFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() throws NatInitializationException {
|
||||
LOG.info("Starting kubernetes NAT manager.");
|
||||
try {
|
||||
|
||||
KubeConfig.registerAuthenticator(new GCPAuthenticator());
|
||||
|
||||
LOG.debug("Trying to update information using Kubernetes client SDK.");
|
||||
final ApiClient client = ClientBuilder.cluster().build();
|
||||
|
||||
// set the global default api-client to the in-cluster one from above
|
||||
Configuration.setDefaultApiClient(client);
|
||||
|
||||
// the CoreV1Api loads default api-client from global configuration.
|
||||
final CoreV1Api api = new CoreV1Api();
|
||||
// invokes the CoreV1Api client
|
||||
final V1Service service =
|
||||
api
|
||||
.listServiceForAllNamespaces(
|
||||
null, null, null, null, null, null, null, null, null, null, null)
|
||||
.getItems()
|
||||
.stream()
|
||||
.filter(
|
||||
v1Service -> v1Service.getMetadata().getName().contains(besuServiceNameFilter))
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new NatInitializationException("Service not found"));
|
||||
updateUsingBesuService(service);
|
||||
} catch (Exception e) {
|
||||
throw new NatInitializationException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update using besu service. Visible for testing.
|
||||
*
|
||||
* @param service the service
|
||||
* @throws RuntimeException the runtime exception
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void updateUsingBesuService(final V1Service service) throws RuntimeException {
|
||||
try {
|
||||
LOG.info("Found Besu service: {}", service.getMetadata().getName());
|
||||
|
||||
internalAdvertisedHost =
|
||||
getIpDetector(service)
|
||||
.detectAdvertisedIp()
|
||||
.orElseThrow(
|
||||
() -> new NatInitializationException("Unable to retrieve IP from service"));
|
||||
|
||||
LOG.info("Setting host IP to: {}.", internalAdvertisedHost);
|
||||
|
||||
final String internalHost = queryLocalIPAddress().get(TIMEOUT_SECONDS, TimeUnit.SECONDS);
|
||||
service
|
||||
.getSpec()
|
||||
.getPorts()
|
||||
.forEach(
|
||||
v1ServicePort -> {
|
||||
try {
|
||||
final NatServiceType natServiceType =
|
||||
NatServiceType.fromString(v1ServicePort.getName());
|
||||
forwardedPorts.add(
|
||||
new NatPortMapping(
|
||||
natServiceType,
|
||||
natServiceType.equals(NatServiceType.DISCOVERY)
|
||||
? NetworkProtocol.UDP
|
||||
: NetworkProtocol.TCP,
|
||||
internalHost,
|
||||
internalAdvertisedHost,
|
||||
v1ServicePort.getPort(),
|
||||
v1ServicePort.getTargetPort().getIntValue()));
|
||||
} catch (IllegalStateException e) {
|
||||
LOG.warn("Ignored unknown Besu port: {}", e.getMessage());
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(
|
||||
"Failed update information using pod metadata : " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
LOG.info("Stopping kubernetes NAT manager.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<String> retrieveExternalIPAddress() {
|
||||
return CompletableFuture.completedFuture(internalAdvertisedHost);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<NatPortMapping>> getPortMappings() {
|
||||
return CompletableFuture.completedFuture(forwardedPorts);
|
||||
}
|
||||
|
||||
private IpDetector getIpDetector(final V1Service v1Service) throws NatInitializationException {
|
||||
final String serviceType = v1Service.getSpec().getType();
|
||||
switch (KubernetesServiceType.fromName(serviceType)) {
|
||||
case CLUSTER_IP:
|
||||
return () -> Optional.ofNullable(v1Service.getSpec().getClusterIP());
|
||||
case LOAD_BALANCER:
|
||||
return new LoadBalancerBasedDetector(v1Service);
|
||||
default:
|
||||
throw new NatInitializationException(String.format("%s is not implemented", serviceType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.nat.kubernetes.service;
|
||||
|
||||
/** The enum Kubernetes service type. */
|
||||
public enum KubernetesServiceType {
|
||||
/** Cluster ip kubernetes service type. */
|
||||
CLUSTER_IP("ClusterIP"),
|
||||
/** Load balancer kubernetes service type. */
|
||||
LOAD_BALANCER("LoadBalancer"),
|
||||
/** Unknown kubernetes service type. */
|
||||
UNKNOWN("");
|
||||
|
||||
/** The Name. */
|
||||
String name;
|
||||
|
||||
KubernetesServiceType(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map KubernetesServiceType from String value.
|
||||
*
|
||||
* @param name the name
|
||||
* @return the kubernetes service type
|
||||
*/
|
||||
public static KubernetesServiceType fromName(final String name) {
|
||||
for (KubernetesServiceType value : values()) {
|
||||
if (value.name.equals(name)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return UNKNOWN;
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.nat.kubernetes.service;
|
||||
|
||||
import org.hyperledger.besu.nat.core.IpDetector;
|
||||
import org.hyperledger.besu.nat.core.exception.NatInitializationException;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Optional;
|
||||
|
||||
import io.kubernetes.client.openapi.models.V1LoadBalancerIngress;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
|
||||
/** The Load balancer based detector. */
|
||||
public class LoadBalancerBasedDetector implements IpDetector {
|
||||
|
||||
private final V1Service v1Service;
|
||||
|
||||
/**
|
||||
* Instantiates a new Load balancer based detector.
|
||||
*
|
||||
* @param v1Service the v 1 service
|
||||
*/
|
||||
public LoadBalancerBasedDetector(final V1Service v1Service) {
|
||||
this.v1Service = v1Service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<String> detectAdvertisedIp() throws Exception {
|
||||
final V1LoadBalancerIngress v1LoadBalancerIngress =
|
||||
v1Service.getStatus().getLoadBalancer().getIngress().stream()
|
||||
.filter(
|
||||
v1LoadBalancerIngress1 ->
|
||||
v1LoadBalancerIngress1.getHostname() != null
|
||||
|| v1LoadBalancerIngress1.getIp() != null)
|
||||
.findFirst()
|
||||
.orElseThrow(() -> new NatInitializationException("Ingress not found"));
|
||||
if (v1LoadBalancerIngress.getHostname() != null) {
|
||||
return Optional.ofNullable(
|
||||
InetAddress.getByName(v1LoadBalancerIngress.getHostname()).getHostAddress());
|
||||
} else {
|
||||
return Optional.ofNullable(v1LoadBalancerIngress.getIp());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.nat.kubernetes;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.nat.core.domain.NatPortMapping;
|
||||
import org.hyperledger.besu.nat.core.domain.NatServiceType;
|
||||
import org.hyperledger.besu.nat.core.domain.NetworkProtocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import io.kubernetes.client.custom.IntOrString;
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.openapi.models.V1ServicePort;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceSpec;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class KubernetesClusterIpNatManagerTest {
|
||||
|
||||
private final String detectedAdvertisedHost = "199.45.69.12";
|
||||
|
||||
private final int p2pPort = 1;
|
||||
private final int rpcHttpPort = 2;
|
||||
|
||||
@Mock private V1Service v1Service;
|
||||
|
||||
private KubernetesNatManager natManager;
|
||||
|
||||
@BeforeEach
|
||||
public void initialize() throws IOException {
|
||||
|
||||
when(v1Service.getSpec())
|
||||
.thenReturn(
|
||||
new V1ServiceSpec()
|
||||
.type("ClusterIP")
|
||||
.clusterIP(detectedAdvertisedHost)
|
||||
.ports(
|
||||
Arrays.asList(
|
||||
new V1ServicePort()
|
||||
.name(NatServiceType.JSON_RPC.getValue())
|
||||
.port(rpcHttpPort)
|
||||
.targetPort(new IntOrString(rpcHttpPort)),
|
||||
new V1ServicePort()
|
||||
.name(NatServiceType.RLPX.getValue())
|
||||
.port(p2pPort)
|
||||
.targetPort(new IntOrString(p2pPort)),
|
||||
new V1ServicePort()
|
||||
.name(NatServiceType.DISCOVERY.getValue())
|
||||
.port(p2pPort)
|
||||
.targetPort(new IntOrString(p2pPort)))));
|
||||
when(v1Service.getMetadata())
|
||||
.thenReturn(new V1ObjectMeta().name(DEFAULT_BESU_SERVICE_NAME_FILTER));
|
||||
natManager = new KubernetesNatManager(DEFAULT_BESU_SERVICE_NAME_FILTER);
|
||||
try {
|
||||
natManager.start();
|
||||
} catch (Exception ignored) {
|
||||
System.err.println("Ignored missing Kube config file in testing context.");
|
||||
}
|
||||
natManager.updateUsingBesuService(v1Service);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatExternalIPIsEqualToRemoteHost()
|
||||
throws ExecutionException, InterruptedException {
|
||||
|
||||
assertThat(natManager.queryExternalIPAddress().get()).isEqualTo(detectedAdvertisedHost);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatLocalIPIsEqualToLocalHost()
|
||||
throws ExecutionException, InterruptedException, UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
assertThat(natManager.queryLocalIPAddress().get()).isEqualTo(internalHost);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatMappingForDiscoveryWorks() throws UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
final NatPortMapping mapping =
|
||||
natManager.getPortMapping(NatServiceType.DISCOVERY, NetworkProtocol.UDP);
|
||||
|
||||
final NatPortMapping expectedMapping =
|
||||
new NatPortMapping(
|
||||
NatServiceType.DISCOVERY,
|
||||
NetworkProtocol.UDP,
|
||||
internalHost,
|
||||
detectedAdvertisedHost,
|
||||
p2pPort,
|
||||
p2pPort);
|
||||
|
||||
assertThat(mapping).usingRecursiveComparison().isEqualTo(expectedMapping);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatMappingForJsonRpcWorks() throws UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
final NatPortMapping mapping =
|
||||
natManager.getPortMapping(NatServiceType.JSON_RPC, NetworkProtocol.TCP);
|
||||
|
||||
final NatPortMapping expectedMapping =
|
||||
new NatPortMapping(
|
||||
NatServiceType.JSON_RPC,
|
||||
NetworkProtocol.TCP,
|
||||
internalHost,
|
||||
detectedAdvertisedHost,
|
||||
rpcHttpPort,
|
||||
rpcHttpPort);
|
||||
|
||||
assertThat(mapping).usingRecursiveComparison().isEqualTo(expectedMapping);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatMappingForRlpxWorks() throws UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
final NatPortMapping mapping =
|
||||
natManager.getPortMapping(NatServiceType.RLPX, NetworkProtocol.TCP);
|
||||
|
||||
final NatPortMapping expectedMapping =
|
||||
new NatPortMapping(
|
||||
NatServiceType.RLPX,
|
||||
NetworkProtocol.TCP,
|
||||
internalHost,
|
||||
detectedAdvertisedHost,
|
||||
p2pPort,
|
||||
p2pPort);
|
||||
|
||||
assertThat(mapping).usingRecursiveComparison().isEqualTo(expectedMapping);
|
||||
}
|
||||
}
|
||||
@@ -1,164 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.nat.kubernetes;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.hyperledger.besu.nat.core.domain.NatPortMapping;
|
||||
import org.hyperledger.besu.nat.core.domain.NatServiceType;
|
||||
import org.hyperledger.besu.nat.core.domain.NetworkProtocol;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import io.kubernetes.client.custom.IntOrString;
|
||||
import io.kubernetes.client.openapi.models.V1LoadBalancerIngress;
|
||||
import io.kubernetes.client.openapi.models.V1LoadBalancerStatus;
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.openapi.models.V1ServicePort;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceSpec;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceStatus;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class KubernetesLoadManagerNatManagerTest {
|
||||
|
||||
private final String detectedAdvertisedHost = "199.45.69.12";
|
||||
|
||||
private final int p2pPort = 1;
|
||||
private final int rpcHttpPort = 2;
|
||||
|
||||
@Mock private V1Service v1Service;
|
||||
|
||||
private KubernetesNatManager natManager;
|
||||
|
||||
@BeforeEach
|
||||
public void initialize() throws IOException {
|
||||
final V1ServiceStatus v1ServiceStatus =
|
||||
new V1ServiceStatus()
|
||||
.loadBalancer(
|
||||
new V1LoadBalancerStatus()
|
||||
.addIngressItem(new V1LoadBalancerIngress().ip(detectedAdvertisedHost)));
|
||||
when(v1Service.getStatus()).thenReturn(v1ServiceStatus);
|
||||
when(v1Service.getSpec())
|
||||
.thenReturn(
|
||||
new V1ServiceSpec()
|
||||
.type("LoadBalancer")
|
||||
.ports(
|
||||
Arrays.asList(
|
||||
new V1ServicePort()
|
||||
.name(NatServiceType.JSON_RPC.getValue())
|
||||
.port(rpcHttpPort)
|
||||
.targetPort(new IntOrString(rpcHttpPort)),
|
||||
new V1ServicePort()
|
||||
.name(NatServiceType.RLPX.getValue())
|
||||
.port(p2pPort)
|
||||
.targetPort(new IntOrString(p2pPort)),
|
||||
new V1ServicePort()
|
||||
.name(NatServiceType.DISCOVERY.getValue())
|
||||
.port(p2pPort)
|
||||
.targetPort(new IntOrString(p2pPort)))));
|
||||
when(v1Service.getMetadata())
|
||||
.thenReturn(new V1ObjectMeta().name(DEFAULT_BESU_SERVICE_NAME_FILTER));
|
||||
natManager = new KubernetesNatManager(DEFAULT_BESU_SERVICE_NAME_FILTER);
|
||||
try {
|
||||
natManager.start();
|
||||
} catch (Exception ignored) {
|
||||
System.err.println("Ignored missing Kube config file in testing context.");
|
||||
}
|
||||
natManager.updateUsingBesuService(v1Service);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatExternalIPIsEqualToRemoteHost()
|
||||
throws ExecutionException, InterruptedException {
|
||||
|
||||
assertThat(natManager.queryExternalIPAddress().get()).isEqualTo(detectedAdvertisedHost);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatLocalIPIsEqualToLocalHost()
|
||||
throws ExecutionException, InterruptedException, UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
assertThat(natManager.queryLocalIPAddress().get()).isEqualTo(internalHost);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatMappingForDiscoveryWorks() throws UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
final NatPortMapping mapping =
|
||||
natManager.getPortMapping(NatServiceType.DISCOVERY, NetworkProtocol.UDP);
|
||||
|
||||
final NatPortMapping expectedMapping =
|
||||
new NatPortMapping(
|
||||
NatServiceType.DISCOVERY,
|
||||
NetworkProtocol.UDP,
|
||||
internalHost,
|
||||
detectedAdvertisedHost,
|
||||
p2pPort,
|
||||
p2pPort);
|
||||
|
||||
assertThat(mapping).usingRecursiveComparison().isEqualTo(expectedMapping);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatMappingForJsonRpcWorks() throws UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
final NatPortMapping mapping =
|
||||
natManager.getPortMapping(NatServiceType.JSON_RPC, NetworkProtocol.TCP);
|
||||
|
||||
final NatPortMapping expectedMapping =
|
||||
new NatPortMapping(
|
||||
NatServiceType.JSON_RPC,
|
||||
NetworkProtocol.TCP,
|
||||
internalHost,
|
||||
detectedAdvertisedHost,
|
||||
rpcHttpPort,
|
||||
rpcHttpPort);
|
||||
|
||||
assertThat(mapping).usingRecursiveComparison().isEqualTo(expectedMapping);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatMappingForRlpxWorks() throws UnknownHostException {
|
||||
final String internalHost = InetAddress.getLocalHost().getHostAddress();
|
||||
|
||||
final NatPortMapping mapping =
|
||||
natManager.getPortMapping(NatServiceType.RLPX, NetworkProtocol.TCP);
|
||||
|
||||
final NatPortMapping expectedMapping =
|
||||
new NatPortMapping(
|
||||
NatServiceType.RLPX,
|
||||
NetworkProtocol.TCP,
|
||||
internalHost,
|
||||
detectedAdvertisedHost,
|
||||
p2pPort,
|
||||
p2pPort);
|
||||
|
||||
assertThat(mapping).usingRecursiveComparison().isEqualTo(expectedMapping);
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright ConsenSys AG.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
package org.hyperledger.besu.nat.kubernetes;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
import static org.hyperledger.besu.nat.kubernetes.KubernetesNatManager.DEFAULT_BESU_SERVICE_NAME_FILTER;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import io.kubernetes.client.openapi.models.V1ObjectMeta;
|
||||
import io.kubernetes.client.openapi.models.V1Service;
|
||||
import io.kubernetes.client.openapi.models.V1ServiceSpec;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
public final class KubernetesUnknownNatManagerTest {
|
||||
|
||||
@Mock private V1Service v1Service;
|
||||
|
||||
private KubernetesNatManager natManager;
|
||||
|
||||
@BeforeEach
|
||||
public void initialize() {
|
||||
|
||||
when(v1Service.getSpec()).thenReturn(new V1ServiceSpec().type("Unknown"));
|
||||
when(v1Service.getMetadata())
|
||||
.thenReturn(new V1ObjectMeta().name(DEFAULT_BESU_SERVICE_NAME_FILTER));
|
||||
natManager = new KubernetesNatManager(DEFAULT_BESU_SERVICE_NAME_FILTER);
|
||||
try {
|
||||
natManager.start();
|
||||
} catch (Exception ignored) {
|
||||
System.err.println("Ignored missing Kube config file in testing context.");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void assertThatNatExceptionIsThrownWithUnknownServiceType() {
|
||||
assertThatThrownBy(() -> natManager.updateUsingBesuService(v1Service))
|
||||
.isInstanceOf(RuntimeException.class);
|
||||
}
|
||||
}
|
||||
@@ -96,8 +96,6 @@ dependencies {
|
||||
api 'info.picocli:picocli:4.7.6'
|
||||
api 'info.picocli:picocli-codegen:4.7.6'
|
||||
|
||||
api 'io.kubernetes:client-java:21.0.1-legacy'
|
||||
|
||||
api 'io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0:2.9.0-alpha'
|
||||
api 'io.opentelemetry.proto:opentelemetry-proto:1.3.2-alpha'
|
||||
api 'io.opentelemetry.semconv:opentelemetry-semconv:1.28.0-alpha'
|
||||
|
||||
Reference in New Issue
Block a user