def test_exec_in_pods_invalid_order(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" container2 = MagicMock() container2.name = "container2" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1, container2] pod2 = MagicMock() pod2.metadata.name = "my-app-2" pod2.spec.containers = [container1, container2] result = MagicMock() result.items = [pod1, pod2] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() with pytest.raises(ActivityFailed) as excinfo: exec_in_pods(name_pattern="my-app-[0-9]$", order="bad_order", cmd="dummy -a -b -c", container_name="container1", qty=2, rand=True) assert "Cannot select pods. Order 'bad_order' is invalid." in str(excinfo.value) assert stream.stream.call_count == 0
def test_exec_in_pods_return_value(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" container2 = MagicMock() container2.name = "container2" container2.metadata.labels = {"dummy_label1": "dummy_value1", "dummy_label1": "dummy_value2"} pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1, container2] pod2 = MagicMock() pod2.metadata.name = "my-app-2" pod2.spec.containers = [container1, container2] result = MagicMock() result.items = [pod1] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.return_value = '{"status":"Success"}' exec_in_pods(label_selector="dummy_label1=dummy_value1", cmd="dummy -a -b -c", container_name="container1", qty=2, rand=True) assert stream.stream.call_count == 1
def test_exec_in_pods_no_pod_found_with_name(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" container2 = MagicMock() container2.name = "container2" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1, container2] pod2 = MagicMock() pod2.metadata.name = "my-app-2" pod2.spec.containers = [container1, container2] result = MagicMock() result.items = [pod1, pod2] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() exec_in_pods(name_pattern="no-app-[0-9]$", cmd="dummy -a -b -c", container_name="container1", qty=2, rand=True) assert stream.stream.call_count == 0
def test_exec_in_pods_cmd_as_string(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1] result = MagicMock() result.items = [pod1] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.return_value = '{"status":"Success"}' exec_in_pods( name_pattern="my-app-1", cmd="dummy -a -b -c", container_name="container1", ) assert stream.stream.call_count == 1 assert stream.stream.call_args[1]["command"] == ["dummy", "-a", "-b", "-c"]
def test_exec_in_pods_no_command_provided(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" container2 = MagicMock() container2.name = "container2" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1, container2] pod2 = MagicMock() pod2.metadata.name = "my-app-2" pod2.spec.containers = [container1, container2] result = MagicMock() result.items = [pod1, pod2] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() with pytest.raises(InvalidActivity) as expinfo: validate_python_activity({ "name": "run-in-pod", "type": "action", "provider": { "type": "python", "module": "chaosk8s.pod.actions", "func": "exec_in_pods", "arguments": dict( name_pattern="my-app-[0-9]$", container_name="container1", qty=2, rand=True ) } }) with pytest.raises(ActivityFailed) as expinfo: exec_in_pods( cmd=None, name_pattern="my-app-[0-9]$", container_name="container1", qty=2, rand=True ) assert "A command must be set to run a container" in str(expinfo.value) assert stream.stream.call_count == 0
def test_exec_in_pods_cmd_as_list(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1] result = MagicMock() result.items = [pod1] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.side_effect = [ "hello", '{"status":"Success"}', ] command = ["dummy", "-l", "Long and 'complex'"] result = exec_in_pods( name_pattern="my-app-1", cmd=command, container_name="container1", ) assert stream.stream.call_count == 1 assert stream.stream.call_args[1]["command"] == command assert result[0]["exit_code"] == 0
def test_exec_in_pods_cmd_as_shlex(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1] result = MagicMock() result.items = [pod1] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.return_value = '{"status":"Success"}' command = "/bin/sh -c ls" result = exec_in_pods( name_pattern="my-app-1", cmd=command, container_name="container1", ) assert stream.stream.call_count == 1 assert stream.stream.call_args[1]["command"] == ["/bin/sh", "-c", "ls"] assert result[0]["exit_code"] == 0
def test_exec_in_pods_stderr_sometimes_not_json(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1] result = MagicMock() result.items = [pod1] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.return_value = "BOOM" result = exec_in_pods( name_pattern="my-app-1", cmd="dummy -a -b -c", container_name="container1", ) assert stream.stream.call_count == 1 assert stream.stream.call_args[1]["command"] == ["dummy", "-a", "-b", "-c"] assert result[0]["exit_code"] == 1 assert result[0]["stderr"] == "BOOM"
def test_exec_in_pods_by_name_pattern_rand(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" container2 = MagicMock() container2.name = "container2" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1, container2] pod2 = MagicMock() pod2.metadata.name = "my-app-2" pod2.spec.containers = [container1, container2] pod3 = MagicMock() pod3.metadata.name = "my-app-3" pod3.spec.containers = [container1, container2] pod4 = MagicMock() pod4.metadata.name = "my-app-test-1" pod4.spec.containers = [container1, container2] result = MagicMock() result.items = [pod1, pod2, pod3, pod4] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.return_value = '{"status":"Success"}' exec_in_pods( name_pattern="my-app-[0-9]$", cmd="dummy -a -b -c", container_name="container2", qty=3, rand=True, ) assert stream.stream.call_count == 3
def test_exec_in_pods_order_by_oldest(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" container2 = MagicMock() container2.name = "container2" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.metadata.creation_timestamp = "2019-11-25T13:50:31Z" pod1.spec.containers = [container1, container2] pod2 = MagicMock() pod2.metadata.name = "my-app-2" pod2.metadata.creation_timestamp = "2019-11-25T13:55:00Z" pod2.spec.containers = [container1, container2] result = MagicMock() result.items = [pod1, pod2] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.return_value = '{"status":"Success"}' exec_in_pods(name_pattern="my-app-[0-9]$", order="oldest", cmd="dummy -a -b -c", container_name="container1", qty=2, rand=True) assert stream.stream.call_count == 2
def test_exec_in_pods_stderr_can_be_json(cl, client, has_conf): has_conf.return_value = False container1 = MagicMock() container1.name = "container1" pod1 = MagicMock() pod1.metadata.name = "my-app-1" pod1.spec.containers = [container1] result = MagicMock() result.items = [pod1] v1 = MagicMock() v1.list_namespaced_pod.return_value = result client.CoreV1Api.return_value = v1 stream.stream = MagicMock() stream.stream.return_value.read_channel = MagicMock() stream.stream.return_value.read_channel.return_value = json.dumps({ "status": "Error", "message": "failed", "details": { "causes": [{ "message": 2 }] }, }) result = exec_in_pods( name_pattern="my-app-1", cmd="dummy -a -b -c", container_name="container1", ) assert stream.stream.call_count == 1 assert stream.stream.call_args[1]["command"] == ["dummy", "-a", "-b", "-c"] assert result[0]["exit_code"] == 2 assert result[0]["stderr"] == "failed"