New module: Add Pritunl VPN organization module (net_tools/pritunl/) (#804)

This commit is contained in:
Florian Dambrine 2021-04-08 13:37:06 -07:00 committed by GitHub
parent 4b71e088c7
commit f0b7c6351e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 1064 additions and 233 deletions

View file

@ -9,7 +9,9 @@ import json
import pytest
from ansible.module_utils.common.dict_transformations import dict_merge
from ansible.module_utils.six import iteritems
from ansible_collections.community.general.plugins.module_utils.net_tools.pritunl import api
from ansible_collections.community.general.plugins.module_utils.net_tools.pritunl import (
api,
)
from mock import MagicMock
__metaclass__ = type
@ -17,6 +19,237 @@ __metaclass__ = type
# Pritunl Mocks
PRITUNL_ORGS = [
{
"auth_api": False,
"name": "Foo",
"auth_token": None,
"user_count": 0,
"auth_secret": None,
"id": "csftwlu6uhralzi2dpmhekz3",
},
{
"auth_api": False,
"name": "GumGum",
"auth_token": None,
"user_count": 3,
"auth_secret": None,
"id": "58070daee63f3b2e6e472c36",
},
{
"auth_api": False,
"name": "Bar",
"auth_token": None,
"user_count": 0,
"auth_secret": None,
"id": "v1sncsxxybnsylc8gpqg85pg",
},
]
NEW_PRITUNL_ORG = {
"auth_api": False,
"name": "NewOrg",
"auth_token": None,
"user_count": 0,
"auth_secret": None,
"id": "604a140ae63f3b36bc34c7bd",
}
PRITUNL_USERS = [
{
"auth_type": "google",
"dns_servers": None,
"pin": True,
"dns_suffix": None,
"servers": [
{
"status": False,
"platform": None,
"server_id": "580711322bb66c1d59b9568f",
"virt_address6": "fd00:c0a8: 9700: 0: 192: 168: 101: 27",
"virt_address": "192.168.101.27",
"name": "vpn-A",
"real_address": None,
"connected_since": None,
"id": "580711322bb66c1d59b9568f",
"device_name": None,
},
{
"status": False,
"platform": None,
"server_id": "5dad2cc6e63f3b3f4a6dfea5",
"virt_address6": "fd00:c0a8:f200: 0: 192: 168: 201: 37",
"virt_address": "192.168.201.37",
"name": "vpn-B",
"real_address": None,
"connected_since": None,
"id": "5dad2cc6e63f3b3f4a6dfea5",
"device_name": None,
},
],
"disabled": False,
"network_links": [],
"port_forwarding": [],
"id": "58070dafe63f3b2e6e472c3b",
"organization_name": "GumGum",
"type": "server",
"email": "bot@company.com",
"status": True,
"dns_mapping": None,
"otp_secret": "123456789ABCDEFG",
"client_to_client": False,
"sso": "google",
"bypass_secondary": False,
"groups": ["admin", "multiregion"],
"audit": False,
"name": "bot",
"gravatar": True,
"otp_auth": True,
"organization": "58070daee63f3b2e6e472c36",
},
{
"auth_type": "google",
"dns_servers": None,
"pin": True,
"dns_suffix": None,
"servers": [
{
"status": False,
"platform": None,
"server_id": "580711322bb66c1d59b9568f",
"virt_address6": "fd00:c0a8: 9700: 0: 192: 168: 101: 27",
"virt_address": "192.168.101.27",
"name": "vpn-A",
"real_address": None,
"connected_since": None,
"id": "580711322bb66c1d59b9568f",
"device_name": None,
},
{
"status": False,
"platform": None,
"server_id": "5dad2cc6e63f3b3f4a6dfea5",
"virt_address6": "fd00:c0a8:f200: 0: 192: 168: 201: 37",
"virt_address": "192.168.201.37",
"name": "vpn-B",
"real_address": None,
"connected_since": None,
"id": "5dad2cc6e63f3b3f4a6dfea5",
"device_name": None,
},
],
"disabled": False,
"network_links": [],
"port_forwarding": [],
"id": "58070dafe63f3b2e6e472c3b",
"organization_name": "GumGum",
"type": "client",
"email": "florian@company.com",
"status": True,
"dns_mapping": None,
"otp_secret": "123456789ABCDEFG",
"client_to_client": False,
"sso": "google",
"bypass_secondary": False,
"groups": ["web", "database"],
"audit": False,
"name": "florian",
"gravatar": True,
"otp_auth": True,
"organization": "58070daee63f3b2e6e472c36",
},
{
"auth_type": "google",
"dns_servers": None,
"pin": True,
"dns_suffix": None,
"servers": [
{
"status": False,
"platform": None,
"server_id": "580711322bb66c1d59b9568f",
"virt_address6": "fd00:c0a8: 9700: 0: 192: 168: 101: 27",
"virt_address": "192.168.101.27",
"name": "vpn-A",
"real_address": None,
"connected_since": None,
"id": "580711322bb66c1d59b9568f",
"device_name": None,
},
{
"status": False,
"platform": None,
"server_id": "5dad2cc6e63f3b3f4a6dfea5",
"virt_address6": "fd00:c0a8:f200: 0: 192: 168: 201: 37",
"virt_address": "192.168.201.37",
"name": "vpn-B",
"real_address": None,
"connected_since": None,
"id": "5dad2cc6e63f3b3f4a6dfea5",
"device_name": None,
},
],
"disabled": False,
"network_links": [],
"port_forwarding": [],
"id": "58070dafe63f3b2e6e472c3b",
"organization_name": "GumGum",
"type": "server",
"email": "ops@company.com",
"status": True,
"dns_mapping": None,
"otp_secret": "123456789ABCDEFG",
"client_to_client": False,
"sso": "google",
"bypass_secondary": False,
"groups": ["web", "database"],
"audit": False,
"name": "ops",
"gravatar": True,
"otp_auth": True,
"organization": "58070daee63f3b2e6e472c36",
},
]
NEW_PRITUNL_USER = {
"auth_type": "local",
"disabled": False,
"dns_servers": None,
"otp_secret": "6M4UWP2BCJBSYZAT",
"name": "alice",
"pin": False,
"dns_suffix": None,
"client_to_client": False,
"email": "alice@company.com",
"organization_name": "GumGum",
"bypass_secondary": False,
"groups": ["a", "b"],
"organization": "58070daee63f3b2e6e472c36",
"port_forwarding": [],
"type": "client",
"id": "590add71e63f3b72d8bb951a",
}
NEW_PRITUNL_USER_UPDATED = dict_merge(
NEW_PRITUNL_USER,
{
"disabled": True,
"name": "bob",
"email": "bob@company.com",
"groups": ["c", "d"],
},
)
class PritunlEmptyOrganizationMock(MagicMock):
"""Pritunl API Mock for organization GET API calls."""
def getcode(self):
return 200
def read(self):
return json.dumps([])
class PritunlListOrganizationMock(MagicMock):
"""Pritunl API Mock for organization GET API calls."""
@ -25,34 +258,7 @@ class PritunlListOrganizationMock(MagicMock):
return 200
def read(self):
return json.dumps(
[
{
"auth_api": False,
"name": "Foo",
"auth_token": None,
"user_count": 0,
"auth_secret": None,
"id": "csftwlu6uhralzi2dpmhekz3",
},
{
"auth_api": False,
"name": "GumGum",
"auth_token": None,
"user_count": 3,
"auth_secret": None,
"id": "58070daee63f3b2e6e472c36",
},
{
"auth_api": False,
"name": "Bar",
"auth_token": None,
"user_count": 0,
"auth_secret": None,
"id": "v1sncsxxybnsylc8gpqg85pg",
},
]
)
return json.dumps(PRITUNL_ORGS)
class PritunlListUserMock(MagicMock):
@ -62,163 +268,7 @@ class PritunlListUserMock(MagicMock):
return 200
def read(self):
return json.dumps(
[
{
"auth_type": "google",
"dns_servers": None,
"pin": True,
"dns_suffix": None,
"servers": [
{
"status": False,
"platform": None,
"server_id": "580711322bb66c1d59b9568f",
"virt_address6": "fd00:c0a8: 9700: 0: 192: 168: 101: 27",
"virt_address": "192.168.101.27",
"name": "vpn-A",
"real_address": None,
"connected_since": None,
"id": "580711322bb66c1d59b9568f",
"device_name": None,
},
{
"status": False,
"platform": None,
"server_id": "5dad2cc6e63f3b3f4a6dfea5",
"virt_address6": "fd00:c0a8:f200: 0: 192: 168: 201: 37",
"virt_address": "192.168.201.37",
"name": "vpn-B",
"real_address": None,
"connected_since": None,
"id": "5dad2cc6e63f3b3f4a6dfea5",
"device_name": None,
},
],
"disabled": False,
"network_links": [],
"port_forwarding": [],
"id": "58070dafe63f3b2e6e472c3b",
"organization_name": "GumGum",
"type": "server",
"email": "bot@company.com",
"status": True,
"dns_mapping": None,
"otp_secret": "123456789ABCDEFG",
"client_to_client": False,
"sso": "google",
"bypass_secondary": False,
"groups": ["admin", "multiregion"],
"audit": False,
"name": "bot",
"gravatar": True,
"otp_auth": True,
"organization": "58070daee63f3b2e6e472c36",
},
{
"auth_type": "google",
"dns_servers": None,
"pin": True,
"dns_suffix": None,
"servers": [
{
"status": False,
"platform": None,
"server_id": "580711322bb66c1d59b9568f",
"virt_address6": "fd00:c0a8: 9700: 0: 192: 168: 101: 27",
"virt_address": "192.168.101.27",
"name": "vpn-A",
"real_address": None,
"connected_since": None,
"id": "580711322bb66c1d59b9568f",
"device_name": None,
},
{
"status": False,
"platform": None,
"server_id": "5dad2cc6e63f3b3f4a6dfea5",
"virt_address6": "fd00:c0a8:f200: 0: 192: 168: 201: 37",
"virt_address": "192.168.201.37",
"name": "vpn-B",
"real_address": None,
"connected_since": None,
"id": "5dad2cc6e63f3b3f4a6dfea5",
"device_name": None,
},
],
"disabled": False,
"network_links": [],
"port_forwarding": [],
"id": "58070dafe63f3b2e6e472c3b",
"organization_name": "GumGum",
"type": "client",
"email": "florian@company.com",
"status": True,
"dns_mapping": None,
"otp_secret": "123456789ABCDEFG",
"client_to_client": False,
"sso": "google",
"bypass_secondary": False,
"groups": ["web", "database"],
"audit": False,
"name": "florian",
"gravatar": True,
"otp_auth": True,
"organization": "58070daee63f3b2e6e472c36",
},
{
"auth_type": "google",
"dns_servers": None,
"pin": True,
"dns_suffix": None,
"servers": [
{
"status": False,
"platform": None,
"server_id": "580711322bb66c1d59b9568f",
"virt_address6": "fd00:c0a8: 9700: 0: 192: 168: 101: 27",
"virt_address": "192.168.101.27",
"name": "vpn-A",
"real_address": None,
"connected_since": None,
"id": "580711322bb66c1d59b9568f",
"device_name": None,
},
{
"status": False,
"platform": None,
"server_id": "5dad2cc6e63f3b3f4a6dfea5",
"virt_address6": "fd00:c0a8:f200: 0: 192: 168: 201: 37",
"virt_address": "192.168.201.37",
"name": "vpn-B",
"real_address": None,
"connected_since": None,
"id": "5dad2cc6e63f3b3f4a6dfea5",
"device_name": None,
},
],
"disabled": False,
"network_links": [],
"port_forwarding": [],
"id": "58070dafe63f3b2e6e472c3b",
"organization_name": "GumGum",
"type": "server",
"email": "ops@company.com",
"status": True,
"dns_mapping": None,
"otp_secret": "123456789ABCDEFG",
"client_to_client": False,
"sso": "google",
"bypass_secondary": False,
"groups": ["web", "database"],
"audit": False,
"name": "ops",
"gravatar": True,
"otp_auth": True,
"organization": "58070daee63f3b2e6e472c36",
},
]
)
return json.dumps(PRITUNL_USERS)
class PritunlErrorMock(MagicMock):
@ -231,6 +281,22 @@ class PritunlErrorMock(MagicMock):
return "{}"
class PritunlPostOrganizationMock(MagicMock):
def getcode(self):
return 200
def read(self):
return json.dumps(NEW_PRITUNL_ORG)
class PritunlListOrganizationAfterPostMock(MagicMock):
def getcode(self):
return 200
def read(self):
return json.dumps(PRITUNL_ORGS + [NEW_PRITUNL_ORG])
class PritunlPostUserMock(MagicMock):
"""Pritunl API Mock for POST API calls."""
@ -238,28 +304,7 @@ class PritunlPostUserMock(MagicMock):
return 200
def read(self):
return json.dumps(
[
{
"auth_type": "local",
"disabled": False,
"dns_servers": None,
"otp_secret": "6M4UWP2BCJBSYZAT",
"name": "alice",
"pin": False,
"dns_suffix": None,
"client_to_client": False,
"email": "alice@company.com",
"organization_name": "GumGum",
"bypass_secondary": False,
"groups": ["a", "b"],
"organization": "58070daee63f3b2e6e472c36",
"port_forwarding": [],
"type": "client",
"id": "590add71e63f3b72d8bb951a",
}
]
)
return json.dumps([NEW_PRITUNL_USER])
class PritunlPutUserMock(MagicMock):
@ -269,26 +314,17 @@ class PritunlPutUserMock(MagicMock):
return 200
def read(self):
return json.dumps(
{
"auth_type": "local",
"disabled": True,
"dns_servers": None,
"otp_secret": "WEJANJYMF3Q2QSLG",
"name": "bob",
"pin": False,
"dns_suffix": False,
"client_to_client": False,
"email": "bob@company.com",
"organization_name": "GumGum",
"bypass_secondary": False,
"groups": ["c", "d"],
"organization": "58070daee63f3b2e6e472c36",
"port_forwarding": [],
"type": "client",
"id": "590add71e63f3b72d8bb951a",
}
)
return json.dumps(NEW_PRITUNL_USER_UPDATED)
class PritunlDeleteOrganizationMock(MagicMock):
"""Pritunl API Mock for DELETE API calls."""
def getcode(self):
return 200
def read(self):
return "{}"
class PritunlDeleteUserMock(MagicMock):
@ -321,14 +357,21 @@ def pritunl_settings():
}
@pytest.fixture
def pritunl_organization_data():
return {
"name": NEW_PRITUNL_ORG["name"],
}
@pytest.fixture
def pritunl_user_data():
return {
"name": "alice",
"email": "alice@company.com",
"groups": ["a", "b"],
"disabled": False,
"type": "client",
"name": NEW_PRITUNL_USER["name"],
"email": NEW_PRITUNL_USER["email"],
"groups": NEW_PRITUNL_USER["groups"],
"disabled": NEW_PRITUNL_USER["disabled"],
"type": NEW_PRITUNL_USER["type"],
}
@ -347,6 +390,11 @@ def get_pritunl_error_mock():
return PritunlErrorMock()
@pytest.fixture
def post_pritunl_organization_mock():
return PritunlPostOrganizationMock()
@pytest.fixture
def post_pritunl_user_mock():
return PritunlPostUserMock()
@ -357,6 +405,11 @@ def put_pritunl_user_mock():
return PritunlPutUserMock()
@pytest.fixture
def delete_pritunl_organization_mock():
return PritunlDeleteOrganizationMock()
@pytest.fixture
def delete_pritunl_user_mock():
return PritunlDeleteUserMock()
@ -460,6 +513,25 @@ class TestPritunlApi:
assert user["name"] == user_expected
# Test for POST operation on Pritunl API
def test_add_pritunl_organization(
self,
pritunl_settings,
pritunl_organization_data,
post_pritunl_organization_mock,
):
api._post_pritunl_organization = post_pritunl_organization_mock()
create_response = api.post_pritunl_organization(
**dict_merge(
pritunl_settings,
{"organization_name": pritunl_organization_data["name"]},
)
)
# Ensure provided settings match with the ones returned by Pritunl
for k, v in iteritems(pritunl_organization_data):
assert create_response[k] == v
@pytest.mark.parametrize("org_id", [("58070daee63f3b2e6e472c36")])
def test_add_and_update_pritunl_user(
self,
@ -513,6 +585,24 @@ class TestPritunlApi:
assert update_response[k] == create_response[k]
# Test for DELETE operation on Pritunl API
@pytest.mark.parametrize("org_id", [("58070daee63f3b2e6e472c36")])
def test_delete_pritunl_organization(
self, pritunl_settings, org_id, delete_pritunl_organization_mock
):
api._delete_pritunl_organization = delete_pritunl_organization_mock()
response = api.delete_pritunl_organization(
**dict_merge(
pritunl_settings,
{
"organization_id": org_id,
},
)
)
assert response == {}
@pytest.mark.parametrize(
"org_id,user_id", [("58070daee63f3b2e6e472c36", "590add71e63f3b72d8bb951a")]
)

View file

@ -0,0 +1,204 @@
# -*- coding: utf-8 -*-
# (c) 2021 Florian Dambrine <android.florian@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
import sys
from ansible.module_utils.common.dict_transformations import dict_merge
from ansible.module_utils.six import iteritems
from ansible_collections.community.general.plugins.modules.net_tools.pritunl import (
pritunl_org,
)
from ansible_collections.community.general.tests.unit.compat.mock import patch
from ansible_collections.community.general.tests.unit.plugins.module_utils.net_tools.pritunl.test_api import (
PritunlDeleteOrganizationMock,
PritunlListOrganizationMock,
PritunlListOrganizationAfterPostMock,
PritunlPostOrganizationMock,
)
from ansible_collections.community.general.tests.unit.plugins.modules.utils import (
AnsibleExitJson,
AnsibleFailJson,
ModuleTestCase,
set_module_args,
)
__metaclass__ = type
class TestPritunlOrg(ModuleTestCase):
def setUp(self):
super(TestPritunlOrg, self).setUp()
self.module = pritunl_org
# Add backward compatibility
if sys.version_info < (3, 2):
self.assertRegex = self.assertRegexpMatches
def tearDown(self):
super(TestPritunlOrg, self).tearDown()
def patch_add_pritunl_organization(self, **kwds):
return patch(
"ansible_collections.community.general.plugins.module_utils.net_tools.pritunl.api._post_pritunl_organization",
autospec=True,
**kwds
)
def patch_delete_pritunl_organization(self, **kwds):
return patch(
"ansible_collections.community.general.plugins.module_utils.net_tools.pritunl.api._delete_pritunl_organization",
autospec=True,
**kwds
)
def patch_get_pritunl_organizations(self, **kwds):
return patch(
"ansible_collections.community.general.plugins.module_utils.net_tools.pritunl.api._get_pritunl_organizations",
autospec=True,
**kwds
)
def test_without_parameters(self):
"""Test without parameters"""
set_module_args({})
with self.assertRaises(AnsibleFailJson):
self.module.main()
def test_present(self):
"""Test Pritunl organization creation."""
org_params = {"name": "NewOrg"}
set_module_args(
dict_merge(
{
"pritunl_api_token": "token",
"pritunl_api_secret": "secret",
"pritunl_url": "https://pritunl.domain.com",
},
org_params,
)
)
# Test creation
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as mock_get:
with self.patch_add_pritunl_organization(
side_effect=PritunlPostOrganizationMock
) as mock_add:
with self.assertRaises(AnsibleExitJson) as create_result:
self.module.main()
create_exc = create_result.exception.args[0]
self.assertTrue(create_exc["changed"])
self.assertEqual(create_exc["response"]["name"], org_params["name"])
self.assertEqual(create_exc["response"]["user_count"], 0)
# Test module idempotency
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationAfterPostMock
) as mock_get:
with self.patch_add_pritunl_organization(
side_effect=PritunlPostOrganizationMock
) as mock_add:
with self.assertRaises(AnsibleExitJson) as idempotent_result:
self.module.main()
idempotent_exc = idempotent_result.exception.args[0]
# Ensure both calls resulted in the same returned value
# except for changed which sould be false the second time
for k, v in iteritems(idempotent_exc):
if k == "changed":
self.assertFalse(idempotent_exc[k])
else:
self.assertEqual(create_exc[k], idempotent_exc[k])
def test_absent(self):
"""Test organization removal from Pritunl."""
org_params = {"name": "NewOrg"}
set_module_args(
dict_merge(
{
"state": "absent",
"pritunl_api_token": "token",
"pritunl_api_secret": "secret",
"pritunl_url": "https://pritunl.domain.com",
},
org_params,
)
)
# Test deletion
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationAfterPostMock
) as mock_get:
with self.patch_delete_pritunl_organization(
side_effect=PritunlDeleteOrganizationMock
) as mock_delete:
with self.assertRaises(AnsibleExitJson) as delete_result:
self.module.main()
delete_exc = delete_result.exception.args[0]
self.assertTrue(delete_exc["changed"])
self.assertEqual(delete_exc["response"], {})
# Test module idempotency
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as mock_get:
with self.patch_delete_pritunl_organization(
side_effect=PritunlDeleteOrganizationMock
) as mock_add:
with self.assertRaises(AnsibleExitJson) as idempotent_result:
self.module.main()
idempotent_exc = idempotent_result.exception.args[0]
# Ensure both calls resulted in the same returned value
# except for changed which sould be false the second time
self.assertFalse(idempotent_exc["changed"])
self.assertEqual(idempotent_exc["response"], delete_exc["response"])
def test_absent_with_existing_users(self):
"""Test organization removal with attached users should fail except if force is true."""
module_args = {
"state": "absent",
"pritunl_api_token": "token",
"pritunl_api_secret": "secret",
"pritunl_url": "https://pritunl.domain.com",
"name": "GumGum",
}
set_module_args(module_args)
# Test deletion
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as mock_get:
with self.patch_delete_pritunl_organization(
side_effect=PritunlDeleteOrganizationMock
) as mock_delete:
with self.assertRaises(AnsibleFailJson) as failure_result:
self.module.main()
failure_exc = failure_result.exception.args[0]
self.assertRegex(failure_exc["msg"], "Can not remove organization")
# Switch force=True which should run successfully
set_module_args(dict_merge(module_args, {"force": True}))
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as mock_get:
with self.patch_delete_pritunl_organization(
side_effect=PritunlDeleteOrganizationMock
) as mock_delete:
with self.assertRaises(AnsibleExitJson) as delete_result:
self.module.main()
delete_exc = delete_result.exception.args[0]
self.assertTrue(delete_exc["changed"])

