Initial support for multi kubernetes clusters for k8s nodes
Change-Id: I6ca132898f8e157e0583de38a637fdc135f21d6f
(cherry picked from commit e2a04cedde73618ef24575e70cb221e03854de1d)
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/HostNodesInfoJsonMatcher.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/HostNodesInfoJsonMatcher.java
new file mode 100644
index 0000000..5de7a71
--- /dev/null
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/HostNodesInfoJsonMatcher.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 org.onosproject.k8snode.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.k8snode.api.HostNodesInfo;
+
+/**
+ * Hamcrest matcher for HostNodesInfo.
+ */
+public final class HostNodesInfoJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final HostNodesInfo hostNodesInfo;
+
+ private static final String HOST_IP = "hostIp";
+ private static final String NODES = "nodes";
+
+ private HostNodesInfoJsonMatcher(HostNodesInfo hostNodesInfo) {
+ this.hostNodesInfo = hostNodesInfo;
+ }
+
+ @Override
+ protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+ // check host IP
+ String jsonHostIp = jsonNode.get(HOST_IP).asText();
+ String hostIp = hostNodesInfo.hostIp().toString();
+ if (!jsonHostIp.equals(hostIp)) {
+ description.appendText("host IP was " + jsonHostIp);
+ return false;
+ }
+
+ // check nodes
+ JsonNode jsonNodes = jsonNode.get(NODES);
+ if (jsonNodes.size() != hostNodesInfo.nodes().size()) {
+ description.appendText("Nodes size was " + jsonNodes.size());
+ return false;
+ }
+
+ boolean nodeFound = true;
+ ArrayNode jsonNodeArray = (ArrayNode) jsonNodes;
+ for (JsonNode jsonNodeTmp : jsonNodeArray) {
+ if (!hostNodesInfo.nodes().contains(jsonNodeTmp.asText())) {
+ nodeFound = false;
+ }
+ }
+
+ if (!nodeFound) {
+ description.appendText("Node not found");
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(hostNodesInfo.toString());
+ }
+
+ /**
+ * Factory to allocate a hostNodesInfo matcher.
+ *
+ * @param info host IP address to nodes mapping info
+ * @return matcher
+ */
+ public static HostNodesInfoJsonMatcher matchesHostNodesInfo(HostNodesInfo info) {
+ return new HostNodesInfoJsonMatcher(info);
+ }
+}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigCodecTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigCodecTest.java
index cca918e..b5deb38 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigCodecTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigCodecTest.java
@@ -18,20 +18,25 @@
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
import org.junit.Before;
import org.junit.Test;
import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.core.CoreService;
+import org.onosproject.k8snode.api.DefaultHostNodesInfo;
import org.onosproject.k8snode.api.DefaultK8sApiConfig;
+import org.onosproject.k8snode.api.HostNodesInfo;
import org.onosproject.k8snode.api.K8sApiConfig;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import static junit.framework.TestCase.assertEquals;
import static org.easymock.EasyMock.createMock;
@@ -51,6 +56,7 @@
MockCodecContext context;
JsonCodec<K8sApiConfig> k8sApiConfigCodec;
+ JsonCodec<HostNodesInfo> hostNodesInfoCodec;
final CoreService mockCoreService = createMock(CoreService.class);
private static final String REST_APP_ID = "org.onosproject.rest";
@@ -62,8 +68,10 @@
public void setUp() {
context = new MockCodecContext();
k8sApiConfigCodec = new K8sApiConfigCodec();
+ hostNodesInfoCodec = new HostNodesInfoCodec();
assertThat(k8sApiConfigCodec, notNullValue());
+ assertThat(hostNodesInfoCodec, notNullValue());
expect(mockCoreService.registerApplication(REST_APP_ID))
.andReturn(APP_ID).anyTimes();
@@ -76,7 +84,16 @@
*/
@Test
public void testK8sApiConfigEncode() {
+ HostNodesInfo info = new DefaultHostNodesInfo.Builder()
+ .hostIp(IpAddress.valueOf("192.168.10.10"))
+ .nodes(ImmutableSet.of("master", "worker"))
+ .build();
+
K8sApiConfig config = DefaultK8sApiConfig.builder()
+ .clusterName("kubernetes")
+ .segmentId(1)
+ .extNetworkCidr(IpPrefix.valueOf("192.168.200.0/24"))
+ .mode(K8sApiConfig.Mode.NORMAL)
.scheme(K8sApiConfig.Scheme.HTTPS)
.ipAddress(IpAddress.valueOf("10.10.10.23"))
.port(6443)
@@ -85,6 +102,7 @@
.caCertData("caCertData")
.clientCertData("clientCertData")
.clientKeyData("clientKeyData")
+ .infos(ImmutableSet.of(info))
.build();
ObjectNode configJson = k8sApiConfigCodec.encode(config, context);
@@ -100,6 +118,10 @@
public void testK8sApiConfigDecode() throws IOException {
K8sApiConfig config = getK8sApiConfig("K8sApiConfig.json");
+ assertEquals("kubernetes", config.clusterName());
+ assertEquals(1, config.segmentId());
+ assertEquals("192.168.200.0/24", config.extNetworkCidr().toString());
+ assertEquals("NORMAL", config.mode().name());
assertEquals("HTTPS", config.scheme().name());
assertEquals("10.134.34.223", config.ipAddress().toString());
assertEquals(6443, config.port());
@@ -107,6 +129,9 @@
assertEquals("caCertData", config.caCertData());
assertEquals("clientCertData", config.clientCertData());
assertEquals("clientKeyData", config.clientKeyData());
+
+ Set<HostNodesInfo> infos = config.infos();
+ assertEquals(1, infos.size());
}
private K8sApiConfig getK8sApiConfig(String resourceName) throws IOException {
@@ -141,6 +166,9 @@
if (entityClass == K8sApiConfig.class) {
return (JsonCodec<T>) k8sApiConfigCodec;
}
+ if (entityClass == HostNodesInfo.class) {
+ return (JsonCodec<T>) hostNodesInfoCodec;
+ }
return manager.getCodec(entityClass);
}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigJsonMatcher.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigJsonMatcher.java
index 2eb42b9..7ec3866 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigJsonMatcher.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sApiConfigJsonMatcher.java
@@ -18,6 +18,7 @@
import com.fasterxml.jackson.databind.JsonNode;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.k8snode.api.HostNodesInfo;
import org.onosproject.k8snode.api.K8sApiConfig;
/**
@@ -27,6 +28,10 @@
private final K8sApiConfig k8sApiConfig;
+ private static final String CLUSTER_NAME = "clusterName";
+ private static final String SEGMENT_ID = "segmentId";
+ private static final String EXT_NETWORK_CIDR = "extNetworkCidr";
+ private static final String MODE = "mode";
private static final String SCHEME = "scheme";
private static final String IP_ADDRESS = "ipAddress";
private static final String PORT = "port";
@@ -35,6 +40,7 @@
private static final String CA_CERT_DATA = "caCertData";
private static final String CLIENT_CERT_DATA = "clientCertData";
private static final String CLIENT_KEY_DATA = "clientKeyData";
+ private static final String HOST_NODES_INFO = "hostNodesInfo";
private K8sApiConfigJsonMatcher(K8sApiConfig k8sApiConfig) {
this.k8sApiConfig = k8sApiConfig;
@@ -43,6 +49,40 @@
@Override
protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+ // check cluster name
+ String jsonClusterName = jsonNode.get(CLUSTER_NAME).asText();
+ String clusterName = k8sApiConfig.clusterName();
+ if (!jsonClusterName.equals(clusterName)) {
+ description.appendText("cluster name was " + jsonClusterName);
+ return false;
+ }
+
+ // check segment ID
+ int jsonSegmentId = jsonNode.get(SEGMENT_ID).asInt();
+ int segmentId = k8sApiConfig.segmentId();
+ if (jsonSegmentId != segmentId) {
+ description.appendText("Segment ID was " + jsonSegmentId);
+ return false;
+ }
+
+ // check mode
+ String jsonMode = jsonNode.get(MODE).asText();
+ String mode = k8sApiConfig.mode().name();
+ if (!jsonMode.equals(mode)) {
+ description.appendText("mode was " + jsonMode);
+ return false;
+ }
+
+ // check external network CIDR
+ JsonNode jsonCidr = jsonNode.get(EXT_NETWORK_CIDR);
+ String cidr = k8sApiConfig.extNetworkCidr().toString();
+ if (jsonCidr != null) {
+ if (!jsonCidr.asText().equals(cidr)) {
+ description.appendText("External network CIDR was " + jsonCidr);
+ return false;
+ }
+ }
+
// check scheme
String jsonScheme = jsonNode.get(SCHEME).asText();
String scheme = k8sApiConfig.scheme().name();
@@ -119,6 +159,29 @@
}
}
+ // check hostNodesInfo size
+ JsonNode jsonInfos = jsonNode.get(HOST_NODES_INFO);
+ if (jsonInfos.size() != k8sApiConfig.infos().size()) {
+ description.appendText("Info size was " + jsonInfos.size());
+ return false;
+ }
+
+ // check info
+ for (HostNodesInfo info : k8sApiConfig.infos()) {
+ boolean infoFound = false;
+ for (int infoIndex = 0; infoIndex < jsonInfos.size(); infoIndex++) {
+ HostNodesInfoJsonMatcher infoMatcher = HostNodesInfoJsonMatcher.matchesHostNodesInfo(info);
+ if (infoMatcher.matches(jsonInfos.get(infoIndex))) {
+ infoFound = true;
+ break;
+ }
+ }
+ if (!infoFound) {
+ description.appendText("Info not found " + info.toString());
+ return false;
+ }
+ }
+
return true;
}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sHostCodecTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sHostCodecTest.java
new file mode 100644
index 0000000..c7cb041
--- /dev/null
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sHostCodecTest.java
@@ -0,0 +1,144 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 org.onosproject.k8snode.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableSet;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.codec.impl.CodecManager;
+import org.onosproject.core.CoreService;
+import org.onosproject.k8snode.api.DefaultK8sHost;
+import org.onosproject.k8snode.api.K8sHost;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.k8snode.api.K8sHostState.INIT;
+import static org.onosproject.k8snode.codec.K8sHostJsonMatcher.matchesK8sHost;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
+public class K8sHostCodecTest {
+
+ MockCodecContext context;
+
+ JsonCodec<K8sHost> k8sHostCodec;
+
+ final CoreService mockCoreService = createMock(CoreService.class);
+ private static final String REST_APP_ID = "org.onosproject.rest";
+
+ /**
+ * Initial setup for this unit test.
+ */
+ @Before
+ public void setUp() {
+ context = new MockCodecContext();
+ k8sHostCodec = new K8sHostCodec();
+
+ assertThat(k8sHostCodec, notNullValue());
+
+ expect(mockCoreService.registerApplication(REST_APP_ID))
+ .andReturn(APP_ID).anyTimes();
+ replay(mockCoreService);
+ context.registerService(CoreService.class, mockCoreService);
+ }
+
+ /**
+ * Tests the kubernetes host encoding.
+ */
+ @Test
+ public void testK8sHostEncode() {
+ K8sHost host = DefaultK8sHost.builder()
+ .hostIp(IpAddress.valueOf("192.168.200.10"))
+ .state(INIT)
+ .nodeNames(ImmutableSet.of("1", "2"))
+ .build();
+
+ ObjectNode hostJson = k8sHostCodec.encode(host, context);
+ assertThat(hostJson, matchesK8sHost(host));
+ }
+
+ /**
+ * Tests the kubernetes host decoding.
+ */
+ @Test
+ public void testK8sHostDecode() throws IOException {
+ K8sHost host = getK8sHost("K8sHost.json");
+
+ assertEquals("192.168.200.10", host.hostIp().toString());
+ assertEquals("INIT", host.state().name());
+ }
+
+ private K8sHost getK8sHost(String resourceName) throws IOException {
+ InputStream jsonStream = K8sHostCodecTest.class.getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ K8sHost host = k8sHostCodec.decode((ObjectNode) json, context);
+ assertThat(host, notNullValue());
+ return host;
+ }
+
+ private class MockCodecContext implements CodecContext {
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final CodecManager manager = new CodecManager();
+ private final Map<Class<?>, Object> services = new HashMap<>();
+
+ /**
+ * Constructs a new mock codec context.
+ */
+ public MockCodecContext() {
+ manager.activate();
+ }
+
+ @Override
+ public ObjectMapper mapper() {
+ return mapper;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> JsonCodec<T> codec(Class<T> entityClass) {
+ if (entityClass == K8sHost.class) {
+ return (JsonCodec<T>) k8sHostCodec;
+ }
+ return manager.getCodec(entityClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ return (T) services.get(serviceClass);
+ }
+
+ // for registering mock services
+ public <T> void registerService(Class<T> serviceClass, T impl) {
+ services.put(serviceClass, impl);
+ }
+ }
+}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sHostJsonMatcher.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sHostJsonMatcher.java
new file mode 100644
index 0000000..4a0cf73
--- /dev/null
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sHostJsonMatcher.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 org.onosproject.k8snode.codec;
+
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.k8snode.api.K8sHost;
+
+/**
+ * Hamcrest matcher for kubernetes host.
+ */
+public final class K8sHostJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final K8sHost host;
+
+ private static final String HOST_IP = "hostIp";
+ private static final String NODE_NAMES = "nodeNames";
+ private static final String STATE = "state";
+
+ private K8sHostJsonMatcher(K8sHost host) {
+ this.host = host;
+ }
+
+ @Override
+ protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+ // check host IP
+ String jsonHostIp = jsonNode.get(HOST_IP).asText();
+ String hostIp = host.hostIp().toString();
+ if (!jsonHostIp.equals(hostIp)) {
+ description.appendText("host IP was " + jsonHostIp);
+ return false;
+ }
+
+ // check state
+ String jsonState = jsonNode.get(STATE).asText();
+ String state = host.state().name();
+ if (!jsonState.equals(state)) {
+ description.appendText("state was " + jsonState);
+ return false;
+ }
+
+ // check node names size
+ JsonNode jsonNames = jsonNode.get(NODE_NAMES);
+ if (jsonNames.size() != host.nodeNames().size()) {
+ description.appendText("Node names size was " + jsonNames.size());
+ return false;
+ }
+
+ // check node names
+ for (String name : host.nodeNames()) {
+ boolean nameFound = false;
+ for (int nameIndex = 0; nameIndex < jsonNames.size(); nameIndex++) {
+ if (name.equals(jsonNames.get(nameIndex).asText())) {
+ nameFound = true;
+ break;
+ }
+ }
+
+ if (!nameFound) {
+ description.appendText("Name not found " + name);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(host.toString());
+ }
+
+ /**
+ * Factory to allocate an k8s host matcher.
+ *
+ * @param host k8s host object we are looking for
+ * @return matcher
+ */
+ public static K8sHostJsonMatcher matchesK8sHost(K8sHost host) {
+ return new K8sHostJsonMatcher(host);
+ }
+}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java
index 556e462..c6861be 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeCodecTest.java
@@ -78,8 +78,10 @@
@Test
public void testK8sMinionNodeEncode() {
K8sNode node = DefaultK8sNode.builder()
+ .clusterName("kubernetes")
.hostname("minion")
.type(K8sNode.Type.MINION)
+ .segmentId(100)
.state(K8sNodeState.INIT)
.managementIp(IpAddress.valueOf("10.10.10.1"))
.dataIp(IpAddress.valueOf("20.20.20.2"))
@@ -102,8 +104,10 @@
public void testK8sMinionNodeDecode() throws IOException {
K8sNode node = getK8sNode("K8sMinionNode.json");
+ assertEquals("kubernetes", node.clusterName());
assertEquals("minion", node.hostname());
assertEquals("MINION", node.type().name());
+ assertEquals(100, node.segmentId());
assertEquals("172.16.130.4", node.managementIp().toString());
assertEquals("172.16.130.4", node.dataIp().toString());
assertEquals("of:00000000000000a1", node.intgBridge().toString());
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeJsonMatcher.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeJsonMatcher.java
index b953f54..816ca76 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeJsonMatcher.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/codec/K8sNodeJsonMatcher.java
@@ -28,8 +28,10 @@
private final K8sNode node;
+ private static final String CLUSTER_NAME = "clusterName";
private static final String HOSTNAME = "hostname";
private static final String TYPE = "type";
+ private static final String SEGMENT_ID = "segmentId";
private static final String MANAGEMENT_IP = "managementIp";
private static final String DATA_IP = "dataIp";
private static final String INTEGRATION_BRIDGE = "integrationBridge";
@@ -45,6 +47,14 @@
@Override
protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+ // check cluster name
+ String jsonClusterName = jsonNode.get(CLUSTER_NAME).asText();
+ String clusterName = node.clusterName();
+ if (!jsonClusterName.equals(clusterName)) {
+ description.appendText("cluster name was " + jsonClusterName);
+ return false;
+ }
+
// check hostname
String jsonHostname = jsonNode.get(HOSTNAME).asText();
String hostname = node.hostname();
@@ -61,6 +71,16 @@
return false;
}
+ // check segment ID
+ JsonNode jsonSegmentId = jsonNode.get(SEGMENT_ID);
+ if (jsonSegmentId != null) {
+ int segmentId = jsonSegmentId.asInt();
+ if (segmentId != node.segmentId()) {
+ description.appendText("segment ID was " + segmentId);
+ return false;
+ }
+ }
+
// check management IP
String jsonMgmtIp = jsonNode.get(MANAGEMENT_IP).asText();
String mgmtIp = node.managementIp().toString();
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/ExternalNetworkManagerTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/ExternalNetworkManagerTest.java
new file mode 100644
index 0000000..f236491
--- /dev/null
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/ExternalNetworkManagerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 org.onosproject.k8snode.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.store.service.TestStorageService;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Unit tests for external network manager.
+ */
+public class ExternalNetworkManagerTest {
+
+ private static final ApplicationId TEST_APP_ID = new DefaultApplicationId(1, "test");
+
+ private ExternalNetworkManager target;
+
+ /**
+ * Initial setup for this unit test.
+ */
+ @Before
+ public void setUp() {
+ target = new ExternalNetworkManager();
+
+ target.coreService = new TestCoreService();
+ target.storageService = new TestStorageService();
+ target.activate();
+ }
+
+ /**
+ * Clean up unit test.
+ */
+ @After
+ public void tearDown() {
+ target.deactivate();
+ target = null;
+ }
+
+ /**
+ * Checks if creating and removing a config work well with proper events.
+ */
+ @Test
+ public void testObtainGatewayIp() {
+ IpPrefix cidr = IpPrefix.valueOf("192.168.200.0/24");
+ target.registerNetwork(cidr);
+
+ assertEquals(target.getGatewayIp(cidr), IpAddress.valueOf("192.168.200.1"));
+ }
+
+ @Test
+ public void testAllocateReleaseIp() {
+ IpPrefix cidr = IpPrefix.valueOf("192.168.200.0/24");
+ target.registerNetwork(cidr);
+ IpAddress ip = target.allocateIp(cidr);
+ assertEquals(251, target.getAllIps(cidr).size());
+
+ target.releaseIp(cidr, ip);
+ assertEquals(252, target.getAllIps(cidr).size());
+ }
+
+ private static class TestCoreService extends CoreServiceAdapter {
+ @Override
+ public ApplicationId registerApplication(String name) {
+ return TEST_APP_ID;
+ }
+ }
+}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sApiConfigManagerTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sApiConfigManagerTest.java
index f46feb8..badfced 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sApiConfigManagerTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sApiConfigManagerTest.java
@@ -72,12 +72,18 @@
public void setUp() {
apiConfig1 = DefaultK8sApiConfig.builder()
+ .clusterName("kubernetes1")
+ .segmentId(1)
+ .mode(K8sApiConfig.Mode.NORMAL)
.scheme(K8sApiConfig.Scheme.HTTP)
.ipAddress(IpAddress.valueOf("10.10.10.2"))
.port(6443)
.state(DISCONNECTED)
.build();
apiConfig2 = DefaultK8sApiConfig.builder()
+ .clusterName("kubernetes2")
+ .segmentId(2)
+ .mode(K8sApiConfig.Mode.NORMAL)
.scheme(K8sApiConfig.Scheme.HTTPS)
.ipAddress(IpAddress.valueOf("10.10.10.3"))
.port(6443)
@@ -88,6 +94,9 @@
.clientKeyData("clientKeyData")
.build();
apiConfig3 = DefaultK8sApiConfig.builder()
+ .clusterName("kubernetes3")
+ .segmentId(3)
+ .mode(K8sApiConfig.Mode.PASSTHROUGH)
.scheme(K8sApiConfig.Scheme.HTTP)
.ipAddress(IpAddress.valueOf("10.10.10.4"))
.port(8080)
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sHostManagerTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sHostManagerTest.java
new file mode 100644
index 0000000..3374672
--- /dev/null
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sHostManagerTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright 2020-present Open Networking Foundation
+ *
+ * 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 org.onosproject.k8snode.impl;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.util.concurrent.MoreExecutors;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.junit.TestUtils;
+import org.onlab.packet.IpAddress;
+import org.onosproject.cluster.ClusterServiceAdapter;
+import org.onosproject.cluster.LeadershipServiceAdapter;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreServiceAdapter;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.event.Event;
+import org.onosproject.k8snode.api.DefaultK8sHost;
+import org.onosproject.k8snode.api.K8sHost;
+import org.onosproject.k8snode.api.K8sHostEvent;
+import org.onosproject.k8snode.api.K8sHostListener;
+import org.onosproject.k8snode.api.K8sHostState;
+import org.onosproject.store.service.TestStorageService;
+
+import java.util.List;
+import java.util.Set;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.onosproject.k8snode.api.K8sHostEvent.Type.K8S_HOST_COMPLETE;
+import static org.onosproject.k8snode.api.K8sHostEvent.Type.K8S_HOST_CREATED;
+import static org.onosproject.k8snode.api.K8sHostEvent.Type.K8S_HOST_REMOVED;
+import static org.onosproject.k8snode.api.K8sHostEvent.Type.K8S_HOST_UPDATED;
+import static org.onosproject.k8snode.api.K8sHostEvent.Type.K8S_NODES_ADDED;
+import static org.onosproject.k8snode.api.K8sHostEvent.Type.K8S_NODES_REMOVED;
+import static org.onosproject.k8snode.api.K8sHostState.COMPLETE;
+import static org.onosproject.k8snode.api.K8sHostState.INIT;
+
+/**
+ * Unit tests for kubernetes host manager.
+ */
+public class K8sHostManagerTest {
+
+ private static final ApplicationId TEST_APP_ID = new DefaultApplicationId(1, "test");
+
+ private static final String ERR_SIZE = "Number of hosts did not match";
+ private static final String ERR_NOT_MATCH = "Host did not match";
+ private static final String ERR_NOT_FOUND = "Host did not exist";
+
+ private static final IpAddress HOST_IP_1 = IpAddress.valueOf("192.168.100.2");
+ private static final IpAddress HOST_IP_2 = IpAddress.valueOf("192.168.101.2");
+ private static final IpAddress HOST_IP_3 = IpAddress.valueOf("192.168.102.2");
+
+ private static final K8sHost HOST_1 = createHost(
+ HOST_IP_1,
+ INIT,
+ ImmutableSet.of("1", "2")
+ );
+
+ private static final K8sHost HOST_2 = createHost(
+ HOST_IP_2,
+ INIT,
+ ImmutableSet.of("3", "4")
+ );
+
+ private static final K8sHost HOST_3 = createHost(
+ HOST_IP_3,
+ COMPLETE,
+ ImmutableSet.of("5", "6")
+ );
+
+ private final TestK8sHostListener testListener = new TestK8sHostListener();
+
+ private K8sHostManager target;
+ private DistributedK8sHostStore hostStore;
+
+ /**
+ * Initial setup for this unit test.
+ */
+ @Before
+ public void setUp() {
+ hostStore = new DistributedK8sHostStore();
+ TestUtils.setField(hostStore, "coreService", new TestCoreService());
+ TestUtils.setField(hostStore, "storageService", new TestStorageService());
+ TestUtils.setField(hostStore, "eventExecutor", MoreExecutors.newDirectExecutorService());
+ hostStore.activate();
+
+ hostStore.createHost(HOST_2);
+ hostStore.createHost(HOST_3);
+
+ target = new K8sHostManager();
+ target.storageService = new TestStorageService();
+ target.coreService = new TestCoreService();
+ target.clusterService = new TestClusterService();
+ target.leadershipService = new TestLeadershipService();
+ target.hostStore = hostStore;
+ target.addListener(testListener);
+ target.activate();
+ testListener.events.clear();
+ }
+
+ /**
+ * Clean up unit test.
+ */
+ @After
+ public void tearDown() {
+ target.removeListener(testListener);
+ target.deactivate();
+ hostStore.deactivate();
+ hostStore = null;
+ target = null;
+ }
+
+ /**
+ * Checks if creating and removing a host work well with proper events.
+ */
+ @Test
+ public void testCreateAndRemoveHost() {
+ target.createHost(HOST_1);
+ assertEquals(ERR_SIZE, 3, target.hosts().size());
+ assertNotNull(target.host(HOST_IP_1));
+
+ target.removeHost(HOST_IP_1);
+ assertEquals(ERR_SIZE, 2, target.hosts().size());
+ assertNull(target.host(HOST_IP_1));
+
+ validateEvents(K8S_HOST_CREATED, K8S_HOST_REMOVED);
+ }
+
+ /**
+ * Checks if creating null host fails with proper exception.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testCreateNullHost() {
+ target.createHost(null);
+ }
+
+ /**
+ * Checks if creating a duplicated host fails with proper exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testCreateDuplicateHost() {
+ target.createHost(HOST_1);
+ target.createHost(HOST_1);
+ }
+
+ /**
+ * Checks if removing null host fails with proper exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testRemoveNullHost() {
+ target.removeHost(null);
+ }
+
+ /**
+ * Checks if updating a host works well with proper event.
+ */
+ @Test
+ public void testUpdateHost() {
+ K8sHost updated = HOST_2.updateState(COMPLETE);
+ target.updateHost(updated);
+ validateEvents(K8S_HOST_UPDATED, K8S_HOST_COMPLETE);
+ }
+
+ /**
+ * Checks if updating a null host fails with proper exception.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testUpdateNullHost() {
+ target.updateHost(null);
+ }
+
+ /**
+ * Checks if updating not existing host fails with proper exception.
+ */
+ @Test(expected = IllegalArgumentException.class)
+ public void testUpdateNotExistingHost() {
+ target.updateHost(HOST_1);
+ }
+
+ /**
+ * Checks if adding nodes into host works well with proper event.
+ */
+ @Test
+ public void testAddNodesToHost() {
+ K8sHost updated = HOST_2.updateNodeNames(ImmutableSet.of("3", "4", "5"));
+ target.updateHost(updated);
+ validateEvents(K8S_HOST_UPDATED, K8S_NODES_ADDED);
+ }
+
+ /**
+ * Checks if removing nodes from host works well with proper event.
+ */
+ @Test
+ public void testRemoveNodesFromHost() {
+ K8sHost updated = HOST_2.updateNodeNames(ImmutableSet.of("3"));
+ target.updateHost(updated);
+ validateEvents(K8S_HOST_UPDATED, K8S_NODES_REMOVED);
+ }
+
+ /**
+ * Checks if getting all hosts method returns correct set of nodes.
+ */
+ @Test
+ public void testGetAllHosts() {
+ assertEquals(ERR_SIZE, 2, target.hosts().size());
+ assertTrue(ERR_NOT_FOUND, target.hosts().contains(HOST_2));
+ assertTrue(ERR_NOT_FOUND, target.hosts().contains(HOST_3));
+ }
+
+ /**
+ * Checks if getting complete hosts method returns correct set of nodes.
+ */
+ @Test
+ public void testGetCompleteHosts() {
+ assertEquals(ERR_SIZE, 1, target.completeHosts().size());
+ assertTrue(ERR_NOT_FOUND, target.completeHosts().contains(HOST_3));
+ }
+
+ private void validateEvents(Enum... types) {
+ int i = 0;
+ assertEquals("Number of events did not match", types.length, testListener.events.size());
+ for (Event event : testListener.events) {
+ assertEquals("Incorrect event received", types[i], event.type());
+ i++;
+ }
+ testListener.events.clear();
+ }
+
+ private static class TestK8sHostListener implements K8sHostListener {
+ private List<K8sHostEvent> events = Lists.newArrayList();
+
+ @Override
+ public void event(K8sHostEvent event) {
+ events.add(event);
+ }
+ }
+
+ private static class TestCoreService extends CoreServiceAdapter {
+ @Override
+ public ApplicationId registerApplication(String name) {
+ return TEST_APP_ID;
+ }
+ }
+
+ private class TestClusterService extends ClusterServiceAdapter {
+
+ }
+
+ private static class TestLeadershipService extends LeadershipServiceAdapter {
+
+ }
+
+ private static K8sHost createHost(IpAddress hostIp, K8sHostState state, Set<String> nodeNames) {
+ return DefaultK8sHost.builder()
+ .hostIp(hostIp)
+ .nodeNames(nodeNames)
+ .state(state)
+ .build();
+ }
+}
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java
index 50d769f..0bb0258 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/impl/K8sNodeManagerTest.java
@@ -68,6 +68,8 @@
private static final String ERR_NOT_MATCH = "Node did not match";
private static final String ERR_NOT_FOUND = "Node did not exist";
+ private static final String CLUSTER_NAME = "kubernetes";
+
private static final String MINION_1_HOSTNAME = "minion_1";
private static final String MINION_2_HOSTNAME = "minion_2";
private static final String MINION_3_HOSTNAME = "minion_3";
@@ -84,31 +86,41 @@
private static final Device MINION_2_LOCAL_DEVICE = createDevice(8);
private static final Device MINION_3_LOCAL_DEVICE = createDevice(9);
+ private static final Device MINION_1_TUN_DEVICE = createDevice(10);
+ private static final Device MINION_2_TUN_DEVICE = createDevice(11);
+ private static final Device MINION_3_TUN_DEVICE = createDevice(12);
+
private static final K8sNode MINION_1 = createNode(
+ CLUSTER_NAME,
MINION_1_HOSTNAME,
MINION,
MINION_1_INTG_DEVICE,
MINION_1_EXT_DEVICE,
MINION_1_LOCAL_DEVICE,
+ MINION_1_TUN_DEVICE,
IpAddress.valueOf("10.100.0.1"),
INIT
);
private static final K8sNode MINION_2 = createNode(
+ CLUSTER_NAME,
MINION_2_HOSTNAME,
MINION,
MINION_2_INTG_DEVICE,
MINION_2_EXT_DEVICE,
MINION_2_LOCAL_DEVICE,
+ MINION_2_TUN_DEVICE,
IpAddress.valueOf("10.100.0.2"),
INIT
);
private static final K8sNode MINION_3 = createNode(
+ CLUSTER_NAME,
MINION_3_HOSTNAME,
MINION,
MINION_3_INTG_DEVICE,
MINION_3_EXT_DEVICE,
MINION_3_LOCAL_DEVICE,
+ MINION_3_TUN_DEVICE,
IpAddress.valueOf("10.100.0.3"),
COMPLETE
);
@@ -334,16 +346,18 @@
}
- private static K8sNode createNode(String hostname, K8sNode.Type type,
+ private static K8sNode createNode(String clusterName, String hostname, K8sNode.Type type,
Device intgBridge, Device extBridge,
- Device localBridge, IpAddress ipAddr,
- K8sNodeState state) {
+ Device localBridge, Device tunBridge,
+ IpAddress ipAddr, K8sNodeState state) {
return DefaultK8sNode.builder()
.hostname(hostname)
+ .clusterName(clusterName)
.type(type)
.intgBridge(intgBridge.id())
.extBridge(extBridge.id())
.localBridge(localBridge.id())
+ .tunBridge(tunBridge.id())
.managementIp(ipAddr)
.dataIp(ipAddr)
.state(state)
diff --git a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java
index 207bd0e..1005ab2 100644
--- a/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java
+++ b/apps/k8s-node/app/src/test/java/org/onosproject/k8snode/web/K8sNodeWebResourceTest.java
@@ -25,11 +25,13 @@
import org.onosproject.codec.impl.CodecManager;
import org.onosproject.k8snode.api.DefaultK8sApiConfig;
import org.onosproject.k8snode.api.DefaultK8sNode;
+import org.onosproject.k8snode.api.HostNodesInfo;
import org.onosproject.k8snode.api.K8sApiConfig;
import org.onosproject.k8snode.api.K8sApiConfigAdminService;
import org.onosproject.k8snode.api.K8sNode;
import org.onosproject.k8snode.api.K8sNodeAdminService;
import org.onosproject.k8snode.api.K8sNodeState;
+import org.onosproject.k8snode.codec.HostNodesInfoCodec;
import org.onosproject.k8snode.codec.K8sApiConfigCodec;
import org.onosproject.k8snode.codec.K8sNodeCodec;
import org.onosproject.net.DeviceId;
@@ -81,6 +83,7 @@
codecService.activate();
codecService.registerCodec(K8sNode.class, new K8sNodeCodec());
codecService.registerCodec(K8sApiConfig.class, new K8sApiConfigCodec());
+ codecService.registerCodec(HostNodesInfo.class, new HostNodesInfoCodec());
ServiceDirectory testDirectory =
new TestServiceDirectory()
.add(K8sNodeAdminService.class, mockK8sNodeAdminService)
@@ -89,6 +92,7 @@
setServiceDirectory(testDirectory);
k8sNode = DefaultK8sNode.builder()
+ .clusterName("kubernetes")
.hostname("minion-node")
.type(K8sNode.Type.MINION)
.dataIp(IpAddress.valueOf("10.134.34.222"))
@@ -99,6 +103,9 @@
.build();
k8sApiConfig = DefaultK8sApiConfig.builder()
+ .clusterName("kubernetes")
+ .segmentId(1)
+ .mode(K8sApiConfig.Mode.NORMAL)
.scheme(K8sApiConfig.Scheme.HTTPS)
.ipAddress(IpAddress.valueOf("10.134.34.223"))
.port(6443)