From 361324eebbfd98be0d56d80812c0ba6710fcb49a Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Tue, 20 Apr 2021 16:34:44 -0400 Subject: [PATCH 01/37] removed repr_model, replaced with api_model --- gremlinapi/attack_helpers.py | 78 ++++++++++++++-------------- gremlinapi/scenario_graph_helpers.py | 22 ++++---- tests/test_attack_helpers.py | 72 ++++++++++++------------- tests/test_scenario_graph_helpers.py | 20 +++---- 4 files changed, 96 insertions(+), 96 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index c74970a..172cd39 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -32,7 +32,7 @@ def __init__(self, *args: tuple, **kwargs: dict): self.strategy_type = kwargs.get("strategy_type", "random") # type: ignore def target_definition(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _target_definition: dict = { "strategyType": self.strategy_type, "strategy": dict(), @@ -60,7 +60,7 @@ def target_definition(self) -> dict: return _target_definition def target_definition_graph(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _target_definition: dict = { "strategy_type": self.strategy_type, "strategy": dict(), @@ -144,7 +144,7 @@ def strategy_type(self, _target_type: str = None) -> None: _target_type.lower(), None ) - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = dict() model["type"] = self.strategy_type if self.exact >= 0 and not self.percent: @@ -158,7 +158,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -183,7 +183,7 @@ def __init__(self, *args: tuple, **kwargs: dict): self.length = kwargs.get("length", 60) # type: ignore def impact_definition(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _impact_definition: dict = { "commandArgs": {"cliArgs": [str(self.shortType)], "length": self.length}, "commandType": str(self.shortType), @@ -192,7 +192,7 @@ def impact_definition(self) -> dict: return _impact_definition def impact_definition_graph(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _impact_definition: dict = { "infra_command_args": { "cli_args": [str(self.shortType)], @@ -260,7 +260,7 @@ def shortType(self, _shortType: str = None) -> None: self._commandType = self._typeMap[_shortType] self._shortType = _shortType - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = { "type": self.shortType, "commandType": self.commandType, @@ -269,7 +269,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -316,7 +316,7 @@ def target(self, _target: GremlinAttackTargetHelper) -> None: raise GremlinCommandTargetError(error_msg) self._target = _target - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = { "target": json.loads(str(self.target)), "command": json.loads(str(self.command)), @@ -324,7 +324,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -450,8 +450,8 @@ def _valid_tag_pair(self, tagKey: str = None, tagValue: str = None) -> bool: return True return False - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.target_all_hosts: model["hosts"] = "all" else: @@ -617,8 +617,8 @@ def _valid_label_pair(self, labelKey: Any = None, labelValue: Any = None) -> boo return True return False - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.target_all_containers: model["containers"] = "all" else: @@ -918,8 +918,8 @@ def tags(self, _tags: Union[list, dict] = None) -> None: self._ids = [] self.target_all_hosts = False - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.device: model["args"].extend(["-d", self.device]) if len(self.ips) > 0: @@ -996,8 +996,8 @@ def cores(self, _cores: int = None) -> None: raise GremlinParameterError(error_msg) self._cores = _cores - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-p", str(self.capacity)]) if self.all_cores: model["args"].append("-a") @@ -1070,8 +1070,8 @@ def amountType(self, _amountType: str = None) -> None: raise GremlinParameterError(error_msg) self._amountType = _amountType.upper() - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.amountType == "MB": model["args"].extend(["-m", str(self.amount)]) elif self.amountType == "GB": @@ -1093,7 +1093,7 @@ def repr_model(self) -> dict: # elif self.amountType == '%': # model['args'].extend(['-p', str(self.amount)]) # else: - # error_msg = f'Fatal error, repr_model model may be corrupted, amountType: {self._amountType} is not valid' + # error_msg = f'Fatal error, api_model model may be corrupted, amountType: {self._amountType} is not valid' # log.fatal(error_msg) # raise GremlinParameterError(error_msg) # return json.dumps(model) @@ -1108,8 +1108,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self.percent: int = kwargs.get("percent", 100) # type: ignore self.workers: int = kwargs.get("workers", 1) # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-d", str(self.directory)]) model["args"].extend(["-w", str(self.workers)]) model["args"].extend(["-b", str(self.blocksize)]) @@ -1163,8 +1163,8 @@ def mode(self, _mode: str = None) -> None: raise GremlinParameterError(error_msg) self._mode = _mode.lower() - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-c", str(self.blockcount)]) model["args"].extend(["-d", self.directory]) model["args"].extend(["-m", self.mode]) @@ -1215,8 +1215,8 @@ def reboot(self, _reboot: bool = None) -> None: raise GremlinParameterError(error_msg) self._reboot = _reboot - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"] = ["-d", str(self.delay)] if self.reboot: model["args"].append("-r") @@ -1376,8 +1376,8 @@ def user(self, _user: str = None) -> None: log.error(error_msg) raise GremlinParameterError(error_msg) - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-i", str(self.interval)]) if self.group: model["args"].extend(["-g", self.group]) @@ -1460,8 +1460,8 @@ def offset(self, offset: int = None) -> None: raise GremlinParameterError(error_msg) self._offset = offset - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-o", str(self.offset)]) if self.block_ntp: model["args"].append("-n") @@ -1483,8 +1483,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self.hostnames: str = kwargs.get("hostnames", "^api.gremlin.com") # type: ignore self.ingress_ports: list = kwargs.get("ingress_ports", []) # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if len(self.egress_ports) > 0: model["args"].extend(["-p", ",".join(self.egress_ports)]) if len(self.hostnames) > 0: @@ -1511,8 +1511,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self._allowed_protocols: list = ["TCP", "UDP"] self.protocol: str = kwargs.get("protocol", "") # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() return model # def __repr__(self): @@ -1542,8 +1542,8 @@ def delay(self, _delay: int = None) -> None: raise GremlinParameterError(error_msg) self._delay = _delay - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-m", str(self.delay)]) if len(self.egress_ports) > 0: model["args"].extend(["-p", ",".join(self.egress_ports)]) @@ -1606,8 +1606,8 @@ def percent(self, _percent: int = None) -> None: raise GremlinParameterError(error_msg) self._percent = _percent - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-r", str(self.percent)]) if len(self.egress_ports) > 0: model["args"].extend(["-p", ",".join(self.egress_ports)]) diff --git a/gremlinapi/scenario_graph_helpers.py b/gremlinapi/scenario_graph_helpers.py index d37c047..f87282c 100644 --- a/gremlinapi/scenario_graph_helpers.py +++ b/gremlinapi/scenario_graph_helpers.py @@ -73,7 +73,7 @@ def add_edge(self, _node: "GremlinScenarioNode", _weight: str = None) -> None: @property def data(self) -> dict: - return self.repr_model() + return self.api_model() @property def id(self) -> str: @@ -151,7 +151,7 @@ def uuid(self) -> str: raise GremlinParameterError(error_msg) return f"{self.name}-{self.id}" - def repr_model(self) -> dict: + def api_model(self) -> dict: model = { "type": self.node_type, "guid": self.uuid, @@ -161,7 +161,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.repr_model) + return json.dumps(self.api_model) class GremlinScenarioGraphHelper(object): @@ -339,7 +339,7 @@ def name(self, _name: str = None) -> None: raise GremlinParameterError(error_msg) self._name = _name - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = { "description": self.description, "hypothesis": self.hypothesis, @@ -356,7 +356,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -427,8 +427,8 @@ def command(self, _command: GremlinAttackCommandHelper) -> None: raise GremlinParameterError(error_msg) self._command = _command - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["impact_definition"] = self.command.impact_definition_graph() model["target_definition"] = self.target.target_definition_graph() return model @@ -466,8 +466,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self._delay: int = kwargs.get("delay", None) # type: ignore self.node_type: str = "Delay" - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["delay"] = self.delay return model @@ -513,8 +513,8 @@ def __init__( "evaluation_response_body_evaluation", "" ) # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["endpointConfiguration"] = { "url": self.endpoint_url, "headers": self.endpoint_headers, diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 16011a0..8bfda1d 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -39,7 +39,7 @@ class TestAttackHelpers(unittest.TestCase): - def test_attack_helper_repr_model(self) -> None: + def test_attack_helper_api_model(self) -> None: # defaults expected_output = { "command": { @@ -50,7 +50,7 @@ def test_attack_helper_repr_model(self) -> None: "target": {"hosts": "all", "percent": 10, "type": "Random"}, } helper = GremlinAttackHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) def test_target_helper_target_definition(self) -> None: @@ -93,11 +93,11 @@ def test_target_helper_target_definition_graph(self) -> None: } self.assertEqual(test_output, expected_output) - def test_attack_target_helper_repr_model(self) -> None: + def test_attack_target_helper_api_model(self) -> None: # defaults expected_output = {"percent": 10, "type": "Random"} helper = GremlinAttackTargetHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) @patch("requests.get") @@ -118,11 +118,11 @@ def mock_json(): helper._filter_active_tags() self.assertEqual(helper._active_tags, expected_output) - def test_target_hosts_repr_model(self) -> None: + def test_target_hosts_api_model(self) -> None: # defaults expected_output = {"hosts": "all", "percent": 10, "type": "Random"} helper = GremlinTargetHosts() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) @patch("requests.get") @@ -141,11 +141,11 @@ def mock_json(): helper._filter_active_labels() self.assertEqual(helper._active_labels, expected_output) - def test_target_containers_repr_model(self) -> None: + def test_target_containers_api_model(self) -> None: # defaults expected_output = {"containers": "all", "percent": 10, "type": "Random"} helper = GremlinTargetContainers() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) def test_impact_definition(self) -> None: @@ -175,18 +175,18 @@ def test_impact_definition_graph(self) -> None: helper_output = helper.impact_definition_graph() self.assertEqual(helper_output, expected_output) - def test_attack_command_helper_repr_model(self) -> None: + def test_attack_command_helper_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "", "type": ""} helper = GremlinAttackCommandHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_resource_attack_helper_repr_model(self) -> None: + def test_resource_attack_helper_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "", "type": ""} helper = GremlinResourceAttackHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) def test__port_maker(self) -> None: @@ -205,14 +205,14 @@ def test__port_maker(self) -> None: helper_output = helper._port_maker(expected_output) self.assertEqual(expected_output, helper_output) - def test_network_attack_helper_repr_model(self) -> None: + def test_network_attack_helper_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "", "type": ""} helper = GremlinNetworkAttackHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_cpu_attack_repr_model(self) -> None: + def test_cpu_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-p", "100", "-c", "1"], @@ -220,10 +220,10 @@ def test_cpu_attack_repr_model(self) -> None: "type": "cpu", } helper = GremlinCPUAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_memory_attack_repr_model(self) -> None: + def test_memory_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-p", "100"], @@ -231,10 +231,10 @@ def test_memory_attack_repr_model(self) -> None: "type": "memory", } helper = GremlinMemoryAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_disk_space_attack_repr_model(self) -> None: + def test_disk_space_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-d", "/tmp", "-w", "1", "-b", "4", "-p", "100"], @@ -242,10 +242,10 @@ def test_disk_space_attack_repr_model(self) -> None: "type": "disk", } helper = GremlinDiskSpaceAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_disk_io_repr_model(self) -> None: + def test_disk_io_api_model(self) -> None: # defaults expected_output = { "args": [ @@ -266,10 +266,10 @@ def test_disk_io_repr_model(self) -> None: "type": "io", } helper = GremlinDiskIOAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_shutdown_attack_repr_model(self) -> None: + def test_shutdown_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-d", "1"], @@ -277,10 +277,10 @@ def test_shutdown_attack_repr_model(self) -> None: "type": "shutdown", } helper = GremlinShutdownAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_process_killer_attack_repr_model(self) -> None: + def test_process_killer_attack_api_model(self) -> None: test_process = "ls" kwargs = {"process": test_process} # defaults @@ -290,10 +290,10 @@ def test_process_killer_attack_repr_model(self) -> None: "type": "process_killer", } helper = GremlinProcessKillerAttack(**kwargs) - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_time_travel_attack_repr_model(self) -> None: + def test_time_travel_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-o", "86400"], @@ -301,10 +301,10 @@ def test_time_travel_attack_repr_model(self) -> None: "type": "time_travel", } helper = GremlinTimeTravelAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_black_hole_attack_repr_model(self) -> None: + def test_black_hole_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-p", "^53", "-h", "^api.gremlin.com"], @@ -312,17 +312,17 @@ def test_black_hole_attack_repr_model(self) -> None: "type": "blackhole", } helper = GremlinBlackholeAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_dns_attack_repr_model(self) -> None: + def test_dns_attack_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "DNS", "type": "dns"} helper = GremlinDNSAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_latency_attack_repr_model(self) -> None: + def test_latency_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-m", "100", "-p", "^53", "-h", "^api.gremlin.com"], @@ -330,10 +330,10 @@ def test_latency_attack_repr_model(self) -> None: "type": "latency", } helper = GremlinLatencyAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_packet_loss_attack_repr_model(self) -> None: + def test_packet_loss_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-r", "1", "-p", "^53", "-h", "^api.gremlin.com"], @@ -341,5 +341,5 @@ def test_packet_loss_attack_repr_model(self) -> None: "type": "packet_loss", } helper = GremlinPacketLossAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) diff --git a/tests/test_scenario_graph_helpers.py b/tests/test_scenario_graph_helpers.py index 7d42d12..5dcf4ce 100644 --- a/tests/test_scenario_graph_helpers.py +++ b/tests/test_scenario_graph_helpers.py @@ -28,7 +28,7 @@ def test_add_node(self) -> None: self.assertEqual(helper._nodes.get_node(helper_node.id), helper_node) self.assertNotEqual(helper._nodes.get_node(helper_node.id), helper_node_2) - def test_gremlin_scenario_graph_helper_repr_model(self) -> None: + def test_gremlin_scenario_graph_helper_api_model(self) -> None: status_check_description = "Check if Gremlin.com is Still Up" endpoint_url = "https://www.google.com" endpoint_headers = dict() @@ -143,10 +143,10 @@ def test_gremlin_scenario_graph_helper_repr_model(self) -> None: "hypothesis": "No Hypothesis", "name": "code_created_scenario_6", } - self.assertEqual(my_scenario.repr_model(), expected_output) + self.assertEqual(my_scenario.api_model(), expected_output) self.maxDiff = t_diff - def test_gremlin_scenario_graph_helper_repr_model_default_add_node(self) -> None: + def test_gremlin_scenario_graph_helper_api_model_default_add_node(self) -> None: status_check_description = "Check if Gremlin.com is Still Up" endpoint_url = "https://www.google.com" endpoint_headers = dict() @@ -258,7 +258,7 @@ def test_gremlin_scenario_graph_helper_repr_model_default_add_node(self) -> None "hypothesis": "No Hypothesis", "name": "code_created_scenario_6", } - self.assertEqual(my_scenario.repr_model(), expected_output) + self.assertEqual(my_scenario.api_model(), expected_output) self.maxDiff = t_diff def test_add_edge(self) -> None: @@ -272,7 +272,7 @@ def test_add_edge(self) -> None: self.assertEqual(len(helper._edges), 1) self.assertEqual(helper._edges[helper_2.id]["node"], helper_2) - def test_gremlin_scenario_node_repr_model(self) -> None: + def test_gremlin_scenario_node_api_model(self) -> None: helper = GremlinScenarioNode(**mock_scenario) expected_output = { "guid": "mock_scenario-%s" % helper.id, @@ -281,7 +281,7 @@ def test_gremlin_scenario_node_repr_model(self) -> None: "type": helper.node_type, } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) def test_gremlin_scenario_ilfi_node_repr_node(self) -> None: helper = GremlinScenarioILFINode(**mock_ilfi_node) @@ -301,7 +301,7 @@ def test_gremlin_scenario_ilfi_node_repr_node(self) -> None: "type": "InfraAttack", } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) def test_gremlin_scenario_delay_node_repr_node(self) -> None: helper = GremlinScenarioDelayNode(**mock_delay_node) @@ -313,9 +313,9 @@ def test_gremlin_scenario_delay_node_repr_node(self) -> None: "type": "Delay", } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) - def test_gremlin_scenario_status_check_node_repr_model(self) -> None: + def test_gremlin_scenario_status_check_node_api_model(self) -> None: helper = GremlinScenarioStatusCheckNode(**mock_status_check_node) expected_output = { "endpointConfiguration": { @@ -335,7 +335,7 @@ def test_gremlin_scenario_status_check_node_repr_model(self) -> None: "thirdPartyPresets": "PythonSDK", "type": "SynchronousStatusCheck", } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) def test_node_graph_add_edge(self) -> None: helper = _GremlinNodeGraph() From 6ea17565fc4575bc0d720289c66f881e7b199620 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Tue, 20 Apr 2021 16:35:08 -0400 Subject: [PATCH 02/37] =?UTF-8?q?Bump=20version:=200.12.2=20=E2=86=92=200.?= =?UTF-8?q?13.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 5608835..dfa6976 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.12.2 +current_version = 0.13.2 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 3beea49..32d43f8 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.12.2" +_version = "0.13.2" def get_version(): From abd2eb76d994c51229488e41af0bf542c9d1e5ca Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Tue, 20 Apr 2021 16:34:44 -0400 Subject: [PATCH 03/37] removed repr_model, replaced with api_model --- gremlinapi/attack_helpers.py | 78 ++++++++++++++-------------- gremlinapi/scenario_graph_helpers.py | 22 ++++---- tests/test_attack_helpers.py | 72 ++++++++++++------------- tests/test_scenario_graph_helpers.py | 20 +++---- 4 files changed, 96 insertions(+), 96 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index c74970a..172cd39 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -32,7 +32,7 @@ def __init__(self, *args: tuple, **kwargs: dict): self.strategy_type = kwargs.get("strategy_type", "random") # type: ignore def target_definition(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _target_definition: dict = { "strategyType": self.strategy_type, "strategy": dict(), @@ -60,7 +60,7 @@ def target_definition(self) -> dict: return _target_definition def target_definition_graph(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _target_definition: dict = { "strategy_type": self.strategy_type, "strategy": dict(), @@ -144,7 +144,7 @@ def strategy_type(self, _target_type: str = None) -> None: _target_type.lower(), None ) - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = dict() model["type"] = self.strategy_type if self.exact >= 0 and not self.percent: @@ -158,7 +158,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -183,7 +183,7 @@ def __init__(self, *args: tuple, **kwargs: dict): self.length = kwargs.get("length", 60) # type: ignore def impact_definition(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _impact_definition: dict = { "commandArgs": {"cliArgs": [str(self.shortType)], "length": self.length}, "commandType": str(self.shortType), @@ -192,7 +192,7 @@ def impact_definition(self) -> dict: return _impact_definition def impact_definition_graph(self) -> dict: - model: dict = self.repr_model() + model: dict = self.api_model() _impact_definition: dict = { "infra_command_args": { "cli_args": [str(self.shortType)], @@ -260,7 +260,7 @@ def shortType(self, _shortType: str = None) -> None: self._commandType = self._typeMap[_shortType] self._shortType = _shortType - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = { "type": self.shortType, "commandType": self.commandType, @@ -269,7 +269,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -316,7 +316,7 @@ def target(self, _target: GremlinAttackTargetHelper) -> None: raise GremlinCommandTargetError(error_msg) self._target = _target - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = { "target": json.loads(str(self.target)), "command": json.loads(str(self.command)), @@ -324,7 +324,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -450,8 +450,8 @@ def _valid_tag_pair(self, tagKey: str = None, tagValue: str = None) -> bool: return True return False - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.target_all_hosts: model["hosts"] = "all" else: @@ -617,8 +617,8 @@ def _valid_label_pair(self, labelKey: Any = None, labelValue: Any = None) -> boo return True return False - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.target_all_containers: model["containers"] = "all" else: @@ -918,8 +918,8 @@ def tags(self, _tags: Union[list, dict] = None) -> None: self._ids = [] self.target_all_hosts = False - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.device: model["args"].extend(["-d", self.device]) if len(self.ips) > 0: @@ -996,8 +996,8 @@ def cores(self, _cores: int = None) -> None: raise GremlinParameterError(error_msg) self._cores = _cores - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-p", str(self.capacity)]) if self.all_cores: model["args"].append("-a") @@ -1070,8 +1070,8 @@ def amountType(self, _amountType: str = None) -> None: raise GremlinParameterError(error_msg) self._amountType = _amountType.upper() - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if self.amountType == "MB": model["args"].extend(["-m", str(self.amount)]) elif self.amountType == "GB": @@ -1093,7 +1093,7 @@ def repr_model(self) -> dict: # elif self.amountType == '%': # model['args'].extend(['-p', str(self.amount)]) # else: - # error_msg = f'Fatal error, repr_model model may be corrupted, amountType: {self._amountType} is not valid' + # error_msg = f'Fatal error, api_model model may be corrupted, amountType: {self._amountType} is not valid' # log.fatal(error_msg) # raise GremlinParameterError(error_msg) # return json.dumps(model) @@ -1108,8 +1108,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self.percent: int = kwargs.get("percent", 100) # type: ignore self.workers: int = kwargs.get("workers", 1) # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-d", str(self.directory)]) model["args"].extend(["-w", str(self.workers)]) model["args"].extend(["-b", str(self.blocksize)]) @@ -1163,8 +1163,8 @@ def mode(self, _mode: str = None) -> None: raise GremlinParameterError(error_msg) self._mode = _mode.lower() - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-c", str(self.blockcount)]) model["args"].extend(["-d", self.directory]) model["args"].extend(["-m", self.mode]) @@ -1215,8 +1215,8 @@ def reboot(self, _reboot: bool = None) -> None: raise GremlinParameterError(error_msg) self._reboot = _reboot - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"] = ["-d", str(self.delay)] if self.reboot: model["args"].append("-r") @@ -1376,8 +1376,8 @@ def user(self, _user: str = None) -> None: log.error(error_msg) raise GremlinParameterError(error_msg) - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-i", str(self.interval)]) if self.group: model["args"].extend(["-g", self.group]) @@ -1460,8 +1460,8 @@ def offset(self, offset: int = None) -> None: raise GremlinParameterError(error_msg) self._offset = offset - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-o", str(self.offset)]) if self.block_ntp: model["args"].append("-n") @@ -1483,8 +1483,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self.hostnames: str = kwargs.get("hostnames", "^api.gremlin.com") # type: ignore self.ingress_ports: list = kwargs.get("ingress_ports", []) # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() if len(self.egress_ports) > 0: model["args"].extend(["-p", ",".join(self.egress_ports)]) if len(self.hostnames) > 0: @@ -1511,8 +1511,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self._allowed_protocols: list = ["TCP", "UDP"] self.protocol: str = kwargs.get("protocol", "") # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() return model # def __repr__(self): @@ -1542,8 +1542,8 @@ def delay(self, _delay: int = None) -> None: raise GremlinParameterError(error_msg) self._delay = _delay - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-m", str(self.delay)]) if len(self.egress_ports) > 0: model["args"].extend(["-p", ",".join(self.egress_ports)]) @@ -1606,8 +1606,8 @@ def percent(self, _percent: int = None) -> None: raise GremlinParameterError(error_msg) self._percent = _percent - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["args"].extend(["-r", str(self.percent)]) if len(self.egress_ports) > 0: model["args"].extend(["-p", ",".join(self.egress_ports)]) diff --git a/gremlinapi/scenario_graph_helpers.py b/gremlinapi/scenario_graph_helpers.py index d37c047..f87282c 100644 --- a/gremlinapi/scenario_graph_helpers.py +++ b/gremlinapi/scenario_graph_helpers.py @@ -73,7 +73,7 @@ def add_edge(self, _node: "GremlinScenarioNode", _weight: str = None) -> None: @property def data(self) -> dict: - return self.repr_model() + return self.api_model() @property def id(self) -> str: @@ -151,7 +151,7 @@ def uuid(self) -> str: raise GremlinParameterError(error_msg) return f"{self.name}-{self.id}" - def repr_model(self) -> dict: + def api_model(self) -> dict: model = { "type": self.node_type, "guid": self.uuid, @@ -161,7 +161,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.repr_model) + return json.dumps(self.api_model) class GremlinScenarioGraphHelper(object): @@ -339,7 +339,7 @@ def name(self, _name: str = None) -> None: raise GremlinParameterError(error_msg) self._name = _name - def repr_model(self) -> dict: + def api_model(self) -> dict: model: dict = { "description": self.description, "hypothesis": self.hypothesis, @@ -356,7 +356,7 @@ def repr_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.repr_model() + model: dict = self.api_model() return json.dumps(model) @@ -427,8 +427,8 @@ def command(self, _command: GremlinAttackCommandHelper) -> None: raise GremlinParameterError(error_msg) self._command = _command - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["impact_definition"] = self.command.impact_definition_graph() model["target_definition"] = self.target.target_definition_graph() return model @@ -466,8 +466,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self._delay: int = kwargs.get("delay", None) # type: ignore self.node_type: str = "Delay" - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["delay"] = self.delay return model @@ -513,8 +513,8 @@ def __init__( "evaluation_response_body_evaluation", "" ) # type: ignore - def repr_model(self) -> dict: - model: dict = super().repr_model() + def api_model(self) -> dict: + model: dict = super().api_model() model["endpointConfiguration"] = { "url": self.endpoint_url, "headers": self.endpoint_headers, diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 16011a0..8bfda1d 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -39,7 +39,7 @@ class TestAttackHelpers(unittest.TestCase): - def test_attack_helper_repr_model(self) -> None: + def test_attack_helper_api_model(self) -> None: # defaults expected_output = { "command": { @@ -50,7 +50,7 @@ def test_attack_helper_repr_model(self) -> None: "target": {"hosts": "all", "percent": 10, "type": "Random"}, } helper = GremlinAttackHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) def test_target_helper_target_definition(self) -> None: @@ -93,11 +93,11 @@ def test_target_helper_target_definition_graph(self) -> None: } self.assertEqual(test_output, expected_output) - def test_attack_target_helper_repr_model(self) -> None: + def test_attack_target_helper_api_model(self) -> None: # defaults expected_output = {"percent": 10, "type": "Random"} helper = GremlinAttackTargetHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) @patch("requests.get") @@ -118,11 +118,11 @@ def mock_json(): helper._filter_active_tags() self.assertEqual(helper._active_tags, expected_output) - def test_target_hosts_repr_model(self) -> None: + def test_target_hosts_api_model(self) -> None: # defaults expected_output = {"hosts": "all", "percent": 10, "type": "Random"} helper = GremlinTargetHosts() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) @patch("requests.get") @@ -141,11 +141,11 @@ def mock_json(): helper._filter_active_labels() self.assertEqual(helper._active_labels, expected_output) - def test_target_containers_repr_model(self) -> None: + def test_target_containers_api_model(self) -> None: # defaults expected_output = {"containers": "all", "percent": 10, "type": "Random"} helper = GremlinTargetContainers() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) def test_impact_definition(self) -> None: @@ -175,18 +175,18 @@ def test_impact_definition_graph(self) -> None: helper_output = helper.impact_definition_graph() self.assertEqual(helper_output, expected_output) - def test_attack_command_helper_repr_model(self) -> None: + def test_attack_command_helper_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "", "type": ""} helper = GremlinAttackCommandHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_resource_attack_helper_repr_model(self) -> None: + def test_resource_attack_helper_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "", "type": ""} helper = GremlinResourceAttackHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) def test__port_maker(self) -> None: @@ -205,14 +205,14 @@ def test__port_maker(self) -> None: helper_output = helper._port_maker(expected_output) self.assertEqual(expected_output, helper_output) - def test_network_attack_helper_repr_model(self) -> None: + def test_network_attack_helper_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "", "type": ""} helper = GremlinNetworkAttackHelper() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_cpu_attack_repr_model(self) -> None: + def test_cpu_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-p", "100", "-c", "1"], @@ -220,10 +220,10 @@ def test_cpu_attack_repr_model(self) -> None: "type": "cpu", } helper = GremlinCPUAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_memory_attack_repr_model(self) -> None: + def test_memory_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-p", "100"], @@ -231,10 +231,10 @@ def test_memory_attack_repr_model(self) -> None: "type": "memory", } helper = GremlinMemoryAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_disk_space_attack_repr_model(self) -> None: + def test_disk_space_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-d", "/tmp", "-w", "1", "-b", "4", "-p", "100"], @@ -242,10 +242,10 @@ def test_disk_space_attack_repr_model(self) -> None: "type": "disk", } helper = GremlinDiskSpaceAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_disk_io_repr_model(self) -> None: + def test_disk_io_api_model(self) -> None: # defaults expected_output = { "args": [ @@ -266,10 +266,10 @@ def test_disk_io_repr_model(self) -> None: "type": "io", } helper = GremlinDiskIOAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_shutdown_attack_repr_model(self) -> None: + def test_shutdown_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-d", "1"], @@ -277,10 +277,10 @@ def test_shutdown_attack_repr_model(self) -> None: "type": "shutdown", } helper = GremlinShutdownAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_process_killer_attack_repr_model(self) -> None: + def test_process_killer_attack_api_model(self) -> None: test_process = "ls" kwargs = {"process": test_process} # defaults @@ -290,10 +290,10 @@ def test_process_killer_attack_repr_model(self) -> None: "type": "process_killer", } helper = GremlinProcessKillerAttack(**kwargs) - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_time_travel_attack_repr_model(self) -> None: + def test_time_travel_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-o", "86400"], @@ -301,10 +301,10 @@ def test_time_travel_attack_repr_model(self) -> None: "type": "time_travel", } helper = GremlinTimeTravelAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_black_hole_attack_repr_model(self) -> None: + def test_black_hole_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-p", "^53", "-h", "^api.gremlin.com"], @@ -312,17 +312,17 @@ def test_black_hole_attack_repr_model(self) -> None: "type": "blackhole", } helper = GremlinBlackholeAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_dns_attack_repr_model(self) -> None: + def test_dns_attack_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "DNS", "type": "dns"} helper = GremlinDNSAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_latency_attack_repr_model(self) -> None: + def test_latency_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-m", "100", "-p", "^53", "-h", "^api.gremlin.com"], @@ -330,10 +330,10 @@ def test_latency_attack_repr_model(self) -> None: "type": "latency", } helper = GremlinLatencyAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - def test_packet_loss_attack_repr_model(self) -> None: + def test_packet_loss_attack_api_model(self) -> None: # defaults expected_output = { "args": ["-l", "60", "-r", "1", "-p", "^53", "-h", "^api.gremlin.com"], @@ -341,5 +341,5 @@ def test_packet_loss_attack_repr_model(self) -> None: "type": "packet_loss", } helper = GremlinPacketLossAttack() - helper_output = helper.repr_model() + helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) diff --git a/tests/test_scenario_graph_helpers.py b/tests/test_scenario_graph_helpers.py index 7d42d12..5dcf4ce 100644 --- a/tests/test_scenario_graph_helpers.py +++ b/tests/test_scenario_graph_helpers.py @@ -28,7 +28,7 @@ def test_add_node(self) -> None: self.assertEqual(helper._nodes.get_node(helper_node.id), helper_node) self.assertNotEqual(helper._nodes.get_node(helper_node.id), helper_node_2) - def test_gremlin_scenario_graph_helper_repr_model(self) -> None: + def test_gremlin_scenario_graph_helper_api_model(self) -> None: status_check_description = "Check if Gremlin.com is Still Up" endpoint_url = "https://www.google.com" endpoint_headers = dict() @@ -143,10 +143,10 @@ def test_gremlin_scenario_graph_helper_repr_model(self) -> None: "hypothesis": "No Hypothesis", "name": "code_created_scenario_6", } - self.assertEqual(my_scenario.repr_model(), expected_output) + self.assertEqual(my_scenario.api_model(), expected_output) self.maxDiff = t_diff - def test_gremlin_scenario_graph_helper_repr_model_default_add_node(self) -> None: + def test_gremlin_scenario_graph_helper_api_model_default_add_node(self) -> None: status_check_description = "Check if Gremlin.com is Still Up" endpoint_url = "https://www.google.com" endpoint_headers = dict() @@ -258,7 +258,7 @@ def test_gremlin_scenario_graph_helper_repr_model_default_add_node(self) -> None "hypothesis": "No Hypothesis", "name": "code_created_scenario_6", } - self.assertEqual(my_scenario.repr_model(), expected_output) + self.assertEqual(my_scenario.api_model(), expected_output) self.maxDiff = t_diff def test_add_edge(self) -> None: @@ -272,7 +272,7 @@ def test_add_edge(self) -> None: self.assertEqual(len(helper._edges), 1) self.assertEqual(helper._edges[helper_2.id]["node"], helper_2) - def test_gremlin_scenario_node_repr_model(self) -> None: + def test_gremlin_scenario_node_api_model(self) -> None: helper = GremlinScenarioNode(**mock_scenario) expected_output = { "guid": "mock_scenario-%s" % helper.id, @@ -281,7 +281,7 @@ def test_gremlin_scenario_node_repr_model(self) -> None: "type": helper.node_type, } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) def test_gremlin_scenario_ilfi_node_repr_node(self) -> None: helper = GremlinScenarioILFINode(**mock_ilfi_node) @@ -301,7 +301,7 @@ def test_gremlin_scenario_ilfi_node_repr_node(self) -> None: "type": "InfraAttack", } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) def test_gremlin_scenario_delay_node_repr_node(self) -> None: helper = GremlinScenarioDelayNode(**mock_delay_node) @@ -313,9 +313,9 @@ def test_gremlin_scenario_delay_node_repr_node(self) -> None: "type": "Delay", } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) - def test_gremlin_scenario_status_check_node_repr_model(self) -> None: + def test_gremlin_scenario_status_check_node_api_model(self) -> None: helper = GremlinScenarioStatusCheckNode(**mock_status_check_node) expected_output = { "endpointConfiguration": { @@ -335,7 +335,7 @@ def test_gremlin_scenario_status_check_node_repr_model(self) -> None: "thirdPartyPresets": "PythonSDK", "type": "SynchronousStatusCheck", } - self.assertEqual(helper.repr_model(), expected_output) + self.assertEqual(helper.api_model(), expected_output) def test_node_graph_add_edge(self) -> None: helper = _GremlinNodeGraph() From c353911449eb1d0e4eba36f26cccecc7ff1477b6 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Tue, 20 Apr 2021 16:35:08 -0400 Subject: [PATCH 04/37] =?UTF-8?q?Bump=20version:=200.12.2=20=E2=86=92=200.?= =?UTF-8?q?13.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index ab757e8..dfa6976 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.1 +current_version = 0.13.2 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index a9ed625..3688e34 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.1" +_version = "0.13.2" def get_version(): From 6f4ce4725f1768c6c42ca35cb3eb5494ff2cf0cf Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Tue, 20 Apr 2021 16:50:53 -0400 Subject: [PATCH 05/37] =?UTF-8?q?Bump=20version:=200.13.2=20=E2=86=92=200.?= =?UTF-8?q?13.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index dfa6976..1e2d153 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.2 +current_version = 0.13.3 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 3688e34..f25749c 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.2" +_version = "0.13.3" def get_version(): From e1dd985f881abe4b289c602c91bdcb006f40a1a1 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Tue, 20 Apr 2021 16:53:01 -0400 Subject: [PATCH 06/37] =?UTF-8?q?Bump=20version:=200.13.2=20=E2=86=92=200.?= =?UTF-8?q?13.3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index dfa6976..1e2d153 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.2 +current_version = 0.13.3 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 3688e34..f25749c 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.2" +_version = "0.13.3" def get_version(): From 8049bc5bbff1f1da9cd529d938fb5196a01b4dd4 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Tue, 20 Apr 2021 16:53:05 -0400 Subject: [PATCH 07/37] =?UTF-8?q?Bump=20version:=200.13.3=20=E2=86=92=200.?= =?UTF-8?q?13.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 1e2d153..100ef6d 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.3 +current_version = 0.13.4 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index f25749c..263ea04 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.3" +_version = "0.13.4" def get_version(): From cb1200b13578bdabd6c9215d36be58e7a43194b6 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 11:09:45 -0400 Subject: [PATCH 08/37] added __repr__ and __str__ stubs, and api_model to all objects --- gremlinapi/attack_helpers.py | 255 +++++++++++---------------- gremlinapi/scenario_graph_helpers.py | 79 ++++++++- 2 files changed, 177 insertions(+), 157 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 172cd39..c8246ee 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -158,8 +158,10 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.api_model() - return json.dumps(model) + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinAttackCommandHelper(object): @@ -269,8 +271,10 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.api_model() - return json.dumps(model) + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinAttackHelper(object): @@ -324,8 +328,10 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.api_model() - return json.dumps(model) + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinTargetHosts(GremlinAttackTargetHelper): @@ -461,20 +467,11 @@ def api_model(self) -> dict: model["hosts"] = {"multiSelectTags": self.tags} return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # if self.target_all_hosts: - # model['hosts'] = 'all' - # else: - # if len(self.ids) > 0: - # model['hosts'] = { - # 'ids': self.ids - # } - # elif len(self.tags) > 0: - # model['hosts'] = { - # 'multiSelectTags': self.tags - # } - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinTargetContainers(GremlinAttackTargetHelper): @@ -628,20 +625,11 @@ def api_model(self) -> dict: model["containers"] = {"multiSelectLabels": self.labels} return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # if self.target_all_containers: - # model['containers'] = 'all' - # else: - # if len(self.ids) > 0: - # model['containers'] = { - # 'ids': self.ids - # } - # elif len(self.labels) > 0: - # model['containers'] = { - # 'multiSelectLabels': self.labels - # } - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinResourceAttackHelper(GremlinAttackCommandHelper): @@ -700,11 +688,31 @@ def workers(self, _workers: int = None) -> None: raise GremlinParameterError(error_msg) self._workers = _workers + def api_model(self) -> dict: + model: dict = super().api_model() + return model + + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinStateAttackHelper(GremlinAttackCommandHelper): def __init__(self, *args: tuple, **kwargs: dict): super().__init__(*args, **kwargs) + def api_model(self) -> dict: + model: dict = super().api_model() + return model + + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinNetworkAttackHelper(GremlinAttackCommandHelper): def __init__(self, *args: tuple, **kwargs: dict): @@ -932,21 +940,11 @@ def api_model(self) -> dict: model["trafficImpactMapping"] = {"multiSelectTags": self.tags} return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # if self.device: - # model['args'].extend(['-d', self.device]) - # if len(self.ips) > 0: - # model['args'].extend(['-i', ','.join(self.ips)]) - # if self.protocol: - # model['args'].extend(['-P', self.protocol]) - # if self.providers and len(self.providers) > 0: - # model['providers'] = self.providers - # if self.tags and len(self.tags) > 0: - # model['trafficImpactMapping'] = { - # 'multiSelectTags': self.tags - # } - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinCPUAttack(GremlinResourceAttackHelper): @@ -1005,14 +1003,11 @@ def api_model(self) -> dict: model["args"].extend(["-c", str(self.cores)]) return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'].extend(['-p', str(self.capacity)]) - # if self.all_cores: - # model['args'].append('-a') - # else: - # model['args'].extend(['-c', str(self.cores)]) - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinMemoryAttack(GremlinResourceAttackHelper): @@ -1084,19 +1079,11 @@ def api_model(self) -> dict: raise GremlinParameterError(error_msg) return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # if self.amountType == 'MB': - # model['args'].extend(['-m', str(self.amount)]) - # elif self.amountType == 'GB': - # model['args'].extend(['-g', str(self.amount)]) - # elif self.amountType == '%': - # model['args'].extend(['-p', str(self.amount)]) - # else: - # error_msg = f'Fatal error, api_model model may be corrupted, amountType: {self._amountType} is not valid' - # log.fatal(error_msg) - # raise GremlinParameterError(error_msg) - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinDiskSpaceAttack(GremlinResourceAttackHelper): @@ -1116,13 +1103,11 @@ def api_model(self) -> dict: model["args"].extend(["-p", str(self.percent)]) return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'].expand(['-d', str(self.directory)]) - # model['args'].expand(['-w', str(self.workers)]) - # model['args'].expand(['-b', str(self.blocksize)]) - # model['args'].expand(['-p', str(self.percent)]) - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinDiskIOAttack(GremlinResourceAttackHelper): @@ -1172,14 +1157,11 @@ def api_model(self) -> dict: model["args"].extend(["-w", str(self.workers)]) return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'].extend(['-c', str(self.blockcount)]) - # model['args'].extend(['-d', self.directory]) - # model['args'].extend(['-m', self.mode]) - # model['args'].extend(['-s', str(self.blocksize)]) - # model['args'].extend(['-w', str(self.workers)]) - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinShutdownAttack(GremlinStateAttackHelper): @@ -1222,12 +1204,11 @@ def api_model(self) -> dict: model["args"].append("-r") return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'] = ['-d', str(self.delay)] - # if self.reboot: - # model['args'].append('-r') - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinProcessKillerAttack(GremlinStateAttackHelper): @@ -1401,30 +1382,11 @@ def api_model(self) -> dict: model["args"].append("-o") return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'].extend(['-i', str(self.interval)]) - # if self.group: - # model['args'].extend(['-g', self.group]) - # if self.process: - # model['args'].extend(['-p', self.process]) - # else: - # error_msg = f'process is required to a be a non-empty string' - # log.fatal(error_msg) - # raise GremlinParameterError(error_msg) - # if self.user: - # model['args'].extend(['-u', self.user]) - # if self.exact: - # model['args'].append('-e') - # if self.full_match: - # model['args'].append('-f') - # if self.kill_children: - # model['args'].append('-c') - # if self.target_newest and not self.target_oldest: - # model['args'].append('-n') - # if self.target_oldest and not self.target_newest: - # model['args'].append('-o') - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinTimeTravelAttack(GremlinStateAttackHelper): @@ -1467,12 +1429,11 @@ def api_model(self) -> dict: model["args"].append("-n") return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'].extend(['-o', str(self.offset)]) - # if self.block_ntp: - # model['args'].append('-n') - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinBlackholeAttack(GremlinNetworkAttackHelper): @@ -1494,14 +1455,10 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = json.loads(super().__repr__()) - if len(self.egress_ports) > 0: - model["args"].extend(["-p", ",".join(self.egress_ports)]) - if len(self.hostnames) > 0: - model["args"].extend(["-h", ",".join(self.hostnames)]) - if len(self.ingress_ports) > 0: - model["args"].extend(["-n", ",".join(self.ingress_ports)]) - return json.dumps(model) + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinDNSAttack(GremlinNetworkAttackHelper): @@ -1515,9 +1472,11 @@ def api_model(self) -> dict: model: dict = super().api_model() return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinLatencyAttack(GremlinNetworkAttackHelper): @@ -1553,16 +1512,11 @@ def api_model(self) -> dict: model["args"].extend(["-s", ",".join(self.source_ports)]) return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'].extend(['-m', str(self.delay)]) - # if len(self.egress_ports) > 0: - # model['args'].extend(['-p', ','.join(self.egress_ports)]) - # if len(self.hostnames) > 0: - # model['args'].extend(['-h', ','.join(self.hostnames)]) - # if len(self.source_ports) > 0: - # model['args'].extend(['-s', ','.join(self.source_ports)]) - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinPacketLossAttack(GremlinNetworkAttackHelper): @@ -1619,15 +1573,8 @@ def api_model(self) -> dict: model["args"].append("-c") return model - # def __repr__(self): - # model = json.loads(super().__repr__()) - # model['args'].extend(['-r', str(self.percent)]) - # if len(self.egress_ports) > 0: - # model['args'].extend(['-p', ','.join(self.egress_ports)]) - # if len(self.hostnames) > 0: - # model['args'].extend(['-h', ','.join(self.hostnames)]) - # if len(self.source_ports) > 0: - # model['args'].extend(['-s', ','.join(self.source_ports)]) - # if self.corrupt: - # model['args'].append('-c') - # return json.dumps(model) + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) diff --git a/gremlinapi/scenario_graph_helpers.py b/gremlinapi/scenario_graph_helpers.py index f87282c..2038c29 100644 --- a/gremlinapi/scenario_graph_helpers.py +++ b/gremlinapi/scenario_graph_helpers.py @@ -161,7 +161,10 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model) + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinScenarioGraphHelper(object): @@ -356,8 +359,10 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - model: dict = self.api_model() - return json.dumps(model) + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) class GremlinScenarioSerialNode(GremlinScenarioNode): @@ -368,6 +373,16 @@ def __init( ): super().__init__(*args, **kwargs) + def api_model(self) -> dict: + model: dict = super().api_model() + return model + + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinScenarioParallelNode(GremlinScenarioNode): def __init( @@ -378,6 +393,16 @@ def __init( super().__init__(*args, **kwargs) raise NotImplementedError("Parallel Scenario Nodes NOT IMPLEMENTED") + def api_model(self) -> dict: + model: dict = super().api_model() + return model + + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinScenarioAttackNode(GremlinScenarioSerialNode): def __init__( @@ -403,6 +428,16 @@ def attack_type(self, _attack_type: str = None) -> None: raise GremlinParameterError(error_msg) self._attack_type = _attack_type + def api_model(self) -> dict: + model: dict = super().api_model() + return model + + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinScenarioILFINode(GremlinScenarioSerialNode): def __init__(self, *args: tuple, **kwargs: dict): @@ -445,6 +480,12 @@ def target(self, _target: GremlinAttackTargetHelper) -> None: raise GremlinParameterError(error_msg) self._target = _target + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinScenarioALFINode(GremlinScenarioSerialNode): def __init__( @@ -456,6 +497,16 @@ def __init__( self.attack_type = "ALFI" raise NotImplementedError("ALFI Scenarios NOT IMPLEMENTED") + def api_model(self) -> dict: + model: dict = super().api_model() + return model + + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinScenarioDelayNode(GremlinScenarioSerialNode): def __init__(self, *args: tuple, **kwargs: dict): @@ -485,6 +536,12 @@ def delay(self, _duration: int = None) -> None: raise GremlinParameterError(error_msg) self._delay = _duration + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class GremlinScenarioStatusCheckNode(GremlinScenarioSerialNode): def __init__( @@ -601,6 +658,12 @@ def evaluation_response_body_evaluation( raise GremlinParameterError(error_msg) self._evaluation_response_body_evaluation = _evaluation_response_body_evaluation + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) + class _GremlinNodeGraph(object): def __init__(self): @@ -843,3 +906,13 @@ def _validate_type(self, _node: GremlinScenarioNode) -> bool: log.error(error_msg) raise GremlinParameterError(error_msg) return True + + def api_model(self) -> dict: + model: dict = {} + return model + + def __repr__(self) -> str: + return json.dumps(self.api_model()) + + def __str__(self) -> str: + return json.dumps(self.api_model()) From efd33a1f6e6be6c6a44994db888e2d016736e5f2 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 11:10:01 -0400 Subject: [PATCH 09/37] =?UTF-8?q?Bump=20version:=200.13.4=20=E2=86=92=200.?= =?UTF-8?q?13.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 100ef6d..4f4bbe7 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.4 +current_version = 0.13.5 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 263ea04..04f426f 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.4" +_version = "0.13.5" def get_version(): From 16636309585c9c7d2daf3ef9e7eab6b5f4ea6ad1 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 11:58:14 -0400 Subject: [PATCH 10/37] completed __repr__ and __str__ for GremlinAttackTargetHelper class --- gremlinapi/attack_helpers.py | 8 ++++++-- tests/test_attack_helpers.py | 9 +++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index c8246ee..874e3ed 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -158,10 +158,14 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["exact"] = self.exact + kwargs["percent"] = self.percent + kwargs["strategy_type"] = self.strategy_type + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinAttackCommandHelper(object): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 8bfda1d..190711d 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -100,6 +100,15 @@ def test_attack_target_helper_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_attack_target_helper_repr_str(self) -> None: + # defaults + expected_output = 'GremlinAttackTargetHelper({"exact": 0, "percent": 10, "strategy_type": "Random"})' + helper = GremlinAttackTargetHelper() + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + @patch("requests.get") def test_filter_active_tags_with_decorator(self, mock_get) -> None: expected_output = { From ebfa31a2bc820e8b860e0556f7f8c9ef9b821a6c Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 11:58:18 -0400 Subject: [PATCH 11/37] =?UTF-8?q?Bump=20version:=200.13.5=20=E2=86=92=200.?= =?UTF-8?q?13.6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 4f4bbe7..8a446e2 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.5 +current_version = 0.13.6 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 04f426f..aa658d8 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.5" +_version = "0.13.6" def get_version(): From cb81c30ae98b91b514b0d0a69c0c5bdb3fcc93fa Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 12:05:25 -0400 Subject: [PATCH 12/37] completed __repr__ and __str__ for GremlinAttackCommandHelper class --- gremlinapi/attack_helpers.py | 6 ++++-- tests/test_attack_helpers.py | 13 ++++++++++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 874e3ed..9902ec3 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -275,10 +275,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinAttackHelper(object): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 190711d..c5adf43 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -103,7 +103,9 @@ def test_attack_target_helper_api_model(self) -> None: def test_attack_target_helper_repr_str(self) -> None: # defaults expected_output = 'GremlinAttackTargetHelper({"exact": 0, "percent": 10, "strategy_type": "Random"})' - helper = GremlinAttackTargetHelper() + helper = GremlinAttackTargetHelper( + {"exact": 0, "percent": 10, "strategy_type": "Random"} + ) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) helper_output = str(helper) @@ -191,6 +193,15 @@ def test_attack_command_helper_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_attack_command_helper_repr_str(self) -> None: + # defaults + expected_output = 'GremlinAttackCommandHelper({"length": 60})' + helper = GremlinAttackCommandHelper({"length": 60}) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_resource_attack_helper_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "", "type": ""} From bacdf8ba10306a970ad43b5c2b1f3b4e22e92809 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 12:05:29 -0400 Subject: [PATCH 13/37] =?UTF-8?q?Bump=20version:=200.13.6=20=E2=86=92=200.?= =?UTF-8?q?13.7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 8a446e2..1bc06d9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.6 +current_version = 0.13.7 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index aa658d8..c9f6ec2 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.6" +_version = "0.13.7" def get_version(): From 6c8e00ea8028011e75f9ca86af6584902fb7a883 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 12:56:50 -0400 Subject: [PATCH 14/37] completed __repr__ and __str__ for GremlinTargetHosts class --- gremlinapi/attack_helpers.py | 21 ++++++++++++++------- tests/test_attack_helpers.py | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 9902ec3..896529b 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -328,17 +328,19 @@ def target(self, _target: GremlinAttackTargetHelper) -> None: def api_model(self) -> dict: model: dict = { - "target": json.loads(str(self.target)), - "command": json.loads(str(self.command)), + "target": self.target.api_model(), + "command": self.command.api_model(), } return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["target"] = repr(self.target) + kwargs["command"] = repr(self.command) + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) - + return repr(self) class GremlinTargetHosts(GremlinAttackTargetHelper): def __init__(self, *args: tuple, **kwargs: dict): @@ -474,10 +476,15 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["exact"] = self.exact + kwargs["percent"] = self.percent + kwargs["strategy_type"] = self.strategy_type + kwargs["target_all_hosts"] = self.target_all_hosts + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinTargetContainers(GremlinAttackTargetHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index c5adf43..06eb886 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -52,6 +52,17 @@ def test_attack_helper_api_model(self) -> None: helper = GremlinAttackHelper() helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + + def test_attack_helper_repr_str(self) -> None: + # defaults + expected_output = 'GremlinAttackHelper({"exact": 0, "percent": 10, "strategy_type": "Random"})' + helper = GremlinAttackHelper( + + ) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) def test_target_helper_target_definition(self) -> None: helper = GremlinAttackTargetHelper(**attack_helper_params_custom) @@ -136,6 +147,17 @@ def test_target_hosts_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_target_hosts_repr_str(self) -> None: + # defaults + expected_output = 'GremlinTargetHosts({"exact": 0, "percent": 10, "strategy_type": "Random", "target_all_hosts": true})' + helper = GremlinTargetHosts( + {"exact": 0, "percent": 10, "strategy_type": "Random", "target_all_hosts": True} + ) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + @patch("requests.get") def test_filter_active_labels_with_decorator(self, mock_get) -> None: expected_output = {"os_type": ["testwindows"], "os-version": ["test10"]} From 11be7f33184162dc951c5e13970261dd20d7a4b0 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 12:56:53 -0400 Subject: [PATCH 15/37] =?UTF-8?q?Bump=20version:=200.13.7=20=E2=86=92=200.?= =?UTF-8?q?13.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 1bc06d9..50556e4 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.7 +current_version = 0.13.8 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index c9f6ec2..834f182 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.7" +_version = "0.13.8" def get_version(): From 279c278f0a653ab27a3091bbdbd698ac658b656e Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 13:24:18 -0400 Subject: [PATCH 16/37] completed __repr__ and __str__ for GremlinTargetHosts, GremlinCPUAttack, and GremlinAttackHelper classes --- gremlinapi/attack_helpers.py | 12 +++++++++--- tests/test_attack_helpers.py | 38 ++++++++++++++++++++++++++++++++---- 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 896529b..9f9b4d1 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -337,11 +337,12 @@ def __repr__(self) -> str: kwargs: dict = {} kwargs["target"] = repr(self.target) kwargs["command"] = repr(self.command) - return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) + return "%s(%s)" % (self.__class__.__name__, kwargs) def __str__(self) -> str: return repr(self) + class GremlinTargetHosts(GremlinAttackTargetHelper): def __init__(self, *args: tuple, **kwargs: dict): super().__init__(*args, **kwargs) @@ -1017,10 +1018,15 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["all_cores"] = self.all_cores + kwargs["capacity"] = self.capacity + kwargs["cores"] = self.cores + kwargs["length"] = self.length + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinMemoryAttack(GremlinResourceAttackHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 06eb886..8c1a420 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -52,12 +52,26 @@ def test_attack_helper_api_model(self) -> None: helper = GremlinAttackHelper() helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) - + def test_attack_helper_repr_str(self) -> None: # defaults - expected_output = 'GremlinAttackHelper({"exact": 0, "percent": 10, "strategy_type": "Random"})' + expected_output = 'GremlinAttackHelper({\'target\': \'GremlinTargetHosts({"exact": 0, "percent": 10, "strategy_type": "Random", "target_all_hosts": true})\', \'command\': \'GremlinCPUAttack({"all_cores": false, "capacity": 100, "cores": 1, "length": 60})\'})' helper = GremlinAttackHelper( - + GremlinAttackHelper( + { + "target": GremlinTargetHosts( + { + "exact": 0, + "percent": 10, + "strategy_type": "Random", + "target_all_hosts": True, + } + ), + "command": GremlinCPUAttack( + {"all_cores": False, "capacity": 100, "cores": 1, "length": 60} + ), + } + ) ) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) @@ -151,7 +165,12 @@ def test_target_hosts_repr_str(self) -> None: # defaults expected_output = 'GremlinTargetHosts({"exact": 0, "percent": 10, "strategy_type": "Random", "target_all_hosts": true})' helper = GremlinTargetHosts( - {"exact": 0, "percent": 10, "strategy_type": "Random", "target_all_hosts": True} + { + "exact": 0, + "percent": 10, + "strategy_type": "Random", + "target_all_hosts": True, + } ) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) @@ -265,6 +284,17 @@ def test_cpu_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_cpu_attack_repr_str(self) -> None: + # defaults + expected_output = 'GremlinCPUAttack({"all_cores": false, "capacity": 100, "cores": 1, "length": 60})' + helper = GremlinCPUAttack( + {"all_cores": False, "capacity": 100, "cores": 1, "length": 60} + ) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_memory_attack_api_model(self) -> None: # defaults expected_output = { From ad0bd1de68440a9b5687e5ddfd4603a20ff28336 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 13:24:23 -0400 Subject: [PATCH 17/37] =?UTF-8?q?Bump=20version:=200.13.8=20=E2=86=92=200.?= =?UTF-8?q?13.9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 50556e4..00b2d38 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.8 +current_version = 0.13.9 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 834f182..c1a13b0 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.8" +_version = "0.13.9" def get_version(): From 00e5ab8bcf8c59bfe689d557593b5030bed6f77a Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 14:48:01 -0400 Subject: [PATCH 18/37] Added GremlinTargetContainers __repr__ and __str__, fixed bug in unit test which caused all tested objects to revert to defaults. --- gremlinapi/attack_helpers.py | 11 ++++- tests/test_attack_helpers.py | 85 ++++++++++++++++++++---------------- 2 files changed, 56 insertions(+), 40 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 9f9b4d1..02486b5 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -640,10 +640,17 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["exact"] = self.exact + kwargs["percent"] = self.percent + kwargs["strategy_type"] = self.strategy_type + kwargs["target_all_containers"] = self.target_all_containers + kwargs["ids"] = self.ids + kwargs["labels"] = self.labels + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinResourceAttackHelper(GremlinAttackCommandHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 8c1a420..3749ee5 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -55,24 +55,19 @@ def test_attack_helper_api_model(self) -> None: def test_attack_helper_repr_str(self) -> None: # defaults - expected_output = 'GremlinAttackHelper({\'target\': \'GremlinTargetHosts({"exact": 0, "percent": 10, "strategy_type": "Random", "target_all_hosts": true})\', \'command\': \'GremlinCPUAttack({"all_cores": false, "capacity": 100, "cores": 1, "length": 60})\'})' - helper = GremlinAttackHelper( - GremlinAttackHelper( - { - "target": GremlinTargetHosts( - { - "exact": 0, - "percent": 10, - "strategy_type": "Random", - "target_all_hosts": True, - } - ), - "command": GremlinCPUAttack( - {"all_cores": False, "capacity": 100, "cores": 1, "length": 60} - ), - } - ) - ) + expected_output = 'GremlinAttackHelper({\'target\': \'GremlinTargetHosts({"exact": 0, "percent": 25, "strategy_type": "Random", "target_all_hosts": true})\', \'command\': \'GremlinCPUAttack({"all_cores": false, "capacity": 90, "cores": 1, "length": 60})\'})' + kwargs_th = { + "exact": 0, + "percent": 25, + "strategy_type": "Random", + "target_all_hosts": True, + } + kwargs_cpua = {"all_cores": False, "capacity": 90, "cores": 1, "length": 60} + kwargs = { + "target": GremlinTargetHosts(**kwargs_th), + "command": GremlinCPUAttack(**kwargs_cpua), + } + helper = GremlinAttackHelper(**kwargs) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) helper_output = str(helper) @@ -127,10 +122,9 @@ def test_attack_target_helper_api_model(self) -> None: def test_attack_target_helper_repr_str(self) -> None: # defaults - expected_output = 'GremlinAttackTargetHelper({"exact": 0, "percent": 10, "strategy_type": "Random"})' - helper = GremlinAttackTargetHelper( - {"exact": 0, "percent": 10, "strategy_type": "Random"} - ) + expected_output = 'GremlinAttackTargetHelper({"exact": 0, "percent": 15, "strategy_type": "Random"})' + kwargs = {"exact": 0, "percent": 15, "strategy_type": "Random"} + helper = GremlinAttackTargetHelper(**kwargs) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) helper_output = str(helper) @@ -163,15 +157,14 @@ def test_target_hosts_api_model(self) -> None: def test_target_hosts_repr_str(self) -> None: # defaults - expected_output = 'GremlinTargetHosts({"exact": 0, "percent": 10, "strategy_type": "Random", "target_all_hosts": true})' - helper = GremlinTargetHosts( - { - "exact": 0, - "percent": 10, - "strategy_type": "Random", - "target_all_hosts": True, - } - ) + expected_output = 'GremlinTargetHosts({"exact": 0, "percent": 25, "strategy_type": "Random", "target_all_hosts": true})' + kwargs = { + "exact": 0, + "percent": 25, + "strategy_type": "Random", + "target_all_hosts": True, + } + helper = GremlinTargetHosts(**kwargs) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) helper_output = str(helper) @@ -200,6 +193,23 @@ def test_target_containers_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_target_containers_repr_str(self) -> None: + # defaults + expected_output = 'GremlinTargetContainers({"exact": 0, "percent": 35, "strategy_type": "Random", "target_all_containers": false, "ids": [], "labels": {}})' + kwargs = { + "exact": 0, + "percent": 35, + "strategy_type": "Random", + "target_all_containers": False, + "ids": [], + "labels": {}, + } + helper = GremlinTargetContainers(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_impact_definition(self) -> None: expected_output = { "commandArgs": {"cliArgs": ["memory", "-l", "100"], "length": 100}, @@ -235,9 +245,9 @@ def test_attack_command_helper_api_model(self) -> None: self.assertEqual(helper_output, expected_output) def test_attack_command_helper_repr_str(self) -> None: - # defaults - expected_output = 'GremlinAttackCommandHelper({"length": 60})' - helper = GremlinAttackCommandHelper({"length": 60}) + expected_output = 'GremlinAttackCommandHelper({"length": 70})' + kwargs = {"length": 70} + helper = GremlinAttackCommandHelper(**kwargs) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) helper_output = str(helper) @@ -286,10 +296,9 @@ def test_cpu_attack_api_model(self) -> None: def test_cpu_attack_repr_str(self) -> None: # defaults - expected_output = 'GremlinCPUAttack({"all_cores": false, "capacity": 100, "cores": 1, "length": 60})' - helper = GremlinCPUAttack( - {"all_cores": False, "capacity": 100, "cores": 1, "length": 60} - ) + expected_output = 'GremlinCPUAttack({"all_cores": false, "capacity": 90, "cores": 2, "length": 60})' + kwargs = {"all_cores": False, "capacity": 90, "cores": 2, "length": 60} + helper = GremlinCPUAttack(**kwargs) helper_output = repr(helper) self.assertEqual(expected_output, helper_output) helper_output = str(helper) From 7873d0e03bbff409598ee4996913bd4716921df3 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Wed, 21 Apr 2021 14:48:38 -0400 Subject: [PATCH 19/37] =?UTF-8?q?Bump=20version:=200.13.9=20=E2=86=92=200.?= =?UTF-8?q?13.10?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 00b2d38..0f59260 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.9 +current_version = 0.13.10 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index c1a13b0..3708d21 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.9" +_version = "0.13.10" def get_version(): From 0e1be4334fdd56c849be2b95a9708e5170a0b079 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:16:13 -0400 Subject: [PATCH 20/37] Added __repr__ and __str__ for GremlinResourceAttackHelper and GremlinStateAttackHelper --- gremlinapi/attack_helpers.py | 12 ++++++++---- tests/test_attack_helpers.py | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 02486b5..acb2996 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -714,10 +714,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinStateAttackHelper(GremlinAttackCommandHelper): @@ -729,10 +731,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + return "%s()" % (self.__class__.__name__) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinNetworkAttackHelper(GremlinAttackCommandHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 3749ee5..ed64f28 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -21,6 +21,7 @@ GremlinDNSAttack, GremlinLatencyAttack, GremlinPacketLossAttack, + GremlinStateAttackHelper, ) from .util import mock_data @@ -260,6 +261,23 @@ def test_resource_attack_helper_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_resource_attack_helper_repr_str(self) -> None: + expected_output = 'GremlinResourceAttackHelper({"length": 70})' + kwargs = {"length": 70} + helper = GremlinResourceAttackHelper(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + + def test_state_attack_helper_repr_str(self) -> None: + expected_output = "GremlinStateAttackHelper()" + helper = GremlinStateAttackHelper() + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test__port_maker(self) -> None: expected_output = [] helper = GremlinNetworkAttackHelper() From ad8c7acc190a987c6029a0173b22af9d15b782f0 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:16:17 -0400 Subject: [PATCH 21/37] =?UTF-8?q?Bump=20version:=200.13.10=20=E2=86=92=200?= =?UTF-8?q?.13.11?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 0f59260..54f5952 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.10 +current_version = 0.13.11 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 3708d21..80a78e0 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.10" +_version = "0.13.11" def get_version(): From b1a16a9b024ec49bda6b064b16b4da7aea376aed Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:22:01 -0400 Subject: [PATCH 22/37] Added __repr__ and __str__ for GremlinNetworkAttackHelper --- gremlinapi/attack_helpers.py | 11 +++++++++-- tests/test_attack_helpers.py | 16 ++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index acb2996..167bcc4 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -966,10 +966,17 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["device"] = self.device + kwargs["ips"] = self.ips + kwargs["protocol"] = self.protocol + kwargs["providers"] = self.providers + kwargs["tags"] = self.tags + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinCPUAttack(GremlinResourceAttackHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index ed64f28..a6949aa 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -301,6 +301,22 @@ def test_network_attack_helper_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_network_attack_helper_repr_str(self) -> None: + expected_output = 'GremlinNetworkAttackHelper({"length": 65, "device": "", "ips": [], "protocol": "", "providers": [], "tags": []})' + kwargs = { + "length": 65, + "device": "", + "ips": [], + "protocol": "", + "providers": [], + "tags": [], + } + helper = GremlinNetworkAttackHelper(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_cpu_attack_api_model(self) -> None: # defaults expected_output = { From 3cceac2e72b674afbd2f6deac830d7a0e5956527 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:34:04 -0400 Subject: [PATCH 23/37] Added __repr__ and __str__ for GremlinMemoryAttack --- gremlinapi/attack_helpers.py | 8 ++++++-- tests/test_attack_helpers.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 167bcc4..269fcf7 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1117,10 +1117,14 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["amount"] = self.amount + kwargs["amountType"] = self.amountType + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinDiskSpaceAttack(GremlinResourceAttackHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index a6949aa..00c4f6f 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -349,6 +349,21 @@ def test_memory_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_memory_attack_repr_str(self) -> None: + expected_output = ( + 'GremlinMemoryAttack({"length": 65, "amount": 99, "amountType": "MB"})' + ) + kwargs = { + "length": 65, + "amount": 99, + "amountType": "MB", + } + helper = GremlinMemoryAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_disk_space_attack_api_model(self) -> None: # defaults expected_output = { From 8ae1c9855264ca2b4b3a11c45b854a71bcb1354f Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:38:03 -0400 Subject: [PATCH 24/37] Added __repr__ and __str__ for GremlinDiskSpaceAttack --- gremlinapi/attack_helpers.py | 16 ++++++++++++---- tests/test_attack_helpers.py | 15 +++++++++++++++ 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 269fcf7..db86f4c 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1145,10 +1145,16 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["blocksize"] = self.blocksize + kwargs["directory"] = self.directory + kwargs["percent"] = self.percent + kwargs["workers"] = self.workers + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinDiskIOAttack(GremlinResourceAttackHelper): @@ -1199,10 +1205,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinShutdownAttack(GremlinStateAttackHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 00c4f6f..89a95b1 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -375,6 +375,21 @@ def test_disk_space_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_disk_space_attack_repr_str(self) -> None: + expected_output = 'GremlinDiskSpaceAttack({"length": 75, "blocksize": 4, "directory": "/tmp", "percent": 95, "workers": 1})' + kwargs = { + "length": 75, + "blocksize": 4, + "directory": "/tmp", + "percent": 95, + "workers": 1, + } + helper = GremlinDiskSpaceAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_disk_io_api_model(self) -> None: # defaults expected_output = { From 637cb626272dfc168d6c01858c21c67c0a3d940c Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:42:15 -0400 Subject: [PATCH 25/37] Added __repr__ and __str__ for GremlinDiskIOAttack --- gremlinapi/attack_helpers.py | 5 +++++ tests/test_attack_helpers.py | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index db86f4c..0f54d30 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1207,6 +1207,11 @@ def api_model(self) -> dict: def __repr__(self) -> str: kwargs: dict = {} kwargs["length"] = self.length + kwargs["blockcount"] = self.blockcount + kwargs["blocksize"] = self.blocksize + kwargs["directory"] = self.directory + kwargs["mode"] = self.mode + kwargs["workers"] = self.workers return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 89a95b1..6f84531 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -414,6 +414,22 @@ def test_disk_io_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_disk_io_repr_str(self) -> None: + expected_output = 'GremlinDiskIOAttack({"length": 85, "blockcount": 1, "blocksize": 4, "directory": "/tmp/usr", "mode": "rw", "workers": 2})' + kwargs = { + "length": 85, + "blockcount": 1, + "blocksize": 4, + "directory": "/tmp/usr", + "mode": "rw", + "workers": 2, + } + helper = GremlinDiskIOAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_shutdown_attack_api_model(self) -> None: # defaults expected_output = { From f161e264d98def980819d19d3ef96ce397193653 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:48:47 -0400 Subject: [PATCH 26/37] Added __repr__ and __str__ for GremlinShutdownAttack --- gremlinapi/attack_helpers.py | 8 ++++++-- tests/test_attack_helpers.py | 15 +++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 0f54d30..40558d3 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1259,10 +1259,14 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["delay"] = self.delay + kwargs["reboot"] = self.reboot + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinProcessKillerAttack(GremlinStateAttackHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 6f84531..652de97 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -441,6 +441,21 @@ def test_shutdown_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_shutdown_attack_repr_str(self) -> None: + expected_output = ( + 'GremlinShutdownAttack({"length": 85, "delay": 20, "reboot": false})' + ) + kwargs = { + "length": 85, + "delay": 20, + "reboot": False, + } + helper = GremlinShutdownAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_process_killer_attack_api_model(self) -> None: test_process = "ls" kwargs = {"process": test_process} From 00f15ed2109281f8e93873a341e05605151fa1f6 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 09:54:53 -0400 Subject: [PATCH 27/37] Added __repr__ and __str__ for GremlinProcessKillerAttack --- gremlinapi/attack_helpers.py | 15 +++++++++++++-- tests/test_attack_helpers.py | 20 ++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 40558d3..cb8a6b6 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1441,10 +1441,21 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["exact"] = self.exact + kwargs["full_match"] = self.full_match + kwargs["group"] = self.group + kwargs["interval"] = self.interval + kwargs["kill_children"] = self.kill_children + kwargs["process"] = self.process + kwargs["target_newest"] = self.target_newest + kwargs["target_oldest"] = self.target_oldest + kwargs["user"] = self.user + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinTimeTravelAttack(GremlinStateAttackHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 652de97..322ebd9 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -469,6 +469,26 @@ def test_process_killer_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_process_killer_attack_repr_str(self) -> None: + expected_output = 'GremlinProcessKillerAttack({"length": 65, "exact": false, "full_match": true, "group": "", "interval": 1, "kill_children": false, "process": "", "target_newest": false, "target_oldest": false, "user": "unittestuser"})' + kwargs = { + "length": 65, + "exact": False, + "full_match": True, + "group": "", + "interval": 1, + "kill_children": False, + "process": "", + "target_newest": False, + "target_oldest": False, + "user": "unittestuser", + } + helper = GremlinProcessKillerAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_time_travel_attack_api_model(self) -> None: # defaults expected_output = { From ed04dbed9298007c82071dfdd4ef3359aa7f803c Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 10:00:47 -0400 Subject: [PATCH 28/37] Added __repr__ and __str__ for GremlinTimeTravelAttack --- gremlinapi/attack_helpers.py | 8 ++++++-- tests/test_attack_helpers.py | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index cb8a6b6..55459b0 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1499,10 +1499,14 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["block_ntp"] = self.block_ntp + kwargs["offset"] = self.offset + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinBlackholeAttack(GremlinNetworkAttackHelper): diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 322ebd9..986c317 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -500,6 +500,19 @@ def test_time_travel_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_time_travel_attack_repr_str(self) -> None: + expected_output = 'GremlinTimeTravelAttack({"length": 65, "block_ntp": false, "offset": 12000})' + kwargs = { + "length": 65, + "block_ntp": False, + "offset": 12000, + } + helper = GremlinTimeTravelAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_black_hole_attack_api_model(self) -> None: # defaults expected_output = { From 0d93dd691b99ca873440849581ebb633a9bf82f6 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 10:19:04 -0400 Subject: [PATCH 29/37] Added __repr__ and __str__ for GremlinBlackholeAttack --- gremlinapi/attack_helpers.py | 47 ++++++++++++++++++++++++++++++------ tests/test_attack_helpers.py | 19 +++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 55459b0..8fccc54 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1528,10 +1528,20 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["device"] = self.device + kwargs["ips"] = self.ips + kwargs["protocol"] = self.protocol + kwargs["providers"] = self.providers + kwargs["tags"] = self.tags + kwargs["egress_ports"] = self.egress_ports + kwargs["hostnames"] = self.hostnames + kwargs["ingress_ports"] = self.ingress_ports + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinDNSAttack(GremlinNetworkAttackHelper): @@ -1546,10 +1556,17 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["device"] = self.device + kwargs["ips"] = self.ips + kwargs["protocol"] = self.protocol + kwargs["providers"] = self.providers + kwargs["tags"] = self.tags + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinLatencyAttack(GremlinNetworkAttackHelper): @@ -1586,10 +1603,17 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["device"] = self.device + kwargs["ips"] = self.ips + kwargs["protocol"] = self.protocol + kwargs["providers"] = self.providers + kwargs["tags"] = self.tags + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinPacketLossAttack(GremlinNetworkAttackHelper): @@ -1647,7 +1671,14 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["length"] = self.length + kwargs["device"] = self.device + kwargs["ips"] = self.ips + kwargs["protocol"] = self.protocol + kwargs["providers"] = self.providers + kwargs["tags"] = self.tags + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index 986c317..a0bd9ce 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -524,6 +524,25 @@ def test_black_hole_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_black_hole_attack_repr_str(self) -> None: + expected_output = 'GremlinBlackholeAttack({"length": 65, "device": "", "ips": [], "protocol": "", "providers": [], "tags": [], "egress_ports": ["^533"], "hostnames": "^api2.gremlin.com", "ingress_ports": []})' + kwargs = { + "length": 65, + "device": "", + "ips": [], + "protocol": "", + "providers": [], + "tags": [], + "egress_ports": ["^533"], + "hostnames": ["^api2.gremlin.com"], + "ingress_ports": [], + } + helper = GremlinBlackholeAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_dns_attack_api_model(self) -> None: # defaults expected_output = {"args": ["-l", "60"], "commandType": "DNS", "type": "dns"} From 51614fece9f70877fd9c4f333a4436e21ce5db03 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 10:19:19 -0400 Subject: [PATCH 30/37] =?UTF-8?q?Bump=20version:=200.13.11=20=E2=86=92=200?= =?UTF-8?q?.13.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 54f5952..052b6f9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.11 +current_version = 0.13.12 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 80a78e0..fdd4be3 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.11" +_version = "0.13.12" def get_version(): From d0cd972fdaeb9ce8c8805ebc5745d0bdfa01a89c Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 10:26:54 -0400 Subject: [PATCH 31/37] Added __repr__ and __str__ for GremlinDNSAttack --- tests/test_attack_helpers.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index a0bd9ce..beb9907 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -550,6 +550,22 @@ def test_dns_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_dns_attack_repr_str(self) -> None: + expected_output = 'GremlinDNSAttack({"length": 75, "device": "", "ips": [], "protocol": "", "providers": [], "tags": []})' + kwargs = { + "length": 75, + "device": "", + "ips": [], + "protocol": "", + "providers": [], + "tags": [], + } + helper = GremlinDNSAttack(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_latency_attack_api_model(self) -> None: # defaults expected_output = { From b894210cec1dfcec0fadaacd7fb8ff654e52b9fe Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 10:44:08 -0400 Subject: [PATCH 32/37] Added __repr__ and __str__ for GremlinLatencyAttack --- gremlinapi/attack_helpers.py | 4 ++++ tests/test_attack_helpers.py | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 8fccc54..810f355 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1610,6 +1610,10 @@ def __repr__(self) -> str: kwargs["protocol"] = self.protocol kwargs["providers"] = self.providers kwargs["tags"] = self.tags + kwargs["delay"] = self.delay + kwargs["egress_ports"] = self.egress_ports + kwargs["hostnames"] = self.hostnames + kwargs["source_ports"] = self.source_ports return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index beb9907..c6740b6 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -577,6 +577,29 @@ def test_latency_attack_api_model(self) -> None: helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + def test_latency_attack_repr_str(self) -> None: + expected_output = 'GremlinLatencyAttack({"length": 75, "device": "", "ips": [], "protocol": "", "providers": [], "tags": [], "delay": 100, "egress_ports": ["^533"], "hostnames": "^api2.gremlin.com", "source_ports": []})' + kwargs = { + "length": 75, + "device": "", + "ips": [], + "protocol": "", + "providers": [], + "tags": [], + "delay": 100, + "egress_ports": ["^533"], + "hostnames": ["^api2.gremlin.com"], + "source_ports": [], + } + helper = GremlinLatencyAttack(**kwargs) + helper_output = repr(helper) + max_diff = self.maxDiff = None + self.maxDiff = None + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + self.maxDiff = max_diff + def test_packet_loss_attack_api_model(self) -> None: # defaults expected_output = { From 07988019853fa37bec09274275b94609329b57b0 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 11:00:06 -0400 Subject: [PATCH 33/37] Added __repr__ and __str__ for GremlinPacketLossAttack --- gremlinapi/attack_helpers.py | 5 +++++ tests/test_attack_helpers.py | 24 ++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/gremlinapi/attack_helpers.py b/gremlinapi/attack_helpers.py index 810f355..1415e72 100644 --- a/gremlinapi/attack_helpers.py +++ b/gremlinapi/attack_helpers.py @@ -1682,6 +1682,11 @@ def __repr__(self) -> str: kwargs["protocol"] = self.protocol kwargs["providers"] = self.providers kwargs["tags"] = self.tags + kwargs["corrupt"] = self.corrupt + kwargs["egress_ports"] = self.egress_ports + kwargs["hostnames"] = self.hostnames + kwargs["percent"] = self.percent + kwargs["source_ports"] = self.source_ports return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: diff --git a/tests/test_attack_helpers.py b/tests/test_attack_helpers.py index c6740b6..5f23c6e 100644 --- a/tests/test_attack_helpers.py +++ b/tests/test_attack_helpers.py @@ -610,3 +610,27 @@ def test_packet_loss_attack_api_model(self) -> None: helper = GremlinPacketLossAttack() helper_output = helper.api_model() self.assertEqual(helper_output, expected_output) + + def test_packet_loss_attack_repr_str(self) -> None: + expected_output = 'GremlinPacketLossAttack({"length": 85, "device": "", "ips": [], "protocol": "", "providers": [], "tags": [], "corrupt": false, "egress_ports": ["^543"], "hostnames": "^api3.gremlin.com", "percent": 1, "source_ports": []})' + kwargs = { + "length": 85, + "device": "", + "ips": [], + "protocol": "", + "providers": [], + "tags": [], + "corrupt": False, + "egress_ports": ["^543"], + "hostnames": ["^api3.gremlin.com"], + "percent": 1, + "source_ports": [], + } + helper = GremlinPacketLossAttack(**kwargs) + helper_output = repr(helper) + max_diff = self.maxDiff = None + self.maxDiff = None + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + self.maxDiff = max_diff From 2cf4fbe33e4daa807909d90dca234241a0b2b745 Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 11:00:11 -0400 Subject: [PATCH 34/37] =?UTF-8?q?Bump=20version:=200.13.12=20=E2=86=92=200?= =?UTF-8?q?.13.13?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 052b6f9..d11abf0 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.12 +current_version = 0.13.13 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index fdd4be3..344d5c0 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.12" +_version = "0.13.13" def get_version(): From 2731a98feaddb61a19d3e07d3b65e156f8a56f0c Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 13:34:00 -0400 Subject: [PATCH 35/37] Added __repr__ and __str__ for all Scenario Graph Helper classes --- gremlinapi/scenario_graph_helpers.py | 76 ++++++++++----- tests/test_scenario_graph_helpers.py | 134 +++++++++++++++++++++++++++ 2 files changed, 188 insertions(+), 22 deletions(-) diff --git a/gremlinapi/scenario_graph_helpers.py b/gremlinapi/scenario_graph_helpers.py index 2038c29..1ff464c 100644 --- a/gremlinapi/scenario_graph_helpers.py +++ b/gremlinapi/scenario_graph_helpers.py @@ -161,10 +161,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioGraphHelper(object): @@ -359,10 +361,14 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + kwargs["description"] = self.description + kwargs["hypothesis"] = self.hypothesis + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioSerialNode(GremlinScenarioNode): @@ -378,10 +384,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioParallelNode(GremlinScenarioNode): @@ -398,10 +406,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioAttackNode(GremlinScenarioSerialNode): @@ -433,10 +443,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioILFINode(GremlinScenarioSerialNode): @@ -447,8 +459,8 @@ def __init__(self, *args: tuple, **kwargs: dict): self._command: GremlinAttackCommandHelper = None # type: ignore self._target: GremlinAttackTargetHelper = None # type: ignore self.node_type: str = "InfraAttack" - self.command: GremlinAttackCommandHelper = kwargs.get("command", self._command) # type: ignore - self.target: GremlinAttackTargetHelper = kwargs.get("target", self._target) # type: ignore + self.command: GremlinAttackCommandHelper = kwargs.get("command", GremlinAttackCommandHelper()) # type: ignore + self.target: GremlinAttackTargetHelper = kwargs.get("target", GremlinAttackTargetHelper()) # type: ignore @property def command(self) -> GremlinAttackCommandHelper: @@ -481,10 +493,14 @@ def target(self, _target: GremlinAttackTargetHelper) -> None: self._target = _target def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + kwargs["command"] = repr(self.command) + kwargs["target"] = repr(self.target) + return "%s(%s)" % (self.__class__.__name__, kwargs) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioALFINode(GremlinScenarioSerialNode): @@ -502,10 +518,12 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioDelayNode(GremlinScenarioSerialNode): @@ -537,10 +555,13 @@ def delay(self, _duration: int = None) -> None: self._delay = _duration def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + kwargs["delay"] = self.delay + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class GremlinScenarioStatusCheckNode(GremlinScenarioSerialNode): @@ -659,10 +680,20 @@ def evaluation_response_body_evaluation( self._evaluation_response_body_evaluation = _evaluation_response_body_evaluation def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + kwargs["name"] = self.name + kwargs["description"] = self.description + kwargs["endpoint_url"] = self.endpoint_url + kwargs["endpoint_headers"] = self.endpoint_headers + kwargs["evaluation_ok_status_codes"] = self.evaluation_ok_status_codes + kwargs["evaluation_ok_latency_max"] = self.evaluation_ok_latency_max + kwargs[ + "evaluation_response_body_evaluation" + ] = self.evaluation_response_body_evaluation + return "%s(%s)" % (self.__class__.__name__, json.dumps(kwargs)) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) class _GremlinNodeGraph(object): @@ -912,7 +943,8 @@ def api_model(self) -> dict: return model def __repr__(self) -> str: - return json.dumps(self.api_model()) + kwargs: dict = {} + return "%s()" % (self.__class__.__name__) def __str__(self) -> str: - return json.dumps(self.api_model()) + return repr(self) diff --git a/tests/test_scenario_graph_helpers.py b/tests/test_scenario_graph_helpers.py index 5dcf4ce..cadbc48 100644 --- a/tests/test_scenario_graph_helpers.py +++ b/tests/test_scenario_graph_helpers.py @@ -4,12 +4,21 @@ from gremlinapi.scenario_graph_helpers import ( GremlinScenarioGraphHelper, GremlinScenarioNode, + GremlinScenarioSerialNode, + GremlinScenarioParallelNode, + GremlinScenarioAttackNode, GremlinScenarioILFINode, + GremlinScenarioALFINode, GremlinScenarioDelayNode, GremlinScenarioStatusCheckNode, _GremlinNodeGraph, ) +from gremlinapi.attack_helpers import ( + GremlinAttackTargetHelper, + GremlinAttackCommandHelper, +) + from .util import ( mock_scenario, mock_ilfi_node, @@ -146,6 +155,19 @@ def test_gremlin_scenario_graph_helper_api_model(self) -> None: self.assertEqual(my_scenario.api_model(), expected_output) self.maxDiff = t_diff + def test_gremlin_scenario_graph_helper_repr_str(self) -> None: + expected_output = 'GremlinScenarioGraphHelper({"name": "code_created_scenario_6", "description": "Three nodes now", "hypothesis": "No Hypothesis"})' + kwargs = { + "name": "code_created_scenario_6", + "description": "Three nodes now", + "hypothesis": "No Hypothesis", + } + helper = GremlinScenarioGraphHelper(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_gremlin_scenario_graph_helper_api_model_default_add_node(self) -> None: status_check_description = "Check if Gremlin.com is Still Up" endpoint_url = "https://www.google.com" @@ -283,6 +305,52 @@ def test_gremlin_scenario_node_api_model(self) -> None: self.assertEqual(helper.api_model(), expected_output) + def test_gremlin_scenario_node_repr_str(self) -> None: + expected_output = 'GremlinScenarioNode({"name": "a mock node"})' + kwargs = { + "name": "a mock node", + } + helper = GremlinScenarioNode(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + + def test_gremlin_scenario_serial_node_repr_str(self) -> None: + expected_output = 'GremlinScenarioSerialNode({"name": "a mock serial node"})' + kwargs = { + "name": "a mock serial node", + } + helper = GremlinScenarioSerialNode(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + + def test_gremlin_scenario_parallel_node_repr_str(self) -> None: + expected_output = ( + 'GremlinScenarioParallelNode({"name": "a mock parallel node"})' + ) + kwargs = { + "name": "a mock parallel node", + } + helper = GremlinScenarioParallelNode(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + + def test_gremlin_scenario_attack_node_repr_str(self) -> None: + expected_output = 'GremlinScenarioAttackNode({"name": "a mock attack node"})' + kwargs = { + "name": "a mock attack node", + } + helper = GremlinScenarioAttackNode(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_gremlin_scenario_ilfi_node_repr_node(self) -> None: helper = GremlinScenarioILFINode(**mock_ilfi_node) expected_output = { @@ -303,6 +371,63 @@ def test_gremlin_scenario_ilfi_node_repr_node(self) -> None: self.assertEqual(helper.api_model(), expected_output) + def test_gremlin_scenario_ilfi_node_repr_str(self) -> None: + expected_output = "GremlinScenarioILFINode({'name': 'mock_scenario', 'command': 'GremlinAttackCommandHelper({\"length\": 70})', 'target': 'GremlinAttackTargetHelper({\"exact\": 0, \"percent\": 15, \"strategy_type\": \"Random\"})'})" + kwargs_ch = {"length": 70} + kwargs_th = {"exact": 0, "percent": 15, "strategy_type": "Random"} + kwargs = { + "name": "mock_scenario", + "command": GremlinAttackCommandHelper(**kwargs_ch), + "target": GremlinAttackTargetHelper(**kwargs_th), + } + helper = GremlinScenarioILFINode(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + + # def test_gremlin_scenario_alfi_node_repr_str(self) -> None: + # expected_output = 'GremlinScenarioALFINode({"name": "a mock alfi node"})' + # kwargs = { + # "name": "a mock alfi node", + # } + # helper = GremlinScenarioALFINode(**kwargs) + # helper_output = repr(helper) + # self.assertEqual(expected_output, helper_output) + # helper_output = str(helper) + # self.assertEqual(expected_output, helper_output) + + def test_gremlin_scenario_delay_node_repr_str(self) -> None: + expected_output = ( + 'GremlinScenarioDelayNode({"name": "a mock delay node", "delay": 100})' + ) + kwargs = { + "name": "a mock delay node", + "delay": 100, + } + helper = GremlinScenarioDelayNode(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + + def test_gremlin_scenario_status_check_node_repr_str(self) -> None: + expected_output = 'GremlinScenarioStatusCheckNode({"name": "a mock status check node", "description": "A mock description", "endpoint_url": "www.example.com", "endpoint_headers": {}, "evaluation_ok_status_codes": ["300-400"], "evaluation_ok_latency_max": 1000, "evaluation_response_body_evaluation": "a mock resposne body"})' + kwargs = { + "name": "a mock status check node", + "description": "A mock description", + "endpoint_url": "www.example.com", + "endpoint_headers": {}, + "evaluation_ok_status_codes": ["300-400"], + "evaluation_ok_latency_max": 1000, + "evaluation_response_body_evaluation": "a mock resposne body", + } + helper = GremlinScenarioStatusCheckNode(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_gremlin_scenario_delay_node_repr_node(self) -> None: helper = GremlinScenarioDelayNode(**mock_delay_node) expected_output = { @@ -337,6 +462,15 @@ def test_gremlin_scenario_status_check_node_api_model(self) -> None: } self.assertEqual(helper.api_model(), expected_output) + def test_node_graph_repr_str(self) -> None: + expected_output = "_GremlinNodeGraph()" + kwargs = {} + helper = _GremlinNodeGraph(**kwargs) + helper_output = repr(helper) + self.assertEqual(expected_output, helper_output) + helper_output = str(helper) + self.assertEqual(expected_output, helper_output) + def test_node_graph_add_edge(self) -> None: helper = _GremlinNodeGraph() helper_node = GremlinScenarioNode(**mock_scenario) From 585a459eb27a4427a68fd6d74c6ed5ec8242be7b Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 13:34:05 -0400 Subject: [PATCH 36/37] =?UTF-8?q?Bump=20version:=200.13.13=20=E2=86=92=200?= =?UTF-8?q?.13.14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index d11abf0..94f3df9 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.13 +current_version = 0.13.14 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index 344d5c0..ea37d57 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.13" +_version = "0.13.14" def get_version(): From ed91d06c34603ad2b998c23a8b8e306ca9f92c1a Mon Sep 17 00:00:00 2001 From: Kyle Bouchard Date: Thu, 22 Apr 2021 15:07:23 -0400 Subject: [PATCH 37/37] =?UTF-8?q?Bump=20version:=200.13.14=20=E2=86=92=200?= =?UTF-8?q?.14.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .bumpversion.cfg | 2 +- gremlinapi/util.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 94f3df9..abc765f 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.13.14 +current_version = 0.14.1 commit = True tag = True diff --git a/gremlinapi/util.py b/gremlinapi/util.py index ea37d57..e7f9a0d 100644 --- a/gremlinapi/util.py +++ b/gremlinapi/util.py @@ -7,7 +7,7 @@ log = logging.getLogger("GremlinAPI.client") -_version = "0.13.14" +_version = "0.14.1" def get_version():