diff --git a/docs/dev/code_reference/models/cloud.md b/docs/dev/code_reference/models/cloud.md new file mode 100644 index 0000000..a874e59 --- /dev/null +++ b/docs/dev/code_reference/models/cloud.md @@ -0,0 +1,5 @@ +# Cloud + +::: pynautobot.models.cloud + options: + show_submodules: true \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index cfaa5c1..ca3cc92 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -163,6 +163,7 @@ nav: - Util: "dev/code_reference/core/util.md" - Models: - Circuits: "dev/code_reference/models/circuits.md" + - Cloud: "dev/code_reference/models/cloud.md" - DCIM: "dev/code_reference/models/dcim.md" - Extras: "dev/code_reference/models/extras.md" - IPAM: "dev/code_reference/models/ipam.md" diff --git a/pynautobot/core/api.py b/pynautobot/core/api.py index 902acb4..1a0840b 100644 --- a/pynautobot/core/api.py +++ b/pynautobot/core/api.py @@ -43,6 +43,7 @@ class Api(object): Attributes: dcim: An instance of the `App` class providing access to DCIM endpoints. + cloud: An instance of the `App` class providing access to Cloud endpoints. ipam: An instance of the `App` class providing access to IPAM endpoints. circuits: An instance of the `App` class providing access to Circuits endpoints. tenancy: An instance of the `App` class providing access to Tenancy endpoints. @@ -103,6 +104,7 @@ def __init__( self.dcim = App(self, "dcim") self.ipam = App(self, "ipam") + self.cloud = App(self, "cloud") self.circuits = App(self, "circuits") self.tenancy = App(self, "tenancy") self.extras = App(self, "extras") diff --git a/pynautobot/core/app.py b/pynautobot/core/app.py index 68c7f65..be74ed2 100644 --- a/pynautobot/core/app.py +++ b/pynautobot/core/app.py @@ -18,7 +18,7 @@ from pynautobot.core.endpoint import Endpoint, JobsEndpoint, GraphqlEndpoint from pynautobot.core.query import Request -from pynautobot.models import circuits, dcim, extras, ipam, users, virtualization +from pynautobot.models import circuits, cloud, dcim, extras, ipam, users, virtualization logger = logging.getLogger(__name__) @@ -37,6 +37,7 @@ class App(object): models = { "dcim": dcim, + "cloud": cloud, "ipam": ipam, "circuits": circuits, "virtualization": virtualization, diff --git a/pynautobot/models/cloud.py b/pynautobot/models/cloud.py new file mode 100644 index 0000000..28e16d7 --- /dev/null +++ b/pynautobot/models/cloud.py @@ -0,0 +1,17 @@ +# (c) 2017 DigitalOcean +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# This file has been modified by NetworktoCode, LLC. + +# Reserved for cloud models diff --git a/tests/integration/test_cloud.py b/tests/integration/test_cloud.py new file mode 100644 index 0000000..0309d7c --- /dev/null +++ b/tests/integration/test_cloud.py @@ -0,0 +1,129 @@ +from packaging import version + +import pytest + + +class TestCloudResourceType: + @pytest.fixture + def skipif_version(self, nb_client): + """Retrieve the current Nautobot version and skip the test if less than 2.3.""" + status = nb_client.status() + nautobot_version = status.get("nautobot-version") + if version.parse(nautobot_version) < version.parse("2.3"): + pytest.skip("Cloud resources are only in Nautobot 2.3+") + + return nautobot_version + + def test_cloud_resource_types(self, skipif_version, nb_client): + """Verify we can CRUD a cloud resource type.""" + assert skipif_version + + # Create + cloud_resource_type = nb_client.cloud.cloud_resource_types.create( + name="Test", provider="Dell", content_types=["cloud.cloudservice"] + ) + assert cloud_resource_type + + # Read + test_cloud_resource_type = nb_client.cloud.cloud_resource_types.get(name="Test") + assert test_cloud_resource_type.name == "Test" + + # Update + test_cloud_resource_type.name = "Updated Test" + test_cloud_resource_type.save() + updated_cloud_resource_type = nb_client.cloud.cloud_resource_types.get(name="Updated Test") + assert updated_cloud_resource_type.name == "Updated Test" + + # Delete + updated_cloud_resource_type.delete() + deleted_cloud_resource_type = nb_client.cloud.cloud_resource_types.get(name="Updated Test") + assert not deleted_cloud_resource_type + + def test_cloud_accounts(self, skipif_version, nb_client): + """Verify we can CRUD a cloud account.""" + assert skipif_version + + # Create + cloud_account = nb_client.cloud.cloud_accounts.create(name="TestAcct", provider="Dell", account_number="424242") + assert cloud_account + + # Read + test_cloud_account = nb_client.cloud.cloud_accounts.get(name="TestAcct") + assert test_cloud_account.name == "TestAcct" + + # Update + test_cloud_account.name = "Updated TestAcct" + test_cloud_account.save() + updated_cloud_account = nb_client.cloud.cloud_accounts.get(name="Updated TestAcct") + assert updated_cloud_account.name == "Updated TestAcct" + + # Delete + updated_cloud_account.delete() + deleted_cloud_account = nb_client.cloud.cloud_accounts.get(name="Updated TestAcct") + assert not deleted_cloud_account + + def test_cloud_services(self, skipif_version, nb_client): + """Verify we can CRUD a cloud service.""" + assert skipif_version + + # Create + cloud_resource_type = nb_client.cloud.cloud_resource_types.create( + name="Test", provider="Dell", content_types=["cloud.cloudservice"] + ) + cloud_account = nb_client.cloud.cloud_accounts.create(name="TestAcct", provider="Dell", account_number="424242") + cloud_service = nb_client.cloud.cloud_services.create( + name="TestService", cloud_resource_type="Test", cloud_account="TestAcct" + ) + assert cloud_service + + # Read + test_cloud_service = nb_client.cloud.cloud_services.get(name="TestService") + assert test_cloud_service.name == "TestService" + + # Update + test_cloud_service.name = "Updated TestService" + test_cloud_service.save() + updated_cloud_service = nb_client.cloud.cloud_services.get(name="Updated TestService") + assert updated_cloud_service.name == "Updated TestService" + + # Delete + updated_cloud_service.delete() + deleted_cloud_service = nb_client.cloud.cloud_services.get(name="Updated TestService") + assert not deleted_cloud_service + + # Cleanup + cloud_resource_type.delete() + cloud_account.delete() + + def test_cloud_networks(self, skipif_version, nb_client): + """Verify we can CRUD a cloud service.""" + assert skipif_version + + # Create + cloud_resource_type = nb_client.cloud.cloud_resource_types.create( + name="Test", provider="Dell", content_types=["cloud.cloudnetwork"] + ) + cloud_account = nb_client.cloud.cloud_accounts.create(name="TestAcct", provider="Dell", account_number="424242") + cloud_network = nb_client.cloud.cloud_networks.create( + name="TestNetwork", cloud_resource_type="Test", cloud_account="TestAcct" + ) + assert cloud_network + + # Read + test_cloud_network = nb_client.cloud.cloud_networks.get(name="TestNetwork") + assert test_cloud_network.name == "TestNetwork" + + # Update + test_cloud_network.name = "Updated TestNetwork" + test_cloud_network.save() + updated_cloud_network = nb_client.cloud.cloud_networks.get(name="Updated TestNetwork") + assert updated_cloud_network.name == "Updated TestNetwork" + + # Delete + updated_cloud_network.delete() + deleted_cloud_network = nb_client.cloud.cloud_networks.get(name="Updated TestNetwork") + assert not deleted_cloud_network + + # Cleanup + cloud_resource_type.delete() + cloud_account.delete()