View file

@ -0,0 +1,137 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Florian Dambrine <android.florian@gmail.com>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
import sys
from ansible_collections.community.general.plugins.modules.net_tools.pritunl import (
pritunl_org_info,
)
from ansible_collections.community.general.tests.unit.compat.mock import patch
from ansible_collections.community.general.tests.unit.plugins.module_utils.net_tools.pritunl.test_api import (
PritunlListOrganizationMock,
PritunlEmptyOrganizationMock,
)
from ansible_collections.community.general.tests.unit.plugins.modules.utils import (
AnsibleExitJson,
AnsibleFailJson,
ModuleTestCase,
set_module_args,
)
__metaclass__ = type
class TestPritunlOrgInfo(ModuleTestCase):
def setUp(self):
super(TestPritunlOrgInfo, self).setUp()
self.module = pritunl_org_info
# Add backward compatibility
if sys.version_info < (3, 2):
self.assertRegex = self.assertRegexpMatches
def tearDown(self):
super(TestPritunlOrgInfo, self).tearDown()
def patch_get_pritunl_organizations(self, **kwds):
return patch(
"ansible_collections.community.general.plugins.module_utils.net_tools.pritunl.api._get_pritunl_organizations",
autospec=True,
**kwds
)
def test_without_parameters(self):
"""Test without parameters"""
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as org_mock:
set_module_args({})
with self.assertRaises(AnsibleFailJson):
self.module.main()
self.assertEqual(org_mock.call_count, 0)
def test_list_empty_organizations(self):
"""Listing all organizations even when no org exists should be valid."""
with self.patch_get_pritunl_organizations(
side_effect=PritunlEmptyOrganizationMock
) as org_mock:
with self.assertRaises(AnsibleExitJson) as result:
set_module_args(
{
"pritunl_api_token": "token",
"pritunl_api_secret": "secret",
"pritunl_url": "https://pritunl.domain.com",
}
)
self.module.main()
self.assertEqual(org_mock.call_count, 1)
exc = result.exception.args[0]
self.assertEqual(len(exc["organizations"]), 0)
def test_list_specific_organization(self):
"""Listing a specific organization should be valid."""
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as org_mock:
with self.assertRaises(AnsibleExitJson) as result:
set_module_args(
{
"pritunl_api_token": "token",
"pritunl_api_secret": "secret",
"pritunl_url": "https://pritunl.domain.com",
"org": "GumGum",
}
)
self.module.main()
self.assertEqual(org_mock.call_count, 1)
exc = result.exception.args[0]
self.assertEqual(len(exc["organizations"]), 1)
def test_list_unknown_organization(self):
"""Listing an unknown organization should result in a failure."""
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as org_mock:
with self.assertRaises(AnsibleFailJson) as result:
set_module_args(
{
"pritunl_api_token": "token",
"pritunl_api_secret": "secret",
"pritunl_url": "https://pritunl.domain.com",
"org": "Unknown",
}
)
self.module.main()
self.assertEqual(org_mock.call_count, 1)
exc = result.exception.args[0]
self.assertRegex(exc["msg"], "does not exist")
def test_list_all_organizations(self):
"""Listing all organizations should be valid."""
with self.patch_get_pritunl_organizations(
side_effect=PritunlListOrganizationMock
) as org_mock:
with self.assertRaises(AnsibleExitJson) as result:
set_module_args(
{
"pritunl_api_token": "token",
"pritunl_api_secret": "secret",
"pritunl_url": "https://pritunl.domain.com",
}
)
self.module.main()
self.assertEqual(org_mock.call_count, 1)
exc = result.exception.args[0]
self.assertEqual(len(exc["organizations"]), 3)