diff --git a/CHANGELOG.md b/CHANGELOG.md index 9eaced8..3085196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,14 +2,28 @@ ## [Unreleased][] -[Unreleased]: https://github.com/chaostoolkit-incubator/chaostoolkit-oci/compare/0.1.0...HEAD +[Unreleased]: https://github.com/chaostoolkit-incubator/chaostoolkit-oci/compare/0.2.0...HEAD -- Stop random instance, allowing to do so in terms of the requested filters. +## [0.2.0][] + +[0.2.0]: https://github.com/chaostoolkit-incubator/chaostoolkit-oci/tree/0.2.0 ### Added -- Probe to count the number of instances in the compartment with the possibility of added filters. -- Associated documentation on how to use the probe. +Actions: + +- Delete route table by ID +- Delete route tables using filter + +Probes: + +- Count route tables + +Other: + +- Updated/organized documentation +- Stop random instance added filters. +- Probe to count instances added filters. ## [0.1.0][] @@ -19,9 +33,9 @@ Actions: -- stop instance -- stop random instance +- Stop instance +- Stop random instance Probes: -- count instances \ No newline at end of file +- Count instances \ No newline at end of file diff --git a/README.md b/README.md index d3fe09a..901e6f1 100644 --- a/README.md +++ b/README.md @@ -7,150 +7,45 @@ This project is a collection of [actions][] and [probes][], gathered as an extension to the [Chaos Toolkit][chaostoolkit]. [actions]: http://chaostoolkit.org/reference/api/experiment/#action -[probes]: http://chaostoolkit.org/reference/api/experiment/#probe +[changelog]: ./CHANGELOG.md [chaostoolkit]: http://chaostoolkit.org +[contributing]: ./docs/dev/contribute.md +[experiments]: ./docs/use/experiments.md +[install chaostoolkit-oci]: ./docs/setup/chaostoolkit.md +[keys and ocids]: https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm +[oci]: ./docs/setup/oci.md +[oci config]: https://docs.cloud.oracle.com/en-us/iaas/Content/API/Concepts/sdkconfig.htm +[probes]: http://chaostoolkit.org/reference/api/experiment/#probe +[python]: ./docs/setup/python.md +[virtualenv]: ./docs/setup/venv.md -[oci-configuration]: https://docs.cloud.oracle.com/iaas/Content/API/Concepts/apisigningkey.htm -[oci-python-sdk]: https://docs.cloud.oracle.com/en-us/iaas/Content/API/SDKDocs/pythonsdk.htm - -## Pre-requisites - -* Install Python 3.5+ -* Install pip - -## Create a virtual environment - -Create a local virtual environment where you can install dependencies: - -``` -python3 -m venv ~/.venvs/chaostk -``` - -Activate the environment: - -``` -source ~/.venvs/chaostk/bin/activate -``` - -## Install dependencies - -If you intend to only __use__ this toolkit, install the following dependencies in your virtual environment: - -``` -pip install chaostoolkit -pip install -U chaostoolkit-oci -``` - -If you intend to develop and contribute or use the latest from this repo, install the additional developer dependencies and point your environment to this directory: - -``` -pip install chaostoolkit -pip install -r requirements-dev.txt -r requirements.txt -python setup.py develop -``` - -Now, you can edit the files and they will be automatically be seen by your -environment, even when running from the `chaos` command locally. - -Verify that the chaostoolkit has been installed properly: - -``` -chaos --version -``` - -## Discover capabilities and experiments - -``` -chaos discover --no-install chaostoolkit-oci -``` - -## Configuration - -### Credentials +## Setup environment -This extension uses the [oci-python-sdk][oci-python-sdk] library under the hood. It expects that you have properly [configured][oci-configuration] your environment to connect and authenticate with the OCI services. +[Install Python and pip][python] -The easiest way of doing this is by having a ~/.oci directory that contains a config file -and the necessary api access pem files. +[Install and create a virtual environment][virtualenv] -``` -[DEFAULT] -user=ocid1.user.oc1..aaaaaaaabyneck4zsklp55y4ebgxxxxxxx7ypsz7hskluh3hpshfb3jelsew -fingerprint=00:ab:23:45:bc:6d:e7:fg:h8:i9:00:jk:lm:12:34:56 -key_file=/home/user/.oci/oci_api_key.pem -tenancy=ocid1.tenancy.oc1..aaaaaaaarx3oltzmcws24bsfxxxxxxxxbqwieembc74s2gohnfjjanmedxqj -compartment=ocid1.compartment.oc1..aaaaaaaaeaoardsao2cyxxxxxxxcrf6okik5uan4msovmdai44akwxje7tla -region=uk-london-1 -namespace=tenancyname -``` +[Install chaostoolkit, chaostoolkit-oci][install chaostoolkit-oci] -## Usage +Configure your [signing keys and obtain your OCIDs][keys and ocids]. -To use the probes and actions from this package, add the following to your -experiment file: +Create your [OCI Configuration file][oci config]. -```json -{ - "type": "action", - "name": "stop-a-compute-instance", - "provider": { - "type": "python", - "module": "chaosoci.core.compute.actions", - "func": "stop_instance", - "arguments": { - "instance_id": "ocid1.instance.oc1.uk-london-1.abwgiljr4hngf7ktirgpp4ebl3w7fdarvhe6if4tu4r7y4fh3tsde7vbm5lq" - } - } -} -``` +## Using chaostoolkit-oci +[Creating and running chaos experiments][experiments]. -That's it! +## Contributing -Now, let us say we only want an action to be executed after probing that a given value is within -a desired threshold; simple enough, we need to add a probe to our experiment, as follows: +[Contributing to chaostoolkit-oci][contributing]. -``` -"type": "probe", -"name": "count-the-number-of-instances", -"tolerance": [2, 10], -"provider": { - "type": "python", - "module": "chaosoci.core.compute.probes", - "func": "count_instances", - "arguments": { - "filters": { - "region": "uk-london-1", - "lifecycle_state": "RUNNING" - } - } -} -``` +## Changelog -For a list of available filters please refer to: [oci.core.models.Instance](https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/api/core/models/oci.core.models.Instance.html#oci.core.models.Instance). +View the [CHANGELOG][changelog]. -Please explore the code to see existing probes and actions. +## Acknowledgement -## Contribute +Chaos installation: [chaostoolkit.org][chaostoolkit] -If you wish to contribute more functions to this package, you are more than -welcome to do so. Please, fork this project, make your changes following the -usual [PEP 8][pep8] code style, sprinkling with tests and submit a PR for -review. - -[pep8]: https://pycodestyle.readthedocs.io/en/latest/ - -The Chaos Toolkit projects require all contributors must sign a -[Developer Certificate of Origin][dco] on each commit they would like to merge -into the master branch of the repository. Please, make sure you can abide by -the rules of the DCO before submitting a PR. - -[dco]: https://github.com/probot/dco#how-it-works - -### Test +Python, pip installation and virtualenv documentation: https://docs.python-guide.org/# -To run the tests for the project execute the following: - -``` -$ pytest -``` - +## License \ No newline at end of file diff --git a/chaosoci/__init__.py b/chaosoci/__init__.py index ac4cc5f..847c85a 100644 --- a/chaosoci/__init__.py +++ b/chaosoci/__init__.py @@ -1,4 +1,6 @@ # -*- coding: utf-8 -*- +# Copyright 2020, Oracle Corporation and/or its affiliates. + from typing import List from oci.config import from_file, validate_config @@ -55,6 +57,10 @@ def load_exported_activities() -> List[DiscoveredActivities]: activities = [] activities.extend(discover_actions("chaosoci.core.compute.actions")) activities.extend(discover_probes("chaosoci.core.compute.probes")) + + activities.extend(discover_actions("chaosoci.core.networking.actions")) + activities.extend(discover_probes("chaosoci.core.networking.probes")) + activities.extend(discover_probes("chaosoci.core.networking.rollbacks")) return activities diff --git a/chaosoci/core/networking/actions.py b/chaosoci/core/networking/actions.py new file mode 100644 index 0000000..5f0007f --- /dev/null +++ b/chaosoci/core/networking/actions.py @@ -0,0 +1,84 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +__all__ = ["delete_route_table_by_id", "delete_route_table_by_filters"] + +from random import choice +from typing import Any, Dict, List + +from chaoslib.exceptions import ActivityFailed +from chaoslib.types import Configuration, Secrets + +from chaosoci import oci_client +from chaosoci.types import OCIResponse +from chaosoci.util.constants import FILTER_ERR + +from logzero import logger + +from oci.config import from_file +from oci.core import VirtualNetworkClient + +from .common import (get_route_tables) + +from .filters import (filter_route_tables) + + +def delete_route_table_by_id(rt_id: str, force: bool = False, + configuration: Configuration = None, + secrets: Secrets = None) -> OCIResponse: + """ + Deletes a given route table using the route table id. + + Parameters: + Required: + - rt_id: the id of the route table + """ + + client = oci_client(VirtualNetworkClient, configuration, secrets, + skip_deserialization=True) + if not rt_id: + raise ActivityFailed('A route table id is required.') + + ret = client.delete_route_table(rt_id=rt_id).data + logger.debug("Route table %s deleted", rt_id) + return ret + + +def delete_route_table_by_filters(compartment_id: str, vcn_id: str, + filters: Dict[str, Any], force: bool = False, + configuration: Configuration = None, + secrets: Secrets = None) -> OCIResponse: + """ + Search for a route table in VCN using the specified filters and + then deletes it. + + Parameters: + Required: + - compartment_id: the compartment id of the VCN + - vcn_id: the id of the VCN + - filters: the set of filters for the route table. + Please refer to + https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/api/core/models/oci.core.models.RouteTable.html# + for the route table filters. + """ + + client = oci_client(VirtualNetworkClient, configuration, secrets, + skip_deserialization=False) + + if compartment_id is None or vcn_id is None: + raise ActivityFailed('A compartment id or vcn id is required.') + else: + unfiltered = get_route_tables(client, compartment_id, vcn_id) + + if filters is None: + raise ActivityFailed(FILTER_ERR) + else: + filtered = filter_route_tables(unfiltered, filters) + + if (len(filtered) == 0): + raise ActivityFailed(FILTER_ERR) + else: + ret = client.delete_route_table(filtered[0].id).data + logger.debug("Route table %s deleted", + filtered[0].display_name) + return ret diff --git a/chaosoci/core/networking/common.py b/chaosoci/core/networking/common.py new file mode 100644 index 0000000..930fda0 --- /dev/null +++ b/chaosoci/core/networking/common.py @@ -0,0 +1,36 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +__all__ = ["get_route_table", "get_route_tables"] + +from typing import Any, Dict, List + +from chaoslib.exceptions import ActivityFailed + +from logzero import logger + +from oci.core import VirtualNetworkClient +from oci.core.models import (RouteRule, + RouteTable) + + +def get_route_tables(client: VirtualNetworkClient = None, + compartment_id: str = None, + vcn_id: str = None) -> List[RouteTable]: + """ + Returns a complete, unfiltered list of route tables of a vcn in the + compartment. + """ + + route_tables = [] + route_tables_raw = client.list_route_tables(compartment_id=compartment_id, + vcn_id=vcn_id) + route_tables.extend(route_tables_raw.data) + while route_tables_raw.has_next_page: + route_tables_raw = client.list_route_tables( + compartment_id=compartment_id, + vcn_id=vcn_id, + page=route_tables_raw.next_page) + route_tables.extend(route_tables_raw.data) + + return route_tables diff --git a/chaosoci/core/networking/filters.py b/chaosoci/core/networking/filters.py new file mode 100644 index 0000000..b116da6 --- /dev/null +++ b/chaosoci/core/networking/filters.py @@ -0,0 +1,48 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +__all__ = ["filter_route_tables"] + +from typing import Any, Dict, List + +from chaoslib.exceptions import ActivityFailed +from chaosoci.util.constants import FILTER_ERR + +from logzero import logger + +from oci.core import VirtualNetworkClient +from oci.core.models import (RouteRule, + RouteTable) + + +def filter_route_tables(route_tables: List[RouteTable] = None, + filters: Dict[str, Any] = None) -> List[RouteTable]: + """ + Return only those route tables that match the filters provided. + """ + route_tables = route_tables or None + + if route_tables is None: + raise ActivityFailed('No route tables were found.') + + filters_set = {x for x in filters} + + available_filters_set = {x for x in route_tables[0].attribute_map} + + # Partial filtering may return route tables we do not want. We avoid it. + if not filters_set.issubset(available_filters_set): + raise ActivityFailed(FILTER_ERR) + + # Walk the route tables and find those that match the given filters. + filtered = [] + for route_table in route_tables: + sentinel = True + for attr, val in filters.items(): + if val != getattr(route_table, attr, None): + sentinel = False + break + + if sentinel: + filtered.append(route_table) + + return filtered diff --git a/chaosoci/core/networking/probes.py b/chaosoci/core/networking/probes.py new file mode 100644 index 0000000..cd0ee5a --- /dev/null +++ b/chaosoci/core/networking/probes.py @@ -0,0 +1,49 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +__all__ = ['count_route_tables'] + +from typing import Any, Dict, List + +from chaoslib.exceptions import ActivityFailed +from chaoslib.types import Configuration, Secrets + +from chaosoci import oci_client + +from logzero import logger + +from oci.config import from_file +from oci.core import VirtualNetworkClient + +from .common import (get_route_tables) + +from .filters import (filter_route_tables) + + +def count_route_tables(filters: List[Dict[str, Any]], + compartment_id: str = None, + vcn_id: str = None, + configuration: Configuration = None, + secrets: Secrets = None) -> int: + """ + Returns the number of Route Tables in the compartment 'compartment_id' + and vcn 'vcn_id' and according to the given filters. + + Please refer to: https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/api/core/models/oci.core.models.RouteTable.html# + + for details on the available filters under the 'parameters' section. + """ # noqa: E501 + compartment_id = compartment_id or from_file().get('compartment') + + if compartment_id is None: + raise ActivityFailed('A valid compartment id is required.') + + client = oci_client(VirtualNetworkClient, configuration, secrets, + skip_deserialization=False) + + filters = filters or None + route_tables = get_route_tables(client, compartment_id, vcn_id) + if filters is not None: + return len(filter_route_tables(route_tables, filters=filters)) + else: + return len(route_tables) diff --git a/chaosoci/core/networking/rollbacks.py b/chaosoci/core/networking/rollbacks.py new file mode 100644 index 0000000..33503a2 --- /dev/null +++ b/chaosoci/core/networking/rollbacks.py @@ -0,0 +1,22 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +__all__ = ["delete_nat_rollback"] + +from random import choice +from typing import Any, Dict, List + +from chaoslib.exceptions import ActivityFailed +from chaoslib.types import Configuration, Secrets + +from chaosoci import oci_client +from chaosoci.types import OCIResponse + +from logzero import logger + +from oci.config import from_file +from oci.core import VirtualNetworkClient + +from .common import (get_route_tables) + +from .filters import (filter_route_tables) diff --git a/chaosoci/util/constants.py b/chaosoci/util/constants.py new file mode 100644 index 0000000..7203bc9 --- /dev/null +++ b/chaosoci/util/constants.py @@ -0,0 +1,4 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +FILTER_ERR = 'Some of the chosen filters were not found, we cannot continue.' diff --git a/docs/dev/contribute.md b/docs/dev/contribute.md new file mode 100644 index 0000000..2d651c8 --- /dev/null +++ b/docs/dev/contribute.md @@ -0,0 +1,56 @@ +[dco]: https://github.com/probot/dco#how-it-works +[oci-python-sdk]: https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/api/landing.html +[pep8]: https://pycodestyle.pycqa.org/en/latest/ +[signing-commits]: https://help.github.com/en/github/authenticating-to-github/signing-commits + +# Contributing to chaostoolkit-oci + +If you are interested to contribute to chaostoolkit-oci, you also need to install some additional libraries: + +``` +pip install -r requirements-dev.txt +``` + +Your contributions should follow the [OCI Python SDK API model][oci-python-sdk] for example: + +* Compute is under `chaosoci/core/compute`, +* VCN is under `chaosoci/core/vcn`, +* MySQL should be under `chaosoci/mysql`, and so on. + +Commits need to be [signed][signing-commits]. + +## Coding Style + +[PEP 8][pep8]. + +## Tests + +You also need to submit tests for your functions. Tests follow the package convention as the [OCI Python SDK API model][oci-python-sdk]. + +To run the tests for the project execute the following: + +``` +pytest +``` + +## External contributors + +If you wish to contribute to this project, follow this process: + +1. Fork this project +2. Create your issue branch (issue-xxx) +3. Write your code and push to your issue branch. +4. Raise a pull request to https://github.com/chaostoolkit-incubator/chaostoolkit-oci/master + +The Chaos Toolkit projects require all contributors must sign a +[Developer Certificate of Origin][dco] on each commit they would like to merge +into the master branch of the repository. Please, make sure you can abide by +the rules of the DCO before submitting a PR. + +## Tests + +To run the tests for the project execute the following: + +``` +pytest +``` \ No newline at end of file diff --git a/docs/setup/chaostoolkit.md b/docs/setup/chaostoolkit.md new file mode 100644 index 0000000..f87a5db --- /dev/null +++ b/docs/setup/chaostoolkit.md @@ -0,0 +1,30 @@ +# Installing chaostoolkit, chaostoolkit-oci and dependencies + +### Clone the repo + +``` +git clone https://github.com/oracle/chaostoolkit-oci.git +cd chaostoolkit-oci +``` + +### Installing chaostoolkit + +pip install -r requirements.txt + +Verify that the chaostoolkit has been installed properly: + +``` +chaos --version +``` + +### Installing chaostoolkit-oci + +``` +python setup.py develop +``` + +### Discovering capabilities + +``` +chaos discover --no-install chaostoolkit-oci +``` diff --git a/docs/setup/python.md b/docs/setup/python.md new file mode 100644 index 0000000..4598d6c --- /dev/null +++ b/docs/setup/python.md @@ -0,0 +1,33 @@ +# Installing Python3 + +Chaostoolkit requires Python 3.5+ and pip. + +### Oracle Linux + +Follow the guide here: https://yum.oracle.com/oracle-linux-python.html. + +### Ubuntu + +Follow the guide here: https://docs.python-guide.org/starting/install3/linux/#install3-linux. + +### macOS + +Follow the guide here: https://docs.python-guide.org/starting/install3/osx/#install3-osx. + +### Windows + +Follow the guide here: https://docs.python-guide.org/starting/install3/win/#install3-windows. + +# Installing pip + +### Linux and macOS + +``` +pip3 install -U pip --user +``` + +### Windows + +``` +python -m pip install -U pip +``` \ No newline at end of file diff --git a/docs/setup/venv.md b/docs/setup/venv.md new file mode 100644 index 0000000..6b92df5 --- /dev/null +++ b/docs/setup/venv.md @@ -0,0 +1,26 @@ +# Installing and creating a virtual environment + + +``` +pip3 install virtualenv --user +``` + +Follow the guide here: https://docs.python-guide.org/dev/virtualenvs/#virtualenvironments-ref. + +You can name your virtual environment oci or chaostk or another name of your preference e.g. : + +``` +virtualenv ~/.venvs/chaostk +``` + +Activate the environment on Linux/macOS: + +``` +source ~/.venvs/chaostk/bin/activate +``` + +Activate the environment on Windows: + +``` +source ~/.venvs/chaostk/Scripts/activate +``` \ No newline at end of file diff --git a/docs/use/experiments.md b/docs/use/experiments.md new file mode 100644 index 0000000..37688f2 --- /dev/null +++ b/docs/use/experiments.md @@ -0,0 +1,53 @@ +# Using chaostoolkit-oci + +### Creating experiments + +To use the probes and actions from this package, add the following to your +experiment file: + +```json +{ + "type": "action", + "name": "stop-a-compute-instance", + "provider": { + "type": "python", + "module": "chaosoci.core.compute.actions", + "func": "stop_instance", + "arguments": { + "instance_id": "ocid1.instance.oc1.uk-london-1.abwgiljr4hngf7ktirgpp4ebl3w7fdarvhe6if4tu4r7y4fh3tsde7vbm5lq" + } + } +} +``` + +That's it! + +Now, let us say we only want an action to be executed after probing that a given value is within +a desired threshold; simple enough, we need to add a probe to our experiment, as follows: + +``` +"type": "probe", +"name": "count-the-number-of-instances", +"tolerance": [2, 10], +"provider": { + "type": "python", + "module": "chaosoci.core.compute.probes", + "func": "count_instances", + "arguments": { + "filters": { + "region": "uk-london-1", + "lifecycle_state": "RUNNING" + } + } +} +``` + +For a list of available filters please refer to: [oci.core.models.Instance](https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/api/core/models/oci.core.models.Instance.html#oci.core.models.Instance). + +Please explore the code to see existing probes and actions. + +### Running experiments + +``` +chaos run experiment.json +``` diff --git a/requirements.txt b/requirements.txt index 177523f..5ca2e16 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1,3 @@ -oci -chaostoolkit-lib>=1.9 +oci>=2.16 +chaostoolkit>=1.4 +chaostoolkit-lib>=1.10 diff --git a/setup.py b/setup.py index b00e65b..46636bb 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,16 @@ #!/usr/bin/env python +# Copyright 2020, Oracle Corporation and/or its affiliates. """chaostoolkit OCI builder and installer""" +from chaosoci import __version__ + import sys import io import setuptools sys.path.insert(0, ".") -from chaosoci import __version__ + sys.path.remove(".") name = 'chaostoolkit-oci' @@ -35,7 +38,8 @@ license = 'Apache License Version 2.0' packages = [ 'chaosoci', - 'chaosoci.core.compute' + 'chaosoci.core.compute', + 'chaosoci.core.networking' ] needs_pytest = set(['pytest', 'test']).intersection(sys.argv) @@ -43,11 +47,11 @@ test_require = [] with io.open('requirements-dev.txt') as f: - test_require = [l.strip() for l in f if not l.startswith('#')] + test_require = [line.strip() for line in f if not line.startswith('#')] install_require = [] with io.open('requirements.txt') as f: - install_require = [l.strip() for l in f if not l.startswith('#')] + install_require = [line.strip() for line in f if not line.startswith('#')] setup_params = dict( name=name, diff --git a/tests/core/networking/test_networking_actions.py b/tests/core/networking/test_networking_actions.py new file mode 100644 index 0000000..11f974e --- /dev/null +++ b/tests/core/networking/test_networking_actions.py @@ -0,0 +1,62 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +import pytest + +from unittest.mock import MagicMock, patch + +from chaoslib.exceptions import ActivityFailed + +from chaosoci.core.networking.actions import (delete_route_table_by_id, + delete_route_table_by_filters) +from chaosoci.util.constants import FILTER_ERR +# FILTER_ERR = 'Some of the chosen filters were not found, we cannot continue.' + +@patch('chaosoci.core.networking.actions.oci_client', autospec=True) +def test_delete_route_table_by_id(oci_client): + network_client = MagicMock() + oci_client.return_value = network_client + rt_id = "ocid1.routetable.oc1.phx.aawnm2cdxq3naniep5dsiixtchqjuypcx7l7" + rt_ids = [rt_id, ""] + for id in rt_ids: + if id == rt_id: + delete_route_table_by_id(id) + network_client.delete_route_table.assert_called_with(rt_id=id) + else: + with pytest.raises(ActivityFailed) as f: + delete_route_table_by_id(id) + assert 'A route table id is required.' + +@patch('chaosoci.core.networking.actions.filter_route_tables', autospec=True) +@patch('chaosoci.core.networking.actions.get_route_tables', autospec=True) +@patch('chaosoci.core.networking.actions.oci_client', autospec=True) +def test_delete_route_table_by_filters(oci_client, get_route_tables, + filter_route_tables): + network_client = MagicMock() + oci_client.return_value = network_client + + c_id = "ocid1.compartment.oc1..oadsocmof6r6ksovxmda44ikwxje7xxu" + vcn_id = "ocid1.vcn.oc1.phx.amaaaaaapwxjxiqavc6zohqv4whr6y65qwwjcexhex" + + c_ids = [c_id, None] + vcn_ids = [vcn_id, None] + filters = [[{'display_name': 'random_name', 'region': 'uk-london-1'}], + None] + + for c in c_ids: + for v in vcn_ids: + for f in filters: + if c is None or v is None: + with pytest.raises(ActivityFailed) as c_failed: + delete_route_table_by_filters(c, v, f) + assert 'A compartment id or vcn id is required.' + elif f is None: + with pytest.raises(ActivityFailed) as f_failed: + delete_route_table_by_filters(c, v, f) + assert FILTER_ERR + else: + with pytest.raises(ActivityFailed) as rt_failed: + delete_route_table_by_filters(c, v, f) + network_client.delete_route_table.assert_called_with( + filter_route_tables(route_tables=get_route_tables( + oci_client, c, v), filters=f)[0].id) diff --git a/tests/core/networking/test_networking_probes.py b/tests/core/networking/test_networking_probes.py new file mode 100644 index 0000000..5d1c614 --- /dev/null +++ b/tests/core/networking/test_networking_probes.py @@ -0,0 +1,35 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +import pytest + +from unittest import TestCase as T +from unittest.mock import MagicMock, patch + +from chaoslib.exceptions import ActivityFailed + +from chaosoci.core.networking.probes import (count_route_tables, + filter_route_tables) + +@patch('chaosoci.core.networking.probes.filter_route_tables', autospec=True) +@patch('chaosoci.core.networking.probes.get_route_tables', autospec=True) +@patch('chaosoci.core.networking.probes.oci_client', autospec=True) +def test_count_route_tables(oci_client, get_route_tables, filter_route_tables): + network_client = MagicMock() + oci_client.return_value = network_client + + c_id = "ocid1.compartment.oc1..oadsocmof6r6ksovxmda44ikwxje7xxu" + filters = [{'display_name': 'random_name', 'region': 'uk-london-1'}] + + c_ids = [c_id] + + for id in c_ids: + if id == c_id: + count_route_tables(filters=filters, compartment_id=id) + filter_route_tables.assert_called_with( + route_tables=get_route_tables( + oci_client, id), filters=filters) + else: + with pytest.raises(ActivityFailed) as f: + count_route_tables(filters=filters, compartment_id=id) + assert 'A valid compartment id is required.' diff --git a/tests/core/networking/test_networking_rollbacks.py b/tests/core/networking/test_networking_rollbacks.py new file mode 100644 index 0000000..7be5e9e --- /dev/null +++ b/tests/core/networking/test_networking_rollbacks.py @@ -0,0 +1,10 @@ +# coding: utf-8 +# Copyright 2020, Oracle Corporation and/or its affiliates. + +import pytest + +from unittest.mock import MagicMock, patch + +from oci.exceptions import ServiceError + +from chaoslib.exceptions import ActivityFailed diff --git a/tests/test_discovery.py b/tests/test_discovery.py index c3c13dd..b237d49 100644 --- a/tests/test_discovery.py +++ b/tests/test_discovery.py @@ -1,4 +1,5 @@ # -*- coding: utf-8 -*- +# Copyright 2020, Oracle Corporation and/or its affiliates. import pytest @@ -9,4 +10,4 @@ def test_discover_extension_capabilities(): discovery = discover(discover_system=False) assert discovery["extension"]["name"] == "chaostoolkit-oci" assert discovery["extension"]["version"] == __version__ - assert len(discovery["activities"]) > 0 \ No newline at end of file + assert len(discovery["activities"]) > 0