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_activity_name_is_logged_correctly_when_function_not_exposed_in_module( ): invalid_python_func_probe = { "name": "hello", "type": "probe", "provider": { "type": "python", "module": "os", "func": "whatever" }, } with pytest.raises(InvalidActivity) as x: validate_python_activity(invalid_python_func_probe) assert str(x.value) == ( "The python module 'os' does not expose a function called 'whatever' in probe" " 'hello'")
def ensure_activity_is_valid(activity: Activity): """ Goes through the activity and checks certain of its properties and raise :exc:`InvalidActivity` whenever one does not respect the expectations. An activity must at least take the following key: * `"type"` the kind of activity, one of `"python"`, `"process"` or `"http"` Depending on the type, an activity requires a variety of other keys. In all failing cases, raises :exc:`InvalidActivity`. """ if not activity: raise InvalidActivity("empty activity is no activity") # when the activity is just a ref, there is little to validate ref = activity.get("ref") if ref is not None: if not isinstance(ref, str) or ref == '': raise InvalidActivity( "reference to activity must be non-empty strings") return activity_type = activity.get("type") if not activity_type: raise InvalidActivity("an activity must have a type") if activity_type not in ("probe", "action"): raise InvalidActivity( "'{t}' is not a supported activity type".format(t=activity_type)) if not activity.get("name"): raise InvalidActivity("an activity must have a name") provider = activity.get("provider") if not provider: raise InvalidActivity("an activity requires a provider") provider_type = provider.get("type") if not provider_type: raise InvalidActivity("a provider must have a type") if provider_type not in ("python", "process", "http"): raise InvalidActivity( "unknown provider type '{type}'".format(type=provider_type)) if not activity.get("name"): raise InvalidActivity("activity must have a name (cannot be empty)") timeout = activity.get("timeout") if timeout is not None: if not isinstance(timeout, numbers.Number): raise InvalidActivity("activity timeout must be a number") pauses = activity.get("pauses") if pauses is not None: before = pauses.get("before") if before is not None and not isinstance(before, numbers.Number): raise InvalidActivity("activity before pause must be a number") after = pauses.get("after") if after is not None and not isinstance(after, numbers.Number): raise InvalidActivity("activity after pause must be a number") if "background" in activity: if not isinstance(activity["background"], bool): raise InvalidActivity("activity background must be a boolean") if provider_type == "python": validate_python_activity(activity) elif provider_type == "process": validate_process_activity(activity) elif provider_type == "http": validate_http_activity(activity)