def create_plugin(self): self.network_config = { "name": self.network_name, "type": self.plugin_type, "ipam": { "type": self.ipam_type, } } self.env = { CNI_COMMAND_ENV: self.command, CNI_CONTAINERID_ENV: self.container_id, CNI_IFNAME_ENV: self.cni_ifname, CNI_ARGS_ENV: self.cni_args, CNI_PATH_ENV: self.cni_path, CNI_NETNS_ENV: self.cni_netns } # Create the CniPlugin to test. plugin = CniPlugin(self.network_config, self.env) # Mock out the datastore client. plugin._client = self.client plugin.policy_driver._client = self.client return plugin
def setUp(self): """ Per-test setup method. """ self.container_id = "ff3afbd1-17ad-499d-b514-72438c009e81" self.network_config = { "name": "ut-network", "type": "calico", "ipam": { "type": "calico-ipam", "subnet": "10.22.0.0/16", "routes": [{"dst": "0.0.0.0/0"}], "range-start": "", "range-end": "", }, } self.env = { CNI_CONTAINERID_ENV: self.container_id, CNI_IFNAME_ENV: "eth0", CNI_ARGS_ENV: "", CNI_COMMAND_ENV: CNI_CMD_ADD, CNI_PATH_ENV: "/usr/bin/rkt/", CNI_NETNS_ENV: "netns", } # Create the CniPlugin to test. self.plugin = CniPlugin(self.network_config, self.env) # Mock out policy driver. self.plugin.policy_driver = MagicMock(spec=DefaultPolicyDriver) # Mock out the datastore client. self.m_datastore_client = MagicMock(spec=DatastoreClient) self.plugin._client = self.m_datastore_client
def setUp(self): """ Per-test setup method. """ self.container_id = "ff3afbd1-17ad-499d-b514-72438c009e81" self.network_config = { "name": "ut-network", "type": "calico", "ipam": { "type": "calico-ipam", "subnet": "10.22.0.0/16", "routes": [{ "dst": "0.0.0.0/0" }], "range-start": "", "range-end": "" } } self.env = { CNI_CONTAINERID_ENV: self.container_id, CNI_IFNAME_ENV: "eth0", CNI_ARGS_ENV: "", CNI_COMMAND_ENV: CNI_CMD_ADD, CNI_PATH_ENV: "/usr/bin/rkt/", CNI_NETNS_ENV: "netns", } # Create the CniPlugin to test. self.plugin = CniPlugin(self.network_config, self.env) # Mock out policy driver. self.plugin.policy_driver = MagicMock(spec=DefaultPolicyDriver) # Mock out the datastore client. self.m_datastore_client = MagicMock(spec=DatastoreClient) self.plugin._client = self.m_datastore_client
class CniPluginTest(unittest.TestCase): """ Test class for CniPlugin class. """ def setUp(self): """ Per-test setup method. """ self.container_id = "ff3afbd1-17ad-499d-b514-72438c009e81" self.network_config = { "name": "ut-network", "type": "calico", "ipam": { "type": "calico-ipam", "subnet": "10.22.0.0/16", "routes": [{ "dst": "0.0.0.0/0" }], "range-start": "", "range-end": "" } } self.env = { CNI_CONTAINERID_ENV: self.container_id, CNI_IFNAME_ENV: "eth0", CNI_ARGS_ENV: "", CNI_COMMAND_ENV: CNI_CMD_ADD, CNI_PATH_ENV: "/usr/bin/rkt/", CNI_NETNS_ENV: "netns", } # Create the CniPlugin to test. self.plugin = CniPlugin(self.network_config, self.env) # Mock out policy driver. self.plugin.policy_driver = MagicMock(spec=DefaultPolicyDriver) # Mock out the datastore client. self.m_datastore_client = MagicMock(spec=DatastoreClient) self.plugin._client = self.m_datastore_client def test_execute_mainline(self): # Mock out _execute() for this test. self.plugin._execute = MagicMock(spec=self.plugin._execute) # Call execute() rc = self.plugin.execute() # Assert success. assert_equal(rc, 0) def test_execute_sys_exit(self): """Test execute() SystemExit handling""" # Mock out _execute to throw SystemExit self.plugin._execute = MagicMock(spec=self.plugin._execute) self.plugin._execute.side_effect = SystemExit(5) # Call execute() rc = self.plugin.execute() # Assert success. assert_equal(rc, 5) def test_execute_unhandled_exception(self): """Test execute() unhandled Exception""" # Mock out _execute to throw KeyError. self.plugin._execute = MagicMock(spec=self.plugin._execute) self.plugin._execute.side_effect = KeyError # Call execute() rc = self.plugin.execute() # Assert returns unhandled error code assert_equal(rc, ERR_CODE_UNHANDLED) def test__execute_add_mainline(self): """Test _execute() ADD Set command to add, assert add() called. """ self.plugin.command = CNI_CMD_ADD self.plugin.add = MagicMock(self.plugin.add) self.plugin._execute() self.plugin.add.assert_called_once_with() def test__execute_del_mainline(self): """Test _execute() DEL Set command to delete, assert delete() called. """ self.plugin.command = CNI_CMD_DELETE self.plugin.delete = MagicMock(self.plugin.delete) self.plugin._execute() self.plugin.delete.assert_called_once_with() @patch("calico_cni.calico_cni.json", autospec=True) def test_add_mainline(self, m_json): # Mock out _assign_ips. ip4 = IPNetwork("10.0.0.1/32") ip6 = IPNetwork("0:0:0:0:0:ffff:a00:1/128") self.plugin._assign_ips = MagicMock(spec=self.plugin._assign_ips) self.plugin._assign_ips.return_value = ip4, ip6 # Mock out IPAM response. ipam_response = json.dumps({ "ip4": { "ip": str(ip4.cidr) }, "ip6": { "ip": str(ip6.cidr) } }) self.plugin.ipam_result = ipam_response # Mock out _create_endpoint. endpoint = MagicMock(spec=Endpoint) self.plugin._create_endpoint = MagicMock( spec=self.plugin._create_endpoint) self.plugin._create_endpoint.return_value = endpoint # Mock out _provision_veth. self.plugin._provision_veth = MagicMock( spec=self.plugin._provision_veth) self.plugin._provision_veth.return_value = endpoint # Mock out _get_endpoint - no endpoint exists. self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = None # Call method. self.plugin.add() # Assert. self.plugin._assign_ips.assert_called_once_with(self.plugin.env) self.plugin._create_endpoint.assert_called_once_with([ip4]) self.plugin._provision_veth.assert_called_once_with(endpoint) self.plugin.policy_driver.apply_profile.assert_called_once_with( endpoint) m_json.dumps.assert_called_once_with(ipam_response) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_exists_new_network(self, m_json): """ Test add when the endpoint already exists, adding to a new network. """ # Mock out methods that should not be called. self.plugin._assign_ips = MagicMock(spec=self.plugin._assign_ips) self.plugin._create_endpoint = MagicMock( spec=self.plugin._create_endpoint) self.plugin._provision_veth = MagicMock( spec=self.plugin._provision_veth) # Mock out _get_endpoint - endpoint exists. ip4 = IPNetwork("10.0.0.1") ip6 = IPNetwork("bad::beef") endpoint = MagicMock(spec=Endpoint) endpoint.ipv4_nets = [ip4] endpoint.ipv6_nets = [ip6] self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Expected response. expected = {"ip4": {"ip": str(ip4)}, "ip6": {"ip": str(ip6)}} # Call method. self.plugin.add() # Assert. assert_false(self.plugin._assign_ips.called) assert_false(self.plugin._create_endpoint.called) assert_false(self.plugin._provision_veth.called) self.plugin.policy_driver.apply_profile.assert_called_once_with( endpoint) m_json.dumps.assert_called_once_with(expected) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_profile_error(self, m_json): """ Test add when the endpoint does not exist, error applying profile. """ # Mock out cleanup methods. self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) self.plugin._remove_endpoint = MagicMock( spec=self.plugin._remove_endpoint) self.plugin._remove_veth = MagicMock(spec=self.plugin._remove_veth) # Mock out _assign_ips. ip4 = IPNetwork("10.0.0.1/32") ip6 = IPNetwork("0:0:0:0:0:ffff:a00:1/128") self.plugin._assign_ips = MagicMock(spec=self.plugin._assign_ips) self.plugin._assign_ips.return_value = ip4, ip6 # Mock out IPAM response. ipam_response = json.dumps({ "ip4": { "ip": str(ip4.cidr) }, "ip6": { "ip": str(ip6.cidr) } }) self.plugin.ipam_result = ipam_response # Mock out _create_endpoint. endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" self.plugin._create_endpoint = MagicMock( spec=self.plugin._create_endpoint) self.plugin._create_endpoint.return_value = endpoint # Mock out _provision_veth. self.plugin._provision_veth = MagicMock( spec=self.plugin._provision_veth) self.plugin._provision_veth.return_value = endpoint # Mock out apply_profile to throw error. msg = "Apply Profile Error Message" error = ApplyProfileError(msg) self.plugin.policy_driver.apply_profile.side_effect = error # Mock out _get_endpoint - endpoint exists. self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = None # Call method. assert_raises(SystemExit, self.plugin.add) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_exists_new_network_profile_error(self, m_json): """ Test add when the endpoint already exists, adding to a new network, error applying profile. """ # Mock out apply_profile to throw error. self.plugin.policy_driver.apply_profile.side_effect = ApplyProfileError # Mock out _get_endpoint - endpoint exists. ip4 = IPNetwork("10.0.0.1") ip6 = IPNetwork("bad::beef") endpoint = MagicMock(spec=Endpoint) endpoint.ipv4_nets = [ip4] endpoint.ipv6_nets = [ip6] endpoint.name = "cali12345" self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Call method. assert_raises(SystemExit, self.plugin.add) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_exists_no_ips(self, m_json): """ Tests add to new network when endpoint exists, no IP addresses are assigned. """ # Mock out _get_endpoint - endpoint exists. endpoint = MagicMock(spec=Endpoint) endpoint.ipv4_nets = [] endpoint.ipv6_nets = [] endpoint.name = "cali12345" self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Call method. self.plugin.add() # Assert profile add is called. self.plugin.policy_driver.apply_profile.assert_called_once_with( endpoint) @patch("calico_cni.calico_cni.netns", autospec=True) def test_delete_mainline(self, m_netns): # Mock out _release_ip. self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Mock out _get_endpoint. endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Mock out _remove_endpoint. self.plugin._remove_endpoint = MagicMock( spec=self.plugin._remove_endpoint) # Call delete() self.plugin.delete() # Assert. self.plugin._release_ip.assert_called_once_with(self.plugin.env) self.plugin._get_endpoint.assert_called_once_with() self.plugin._remove_endpoint.assert_called_once_with() m_netns.remove_veth.assert_called_once_with("cali12345") self.plugin.policy_driver.remove_profile.assert_called_once_with() @patch("calico_cni.calico_cni.netns", autospec=True) def test_delete_no_endpoint(self, m_netns): # Mock out _release_ip. self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Mock out _remove_endpoint. self.plugin._remove_endpoint = MagicMock( spec=self.plugin._remove_endpoint) # Mock out _get_endpoint. self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = None # Call delete() assert_raises(SystemExit, self.plugin.delete) # Assert. self.plugin._release_ip.assert_called_once_with(self.plugin.env) self.plugin._get_endpoint.assert_called_once_with() assert_false(self.plugin._remove_endpoint.called) assert_false(m_netns.remove_veth.called) def test_assign_ip_mainline(self): # Mock _call_ipam_plugin. ip4 = "10.0.0.1/32" ip6 = "0:0:0:0:0:ffff:a00:1" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}, "ip6": {"ip": ip6}}) self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. assigned_ips = self.plugin._assign_ips(env) # Assert. assert_equal(assigned_ips, (IPNetwork(ip4), IPNetwork(ip6))) def test_assign_ip_invalid_response(self): # Mock _call_ipam_plugin. rc = 1 ipam_result = "Invalid json" self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_bad_rc(self): # Mock _call_ipam_plugin. rc = ERR_CODE_GENERIC msg = "Message" details = "Details" ipam_result = json.dumps({"code": rc, "msg": msg, "details": details}) self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_no_ipv4(self): # Mock _call_ipam_plugin. ip6 = "0:0:0:0:0:ffff:a00:1" rc = 0 ipam_result = json.dumps({"ip4": {}, "ip6": {"ip": ip6}}) self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_no_ipv6(self): # Mock _call_ipam_plugin. ip4 = "10.0.0.1" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}}) self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_invalid_ipv6(self): # Mock _call_ipam_plugin. ip6 = "invalid" ip4 = "10.0.0.5" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}, "ip6": {"ip": ip6}}) self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_invalid_ipv4(self): # Mock _call_ipam_plugin. ip4 = "10.0.0.500" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}}) self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_release_ip_mainline(self): # Mock _call_ipam_plugin. rc = 0 self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, "" env = {CNI_COMMAND_ENV: CNI_CMD_DELETE} # Call _release_ip. self.plugin._release_ip(env) def test_release_ip_failed(self): # Mock _call_ipam_plugin. rc = 100 self.plugin._call_ipam_plugin = MagicMock( spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, "" env = {CNI_COMMAND_ENV: CNI_CMD_DELETE} # Call _release_ip. self.plugin._release_ip(env) @patch("calico_cni.calico_cni.Popen", autospec=True) def test_call_ipam_plugin_mainline(self, m_popen): # Mock _find_ipam_plugin. plugin_path = "/opt/bin/cni/calico-ipam" self.plugin._find_ipam_plugin = MagicMock( spec=self.plugin._find_ipam_plugin) self.plugin._find_ipam_plugin.return_value = plugin_path # Mock out return values. ip4 = "10.0.0.1/32" ip6 = "0:0:0:0:0:ffff:a00:1" stdout = json.dumps({"ip4": {"ip": ip4}, "ip6": {"ip": ip6}}) stderr = "" m_proc = MagicMock(spec=Popen) m_proc.communicate.return_value = (stdout, stderr) m_proc.returncode = 0 m_popen.return_value = m_proc env = {} # Call _call_ipam_plugin. rc, result = self.plugin._call_ipam_plugin(env) # Assert. assert_equal(rc, 0) m_popen.assert_called_once_with(plugin_path, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) m_proc.communicate.assert_called_once_with( json.dumps(self.plugin.network_config)) assert_equal(result, stdout) @patch("calico_cni.calico_cni.Popen", autospec=True) def test_call_ipam_plugin_missing(self, m_popen): """ Unable to find IPAM plugin. """ # Mock _find_ipam_plugin. self.plugin._find_ipam_plugin = MagicMock( spec=self.plugin._find_ipam_plugin) self.plugin._find_ipam_plugin.return_value = None env = {} # Call method. with assert_raises(SystemExit) as err: self.plugin._call_ipam_plugin(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_create_endpoint_mainline(self): # Mock. ip4 = IPNetwork("10.0.0.1") ip_list = [ip4] endpoint = MagicMock(spec=Endpoint) self.plugin._client.create_endpoint.return_value = endpoint # Call. ep = self.plugin._create_endpoint(ip_list) # Assert. self.plugin._client.create_endpoint.assert_called_once_with( ANY, "cni", self.container_id, ip_list) assert_equal(ep, endpoint) def test_create_endpoint_error(self): # Mock. ip4 = IPNetwork("10.0.0.1") ip_list = [ip4] self.plugin._client.create_endpoint.side_effect = KeyError self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Call. with assert_raises(SystemExit) as err: self.plugin._create_endpoint(ip_list) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) expected_env = self.env.copy() expected_env[CNI_COMMAND_ENV] = CNI_CMD_DELETE self.plugin._release_ip.assert_called_once_with(expected_env) def test_remove_endpoint_mainline(self): # Call self.plugin._remove_endpoint() # Assert self.plugin._client.remove_workload.assert_called_once_with( hostname=ANY, workload_id=self.container_id, orchestrator_id="cni") def test_remove_endpoint_does_not_exist(self): """ Make sure we handle this case gracefully - no exception raised. """ self.plugin._client.remove_workload.side_effect = KeyError self.plugin._remove_endpoint() @patch("calico_cni.calico_cni.os", autospec=True) @patch("calico_cni.calico_cni.Namespace", autospec=True) def test_provision_veth_mainline(self, m_ns, m_os): # Mock endpoint = MagicMock(spec=Endpoint) mac = "aa:bb:cc:dd:ee:ff" endpoint.provision_veth.return_value = mac m_os.path.abspath.return_value = "/path/to/netns" # Call method self.plugin._provision_veth(endpoint) # Assert. assert_equal(endpoint.mac, mac) m_ns.assert_called_once_with("/path/to/netns") endpoint.provision_veth.assert_called_once_with( m_ns("/path/to/netns"), "eth0") self.plugin._client.set_endpoint.assert_called_once_with(endpoint) @patch("calico_cni.calico_cni.os", autospec=True) @patch("calico_cni.calico_cni.Namespace", autospec=True) @patch("calico_cni.calico_cni.print_cni_error", autospec=True) def test_provision_veth_error(self, m_print, m_ns, m_os): # Mock endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" m_os.path.abspath.return_value = "/path/to/netns" endpoint.provision_veth.side_effect = CalledProcessError(1, "cmd", 3) # Mock out cleanup methods. self.plugin._remove_endpoint = MagicMock( spec=self.plugin._remove_endpoint) self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Call method with assert_raises(SystemExit) as err: self.plugin._provision_veth(endpoint) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) # Assert. m_ns.assert_called_once_with("/path/to/netns") endpoint.provision_veth.assert_called_once_with( m_ns("/path/to/netns"), "eth0") assert_false(self.plugin._client.set_endpoint.called) self.plugin._remove_endpoint.assert_called_once_with() self.plugin._release_ip.assert_called_once_with(ANY) @patch("calico_cni.calico_cni.netns", autospec=True) def test_remove_veth_mainline(self, m_netns): # Mock endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" # Call self.plugin._remove_veth(endpoint) # Assert m_netns.remove_veth.assert_called_once_with(endpoint.name) @patch("calico_cni.calico_cni.netns", autospec=True) def test_remove_veth_error(self, m_netns): """ Make sure we handle errors gracefully - don't re-raise. """ # Mock endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" m_netns.remove_veth.side_effect = CalledProcessError(1, "cmd2", 3) # Call self.plugin._remove_veth(endpoint) def test_get_container_engine_docker(self): self.plugin.cni_args = {K8S_POD_NAME: "podname"} eng = self.plugin._get_container_engine() assert_true(isinstance(eng, DockerEngine)) def test_get_policy_driver_default_k8s(self): self.plugin.cni_args = {K8S_POD_NAME: "podname"} driver = self.plugin._get_policy_driver() assert_true(isinstance(driver, KubernetesDefaultPolicyDriver)) @patch("calico_cni.calico_cni.policy_drivers", autospec=True) def test_get_policy_driver_value_error(self, m_drivers): # Mock m_drivers.DefaultPolicyDriver.side_effect = ValueError # Call with assert_raises(SystemExit) as err: self.plugin._get_policy_driver() e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_get_endpoint_mainline(self): # Mock endpoint = MagicMock(spec=Endpoint) self.plugin._client.get_endpoint.return_value = endpoint # Call ep = self.plugin._get_endpoint() # Assert assert_equal(ep, endpoint) self.plugin._client.get_endpoint.assert_called_once_with( hostname=ANY, orchestrator_id="cni", workload_id=self.plugin.container_id) def test_get_endpoint_no_endpoint(self): # Mock self.plugin._client.get_endpoint.side_effect = KeyError # Call ep = self.plugin._get_endpoint() # Assert assert_equal(ep, None) self.plugin._client.get_endpoint.assert_called_once_with( hostname=ANY, orchestrator_id="cni", workload_id=self.plugin.container_id) def test_get_endpoint_multiple_endpoints(self): # Mock self.plugin._client.get_endpoint.side_effect = MultipleEndpointsMatch # Call with assert_raises(SystemExit) as err: self.plugin._get_endpoint() e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) # Assert self.plugin._client.get_endpoint.assert_called_once_with( hostname=ANY, orchestrator_id="cni", workload_id=self.plugin.container_id) @patch("calico_cni.calico_cni.os", autospec=True) def test_find_ipam_plugin(self, m_os): # Mock m_os.path.isfile.side_effect = iter([False, True ]) # Second time returns true. m_os.path.join.side_effect = lambda x, y: x + y m_os.path.abspath.side_effect = lambda x: x self.plugin.cni_path = "/opt/bin/cni/:/opt/cni/bin/" # Call path = self.plugin._find_ipam_plugin() # Assert assert_equal(path, "/opt/cni/bin/calico-ipam") @patch("calico_cni.calico_cni.os", autospec=True) @patch("calico_cni.calico_cni.sys", autospec=True) @patch("calico_cni.calico_cni.CniPlugin", autospec=True) @patch("calico_cni.calico_cni.configure_logging", autospec=True) def test_main(self, m_conf_log, m_plugin, m_sys, m_os): # Mock m_os.environ = self.env m_sys.stdin.readlines.return_value = json.dumps(self.network_config) m_plugin(self.env, self.network_config).execute.return_value = 0 m_plugin.reset_mock() # Call main() # Assert m_plugin.assert_called_once_with(self.network_config, self.env) m_conf_log.assert_called_once_with(ANY, "cni.log", log_level="INFO") m_sys.exit.assert_called_once_with(0)
class CniPluginTest(unittest.TestCase): """ Test class for CniPlugin class. """ def setUp(self): """ Per-test setup method. """ self.container_id = "ff3afbd1-17ad-499d-b514-72438c009e81" self.network_config = { "name": "ut-network", "type": "calico", "ipam": { "type": "calico-ipam", "subnet": "10.22.0.0/16", "routes": [{"dst": "0.0.0.0/0"}], "range-start": "", "range-end": "", }, } self.env = { CNI_CONTAINERID_ENV: self.container_id, CNI_IFNAME_ENV: "eth0", CNI_ARGS_ENV: "", CNI_COMMAND_ENV: CNI_CMD_ADD, CNI_PATH_ENV: "/usr/bin/rkt/", CNI_NETNS_ENV: "netns", } # Create the CniPlugin to test. self.plugin = CniPlugin(self.network_config, self.env) # Mock out policy driver. self.plugin.policy_driver = MagicMock(spec=DefaultPolicyDriver) # Mock out the datastore client. self.m_datastore_client = MagicMock(spec=DatastoreClient) self.plugin._client = self.m_datastore_client def test_execute_mainline(self): # Mock out _execute() for this test. self.plugin._execute = MagicMock(spec=self.plugin._execute) # Call execute() rc = self.plugin.execute() # Assert success. assert_equal(rc, 0) def test_execute_sys_exit(self): """Test execute() SystemExit handling""" # Mock out _execute to throw SystemExit self.plugin._execute = MagicMock(spec=self.plugin._execute) self.plugin._execute.side_effect = SystemExit(5) # Call execute() rc = self.plugin.execute() # Assert success. assert_equal(rc, 5) def test_execute_unhandled_exception(self): """Test execute() unhandled Exception""" # Mock out _execute to throw KeyError. self.plugin._execute = MagicMock(spec=self.plugin._execute) self.plugin._execute.side_effect = KeyError # Call execute() rc = self.plugin.execute() # Assert returns unhandled error code assert_equal(rc, ERR_CODE_UNHANDLED) def test__execute_add_mainline(self): """Test _execute() ADD Set command to add, assert add() called. """ self.plugin.command = CNI_CMD_ADD self.plugin.add = MagicMock(self.plugin.add) self.plugin._execute() self.plugin.add.assert_called_once_with() def test__execute_del_mainline(self): """Test _execute() DEL Set command to delete, assert delete() called. """ self.plugin.command = CNI_CMD_DELETE self.plugin.delete = MagicMock(self.plugin.delete) self.plugin._execute() self.plugin.delete.assert_called_once_with() @patch("calico_cni.calico_cni.json", autospec=True) def test_add_mainline(self, m_json): # Mock out _assign_ips. ip4 = IPNetwork("10.0.0.1/32") ip6 = IPNetwork("0:0:0:0:0:ffff:a00:1/128") self.plugin._assign_ips = MagicMock(spec=self.plugin._assign_ips) self.plugin._assign_ips.return_value = ip4, ip6 # Mock out IPAM response. ipam_response = json.dumps({"ip4": {"ip": str(ip4.cidr)}, "ip6": {"ip": str(ip6.cidr)}}) self.plugin.ipam_result = ipam_response # Mock out _create_endpoint. endpoint = MagicMock(spec=Endpoint) self.plugin._create_endpoint = MagicMock(spec=self.plugin._create_endpoint) self.plugin._create_endpoint.return_value = endpoint # Mock out _provision_veth. self.plugin._provision_veth = MagicMock(spec=self.plugin._provision_veth) self.plugin._provision_veth.return_value = endpoint # Mock out _get_endpoint - no endpoint exists. self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = None # Call method. self.plugin.add() # Assert. self.plugin._assign_ips.assert_called_once_with(self.plugin.env) self.plugin._create_endpoint.assert_called_once_with([ip4]) self.plugin._provision_veth.assert_called_once_with(endpoint) self.plugin.policy_driver.apply_profile.assert_called_once_with(endpoint) m_json.dumps.assert_called_once_with(ipam_response) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_exists_new_network(self, m_json): """ Test add when the endpoint already exists, adding to a new network. """ # Mock out methods that should not be called. self.plugin._assign_ips = MagicMock(spec=self.plugin._assign_ips) self.plugin._create_endpoint = MagicMock(spec=self.plugin._create_endpoint) self.plugin._provision_veth = MagicMock(spec=self.plugin._provision_veth) # Mock out _get_endpoint - endpoint exists. ip4 = IPNetwork("10.0.0.1") ip6 = IPNetwork("bad::beef") endpoint = MagicMock(spec=Endpoint) endpoint.ipv4_nets = [ip4] endpoint.ipv6_nets = [ip6] self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Expected response. expected = {"ip4": {"ip": str(ip4)}, "ip6": {"ip": str(ip6)}} # Call method. self.plugin.add() # Assert. assert_false(self.plugin._assign_ips.called) assert_false(self.plugin._create_endpoint.called) assert_false(self.plugin._provision_veth.called) self.plugin.policy_driver.apply_profile.assert_called_once_with(endpoint) m_json.dumps.assert_called_once_with(expected) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_profile_error(self, m_json): """ Test add when the endpoint does not exist, error applying profile. """ # Mock out cleanup methods. self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) self.plugin._remove_endpoint = MagicMock(spec=self.plugin._remove_endpoint) self.plugin._remove_veth = MagicMock(spec=self.plugin._remove_veth) # Mock out _assign_ips. ip4 = IPNetwork("10.0.0.1/32") ip6 = IPNetwork("0:0:0:0:0:ffff:a00:1/128") self.plugin._assign_ips = MagicMock(spec=self.plugin._assign_ips) self.plugin._assign_ips.return_value = ip4, ip6 # Mock out IPAM response. ipam_response = json.dumps({"ip4": {"ip": str(ip4.cidr)}, "ip6": {"ip": str(ip6.cidr)}}) self.plugin.ipam_result = ipam_response # Mock out _create_endpoint. endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" self.plugin._create_endpoint = MagicMock(spec=self.plugin._create_endpoint) self.plugin._create_endpoint.return_value = endpoint # Mock out _provision_veth. self.plugin._provision_veth = MagicMock(spec=self.plugin._provision_veth) self.plugin._provision_veth.return_value = endpoint # Mock out apply_profile to throw error. msg = "Apply Profile Error Message" error = ApplyProfileError(msg) self.plugin.policy_driver.apply_profile.side_effect = error # Mock out _get_endpoint - endpoint exists. self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = None # Call method. assert_raises(SystemExit, self.plugin.add) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_exists_new_network_profile_error(self, m_json): """ Test add when the endpoint already exists, adding to a new network, error applying profile. """ # Mock out apply_profile to throw error. self.plugin.policy_driver.apply_profile.side_effect = ApplyProfileError # Mock out _get_endpoint - endpoint exists. ip4 = IPNetwork("10.0.0.1") ip6 = IPNetwork("bad::beef") endpoint = MagicMock(spec=Endpoint) endpoint.ipv4_nets = [ip4] endpoint.ipv6_nets = [ip6] endpoint.name = "cali12345" self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Call method. assert_raises(SystemExit, self.plugin.add) @patch("calico_cni.calico_cni.json", autospec=True) def test_add_exists_no_ips(self, m_json): """ Tests add to new network when endpoint exists, no IP addresses are assigned. """ # Mock out _get_endpoint - endpoint exists. endpoint = MagicMock(spec=Endpoint) endpoint.ipv4_nets = [] endpoint.ipv6_nets = [] endpoint.name = "cali12345" self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Call method. self.plugin.add() # Assert profile add is called. self.plugin.policy_driver.apply_profile.assert_called_once_with(endpoint) @patch("calico_cni.calico_cni.netns", autospec=True) def test_delete_mainline(self, m_netns): # Mock out _release_ip. self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Mock out _get_endpoint. endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = endpoint # Mock out _remove_endpoint. self.plugin._remove_endpoint = MagicMock(spec=self.plugin._remove_endpoint) # Call delete() self.plugin.delete() # Assert. self.plugin._release_ip.assert_called_once_with(self.plugin.env) self.plugin._get_endpoint.assert_called_once_with() self.plugin._remove_endpoint.assert_called_once_with() m_netns.remove_veth.assert_called_once_with("cali12345") self.plugin.policy_driver.remove_profile.assert_called_once_with() @patch("calico_cni.calico_cni.netns", autospec=True) def test_delete_no_endpoint(self, m_netns): # Mock out _release_ip. self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Mock out _remove_endpoint. self.plugin._remove_endpoint = MagicMock(spec=self.plugin._remove_endpoint) # Mock out _get_endpoint. self.plugin._get_endpoint = MagicMock(spec=self.plugin._get_endpoint) self.plugin._get_endpoint.return_value = None # Call delete() assert_raises(SystemExit, self.plugin.delete) # Assert. self.plugin._release_ip.assert_called_once_with(self.plugin.env) self.plugin._get_endpoint.assert_called_once_with() assert_false(self.plugin._remove_endpoint.called) assert_false(m_netns.remove_veth.called) def test_assign_ip_mainline(self): # Mock _call_ipam_plugin. ip4 = "10.0.0.1/32" ip6 = "0:0:0:0:0:ffff:a00:1" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}, "ip6": {"ip": ip6}}) self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. assigned_ips = self.plugin._assign_ips(env) # Assert. assert_equal(assigned_ips, (IPNetwork(ip4), IPNetwork(ip6))) def test_assign_ip_invalid_response(self): # Mock _call_ipam_plugin. rc = 1 ipam_result = "Invalid json" self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_bad_rc(self): # Mock _call_ipam_plugin. rc = ERR_CODE_GENERIC msg = "Message" details = "Details" ipam_result = json.dumps({"code": rc, "msg": msg, "details": details}) self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_no_ipv4(self): # Mock _call_ipam_plugin. ip6 = "0:0:0:0:0:ffff:a00:1" rc = 0 ipam_result = json.dumps({"ip4": {}, "ip6": {"ip": ip6}}) self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_no_ipv6(self): # Mock _call_ipam_plugin. ip4 = "10.0.0.1" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}}) self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_invalid_ipv6(self): # Mock _call_ipam_plugin. ip6 = "invalid" ip4 = "10.0.0.5" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}, "ip6": {"ip": ip6}}) self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_assign_ip_invalid_ipv4(self): # Mock _call_ipam_plugin. ip4 = "10.0.0.500" rc = 0 ipam_result = json.dumps({"ip4": {"ip": ip4}}) self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, ipam_result env = {CNI_COMMAND_ENV: CNI_CMD_ADD} # Call _assign_ips. with assert_raises(SystemExit) as err: self.plugin._assign_ips(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_release_ip_mainline(self): # Mock _call_ipam_plugin. rc = 0 self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, "" env = {CNI_COMMAND_ENV: CNI_CMD_DELETE} # Call _release_ip. self.plugin._release_ip(env) def test_release_ip_failed(self): # Mock _call_ipam_plugin. rc = 100 self.plugin._call_ipam_plugin = MagicMock(spec=self.plugin._call_ipam_plugin) self.plugin._call_ipam_plugin.return_value = rc, "" env = {CNI_COMMAND_ENV: CNI_CMD_DELETE} # Call _release_ip. self.plugin._release_ip(env) @patch("calico_cni.calico_cni.Popen", autospec=True) def test_call_ipam_plugin_mainline(self, m_popen): # Mock _find_ipam_plugin. plugin_path = "/opt/bin/cni/calico-ipam" self.plugin._find_ipam_plugin = MagicMock(spec=self.plugin._find_ipam_plugin) self.plugin._find_ipam_plugin.return_value = plugin_path # Mock out return values. ip4 = "10.0.0.1/32" ip6 = "0:0:0:0:0:ffff:a00:1" stdout = json.dumps({"ip4": {"ip": ip4}, "ip6": {"ip": ip6}}) stderr = "" m_proc = MagicMock(spec=Popen) m_proc.communicate.return_value = (stdout, stderr) m_proc.returncode = 0 m_popen.return_value = m_proc env = {} # Call _call_ipam_plugin. rc, result = self.plugin._call_ipam_plugin(env) # Assert. assert_equal(rc, 0) m_popen.assert_called_once_with(plugin_path, stdin=PIPE, stdout=PIPE, stderr=PIPE, env=env) m_proc.communicate.assert_called_once_with(json.dumps(self.plugin.network_config)) assert_equal(result, stdout) @patch("calico_cni.calico_cni.Popen", autospec=True) def test_call_ipam_plugin_missing(self, m_popen): """ Unable to find IPAM plugin. """ # Mock _find_ipam_plugin. self.plugin._find_ipam_plugin = MagicMock(spec=self.plugin._find_ipam_plugin) self.plugin._find_ipam_plugin.return_value = None env = {} # Call method. with assert_raises(SystemExit) as err: self.plugin._call_ipam_plugin(env) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_create_endpoint_mainline(self): # Mock. ip4 = IPNetwork("10.0.0.1") ip_list = [ip4] endpoint = MagicMock(spec=Endpoint) self.plugin._client.create_endpoint.return_value = endpoint # Call. ep = self.plugin._create_endpoint(ip_list) # Assert. self.plugin._client.create_endpoint.assert_called_once_with(ANY, "cni", self.container_id, ip_list) assert_equal(ep, endpoint) def test_create_endpoint_error(self): # Mock. ip4 = IPNetwork("10.0.0.1") ip_list = [ip4] self.plugin._client.create_endpoint.side_effect = KeyError self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Call. with assert_raises(SystemExit) as err: self.plugin._create_endpoint(ip_list) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) expected_env = self.env.copy() expected_env[CNI_COMMAND_ENV] = CNI_CMD_DELETE self.plugin._release_ip.assert_called_once_with(expected_env) def test_remove_endpoint_mainline(self): # Call self.plugin._remove_endpoint() # Assert self.plugin._client.remove_workload.assert_called_once_with( hostname=ANY, workload_id=self.container_id, orchestrator_id="cni" ) def test_remove_endpoint_does_not_exist(self): """ Make sure we handle this case gracefully - no exception raised. """ self.plugin._client.remove_workload.side_effect = KeyError self.plugin._remove_endpoint() @patch("calico_cni.calico_cni.os", autospec=True) @patch("calico_cni.calico_cni.Namespace", autospec=True) def test_provision_veth_mainline(self, m_ns, m_os): # Mock endpoint = MagicMock(spec=Endpoint) mac = "aa:bb:cc:dd:ee:ff" endpoint.provision_veth.return_value = mac m_os.path.abspath.return_value = "/path/to/netns" # Call method self.plugin._provision_veth(endpoint) # Assert. assert_equal(endpoint.mac, mac) m_ns.assert_called_once_with("/path/to/netns") endpoint.provision_veth.assert_called_once_with(m_ns("/path/to/netns"), "eth0") self.plugin._client.set_endpoint.assert_called_once_with(endpoint) @patch("calico_cni.calico_cni.os", autospec=True) @patch("calico_cni.calico_cni.Namespace", autospec=True) @patch("calico_cni.calico_cni.print_cni_error", autospec=True) def test_provision_veth_error(self, m_print, m_ns, m_os): # Mock endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" m_os.path.abspath.return_value = "/path/to/netns" endpoint.provision_veth.side_effect = CalledProcessError(1, "cmd", 3) # Mock out cleanup methods. self.plugin._remove_endpoint = MagicMock(spec=self.plugin._remove_endpoint) self.plugin._release_ip = MagicMock(spec=self.plugin._release_ip) # Call method with assert_raises(SystemExit) as err: self.plugin._provision_veth(endpoint) e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) # Assert. m_ns.assert_called_once_with("/path/to/netns") endpoint.provision_veth.assert_called_once_with(m_ns("/path/to/netns"), "eth0") assert_false(self.plugin._client.set_endpoint.called) self.plugin._remove_endpoint.assert_called_once_with() self.plugin._release_ip.assert_called_once_with(ANY) @patch("calico_cni.calico_cni.netns", autospec=True) def test_remove_veth_mainline(self, m_netns): # Mock endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" # Call self.plugin._remove_veth(endpoint) # Assert m_netns.remove_veth.assert_called_once_with(endpoint.name) @patch("calico_cni.calico_cni.netns", autospec=True) def test_remove_veth_error(self, m_netns): """ Make sure we handle errors gracefully - don't re-raise. """ # Mock endpoint = MagicMock(spec=Endpoint) endpoint.name = "cali12345" m_netns.remove_veth.side_effect = CalledProcessError(1, "cmd2", 3) # Call self.plugin._remove_veth(endpoint) def test_get_container_engine_docker(self): self.plugin.cni_args = {K8S_POD_NAME: "podname"} eng = self.plugin._get_container_engine() assert_true(isinstance(eng, DockerEngine)) def test_get_policy_driver_default_k8s(self): self.plugin.cni_args = {K8S_POD_NAME: "podname"} driver = self.plugin._get_policy_driver() assert_true(isinstance(driver, KubernetesDefaultPolicyDriver)) @patch("calico_cni.calico_cni.policy_drivers", autospec=True) def test_get_policy_driver_value_error(self, m_drivers): # Mock m_drivers.DefaultPolicyDriver.side_effect = ValueError # Call with assert_raises(SystemExit) as err: self.plugin._get_policy_driver() e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) def test_get_endpoint_mainline(self): # Mock endpoint = MagicMock(spec=Endpoint) self.plugin._client.get_endpoint.return_value = endpoint # Call ep = self.plugin._get_endpoint() # Assert assert_equal(ep, endpoint) self.plugin._client.get_endpoint.assert_called_once_with( hostname=ANY, orchestrator_id="cni", workload_id=self.plugin.container_id ) def test_get_endpoint_no_endpoint(self): # Mock self.plugin._client.get_endpoint.side_effect = KeyError # Call ep = self.plugin._get_endpoint() # Assert assert_equal(ep, None) self.plugin._client.get_endpoint.assert_called_once_with( hostname=ANY, orchestrator_id="cni", workload_id=self.plugin.container_id ) def test_get_endpoint_multiple_endpoints(self): # Mock self.plugin._client.get_endpoint.side_effect = MultipleEndpointsMatch # Call with assert_raises(SystemExit) as err: self.plugin._get_endpoint() e = err.exception assert_equal(e.code, ERR_CODE_GENERIC) # Assert self.plugin._client.get_endpoint.assert_called_once_with( hostname=ANY, orchestrator_id="cni", workload_id=self.plugin.container_id ) @patch("calico_cni.calico_cni.os", autospec=True) def test_find_ipam_plugin(self, m_os): # Mock m_os.path.isfile.side_effect = iter([False, True]) # Second time returns true. m_os.path.join.side_effect = lambda x, y: x + y m_os.path.abspath.side_effect = lambda x: x self.plugin.cni_path = "/opt/bin/cni/:/opt/cni/bin/" # Call path = self.plugin._find_ipam_plugin() # Assert assert_equal(path, "/opt/cni/bin/calico-ipam") @patch("calico_cni.calico_cni.os", autospec=True) @patch("calico_cni.calico_cni.sys", autospec=True) @patch("calico_cni.calico_cni.CniPlugin", autospec=True) @patch("calico_cni.calico_cni.configure_logging", autospec=True) def test_main(self, m_conf_log, m_plugin, m_sys, m_os): # Mock m_os.environ = self.env m_sys.stdin.readlines.return_value = json.dumps(self.network_config) m_plugin(self.env, self.network_config).execute.return_value = 0 m_plugin.reset_mock() # Call main() # Assert m_plugin.assert_called_once_with(self.network_config, self.env) m_conf_log.assert_called_once_with(ANY, "cni.log", log_level="INFO") m_sys.exit.assert_called_once_with(0)