mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-08-03 20:54:24 -07:00
Remove deprecated features and plugins for 11.0.0 (#10126)
Some checks failed
EOL CI / EOL Sanity (Ⓐ2.15) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py2.7) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py3.10) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py3.5) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/1/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/2/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/3/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/1/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/2/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/3/) (push) Has been cancelled
nox / Run extra sanity tests (push) Has been cancelled
Some checks failed
EOL CI / EOL Sanity (Ⓐ2.15) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py2.7) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py3.10) (push) Has been cancelled
EOL CI / EOL Units (Ⓐ2.15+py3.5) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/1/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/2/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+alpine3+py:azp/posix/3/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/1/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/2/) (push) Has been cancelled
EOL CI / EOL I (Ⓐ2.15+fedora37+py:azp/posix/3/) (push) Has been cancelled
nox / Run extra sanity tests (push) Has been cancelled
* Bump version to 11.0.0. * Removed deprecated plugins/modules. * Remove _init_session(). * Remove ack_venv_creation_deprecation. * Change behavior of state. * Remove value reading. * Remove list_all. * Remove various deprecated module helper things. * Change default of proxmox's update parameter. * Fix constructor command order. Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> * MH: adjust guide --------- Co-authored-by: Alexei Znamensky <103110+russoz@users.noreply.github.com> Co-authored-by: Alexei Znamensky <russoz@gmail.com>
This commit is contained in:
parent
b861850e1a
commit
9d7b3f13bd
74 changed files with 89 additions and 10574 deletions
|
@ -1,206 +0,0 @@
|
|||
# Copyright (c) 2020 Shay Rybak <shay.rybak@stackpath.com>
|
||||
# Copyright (c) 2020 Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.inventory.data import InventoryData
|
||||
from ansible_collections.community.general.plugins.inventory.stackpath_compute import InventoryModule
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def inventory():
|
||||
r = InventoryModule()
|
||||
r.inventory = InventoryData()
|
||||
return r
|
||||
|
||||
|
||||
def test_get_stack_slugs(inventory):
|
||||
stacks = [
|
||||
{
|
||||
'status': 'ACTIVE',
|
||||
'name': 'test1',
|
||||
'id': 'XXXX',
|
||||
'updatedAt': '2020-07-08T01:00:00.000000Z',
|
||||
'slug': 'test1',
|
||||
'createdAt': '2020-07-08T00:00:00.000000Z',
|
||||
'accountId': 'XXXX',
|
||||
}, {
|
||||
'status': 'ACTIVE',
|
||||
'name': 'test2',
|
||||
'id': 'XXXX',
|
||||
'updatedAt': '2019-10-22T18:00:00.000000Z',
|
||||
'slug': 'test2',
|
||||
'createdAt': '2019-10-22T18:00:00.000000Z',
|
||||
'accountId': 'XXXX',
|
||||
}, {
|
||||
'status': 'DISABLED',
|
||||
'name': 'test3',
|
||||
'id': 'XXXX',
|
||||
'updatedAt': '2020-01-16T20:00:00.000000Z',
|
||||
'slug': 'test3',
|
||||
'createdAt': '2019-10-15T13:00:00.000000Z',
|
||||
'accountId': 'XXXX',
|
||||
}, {
|
||||
'status': 'ACTIVE',
|
||||
'name': 'test4',
|
||||
'id': 'XXXX',
|
||||
'updatedAt': '2019-11-20T22:00:00.000000Z',
|
||||
'slug': 'test4',
|
||||
'createdAt': '2019-11-20T22:00:00.000000Z',
|
||||
'accountId': 'XXXX',
|
||||
}
|
||||
]
|
||||
inventory._get_stack_slugs(stacks)
|
||||
assert len(inventory.stack_slugs) == 4
|
||||
assert inventory.stack_slugs == [
|
||||
"test1",
|
||||
"test2",
|
||||
"test3",
|
||||
"test4"
|
||||
]
|
||||
|
||||
|
||||
def test_verify_file(tmp_path, inventory):
|
||||
file = tmp_path / "foobar.stackpath_compute.yml"
|
||||
file.touch()
|
||||
assert inventory.verify_file(str(file)) is True
|
||||
|
||||
|
||||
def test_verify_file_bad_config(inventory):
|
||||
assert inventory.verify_file('foobar.stackpath_compute.yml') is False
|
||||
|
||||
|
||||
def test_validate_config(inventory):
|
||||
config = {
|
||||
"client_secret": "short_client_secret",
|
||||
"use_internal_ip": False,
|
||||
"stack_slugs": ["test1"],
|
||||
"client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
"plugin": "community.general.stackpath_compute",
|
||||
}
|
||||
with pytest.raises(AnsibleError) as error_message:
|
||||
inventory._validate_config(config)
|
||||
assert "client_secret must be 64 characters long" in error_message
|
||||
|
||||
config = {
|
||||
"client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
"use_internal_ip": True,
|
||||
"stack_slugs": ["test1"],
|
||||
"client_id": "short_client_id",
|
||||
"plugin": "community.general.stackpath_compute",
|
||||
}
|
||||
with pytest.raises(AnsibleError) as error_message:
|
||||
inventory._validate_config(config)
|
||||
assert "client_id must be 32 characters long" in error_message
|
||||
|
||||
config = {
|
||||
"use_internal_ip": True,
|
||||
"stack_slugs": ["test1"],
|
||||
"client_id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
"plugin": "community.general.stackpath_compute",
|
||||
}
|
||||
with pytest.raises(AnsibleError) as error_message:
|
||||
inventory._validate_config(config)
|
||||
assert "config missing client_secret, a required parameter" in error_message
|
||||
|
||||
config = {
|
||||
"client_secret": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
|
||||
"use_internal_ip": False,
|
||||
"plugin": "community.general.stackpath_compute",
|
||||
}
|
||||
with pytest.raises(AnsibleError) as error_message:
|
||||
inventory._validate_config(config)
|
||||
assert "config missing client_id, a required parameter" in error_message
|
||||
|
||||
|
||||
def test_populate(inventory):
|
||||
instances = [
|
||||
{
|
||||
"name": "instance1",
|
||||
"countryCode": "SE",
|
||||
"workloadSlug": "wokrload1",
|
||||
"continent": "Europe",
|
||||
"workloadId": "id1",
|
||||
"cityCode": "ARN",
|
||||
"externalIpAddress": "20.0.0.1",
|
||||
"target": "target1",
|
||||
"stackSlug": "stack1",
|
||||
"ipAddress": "10.0.0.1",
|
||||
},
|
||||
{
|
||||
"name": "instance2",
|
||||
"countryCode": "US",
|
||||
"workloadSlug": "wokrload2",
|
||||
"continent": "America",
|
||||
"workloadId": "id2",
|
||||
"cityCode": "JFK",
|
||||
"externalIpAddress": "20.0.0.2",
|
||||
"target": "target2",
|
||||
"stackSlug": "stack1",
|
||||
"ipAddress": "10.0.0.2",
|
||||
},
|
||||
{
|
||||
"name": "instance3",
|
||||
"countryCode": "SE",
|
||||
"workloadSlug": "workload3",
|
||||
"continent": "Europe",
|
||||
"workloadId": "id3",
|
||||
"cityCode": "ARN",
|
||||
"externalIpAddress": "20.0.0.3",
|
||||
"target": "target1",
|
||||
"stackSlug": "stack2",
|
||||
"ipAddress": "10.0.0.3",
|
||||
},
|
||||
{
|
||||
"name": "instance4",
|
||||
"countryCode": "US",
|
||||
"workloadSlug": "workload3",
|
||||
"continent": "America",
|
||||
"workloadId": "id4",
|
||||
"cityCode": "JFK",
|
||||
"externalIpAddress": "20.0.0.4",
|
||||
"target": "target2",
|
||||
"stackSlug": "stack2",
|
||||
"ipAddress": "10.0.0.4",
|
||||
},
|
||||
]
|
||||
inventory.hostname_key = "externalIpAddress"
|
||||
inventory._populate(instances)
|
||||
# get different hosts
|
||||
host1 = inventory.inventory.get_host('20.0.0.1')
|
||||
host2 = inventory.inventory.get_host('20.0.0.2')
|
||||
host3 = inventory.inventory.get_host('20.0.0.3')
|
||||
host4 = inventory.inventory.get_host('20.0.0.4')
|
||||
|
||||
# get different groups
|
||||
assert 'citycode_arn' in inventory.inventory.groups
|
||||
group_citycode_arn = inventory.inventory.groups['citycode_arn']
|
||||
assert 'countrycode_se' in inventory.inventory.groups
|
||||
group_countrycode_se = inventory.inventory.groups['countrycode_se']
|
||||
assert 'continent_america' in inventory.inventory.groups
|
||||
group_continent_america = inventory.inventory.groups['continent_america']
|
||||
assert 'name_instance1' in inventory.inventory.groups
|
||||
group_name_instance1 = inventory.inventory.groups['name_instance1']
|
||||
assert 'stackslug_stack1' in inventory.inventory.groups
|
||||
group_stackslug_stack1 = inventory.inventory.groups['stackslug_stack1']
|
||||
assert 'target_target1' in inventory.inventory.groups
|
||||
group_target_target1 = inventory.inventory.groups['target_target1']
|
||||
assert 'workloadslug_workload3' in inventory.inventory.groups
|
||||
group_workloadslug_workload3 = inventory.inventory.groups['workloadslug_workload3']
|
||||
assert 'workloadid_id1' in inventory.inventory.groups
|
||||
group_workloadid_id1 = inventory.inventory.groups['workloadid_id1']
|
||||
|
||||
assert group_citycode_arn.hosts == [host1, host3]
|
||||
assert group_countrycode_se.hosts == [host1, host3]
|
||||
assert group_continent_america.hosts == [host2, host4]
|
||||
assert group_name_instance1.hosts == [host1]
|
||||
assert group_stackslug_stack1.hosts == [host1, host2]
|
||||
assert group_target_target1.hosts == [host1, host3]
|
||||
assert group_workloadslug_workload3.hosts == [host3, host4]
|
||||
assert group_workloadid_id1.hosts == [host1]
|
|
@ -1,537 +0,0 @@
|
|||
# Copyright (c) 2018, Arigato Machine Inc.
|
||||
# Copyright (c) 2018, Ansible Project
|
||||
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
from __future__ import (absolute_import, division, print_function)
|
||||
__metaclass__ = type
|
||||
|
||||
from ansible_collections.community.internal_test_tools.tests.unit.compat import unittest
|
||||
from ansible_collections.community.internal_test_tools.tests.unit.compat.mock import patch, call
|
||||
from ansible.errors import AnsibleError
|
||||
from ansible.module_utils.urls import ConnectionError, SSLValidationError
|
||||
from ansible.module_utils.six.moves.urllib.error import HTTPError, URLError
|
||||
from ansible.module_utils import six
|
||||
from ansible.plugins.loader import lookup_loader
|
||||
from ansible_collections.community.general.plugins.lookup.manifold import ManifoldApiClient, ApiError
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
API_FIXTURES = {
|
||||
'https://api.marketplace.manifold.co/v1/resources':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-1",
|
||||
"name": "Resource 1"
|
||||
},
|
||||
"id": "rid-1"
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-2",
|
||||
"name": "Resource 2"
|
||||
},
|
||||
"id": "rid-2"
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/resources?label=resource-1':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-1",
|
||||
"name": "Resource 1"
|
||||
},
|
||||
"id": "rid-1"
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/resources?label=resource-2':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-2",
|
||||
"name": "Resource 2"
|
||||
},
|
||||
"id": "rid-2"
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/resources?team_id=tid-1':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-1",
|
||||
"name": "Resource 1"
|
||||
},
|
||||
"id": "rid-1"
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/resources?project_id=pid-1':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-2",
|
||||
"name": "Resource 2"
|
||||
},
|
||||
"id": "rid-2"
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/resources?project_id=pid-2':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-1",
|
||||
"name": "Resource 1"
|
||||
},
|
||||
"id": "rid-1"
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-3",
|
||||
"name": "Resource 3"
|
||||
},
|
||||
"id": "rid-3"
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/resources?team_id=tid-1&project_id=pid-1':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "resource-1",
|
||||
"name": "Resource 1"
|
||||
},
|
||||
"id": "rid-1"
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/projects':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "project-1",
|
||||
"name": "Project 1",
|
||||
},
|
||||
"id": "pid-1",
|
||||
},
|
||||
{
|
||||
"body": {
|
||||
"label": "project-2",
|
||||
"name": "Project 2",
|
||||
},
|
||||
"id": "pid-2",
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/projects?label=project-2':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"label": "project-2",
|
||||
"name": "Project 2",
|
||||
},
|
||||
"id": "pid-2",
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/credentials?resource_id=rid-1':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"resource_id": "rid-1",
|
||||
"values": {
|
||||
"RESOURCE_TOKEN_1": "token-1",
|
||||
"RESOURCE_TOKEN_2": "token-2"
|
||||
}
|
||||
},
|
||||
"id": "cid-1",
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/credentials?resource_id=rid-2':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"resource_id": "rid-2",
|
||||
"values": {
|
||||
"RESOURCE_TOKEN_3": "token-3",
|
||||
"RESOURCE_TOKEN_4": "token-4"
|
||||
}
|
||||
},
|
||||
"id": "cid-2",
|
||||
}
|
||||
],
|
||||
'https://api.marketplace.manifold.co/v1/credentials?resource_id=rid-3':
|
||||
[
|
||||
{
|
||||
"body": {
|
||||
"resource_id": "rid-3",
|
||||
"values": {
|
||||
"RESOURCE_TOKEN_1": "token-5",
|
||||
"RESOURCE_TOKEN_2": "token-6"
|
||||
}
|
||||
},
|
||||
"id": "cid-3",
|
||||
}
|
||||
],
|
||||
'https://api.identity.manifold.co/v1/teams':
|
||||
[
|
||||
{
|
||||
"id": "tid-1",
|
||||
"body": {
|
||||
"name": "Team 1",
|
||||
"label": "team-1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": "tid-2",
|
||||
"body": {
|
||||
"name": "Team 2",
|
||||
"label": "team-2"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
def mock_fixture(open_url_mock, fixture=None, data=None, headers=None):
|
||||
if not headers:
|
||||
headers = {}
|
||||
if fixture:
|
||||
data = json.dumps(API_FIXTURES[fixture])
|
||||
if 'content-type' not in headers:
|
||||
headers['content-type'] = 'application/json'
|
||||
|
||||
open_url_mock.return_value.read.return_value = data
|
||||
open_url_mock.return_value.headers = headers
|
||||
|
||||
|
||||
class TestManifoldApiClient(unittest.TestCase):
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_sends_default_headers(self, open_url_mock):
|
||||
mock_fixture(open_url_mock, data='hello')
|
||||
client = ManifoldApiClient('token-123')
|
||||
client.request('test', 'endpoint')
|
||||
open_url_mock.assert_called_with('https://api.test.manifold.co/v1/endpoint',
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_decodes_json(self, open_url_mock):
|
||||
mock_fixture(open_url_mock, fixture='https://api.marketplace.manifold.co/v1/resources')
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertIsInstance(client.request('marketplace', 'resources'), list)
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_streams_text(self, open_url_mock):
|
||||
mock_fixture(open_url_mock, data='hello', headers={'content-type': "text/plain"})
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertEqual('hello', client.request('test', 'endpoint'))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_processes_parameterized_headers(self, open_url_mock):
|
||||
mock_fixture(open_url_mock, data='hello')
|
||||
client = ManifoldApiClient('token-123')
|
||||
client.request('test', 'endpoint', headers={'X-HEADER': 'MANIFOLD'})
|
||||
open_url_mock.assert_called_with('https://api.test.manifold.co/v1/endpoint',
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123',
|
||||
'X-HEADER': 'MANIFOLD'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_passes_arbitrary_parameters(self, open_url_mock):
|
||||
mock_fixture(open_url_mock, data='hello')
|
||||
client = ManifoldApiClient('token-123')
|
||||
client.request('test', 'endpoint', use_proxy=False, timeout=5)
|
||||
open_url_mock.assert_called_with('https://api.test.manifold.co/v1/endpoint',
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0',
|
||||
use_proxy=False, timeout=5)
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_raises_on_incorrect_json(self, open_url_mock):
|
||||
mock_fixture(open_url_mock, data='noJson', headers={'content-type': "application/json"})
|
||||
client = ManifoldApiClient('token-123')
|
||||
with self.assertRaises(ApiError) as context:
|
||||
client.request('test', 'endpoint')
|
||||
self.assertEqual('JSON response can\'t be parsed while requesting https://api.test.manifold.co/v1/endpoint:\n'
|
||||
'noJson',
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_raises_on_status_500(self, open_url_mock):
|
||||
open_url_mock.side_effect = HTTPError('https://api.test.manifold.co/v1/endpoint',
|
||||
500, 'Server error', {}, six.StringIO('ERROR'))
|
||||
client = ManifoldApiClient('token-123')
|
||||
with self.assertRaises(ApiError) as context:
|
||||
client.request('test', 'endpoint')
|
||||
self.assertEqual('Server returned: HTTP Error 500: Server error while requesting '
|
||||
'https://api.test.manifold.co/v1/endpoint:\nERROR',
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_raises_on_bad_url(self, open_url_mock):
|
||||
open_url_mock.side_effect = URLError('URL is invalid')
|
||||
client = ManifoldApiClient('token-123')
|
||||
with self.assertRaises(ApiError) as context:
|
||||
client.request('test', 'endpoint')
|
||||
self.assertEqual('Failed lookup url for https://api.test.manifold.co/v1/endpoint : <url'
|
||||
'open error URL is invalid>',
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_raises_on_ssl_error(self, open_url_mock):
|
||||
open_url_mock.side_effect = SSLValidationError('SSL Error')
|
||||
client = ManifoldApiClient('token-123')
|
||||
with self.assertRaises(ApiError) as context:
|
||||
client.request('test', 'endpoint')
|
||||
self.assertEqual('Error validating the server\'s certificate for https://api.test.manifold.co/v1/endpoint: '
|
||||
'SSL Error',
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_request_raises_on_connection_error(self, open_url_mock):
|
||||
open_url_mock.side_effect = ConnectionError('Unknown connection error')
|
||||
client = ManifoldApiClient('token-123')
|
||||
with self.assertRaises(ApiError) as context:
|
||||
client.request('test', 'endpoint')
|
||||
self.assertEqual('Error connecting to https://api.test.manifold.co/v1/endpoint: Unknown connection error',
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_resources_get_all(self, open_url_mock):
|
||||
url = 'https://api.marketplace.manifold.co/v1/resources'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url], client.get_resources())
|
||||
open_url_mock.assert_called_with(url,
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_resources_filter_label(self, open_url_mock):
|
||||
url = 'https://api.marketplace.manifold.co/v1/resources?label=resource-1'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url], client.get_resources(label='resource-1'))
|
||||
open_url_mock.assert_called_with(url,
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_resources_filter_team_and_project(self, open_url_mock):
|
||||
url = 'https://api.marketplace.manifold.co/v1/resources?team_id=tid-1&project_id=pid-1'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url], client.get_resources(team_id='tid-1', project_id='pid-1'))
|
||||
args, kwargs = open_url_mock.call_args
|
||||
url_called = args[0]
|
||||
# Dict order is not guaranteed, so an url may have querystring parameters order randomized
|
||||
self.assertIn('team_id=tid-1', url_called)
|
||||
self.assertIn('project_id=pid-1', url_called)
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_teams_get_all(self, open_url_mock):
|
||||
url = 'https://api.identity.manifold.co/v1/teams'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url], client.get_teams())
|
||||
open_url_mock.assert_called_with(url,
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_teams_filter_label(self, open_url_mock):
|
||||
url = 'https://api.identity.manifold.co/v1/teams'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url][1:2], client.get_teams(label='team-2'))
|
||||
open_url_mock.assert_called_with(url,
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_projects_get_all(self, open_url_mock):
|
||||
url = 'https://api.marketplace.manifold.co/v1/projects'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url], client.get_projects())
|
||||
open_url_mock.assert_called_with(url,
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_projects_filter_label(self, open_url_mock):
|
||||
url = 'https://api.marketplace.manifold.co/v1/projects?label=project-2'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url], client.get_projects(label='project-2'))
|
||||
open_url_mock.assert_called_with(url,
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.open_url')
|
||||
def test_get_credentials(self, open_url_mock):
|
||||
url = 'https://api.marketplace.manifold.co/v1/credentials?resource_id=rid-1'
|
||||
mock_fixture(open_url_mock, fixture=url)
|
||||
client = ManifoldApiClient('token-123')
|
||||
self.assertListEqual(API_FIXTURES[url], client.get_credentials(resource_id='rid-1'))
|
||||
open_url_mock.assert_called_with(url,
|
||||
headers={'Accept': '*/*', 'Authorization': 'Bearer token-123'},
|
||||
http_agent='python-manifold-ansible-1.0.0')
|
||||
|
||||
|
||||
class TestLookupModule(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.lookup = lookup_loader.get('community.general.manifold')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_get_all(self, client_mock):
|
||||
expected_result = [{'RESOURCE_TOKEN_1': 'token-1',
|
||||
'RESOURCE_TOKEN_2': 'token-2',
|
||||
'RESOURCE_TOKEN_3': 'token-3',
|
||||
'RESOURCE_TOKEN_4': 'token-4'
|
||||
}]
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources']
|
||||
client_mock.return_value.get_credentials.side_effect = lambda x: API_FIXTURES['https://api.marketplace.manifold.co/v1/'
|
||||
'credentials?resource_id={0}'.format(x)]
|
||||
self.assertListEqual(expected_result, self.lookup.run([], api_token='token-123'))
|
||||
client_mock.assert_called_with('token-123')
|
||||
client_mock.return_value.get_resources.assert_called_with(team_id=None, project_id=None)
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_get_one_resource(self, client_mock):
|
||||
expected_result = [{'RESOURCE_TOKEN_3': 'token-3',
|
||||
'RESOURCE_TOKEN_4': 'token-4'
|
||||
}]
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources?label=resource-2']
|
||||
client_mock.return_value.get_credentials.side_effect = lambda x: API_FIXTURES['https://api.marketplace.manifold.co/v1/'
|
||||
'credentials?resource_id={0}'.format(x)]
|
||||
self.assertListEqual(expected_result, self.lookup.run(['resource-2'], api_token='token-123'))
|
||||
client_mock.return_value.get_resources.assert_called_with(team_id=None, project_id=None, label='resource-2')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_get_two_resources(self, client_mock):
|
||||
expected_result = [{'RESOURCE_TOKEN_1': 'token-1',
|
||||
'RESOURCE_TOKEN_2': 'token-2',
|
||||
'RESOURCE_TOKEN_3': 'token-3',
|
||||
'RESOURCE_TOKEN_4': 'token-4'
|
||||
}]
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources']
|
||||
client_mock.return_value.get_credentials.side_effect = lambda x: API_FIXTURES['https://api.marketplace.manifold.co/v1/'
|
||||
'credentials?resource_id={0}'.format(x)]
|
||||
self.assertListEqual(expected_result, self.lookup.run(['resource-1', 'resource-2'], api_token='token-123'))
|
||||
client_mock.assert_called_with('token-123')
|
||||
client_mock.return_value.get_resources.assert_called_with(team_id=None, project_id=None)
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.display')
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_get_resources_with_same_credential_names(self, client_mock, display_mock):
|
||||
expected_result = [{'RESOURCE_TOKEN_1': 'token-5',
|
||||
'RESOURCE_TOKEN_2': 'token-6'
|
||||
}]
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources?project_id=pid-2']
|
||||
client_mock.return_value.get_projects.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/projects?label=project-2']
|
||||
client_mock.return_value.get_credentials.side_effect = lambda x: API_FIXTURES['https://api.marketplace.manifold.co/v1/'
|
||||
'credentials?resource_id={0}'.format(x)]
|
||||
self.assertListEqual(expected_result, self.lookup.run([], api_token='token-123', project='project-2'))
|
||||
client_mock.assert_called_with('token-123')
|
||||
display_mock.warning.assert_has_calls([
|
||||
call("'RESOURCE_TOKEN_1' with label 'resource-1' was replaced by resource data with label 'resource-3'"),
|
||||
call("'RESOURCE_TOKEN_2' with label 'resource-1' was replaced by resource data with label 'resource-3'")],
|
||||
any_order=True
|
||||
)
|
||||
client_mock.return_value.get_resources.assert_called_with(team_id=None, project_id='pid-2')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_filter_by_team(self, client_mock):
|
||||
expected_result = [{'RESOURCE_TOKEN_1': 'token-1',
|
||||
'RESOURCE_TOKEN_2': 'token-2'
|
||||
}]
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources?team_id=tid-1']
|
||||
client_mock.return_value.get_teams.return_value = API_FIXTURES['https://api.identity.manifold.co/v1/teams'][0:1]
|
||||
client_mock.return_value.get_credentials.side_effect = lambda x: API_FIXTURES['https://api.marketplace.manifold.co/v1/'
|
||||
'credentials?resource_id={0}'.format(x)]
|
||||
self.assertListEqual(expected_result, self.lookup.run([], api_token='token-123', team='team-1'))
|
||||
client_mock.assert_called_with('token-123')
|
||||
client_mock.return_value.get_resources.assert_called_with(team_id='tid-1', project_id=None)
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_filter_by_project(self, client_mock):
|
||||
expected_result = [{'RESOURCE_TOKEN_3': 'token-3',
|
||||
'RESOURCE_TOKEN_4': 'token-4'
|
||||
}]
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources?project_id=pid-1']
|
||||
client_mock.return_value.get_projects.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/projects'][0:1]
|
||||
client_mock.return_value.get_credentials.side_effect = lambda x: API_FIXTURES['https://api.marketplace.manifold.co/v1/'
|
||||
'credentials?resource_id={0}'.format(x)]
|
||||
self.assertListEqual(expected_result, self.lookup.run([], api_token='token-123', project='project-1'))
|
||||
client_mock.assert_called_with('token-123')
|
||||
client_mock.return_value.get_resources.assert_called_with(team_id=None, project_id='pid-1')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_filter_by_team_and_project(self, client_mock):
|
||||
expected_result = [{'RESOURCE_TOKEN_1': 'token-1',
|
||||
'RESOURCE_TOKEN_2': 'token-2'
|
||||
}]
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources?team_id=tid-1&project_id=pid-1']
|
||||
client_mock.return_value.get_teams.return_value = API_FIXTURES['https://api.identity.manifold.co/v1/teams'][0:1]
|
||||
client_mock.return_value.get_projects.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/projects'][0:1]
|
||||
client_mock.return_value.get_credentials.side_effect = lambda x: API_FIXTURES['https://api.marketplace.manifold.co/v1/'
|
||||
'credentials?resource_id={0}'.format(x)]
|
||||
self.assertListEqual(expected_result, self.lookup.run([], api_token='token-123', project='project-1'))
|
||||
client_mock.assert_called_with('token-123')
|
||||
client_mock.return_value.get_resources.assert_called_with(team_id=None, project_id='pid-1')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_raise_team_doesnt_exist(self, client_mock):
|
||||
client_mock.return_value.get_teams.return_value = []
|
||||
with self.assertRaises(AnsibleError) as context:
|
||||
self.lookup.run([], api_token='token-123', team='no-team')
|
||||
self.assertEqual("Team 'no-team' does not exist",
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_raise_project_doesnt_exist(self, client_mock):
|
||||
client_mock.return_value.get_projects.return_value = []
|
||||
with self.assertRaises(AnsibleError) as context:
|
||||
self.lookup.run([], api_token='token-123', project='no-project')
|
||||
self.assertEqual("Project 'no-project' does not exist",
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_raise_resource_doesnt_exist(self, client_mock):
|
||||
client_mock.return_value.get_resources.return_value = API_FIXTURES['https://api.marketplace.manifold.co/v1/resources']
|
||||
with self.assertRaises(AnsibleError) as context:
|
||||
self.lookup.run(['resource-1', 'no-resource-1', 'no-resource-2'], api_token='token-123')
|
||||
self.assertEqual("Resource(s) no-resource-1, no-resource-2 do not exist",
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_catch_api_error(self, client_mock):
|
||||
client_mock.side_effect = ApiError('Generic error')
|
||||
with self.assertRaises(AnsibleError) as context:
|
||||
self.lookup.run([], api_token='token-123')
|
||||
self.assertEqual("API Error: Generic error",
|
||||
str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_catch_unhandled_exception(self, client_mock):
|
||||
client_mock.side_effect = Exception('Unknown error')
|
||||
with self.assertRaises(AnsibleError) as context:
|
||||
self.lookup.run([], api_token='token-123')
|
||||
self.assertTrue('Exception: Unknown error' in str(context.exception))
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_falls_back_to_env_var(self, client_mock):
|
||||
client_mock.return_value.get_resources.return_value = []
|
||||
client_mock.return_value.get_credentials.return_value = []
|
||||
try:
|
||||
os.environ['MANIFOLD_API_TOKEN'] = 'token-321'
|
||||
self.lookup.run([])
|
||||
finally:
|
||||
os.environ.pop('MANIFOLD_API_TOKEN', None)
|
||||
client_mock.assert_called_with('token-321')
|
||||
|
||||
@patch('ansible_collections.community.general.plugins.lookup.manifold.ManifoldApiClient')
|
||||
def test_falls_raises_on_no_token(self, client_mock):
|
||||
client_mock.return_value.get_resources.return_value = []
|
||||
client_mock.return_value.get_credentials.return_value = []
|
||||
os.environ.pop('MANIFOLD_API_TOKEN', None)
|
||||
with self.assertRaises(AnsibleError) as context:
|
||||
self.lookup.run([])
|
||||
assert 'api_token' in str(context.exception)
|
|
@ -10,123 +10,13 @@ __metaclass__ = type
|
|||
import pytest
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.module_helper import (
|
||||
DependencyCtxMgr, VarMeta, VarDict, cause_changes
|
||||
cause_changes
|
||||
)
|
||||
|
||||
|
||||
# remove in 11.0.0
|
||||
def test_dependency_ctxmgr():
|
||||
ctx = DependencyCtxMgr("POTATOES", "Potatoes must be installed")
|
||||
with ctx:
|
||||
import potatoes_that_will_never_be_there # noqa: F401, pylint: disable=unused-import
|
||||
print("POTATOES: ctx.text={0}".format(ctx.text))
|
||||
assert ctx.text == "Potatoes must be installed"
|
||||
assert not ctx.has_it
|
||||
|
||||
ctx = DependencyCtxMgr("POTATOES2")
|
||||
with ctx:
|
||||
import potatoes_that_will_never_be_there_again # noqa: F401, pylint: disable=unused-import
|
||||
assert not ctx.has_it
|
||||
print("POTATOES2: ctx.text={0}".format(ctx.text))
|
||||
assert ctx.text.startswith("No module named")
|
||||
assert "potatoes_that_will_never_be_there_again" in ctx.text
|
||||
|
||||
ctx = DependencyCtxMgr("TYPING")
|
||||
with ctx:
|
||||
import sys # noqa: F401, pylint: disable=unused-import
|
||||
assert ctx.has_it
|
||||
|
||||
|
||||
# remove in 11.0.0
|
||||
def test_variable_meta():
|
||||
meta = VarMeta()
|
||||
assert meta.output is True
|
||||
assert meta.diff is False
|
||||
assert meta.value is None
|
||||
meta.set_value("abc")
|
||||
assert meta.initial_value == "abc"
|
||||
assert meta.value == "abc"
|
||||
assert meta.diff_result is None
|
||||
meta.set_value("def")
|
||||
assert meta.initial_value == "abc"
|
||||
assert meta.value == "def"
|
||||
assert meta.diff_result is None
|
||||
|
||||
|
||||
# remove in 11.0.0
|
||||
def test_variable_meta_diff():
|
||||
meta = VarMeta(diff=True)
|
||||
assert meta.output is True
|
||||
assert meta.diff is True
|
||||
assert meta.value is None
|
||||
meta.set_value("abc")
|
||||
assert meta.initial_value == "abc"
|
||||
assert meta.value == "abc"
|
||||
assert meta.diff_result is None
|
||||
meta.set_value("def")
|
||||
assert meta.initial_value == "abc"
|
||||
assert meta.value == "def"
|
||||
assert meta.diff_result == {"before": "abc", "after": "def"}
|
||||
meta.set_value("ghi")
|
||||
assert meta.initial_value == "abc"
|
||||
assert meta.value == "ghi"
|
||||
assert meta.diff_result == {"before": "abc", "after": "ghi"}
|
||||
|
||||
|
||||
# remove in 11.0.0
|
||||
def test_vardict():
|
||||
vd = VarDict()
|
||||
vd.set('a', 123)
|
||||
assert vd['a'] == 123
|
||||
assert vd.a == 123
|
||||
assert 'a' in vd._meta
|
||||
assert vd.meta('a').output is True
|
||||
assert vd.meta('a').diff is False
|
||||
assert vd.meta('a').change is False
|
||||
vd['b'] = 456
|
||||
assert vd.meta('b').output is True
|
||||
assert vd.meta('b').diff is False
|
||||
assert vd.meta('b').change is False
|
||||
vd.set_meta('a', diff=True, change=True)
|
||||
vd.set_meta('b', diff=True, output=False)
|
||||
vd['c'] = 789
|
||||
assert vd.has_changed('c') is False
|
||||
vd['a'] = 'new_a'
|
||||
assert vd.has_changed('a') is True
|
||||
vd['c'] = 'new_c'
|
||||
assert vd.has_changed('c') is False
|
||||
vd['b'] = 'new_b'
|
||||
assert vd.has_changed('b') is False
|
||||
assert vd.a == 'new_a'
|
||||
assert vd.c == 'new_c'
|
||||
assert vd.output() == {'a': 'new_a', 'c': 'new_c'}
|
||||
assert vd.diff() == {'before': {'a': 123}, 'after': {'a': 'new_a'}}, "diff={0}".format(vd.diff())
|
||||
|
||||
|
||||
# remove in 11.0.0
|
||||
def test_variable_meta_change():
|
||||
vd = VarDict()
|
||||
vd.set('a', 123, change=True)
|
||||
vd.set('b', [4, 5, 6], change=True)
|
||||
vd.set('c', {'m': 7, 'n': 8, 'o': 9}, change=True)
|
||||
vd.set('d', {'a1': {'a11': 33, 'a12': 34}}, change=True)
|
||||
|
||||
vd.a = 1234
|
||||
assert vd.has_changed('a') is True
|
||||
vd.b.append(7)
|
||||
assert vd.b == [4, 5, 6, 7]
|
||||
assert vd.has_changed('b')
|
||||
vd.c.update({'p': 10})
|
||||
assert vd.c == {'m': 7, 'n': 8, 'o': 9, 'p': 10}
|
||||
assert vd.has_changed('c')
|
||||
vd.d['a1'].update({'a13': 35})
|
||||
assert vd.d == {'a1': {'a11': 33, 'a12': 34, 'a13': 35}}
|
||||
assert vd.has_changed('d')
|
||||
|
||||
|
||||
#
|
||||
# DEPRECATION NOTICE
|
||||
# Parameters on_success and on_failure are deprecated and will be removed in community.genral 12.0.0
|
||||
# Parameters on_success and on_failure are deprecated and will be removed in community.general 12.0.0
|
||||
# Remove testcases with those params when releasing 12.0.0
|
||||
#
|
||||
CAUSE_CHG_DECO_PARAMS = ['deco_args', 'expect_exception', 'expect_changed']
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue