[ONOS-7905] Add default implementation for kubernetes data model
Change-Id: I08e9266dec2050e8299e4189745608a6e03fd06e
diff --git a/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sIpam.java b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sIpam.java
new file mode 100644
index 0000000..cb488b3
--- /dev/null
+++ b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sIpam.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2019-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.k8snetworking.api;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.packet.IpAddress;
+
+/**
+ * Default implementation of kubernetes IPAM instance.
+ */
+public final class DefaultK8sIpam implements K8sIpam {
+
+ private final IpAddress ipAddress;
+ private final String networkId;
+
+ // private constructor not intended for external invocation
+ public DefaultK8sIpam(IpAddress ipAddress, String networkId) {
+ this.ipAddress = ipAddress;
+ this.networkId = networkId;
+ }
+
+ @Override
+ public IpAddress ipAddress() {
+ return ipAddress;
+ }
+
+ @Override
+ public String networkId() {
+ return networkId;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DefaultK8sIpam that = (DefaultK8sIpam) o;
+ return Objects.equal(ipAddress, that.ipAddress) &&
+ Objects.equal(networkId, that.networkId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(ipAddress, networkId);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("ipAddress", ipAddress)
+ .add("networkId", networkId)
+ .toString();
+ }
+}
diff --git a/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sNetwork.java b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sNetwork.java
new file mode 100644
index 0000000..3ac1230
--- /dev/null
+++ b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sNetwork.java
@@ -0,0 +1,187 @@
+/*
+ * Copyright 2019-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.k8snetworking.api;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.packet.IpAddress;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Default implementation of kubernetes network.
+ */
+public final class DefaultK8sNetwork implements K8sNetwork {
+
+ private static final int DEFAULT_MTU = 1500;
+
+ private final String networkId;
+ private final Type type;
+ private final Integer mtu;
+ private final String segmentId;
+ private final IpAddress gatewayIp;
+ private final String cidr;
+
+ private static final String NOT_NULL_MSG = "Network % cannot be null";
+
+ // private constructor not intended for external invocation
+ private DefaultK8sNetwork(String networkId, Type type, Integer mtu,
+ String segmentId, IpAddress gatewayIp, String cidr) {
+ this.networkId = networkId;
+ this.type = type;
+ this.mtu = mtu;
+ this.segmentId = segmentId;
+ this.gatewayIp = gatewayIp;
+ this.cidr = cidr;
+ }
+
+ @Override
+ public String networkId() {
+ return networkId;
+ }
+
+ @Override
+ public Type type() {
+ return type;
+ }
+
+ @Override
+ public Integer mtu() {
+ return mtu;
+ }
+
+ @Override
+ public String segmentId() {
+ return segmentId;
+ }
+
+ @Override
+ public IpAddress gatewayIp() {
+ return gatewayIp;
+ }
+
+ @Override
+ public String cidr() {
+ return cidr;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DefaultK8sNetwork that = (DefaultK8sNetwork) o;
+ return Objects.equal(networkId, that.networkId) &&
+ type == that.type &&
+ Objects.equal(mtu, that.mtu) &&
+ Objects.equal(segmentId, that.segmentId) &&
+ Objects.equal(gatewayIp, that.gatewayIp) &&
+ Objects.equal(cidr, that.cidr);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(networkId, type, mtu, segmentId, gatewayIp, cidr);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("networkId", networkId)
+ .add("type", type)
+ .add("mtu", mtu)
+ .add("segmentId", segmentId)
+ .add("gatewayIp", gatewayIp)
+ .add("cidr", cidr)
+ .toString();
+ }
+
+ /**
+ * Returns new builder instance.
+ *
+ * @return kubernetes network builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Default implementation of kubernetes network builder.
+ */
+ public static final class Builder implements K8sNetwork.Builder {
+
+ private String networkId;
+ private Type type;
+ private Integer mtu;
+ private String segmentId;
+ private IpAddress gatewayIp;
+ private String cidr;
+
+ @Override
+ public K8sNetwork build() {
+ checkArgument(networkId != null, NOT_NULL_MSG, "networkId");
+ checkArgument(type != null, NOT_NULL_MSG, "type");
+ checkArgument(segmentId != null, NOT_NULL_MSG, "segmentId");
+ checkArgument(gatewayIp != null, NOT_NULL_MSG, "gatewayIp");
+ checkArgument(cidr != null, NOT_NULL_MSG, "cidr");
+
+ if (mtu == null) {
+ mtu = DEFAULT_MTU;
+ }
+
+ return new DefaultK8sNetwork(networkId, type, mtu, segmentId, gatewayIp, cidr);
+ }
+
+ @Override
+ public Builder networkId(String networkId) {
+ this.networkId = networkId;
+ return this;
+ }
+
+ @Override
+ public Builder type(Type type) {
+ this.type = type;
+ return this;
+ }
+
+ @Override
+ public Builder mtu(Integer mtu) {
+ this.mtu = mtu;
+ return this;
+ }
+
+ @Override
+ public Builder segmentId(String segmentId) {
+ this.segmentId = segmentId;
+ return this;
+ }
+
+ @Override
+ public Builder gatewayIp(IpAddress ipAddress) {
+ this.gatewayIp = ipAddress;
+ return this;
+ }
+
+ @Override
+ public Builder cidr(String cidr) {
+ this.cidr = cidr;
+ return this;
+ }
+ }
+}
diff --git a/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sPort.java b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sPort.java
new file mode 100644
index 0000000..e545f69
--- /dev/null
+++ b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/DefaultK8sPort.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright 2019-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.k8snetworking.api;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+/**
+ * Default implementation of kubernetes port.
+ */
+public final class DefaultK8sPort implements K8sPort {
+
+ private static final String NOT_NULL_MSG = "Port % cannot be null";
+
+ private final String networkId;
+ private final String portId;
+ private final MacAddress macAddress;
+ private final IpAddress ipAddress;
+ private final DeviceId deviceId;
+ private final PortNumber portNumber;
+ private final State state;
+
+ // private constructor not intended for external invocation
+ private DefaultK8sPort(String networkId, String portId, MacAddress macAddress,
+ IpAddress ipAddress, DeviceId deviceId,
+ PortNumber portNumber, State state) {
+ this.networkId = networkId;
+ this.portId = portId;
+ this.macAddress = macAddress;
+ this.ipAddress = ipAddress;
+ this.deviceId = deviceId;
+ this.portNumber = portNumber;
+ this.state = state;
+ }
+
+ @Override
+ public String networkId() {
+ return networkId;
+ }
+
+ @Override
+ public String portId() {
+ return portId;
+ }
+
+ @Override
+ public MacAddress macAddress() {
+ return macAddress;
+ }
+
+ @Override
+ public IpAddress ipAddress() {
+ return ipAddress;
+ }
+
+ @Override
+ public DeviceId deviceId() {
+ return deviceId;
+ }
+
+ @Override
+ public PortNumber portNumber() {
+ return portNumber;
+ }
+
+ @Override
+ public State state() {
+ return state;
+ }
+
+ @Override
+ public K8sPort updateState(State newState) {
+ return new Builder()
+ .networkId(networkId)
+ .portId(portId)
+ .macAddress(macAddress)
+ .ipAddress(ipAddress)
+ .deviceId(deviceId)
+ .portNumber(portNumber)
+ .state(newState)
+ .build();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ DefaultK8sPort that = (DefaultK8sPort) o;
+ return Objects.equal(networkId, that.networkId) &&
+ Objects.equal(portId, that.portId) &&
+ Objects.equal(macAddress, that.macAddress) &&
+ Objects.equal(ipAddress, that.ipAddress) &&
+ Objects.equal(deviceId, that.deviceId) &&
+ Objects.equal(portNumber, that.portNumber) &&
+ state == that.state;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(networkId, portId, macAddress, ipAddress,
+ deviceId, portNumber, state);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("networkId", networkId)
+ .add("portId", portId)
+ .add("macAddress", macAddress)
+ .add("ipAddress", ipAddress)
+ .add("deviceId", deviceId)
+ .add("portNumber", portNumber)
+ .add("state", state)
+ .toString();
+ }
+
+ /**
+ * Returns new builder instance.
+ *
+ * @return kubernetes port builder
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ /**
+ * Default builder implementation.
+ */
+ public static final class Builder implements K8sPort.Builder {
+
+ private String networkId;
+ private String portId;
+ private MacAddress macAddress;
+ private IpAddress ipAddress;
+ private DeviceId deviceId;
+ private PortNumber portNumber;
+ private State state;
+
+ // private constructor not intended to use from external
+ private Builder() {
+ }
+
+ @Override
+ public K8sPort build() {
+ checkArgument(networkId != null, NOT_NULL_MSG, "networkId");
+ checkArgument(portId != null, NOT_NULL_MSG, "portId");
+ checkArgument(macAddress != null, NOT_NULL_MSG, "macAddress");
+ checkArgument(ipAddress != null, NOT_NULL_MSG, "ipAddress");
+ checkArgument(deviceId != null, NOT_NULL_MSG, "deviceId");
+ checkArgument(portNumber != null, NOT_NULL_MSG, "portNumber");
+ checkArgument(state != null, NOT_NULL_MSG, "state");
+
+ return new DefaultK8sPort(networkId, portId, macAddress, ipAddress,
+ deviceId, portNumber, state);
+ }
+
+ @Override
+ public Builder networkId(String networkId) {
+ this.networkId = networkId;
+ return this;
+ }
+
+ @Override
+ public Builder portId(String portId) {
+ this.portId = portId;
+ return this;
+ }
+
+ @Override
+ public Builder macAddress(MacAddress macAddress) {
+ this.macAddress = macAddress;
+ return this;
+ }
+
+ @Override
+ public Builder ipAddress(IpAddress ipAddress) {
+ this.ipAddress = ipAddress;
+ return this;
+ }
+
+ @Override
+ public Builder deviceId(DeviceId deviceId) {
+ this.deviceId = deviceId;
+ return this;
+ }
+
+ @Override
+ public Builder portNumber(PortNumber portNumber) {
+ this.portNumber = portNumber;
+ return this;
+ }
+
+ @Override
+ public Builder state(State state) {
+ this.state = state;
+ return this;
+ }
+ }
+}
diff --git a/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/K8sIpam.java b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/K8sIpam.java
index 57f2130..9969f30 100644
--- a/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/K8sIpam.java
+++ b/apps/k8s-networking/api/src/main/java/org/onosproject/k8snetworking/api/K8sIpam.java
@@ -27,7 +27,7 @@
*
* @return IP address
*/
- IpAddress ipaddress();
+ IpAddress ipAddress();
/**
* Returns the kubernetes network ID.
diff --git a/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sIpamTest.java b/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sIpamTest.java
new file mode 100644
index 0000000..bfb5670
--- /dev/null
+++ b/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sIpamTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019-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.k8snetworking.api;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for the default kubernetes IPAM.
+ */
+public class DefaultK8sIpamTest {
+
+ private static final IpAddress IP_ADDRESS_1 = IpAddress.valueOf("10.10.10.10");
+ private static final IpAddress IP_ADDRESS_2 = IpAddress.valueOf("20.20.20.20");
+ private static final String NETWORK_ID_1 = "network-1";
+ private static final String NETWORK_ID_2 = "network-2";
+
+ private K8sIpam ipam1;
+ private K8sIpam sameAsIpam1;
+ private K8sIpam ipam2;
+
+ /**
+ * Tests class immutability.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultK8sIpam.class);
+ }
+
+ /**
+ * Initial setup for this unit test.
+ */
+ @Before
+ public void setUp() {
+ ipam1 = new DefaultK8sIpam(IP_ADDRESS_1, NETWORK_ID_1);
+ sameAsIpam1 = new DefaultK8sIpam(IP_ADDRESS_1, NETWORK_ID_1);
+ ipam2 = new DefaultK8sIpam(IP_ADDRESS_2, NETWORK_ID_2);
+ }
+
+ /**
+ * Tests object equality.
+ */
+ @Test
+ public void testEquality() {
+ new EqualsTester().addEqualityGroup(ipam1, sameAsIpam1)
+ .addEqualityGroup(ipam2)
+ .testEquals();
+ }
+
+ /**
+ * Test object construction.
+ */
+ @Test
+ public void testConstruction() {
+ K8sIpam ipam = ipam1;
+
+ assertEquals(IP_ADDRESS_1, ipam.ipAddress());
+ assertEquals(NETWORK_ID_1, ipam.networkId());
+ }
+}
diff --git a/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sNetworkTest.java b/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sNetworkTest.java
new file mode 100644
index 0000000..727b0ad
--- /dev/null
+++ b/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sNetworkTest.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright 2019-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.k8snetworking.api;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Unit tests for the default kubernetes network class.
+ */
+public class DefaultK8sNetworkTest {
+
+ private static final String NETWORK_ID_1 = "network-1";
+ private static final String NETWORK_ID_2 = "network-2";
+ private static final K8sNetwork.Type TYPE_1 = K8sNetwork.Type.VXLAN;
+ private static final K8sNetwork.Type TYPE_2 = K8sNetwork.Type.GENEVE;
+ private static final Integer MTU_1 = 1500;
+ private static final Integer MTU_2 = 1600;
+ private static final String SEGMENT_ID_1 = "1";
+ private static final String SEGMENT_ID_2 = "2";
+ private static final IpAddress GATEWAY_IP_1 = IpAddress.valueOf("10.10.10.1");
+ private static final IpAddress GATEWAY_IP_2 = IpAddress.valueOf("20.20.20.1");
+ private static final String CIDR_1 = "32";
+ private static final String CIDR_2 = "32";
+
+ private K8sNetwork k8sNetwork1;
+ private K8sNetwork sameAsK8sNetwork1;
+ private K8sNetwork k8sNetwork2;
+
+ /**
+ * Initial setup for this unit test.
+ */
+ @Before
+ public void setUp() {
+ k8sNetwork1 = DefaultK8sNetwork.builder()
+ .networkId(NETWORK_ID_1)
+ .type(TYPE_1)
+ .mtu(MTU_1)
+ .segmentId(SEGMENT_ID_1)
+ .gatewayIp(GATEWAY_IP_1)
+ .cidr(CIDR_1)
+ .build();
+
+ sameAsK8sNetwork1 = DefaultK8sNetwork.builder()
+ .networkId(NETWORK_ID_1)
+ .type(TYPE_1)
+ .mtu(MTU_1)
+ .segmentId(SEGMENT_ID_1)
+ .gatewayIp(GATEWAY_IP_1)
+ .cidr(CIDR_1)
+ .build();
+
+ k8sNetwork2 = DefaultK8sNetwork.builder()
+ .networkId(NETWORK_ID_2)
+ .type(TYPE_2)
+ .mtu(MTU_2)
+ .segmentId(SEGMENT_ID_2)
+ .gatewayIp(GATEWAY_IP_2)
+ .cidr(CIDR_2)
+ .build();
+ }
+
+ /**
+ * Tests class immutability.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultK8sNetwork.class);
+ }
+
+ /**
+ * Tests object equality.
+ */
+ @Test
+ public void testEquality() {
+ new EqualsTester().addEqualityGroup(k8sNetwork1, sameAsK8sNetwork1)
+ .addEqualityGroup(k8sNetwork2)
+ .testEquals();
+ }
+
+ /**
+ * Test object construction.
+ */
+ @Test
+ public void testConstruction() {
+ K8sNetwork k8sNetwork = k8sNetwork1;
+
+ assertEquals(NETWORK_ID_1, k8sNetwork.networkId());
+ assertEquals(TYPE_1, k8sNetwork.type());
+ assertEquals(MTU_1, k8sNetwork.mtu());
+ assertEquals(SEGMENT_ID_1, k8sNetwork.segmentId());
+ assertEquals(GATEWAY_IP_1, k8sNetwork.gatewayIp());
+ assertEquals(CIDR_1, k8sNetwork.cidr());
+ }
+}
diff --git a/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sPortTest.java b/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sPortTest.java
new file mode 100644
index 0000000..0315a7f
--- /dev/null
+++ b/apps/k8s-networking/api/src/test/java/org/onosproject/k8snetworking/api/DefaultK8sPortTest.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright 2019-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.k8snetworking.api;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.k8snetworking.api.K8sPort.State;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertSame;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onosproject.k8snetworking.api.K8sPort.State.ACTIVE;
+import static org.onosproject.k8snetworking.api.K8sPort.State.INACTIVE;
+
+/**
+ * Unit tests for the default kubernetes port class.
+ */
+public class DefaultK8sPortTest {
+
+ private static final String NETWORK_ID_1 = "network-1";
+ private static final String NETWORK_ID_2 = "network-2";
+ private static final String PORT_ID_1 = "port-1";
+ private static final String PORT_ID_2 = "port-2";
+ private static final MacAddress MAC_ADDRESS_1 = MacAddress.valueOf("00:11:22:33:44:55");
+ private static final MacAddress MAC_ADDRESS_2 = MacAddress.valueOf("11:22:33:44:55:66");
+ private static final IpAddress IP_ADDRESS_1 = IpAddress.valueOf("10.10.10.10");
+ private static final IpAddress IP_ADDRESS_2 = IpAddress.valueOf("20.20.20.20");
+ private static final DeviceId DEVICE_ID_1 = DeviceId.deviceId("of:000000000000001");
+ private static final DeviceId DEVICE_ID_2 = DeviceId.deviceId("of:000000000000002");
+ private static final PortNumber PORT_NUMBER_1 = PortNumber.portNumber(1);
+ private static final PortNumber PORT_NUMBER_2 = PortNumber.portNumber(2);
+ private static final State STATE_1 = ACTIVE;
+ private static final State STATE_2 = INACTIVE;
+
+ private K8sPort port1;
+ private K8sPort sameAsPort1;
+ private K8sPort port2;
+
+ /**
+ * Tests class immutability.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(DefaultK8sPort.class);
+ }
+
+ /**
+ * Initial setup for this unit test.
+ */
+ @Before
+ public void setUp() {
+ port1 = DefaultK8sPort.builder()
+ .networkId(NETWORK_ID_1)
+ .portId(PORT_ID_1)
+ .macAddress(MAC_ADDRESS_1)
+ .ipAddress(IP_ADDRESS_1)
+ .deviceId(DEVICE_ID_1)
+ .portNumber(PORT_NUMBER_1)
+ .state(STATE_1)
+ .build();
+
+ sameAsPort1 = DefaultK8sPort.builder()
+ .networkId(NETWORK_ID_1)
+ .portId(PORT_ID_1)
+ .macAddress(MAC_ADDRESS_1)
+ .ipAddress(IP_ADDRESS_1)
+ .deviceId(DEVICE_ID_1)
+ .portNumber(PORT_NUMBER_1)
+ .state(STATE_1)
+ .build();
+
+ port2 = DefaultK8sPort.builder()
+ .networkId(NETWORK_ID_2)
+ .portId(PORT_ID_2)
+ .macAddress(MAC_ADDRESS_2)
+ .ipAddress(IP_ADDRESS_2)
+ .deviceId(DEVICE_ID_2)
+ .portNumber(PORT_NUMBER_2)
+ .state(STATE_2)
+ .build();
+ }
+
+ /**
+ * Tests object equality.
+ */
+ @Test
+ public void testEquality() {
+ new EqualsTester().addEqualityGroup(port1, sameAsPort1)
+ .addEqualityGroup(port2)
+ .testEquals();
+ }
+
+ /**
+ * Test object construction.
+ */
+ @Test
+ public void testConstruction() {
+ K8sPort port = port1;
+
+ assertEquals(NETWORK_ID_1, port.networkId());
+ assertEquals(PORT_ID_1, port.portId());
+ assertEquals(MAC_ADDRESS_1, port.macAddress());
+ assertEquals(IP_ADDRESS_1, port.ipAddress());
+ assertEquals(DEVICE_ID_1, port.deviceId());
+ assertEquals(PORT_NUMBER_1, port.portNumber());
+ assertSame(STATE_1, port.state());
+ }
+}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sIpamCodec.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sIpamCodec.java
new file mode 100644
index 0000000..695156c
--- /dev/null
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sIpamCodec.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.IpAddress;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.k8snetworking.api.DefaultK8sIpam;
+import org.onosproject.k8snetworking.api.K8sIpam;
+import org.slf4j.Logger;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Kubernetes IPAM codec used for serializing and de-serializing JSON string.
+ */
+public final class K8sIpamCodec extends JsonCodec<K8sIpam> {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String IP_ADDRESS = "ipAddress";
+ private static final String NETWORK_ID = "networkId";
+
+ private static final String MISSING_MESSAGE = " is required in K8sIPAM";
+
+ @Override
+ public ObjectNode encode(K8sIpam ipam, CodecContext context) {
+ checkNotNull(ipam, "Kubernetes IPAM cannot be null");
+
+ return context.mapper().createObjectNode()
+ .put(IP_ADDRESS, ipam.ipAddress().toString())
+ .put(NETWORK_ID, ipam.networkId());
+ }
+
+ @Override
+ public K8sIpam decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ String ipAddress = nullIsIllegal(json.get(IP_ADDRESS).asText(),
+ IP_ADDRESS + MISSING_MESSAGE);
+ String networkId = nullIsIllegal(json.get(NETWORK_ID).asText(),
+ NETWORK_ID + MISSING_MESSAGE);
+
+ return new DefaultK8sIpam(IpAddress.valueOf(ipAddress), networkId);
+ }
+}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sNetworkCodec.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sNetworkCodec.java
new file mode 100644
index 0000000..e6e646b
--- /dev/null
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sNetworkCodec.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.IpAddress;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.k8snetworking.api.DefaultK8sNetwork;
+import org.onosproject.k8snetworking.api.K8sNetwork;
+import org.slf4j.Logger;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Kubernetes network codec used for serializing and de-serializing JSON string.
+ */
+public final class K8sNetworkCodec extends JsonCodec<K8sNetwork> {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String NETWORK_ID = "networkId";
+ private static final String TYPE = "type";
+ private static final String MTU = "mtu";
+ private static final String SEGMENT_ID = "segmentId";
+ private static final String GATEWAY_IP = "gatewayIp";
+ private static final String CIDR = "cidr";
+
+ private static final String MISSING_MESSAGE = " is required in K8sNetwork";
+
+ @Override
+ public ObjectNode encode(K8sNetwork network, CodecContext context) {
+ checkNotNull(network, "Kubernetes network cannot be null");
+
+ ObjectNode result = context.mapper().createObjectNode()
+ .put(NETWORK_ID, network.networkId())
+ .put(TYPE, network.type().name())
+ .put(SEGMENT_ID, network.segmentId())
+ .put(GATEWAY_IP, network.gatewayIp().toString())
+ .put(CIDR, network.cidr());
+
+ if (network.mtu() != null) {
+ result.put(MTU, network.mtu());
+ }
+
+ return result;
+ }
+
+ @Override
+ public K8sNetwork decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ String networkId = nullIsIllegal(json.get(NETWORK_ID).asText(),
+ NETWORK_ID + MISSING_MESSAGE);
+ String type = nullIsIllegal(json.get(TYPE).asText(),
+ TYPE + MISSING_MESSAGE);
+ String segmentId = nullIsIllegal(json.get(SEGMENT_ID).asText(),
+ SEGMENT_ID + MISSING_MESSAGE);
+ String gatewayIp = nullIsIllegal(json.get(GATEWAY_IP).asText(),
+ GATEWAY_IP + MISSING_MESSAGE);
+ String cidr = nullIsIllegal(json.get(CIDR).asText(),
+ CIDR + MISSING_MESSAGE);
+
+ DefaultK8sNetwork.Builder networkBuilder = DefaultK8sNetwork.builder()
+ .networkId(networkId)
+ .type(K8sNetwork.Type.valueOf(type))
+ .segmentId(segmentId)
+ .gatewayIp(IpAddress.valueOf(gatewayIp))
+ .cidr(cidr);
+
+ if (json.get(MTU) != null) {
+ networkBuilder.mtu(json.get(MTU).asInt());
+ }
+
+ return networkBuilder.build();
+ }
+}
diff --git a/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sPortCodec.java b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sPortCodec.java
new file mode 100644
index 0000000..9ca74cb
--- /dev/null
+++ b/apps/k8s-networking/app/src/main/java/org/onosproject/k8snetworking/codec/K8sPortCodec.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.k8snetworking.api.DefaultK8sPort;
+import org.onosproject.k8snetworking.api.K8sPort;
+import org.onosproject.k8snetworking.api.K8sPort.State;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.slf4j.Logger;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Kubernetes port codec used for serializing and de-serializing JSON string.
+ */
+public final class K8sPortCodec extends JsonCodec<K8sPort> {
+
+ private final Logger log = getLogger(getClass());
+
+ private static final String NETWORK_ID = "networkId";
+ private static final String PORT_ID = "portId";
+ private static final String MAC_ADDRESS = "macAddress";
+ private static final String IP_ADDRESS = "ipAddress";
+ private static final String DEVICE_ID = "deviceId";
+ private static final String PORT_NUMBER = "portNumber";
+ private static final String STATE = "state";
+
+ private static final String MISSING_MESSAGE = " is required in K8sPort";
+
+ @Override
+ public ObjectNode encode(K8sPort port, CodecContext context) {
+ checkNotNull(port, "Kubernetes port cannot be null");
+
+ return context.mapper().createObjectNode()
+ .put(NETWORK_ID, port.networkId())
+ .put(PORT_ID, port.portId())
+ .put(MAC_ADDRESS, port.macAddress().toString())
+ .put(IP_ADDRESS, port.ipAddress().toString())
+ .put(DEVICE_ID, port.deviceId().toString())
+ .put(PORT_NUMBER, port.portNumber().toString())
+ .put(STATE, port.state().name());
+ }
+
+ @Override
+ public K8sPort decode(ObjectNode json, CodecContext context) {
+ if (json == null || !json.isObject()) {
+ return null;
+ }
+
+ String networkId = nullIsIllegal(json.get(NETWORK_ID).asText(),
+ NETWORK_ID + MISSING_MESSAGE);
+ String portId = nullIsIllegal(json.get(PORT_ID).asText(),
+ PORT_ID + MISSING_MESSAGE);
+ String macAddress = nullIsIllegal(json.get(MAC_ADDRESS).asText(),
+ MAC_ADDRESS + MISSING_MESSAGE);
+ String ipAddress = nullIsIllegal(json.get(IP_ADDRESS).asText(),
+ IP_ADDRESS + MISSING_MESSAGE);
+ String deviceId = nullIsIllegal(json.get(DEVICE_ID).asText(),
+ DEVICE_ID + MISSING_MESSAGE);
+ String portNumber = nullIsIllegal(json.get(PORT_NUMBER).asText(),
+ PORT_NUMBER + MISSING_MESSAGE);
+ String state = nullIsIllegal(json.get(STATE).asText(),
+ STATE + MISSING_MESSAGE);
+
+ return DefaultK8sPort.builder()
+ .networkId(networkId)
+ .portId(portId)
+ .macAddress(MacAddress.valueOf(macAddress))
+ .ipAddress(IpAddress.valueOf(ipAddress))
+ .deviceId(DeviceId.deviceId(deviceId))
+ .portNumber(PortNumber.portNumber(portNumber))
+ .state(State.valueOf(state))
+ .build();
+ }
+}
diff --git a/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sIpamCodecTest.java b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sIpamCodecTest.java
new file mode 100644
index 0000000..8335867
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sIpamCodecTest.java
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.hamcrest.MatcherAssert;
+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.k8snetworking.api.DefaultK8sIpam;
+import org.onosproject.k8snetworking.api.K8sIpam;
+
+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.k8snetworking.codec.K8sIpamJsonMatcher.matchesK8sIpam;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
+/**
+ * Unit tests for kubernetes IPAM codec.
+ */
+public class K8sIpamCodecTest {
+
+ MockCodecContext context;
+
+ JsonCodec<K8sIpam> k8sIpamCodec;
+
+ 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();
+ k8sIpamCodec = new K8sIpamCodec();
+
+ assertThat(k8sIpamCodec, notNullValue());
+
+ expect(mockCoreService.registerApplication(REST_APP_ID))
+ .andReturn(APP_ID).anyTimes();
+ replay(mockCoreService);
+ context.registerService(CoreService.class, mockCoreService);
+ }
+
+ /**
+ * Tests the kubernetes IPAM encoding.
+ */
+ @Test
+ public void testK8sIpamEncode() {
+ K8sIpam ipam = new DefaultK8sIpam(
+ IpAddress.valueOf("10.10.10.10"), "network-1");
+
+ ObjectNode nodeJson = k8sIpamCodec.encode(ipam, context);
+ assertThat(nodeJson, matchesK8sIpam(ipam));
+ }
+
+ /**
+ * Tests the kubernetes IPAM decoding.
+ */
+ @Test
+ public void testK8sIpamDecode() throws IOException {
+ K8sIpam ipam = getK8sIpam("K8sIpam.json");
+
+ assertEquals("10.10.10.2", ipam.ipAddress().toString());
+ assertEquals("network-1", ipam.networkId());
+ }
+
+ /**
+ * Reads in an kubernetes IPAM from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded kubernetes node
+ * @throws IOException if processing the resource fails
+ */
+ private K8sIpam getK8sIpam(String resourceName) throws IOException {
+ InputStream jsonStream = K8sIpamCodecTest.class.getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ MatcherAssert.assertThat(json, notNullValue());
+ K8sIpam node = k8sIpamCodec.decode((ObjectNode) json, context);
+ assertThat(node, notNullValue());
+ return node;
+ }
+
+ /**
+ * Mock codec context for use in codec unit tests.
+ */
+ 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 == K8sIpam.class) {
+ return (JsonCodec<T>) k8sIpamCodec;
+ }
+ 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-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sIpamJsonMatcher.java b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sIpamJsonMatcher.java
new file mode 100644
index 0000000..81bbf10
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sIpamJsonMatcher.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.k8snetworking.api.K8sIpam;
+
+/**
+ * Hamcrest matcher for kubernetes IPAM.
+ */
+public final class K8sIpamJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final K8sIpam ipam;
+
+ private static final String IP_ADDRESS = "ipAddress";
+ private static final String NETWORK_ID = "networkId";
+
+ private K8sIpamJsonMatcher(K8sIpam ipam) {
+ this.ipam = ipam;
+ }
+
+ @Override
+ protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+ // check IP address
+ String jsonIpAddress = jsonNode.get(IP_ADDRESS).asText();
+ String ipAddress = ipam.ipAddress().toString();
+ if (!jsonIpAddress.equals(ipAddress)) {
+ description.appendText("IP address was " + jsonIpAddress);
+ return false;
+ }
+
+ // check network ID
+ String jsonNetworkId = jsonNode.get(NETWORK_ID).asText();
+ String networkId = ipam.networkId();
+ if (!jsonNetworkId.equals(networkId)) {
+ description.appendText("Network ID was " + jsonNetworkId);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(ipam.toString());
+ }
+
+ /**
+ * Factory to allocate kubernetes IPAM matcher.
+ *
+ * @param ipam kubernetes IPAM object we are looking for
+ * @return matcher
+ */
+ public static K8sIpamJsonMatcher matchesK8sIpam(K8sIpam ipam) {
+ return new K8sIpamJsonMatcher(ipam);
+ }
+}
diff --git a/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sNetworkCodecTest.java b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sNetworkCodecTest.java
new file mode 100644
index 0000000..9d7fd99
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sNetworkCodecTest.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.hamcrest.MatcherAssert;
+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.k8snetworking.api.DefaultK8sNetwork;
+import org.onosproject.k8snetworking.api.K8sNetwork;
+
+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.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.k8snetworking.codec.K8sNetworkJsonMatcher.matchesK8sNetwork;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
+/**
+ * Unit tests for kubernetes network codec.
+ */
+public class K8sNetworkCodecTest {
+
+ MockCodecContext context;
+
+ JsonCodec<K8sNetwork> k8sNetworkCodec;
+
+ 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();
+ k8sNetworkCodec = new K8sNetworkCodec();
+
+ assertThat(k8sNetworkCodec, notNullValue());
+
+ expect(mockCoreService.registerApplication(REST_APP_ID))
+ .andReturn(APP_ID).anyTimes();
+ replay(mockCoreService);
+ context.registerService(CoreService.class, mockCoreService);
+ }
+
+ /**
+ * Tests the kubernetes network encoding.
+ */
+ @Test
+ public void testK8sNetworkEncode() {
+ K8sNetwork network = DefaultK8sNetwork.builder()
+ .networkId("network-1")
+ .segmentId("1")
+ .type(K8sNetwork.Type.VXLAN)
+ .gatewayIp(IpAddress.valueOf("10.10.10.1"))
+ .cidr("32")
+ .mtu(1500)
+ .build();
+
+ ObjectNode nodeJson = k8sNetworkCodec.encode(network, context);
+ assertThat(nodeJson, matchesK8sNetwork(network));
+ }
+
+ /**
+ * Tests the kubernetes network decoding.
+ */
+ @Test
+ public void testK8sNetworkDecode() throws IOException {
+ K8sNetwork network = getK8sNetwork("K8sNetwork.json");
+
+ assertEquals("network-1", network.networkId());
+ assertEquals("1", network.segmentId());
+ assertEquals("VXLAN", network.type().name());
+ assertEquals("10.10.10.1", network.gatewayIp().toString());
+ assertEquals("32", network.cidr());
+ assertThat(network.mtu(), is(1500));
+ }
+
+ /**
+ * Reads in an kubernetes network from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded kubernetes network
+ * @throws IOException if processing the resource fails
+ */
+ private K8sNetwork getK8sNetwork(String resourceName) throws IOException {
+ InputStream jsonStream = K8sNetworkCodecTest.class.getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ MatcherAssert.assertThat(json, notNullValue());
+ K8sNetwork network = k8sNetworkCodec.decode((ObjectNode) json, context);
+ assertThat(network, notNullValue());
+ return network;
+ }
+
+ 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 == K8sNetwork.class) {
+ return (JsonCodec<T>) k8sNetworkCodec;
+ }
+ 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-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sNetworkJsonMatcher.java b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sNetworkJsonMatcher.java
new file mode 100644
index 0000000..435de0f
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sNetworkJsonMatcher.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.k8snetworking.api.K8sNetwork;
+
+/**
+ * Hamcrest matcher for kubernetes network.
+ */
+public final class K8sNetworkJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final K8sNetwork network;
+
+ private static final String NETWORK_ID = "networkId";
+ private static final String TYPE = "type";
+ private static final String MTU = "mtu";
+ private static final String SEGMENT_ID = "segmentId";
+ private static final String GATEWAY_IP = "gatewayIp";
+ private static final String CIDR = "cidr";
+
+ private K8sNetworkJsonMatcher(K8sNetwork network) {
+ this.network = network;
+ }
+
+ @Override
+ protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+ // check network ID
+ String jsonNetworkId = jsonNode.get(NETWORK_ID).asText();
+ String networkId = network.networkId();
+ if (!jsonNetworkId.equals(networkId)) {
+ description.appendText("network ID was " + jsonNetworkId);
+ return false;
+ }
+
+ // check type
+ String jsonType = jsonNode.get(TYPE).asText();
+ String type = network.type().name();
+ if (!jsonType.equals(type)) {
+ description.appendText("network type was " + jsonType);
+ return false;
+ }
+
+ // check MTU
+ int jsonMtu = jsonNode.get(MTU).asInt();
+ int mtu = network.mtu();
+ if (jsonMtu != mtu) {
+ description.appendText("MTU was " + jsonMtu);
+ return false;
+ }
+
+ // check segment ID
+ String jsonSegmentId = jsonNode.get(SEGMENT_ID).asText();
+ String segmentId = network.segmentId();
+ if (!jsonSegmentId.equals(segmentId)) {
+ description.appendText("segment ID was " + jsonSegmentId);
+ return false;
+ }
+
+ // check gateway IP
+ String jsonGatewayIp = jsonNode.get(GATEWAY_IP).asText();
+ String gatewayIp = network.gatewayIp().toString();
+ if (!jsonGatewayIp.equals(gatewayIp)) {
+ description.appendText("gateway IP was " + jsonGatewayIp);
+ return false;
+ }
+
+ // check CIDR
+ String jsonCidr = jsonNode.get(CIDR).asText();
+ String cidr = network.cidr();
+ if (!jsonCidr.equals(cidr)) {
+ description.appendText("CIDR was " + jsonCidr);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(network.toString());
+ }
+
+ /**
+ * Factory to allocate a kubernetes network matcher.
+ *
+ * @param network kubernetes network object we are looking for
+ * @return matcher
+ */
+ public static K8sNetworkJsonMatcher matchesK8sNetwork(K8sNetwork network) {
+ return new K8sNetworkJsonMatcher(network);
+ }
+}
diff --git a/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sPortCodecTest.java b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sPortCodecTest.java
new file mode 100644
index 0000000..cea53f2
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sPortCodecTest.java
@@ -0,0 +1,166 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.hamcrest.MatcherAssert;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.MacAddress;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.codec.impl.CodecManager;
+import org.onosproject.core.CoreService;
+import org.onosproject.k8snetworking.api.DefaultK8sPort;
+import org.onosproject.k8snetworking.api.K8sPort;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+
+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.k8snetworking.api.K8sPort.State.ACTIVE;
+import static org.onosproject.k8snetworking.codec.K8sPortJsonMatcher.matchesK8sPort;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
+/**
+ * Unit tests for kubernetes port codec.
+ */
+public class K8sPortCodecTest {
+
+ MockCodecContext context;
+
+ JsonCodec<K8sPort> k8sPortCodec;
+
+ 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();
+ k8sPortCodec = new K8sPortCodec();
+
+ assertThat(k8sPortCodec, notNullValue());
+
+ expect(mockCoreService.registerApplication(REST_APP_ID))
+ .andReturn(APP_ID).anyTimes();
+ replay(mockCoreService);
+ context.registerService(CoreService.class, mockCoreService);
+ }
+
+ /**
+ * Tests the kubernetes port encoding.
+ */
+ @Test
+ public void testK8sPortEncode() {
+ K8sPort port = DefaultK8sPort.builder()
+ .networkId("network-1")
+ .portId("port-1")
+ .deviceId(DeviceId.deviceId("of:0000000000000001"))
+ .ipAddress(IpAddress.valueOf("10.10.10.2"))
+ .macAddress(MacAddress.valueOf("00:11:22:33:44:55"))
+ .portNumber(PortNumber.portNumber(1))
+ .state(ACTIVE)
+ .build();
+
+ ObjectNode nodeJson = k8sPortCodec.encode(port, context);
+ assertThat(nodeJson, matchesK8sPort(port));
+ }
+
+ /**
+ * Tests the kubernetes port decoding.
+ */
+ @Test
+ public void testK8sPortDecode() throws IOException {
+ K8sPort port = getK8sPort("K8sPort.json");
+
+ assertEquals("network-1", port.networkId());
+ assertEquals("port-1", port.portId());
+ assertEquals("00:11:22:33:44:55", port.macAddress().toString());
+ assertEquals("10.10.10.10", port.ipAddress().toString());
+ assertEquals("of:0000000000000001", port.deviceId().toString());
+ assertEquals("1", port.portNumber().toString());
+ assertEquals("ACTIVE", port.state().name());
+ }
+
+ /**
+ * Reads in an kubernetes port from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded kubernetes port
+ * @throws IOException if processing the resource fails
+ */
+ private K8sPort getK8sPort(String resourceName) throws IOException {
+ InputStream jsonStream = K8sPortCodecTest.class.getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ MatcherAssert.assertThat(json, notNullValue());
+ K8sPort port = k8sPortCodec.decode((ObjectNode) json, context);
+ assertThat(port, notNullValue());
+ return port;
+ }
+
+ 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 == K8sPort.class) {
+ return (JsonCodec<T>) k8sPortCodec;
+ }
+ 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-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sPortJsonMatcher.java b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sPortJsonMatcher.java
new file mode 100644
index 0000000..b0f327e
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/java/org/onosproject/k8snetworking/codec/K8sPortJsonMatcher.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2019-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.k8snetworking.codec;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.k8snetworking.api.K8sPort;
+
+/**
+ * Hamcrest matcher for kubernetes port.
+ */
+public final class K8sPortJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final K8sPort port;
+
+ private static final String NETWORK_ID = "networkId";
+ private static final String PORT_ID = "portId";
+ private static final String MAC_ADDRESS = "macAddress";
+ private static final String IP_ADDRESS = "ipAddress";
+ private static final String DEVICE_ID = "deviceId";
+ private static final String PORT_NUMBER = "portNumber";
+ private static final String STATE = "state";
+
+ private K8sPortJsonMatcher(K8sPort port) {
+ this.port = port;
+ }
+
+ @Override
+ protected boolean matchesSafely(JsonNode jsonNode, Description description) {
+
+ // check network ID
+ String jsonNetworkId = jsonNode.get(NETWORK_ID).asText();
+ String networkId = port.networkId();
+ if (!jsonNetworkId.equals(networkId)) {
+ description.appendText("network ID was " + jsonNetworkId);
+ return false;
+ }
+
+ // check port ID
+ String jsonPortId = jsonNode.get(PORT_ID).asText();
+ String portId = port.portId();
+ if (!jsonPortId.equals(portId)) {
+ description.appendText("port ID was " + jsonPortId);
+ return false;
+ }
+
+ // check MAC address
+ String jsonMacAddress = jsonNode.get(MAC_ADDRESS).asText();
+ String macAddress = port.macAddress().toString();
+ if (!jsonMacAddress.equals(macAddress)) {
+ description.appendText("MAC address was " + jsonMacAddress);
+ return false;
+ }
+
+ // check IP address
+ String jsonIpAddress = jsonNode.get(IP_ADDRESS).asText();
+ String ipAddress = port.ipAddress().toString();
+ if (!jsonIpAddress.equals(ipAddress)) {
+ description.appendText("IP address was " + jsonIpAddress);
+ return false;
+ }
+
+ // check device ID
+ String jsonDeviceId = jsonNode.get(DEVICE_ID).asText();
+ String deviceId = port.deviceId().toString();
+ if (!jsonDeviceId.equals(deviceId)) {
+ description.appendText("device ID was " + jsonDeviceId);
+ return false;
+ }
+
+ // check port number
+ String jsonPortNumber = jsonNode.get(PORT_NUMBER).asText();
+ String portNumber = port.portNumber().toString();
+ if (!jsonPortNumber.equals(portNumber)) {
+ description.appendText("port number was " + jsonPortNumber);
+ return false;
+ }
+
+ // check state
+ String jsonState = jsonNode.get(STATE).asText();
+ String state = port.state().name();
+ if (!jsonState.equals(state)) {
+ description.appendText("state was " + jsonState);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(port.toString());
+ }
+
+ /**
+ * Factory to allocate an kubernetes port matcher.
+ *
+ * @param port kubernetes port object we are looking for
+ * @return matcher
+ */
+ public static K8sPortJsonMatcher matchesK8sPort(K8sPort port) {
+ return new K8sPortJsonMatcher(port);
+ }
+}
diff --git a/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sIpam.json b/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sIpam.json
new file mode 100644
index 0000000..22e1c19
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sIpam.json
@@ -0,0 +1,4 @@
+{
+ "ipAddress": "10.10.10.2",
+ "networkId": "network-1"
+}
\ No newline at end of file
diff --git a/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sNetwork.json b/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sNetwork.json
new file mode 100644
index 0000000..ce15c92
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sNetwork.json
@@ -0,0 +1,8 @@
+{
+ "networkId": "network-1",
+ "type": "VXLAN",
+ "mtu": 1500,
+ "segmentId": "1",
+ "gatewayIp": "10.10.10.1",
+ "cidr": "32"
+}
\ No newline at end of file
diff --git a/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sPort.json b/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sPort.json
new file mode 100644
index 0000000..9c0214c
--- /dev/null
+++ b/apps/k8s-networking/app/src/test/resources/org/onosproject/k8snetworking/codec/K8sPort.json
@@ -0,0 +1,9 @@
+{
+ "networkId": "network-1",
+ "portId": "port-1",
+ "macAddress": "00:11:22:33:44:55",
+ "ipAddress": "10.10.10.10",
+ "deviceId": "of:0000000000000001",
+ "portNumber": "1",
+ "state": "ACTIVE"
+}
\ No newline at end of file