mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-22 19:59:07 +00:00
Prepare main for 13.0.0 (#11834)
* Bump version to 13.0.0. * Remove deprecated modules and plugins. * Remove deprecated module utils. * Remove leftovers. * Remove mode=compatibility. * Change default of is_pre740 from true to false. * Change default of force_defaults from true to false. * Remove support for ubuntu_legacy mechanism. * Remove cpanm compatibility tests.
This commit is contained in:
parent
7ce198f0e7
commit
72c13c85ad
62 changed files with 104 additions and 13052 deletions
|
|
@ -1,51 +0,0 @@
|
|||
# Copyright (c) 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 annotations
|
||||
|
||||
import random
|
||||
import unittest
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.cloud import _exponential_backoff, _full_jitter_backoff
|
||||
|
||||
|
||||
class ExponentialBackoffStrategyTestCase(unittest.TestCase):
|
||||
def test_no_retries(self):
|
||||
strategy = _exponential_backoff(retries=0)
|
||||
result = list(strategy())
|
||||
self.assertEqual(result, [], "list should be empty")
|
||||
|
||||
def test_exponential_backoff(self):
|
||||
strategy = _exponential_backoff(retries=5, delay=1, backoff=2)
|
||||
result = list(strategy())
|
||||
self.assertEqual(result, [1, 2, 4, 8, 16])
|
||||
|
||||
def test_max_delay(self):
|
||||
strategy = _exponential_backoff(retries=7, delay=1, backoff=2, max_delay=60)
|
||||
result = list(strategy())
|
||||
self.assertEqual(result, [1, 2, 4, 8, 16, 32, 60])
|
||||
|
||||
def test_max_delay_none(self):
|
||||
strategy = _exponential_backoff(retries=7, delay=1, backoff=2, max_delay=None)
|
||||
result = list(strategy())
|
||||
self.assertEqual(result, [1, 2, 4, 8, 16, 32, 64])
|
||||
|
||||
|
||||
class FullJitterBackoffStrategyTestCase(unittest.TestCase):
|
||||
def test_no_retries(self):
|
||||
strategy = _full_jitter_backoff(retries=0)
|
||||
result = list(strategy())
|
||||
self.assertEqual(result, [], "list should be empty")
|
||||
|
||||
def test_full_jitter(self):
|
||||
retries = 5
|
||||
seed = 1
|
||||
|
||||
r = random.Random(seed)
|
||||
expected = [r.randint(0, 2**i) for i in range(0, retries)]
|
||||
|
||||
strategy = _full_jitter_backoff(retries=retries, delay=1, _random=random.Random(seed))
|
||||
result = list(strategy())
|
||||
|
||||
self.assertEqual(result, expected)
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
# Copyright (c) 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 annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.database import (
|
||||
SQLParseError,
|
||||
is_input_dangerous,
|
||||
pg_quote_identifier,
|
||||
)
|
||||
|
||||
# These are all valid strings
|
||||
# The results are based on interpreting the identifier as a table name
|
||||
VALID = {
|
||||
# User quoted
|
||||
'"public.table"': '"public.table"',
|
||||
'"public"."table"': '"public"."table"',
|
||||
'"schema test"."table test"': '"schema test"."table test"',
|
||||
# We quote part
|
||||
"public.table": '"public"."table"',
|
||||
'"public".table': '"public"."table"',
|
||||
'public."table"': '"public"."table"',
|
||||
"schema test.table test": '"schema test"."table test"',
|
||||
'"schema test".table test': '"schema test"."table test"',
|
||||
'schema test."table test"': '"schema test"."table test"',
|
||||
# Embedded double quotes
|
||||
'table "test"': '"table ""test"""',
|
||||
'public."table ""test"""': '"public"."table ""test"""',
|
||||
'public.table "test"': '"public"."table ""test"""',
|
||||
'schema "test".table': '"schema ""test"""."table"',
|
||||
'"schema ""test""".table': '"schema ""test"""."table"',
|
||||
'"""wat"""."""test"""': '"""wat"""."""test"""',
|
||||
# Sigh, handle these as well:
|
||||
'"no end quote': '"""no end quote"',
|
||||
'schema."table': '"schema"."""table"',
|
||||
'"schema.table': '"""schema"."table"',
|
||||
'schema."table.something': '"schema"."""table"."something"',
|
||||
# Embedded dots
|
||||
'"schema.test"."table.test"': '"schema.test"."table.test"',
|
||||
'"schema.".table': '"schema."."table"',
|
||||
'"schema."."table"': '"schema."."table"',
|
||||
'schema.".table"': '"schema".".table"',
|
||||
'"schema".".table"': '"schema".".table"',
|
||||
'"schema.".".table"': '"schema.".".table"',
|
||||
# These are valid but maybe not what the user intended
|
||||
'."table"': '".""table"""',
|
||||
"table.": '"table."',
|
||||
}
|
||||
|
||||
INVALID = {
|
||||
("test.too.many.dots", "table"): "PostgreSQL does not support table with more than 3 dots",
|
||||
('"test.too".many.dots', "database"): "PostgreSQL does not support database with more than 1 dots",
|
||||
('test.too."many.dots"', "database"): "PostgreSQL does not support database with more than 1 dots",
|
||||
('"test"."too"."many"."dots"', "database"): "PostgreSQL does not support database with more than 1 dots",
|
||||
('"test"."too"."many"."dots"', "schema"): "PostgreSQL does not support schema with more than 2 dots",
|
||||
('"test"."too"."many"."dots"', "table"): "PostgreSQL does not support table with more than 3 dots",
|
||||
('"test"."too"."many"."dots"."for"."column"', "column"): "PostgreSQL does not support column with more than 4 dots",
|
||||
('"table "invalid" double quote"', "table"): "User escaped identifiers must escape extra quotes",
|
||||
('"schema "invalid"""."table "invalid"', "table"): "User escaped identifiers must escape extra quotes",
|
||||
('"schema."table"', "table"): "User escaped identifiers must escape extra quotes",
|
||||
('"schema".', "table"): "Identifier name unspecified or unquoted trailing dot",
|
||||
}
|
||||
|
||||
HOW_MANY_DOTS = (
|
||||
("role", "role", '"role"', "PostgreSQL does not support role with more than 1 dots"),
|
||||
("db", "database", '"db"', "PostgreSQL does not support database with more than 1 dots"),
|
||||
("db.schema", "schema", '"db"."schema"', "PostgreSQL does not support schema with more than 2 dots"),
|
||||
("db.schema.table", "table", '"db"."schema"."table"', "PostgreSQL does not support table with more than 3 dots"),
|
||||
(
|
||||
"db.schema.table.column",
|
||||
"column",
|
||||
'"db"."schema"."table"."column"',
|
||||
"PostgreSQL does not support column with more than 4 dots",
|
||||
),
|
||||
)
|
||||
|
||||
VALID_QUOTES = ((test, VALID[test]) for test in sorted(VALID))
|
||||
INVALID_QUOTES = ((test[0], test[1], INVALID[test]) for test in sorted(INVALID))
|
||||
|
||||
IS_STRINGS_DANGEROUS = (
|
||||
("", False),
|
||||
(" ", False),
|
||||
("alternative database", False),
|
||||
("backup of TRUNCATED table", False),
|
||||
("bob.dropper", False),
|
||||
("d'artagnan", False),
|
||||
("user_with_select_update_truncate_right", False),
|
||||
(";DROP DATABASE fluffy_pets_photos", True),
|
||||
(";drop DATABASE fluffy_pets_photos", True),
|
||||
("; TRUNCATE TABLE his_valuable_table", True),
|
||||
("; truncate TABLE his_valuable_table", True),
|
||||
("'--", True),
|
||||
('"--', True),
|
||||
("' union select username, password from admin_credentials", True),
|
||||
("' UNION SELECT username, password from admin_credentials", True),
|
||||
("' intersect select", True),
|
||||
("' INTERSECT select", True),
|
||||
("' except select", True),
|
||||
("' EXCEPT select", True),
|
||||
(";ALTER TABLE prices", True),
|
||||
(";alter table prices", True),
|
||||
("; UPDATE products SET price = '0'", True),
|
||||
(";update products SET price = '0'", True),
|
||||
("; DELETE FROM products", True),
|
||||
("; delete FROM products", True),
|
||||
("; SELECT * FROM products", True),
|
||||
(" ; select * from products", True),
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("identifier, quoted_identifier", VALID_QUOTES)
|
||||
def test_valid_quotes(identifier, quoted_identifier):
|
||||
assert pg_quote_identifier(identifier, "table") == quoted_identifier
|
||||
|
||||
|
||||
@pytest.mark.parametrize("identifier, id_type, msg", INVALID_QUOTES)
|
||||
def test_invalid_quotes(identifier, id_type, msg):
|
||||
with pytest.raises(SQLParseError) as ex:
|
||||
pg_quote_identifier(identifier, id_type)
|
||||
|
||||
ex.match(msg)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("identifier, id_type, quoted_identifier, msg", HOW_MANY_DOTS)
|
||||
def test_how_many_dots(identifier, id_type, quoted_identifier, msg):
|
||||
assert pg_quote_identifier(identifier, id_type) == quoted_identifier
|
||||
|
||||
with pytest.raises(SQLParseError) as ex:
|
||||
pg_quote_identifier(f"{identifier}.more", id_type)
|
||||
|
||||
ex.match(msg)
|
||||
|
||||
|
||||
@pytest.mark.parametrize("string, result", IS_STRINGS_DANGEROUS)
|
||||
def test_is_input_dangerous(string, result):
|
||||
assert is_input_dangerous(string) == result
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
# (c) 2015, Michael Scherer <mscherer@redhat.com>
|
||||
# Copyright (c) 2017 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 annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils import known_hosts
|
||||
|
||||
URLS = {
|
||||
"ssh://one.example.org/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "one.example.org",
|
||||
"add_host_key_cmd": " -t rsa one.example.org",
|
||||
"port": None,
|
||||
},
|
||||
"ssh+git://two.example.org/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "two.example.org",
|
||||
"add_host_key_cmd": " -t rsa two.example.org",
|
||||
"port": None,
|
||||
},
|
||||
"rsync://three.example.org/user/example.git": {
|
||||
"is_ssh_url": False,
|
||||
"get_fqdn": "three.example.org",
|
||||
"add_host_key_cmd": None, # not called for non-ssh urls
|
||||
"port": None,
|
||||
},
|
||||
"git@four.example.org:user/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "four.example.org",
|
||||
"add_host_key_cmd": " -t rsa four.example.org",
|
||||
"port": None,
|
||||
},
|
||||
"git+ssh://five.example.org/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "five.example.org",
|
||||
"add_host_key_cmd": " -t rsa five.example.org",
|
||||
"port": None,
|
||||
},
|
||||
"ssh://six.example.org:21/example.org": {
|
||||
# ssh on FTP Port?
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "six.example.org",
|
||||
"add_host_key_cmd": " -t rsa -p 21 six.example.org",
|
||||
"port": "21",
|
||||
},
|
||||
"ssh://[2001:DB8::abcd:abcd]/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "[2001:DB8::abcd:abcd]",
|
||||
"add_host_key_cmd": " -t rsa [2001:DB8::abcd:abcd]",
|
||||
"port": None,
|
||||
},
|
||||
"ssh://[2001:DB8::abcd:abcd]:22/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "[2001:DB8::abcd:abcd]",
|
||||
"add_host_key_cmd": " -t rsa -p 22 [2001:DB8::abcd:abcd]",
|
||||
"port": "22",
|
||||
},
|
||||
"username@[2001:DB8::abcd:abcd]/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "[2001:DB8::abcd:abcd]",
|
||||
"add_host_key_cmd": " -t rsa [2001:DB8::abcd:abcd]",
|
||||
"port": None,
|
||||
},
|
||||
"username@[2001:DB8::abcd:abcd]:path/example.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "[2001:DB8::abcd:abcd]",
|
||||
"add_host_key_cmd": " -t rsa [2001:DB8::abcd:abcd]",
|
||||
"port": None,
|
||||
},
|
||||
"ssh://internal.git.server:7999/repos/repo.git": {
|
||||
"is_ssh_url": True,
|
||||
"get_fqdn": "internal.git.server",
|
||||
"add_host_key_cmd": " -t rsa -p 7999 internal.git.server",
|
||||
"port": "7999",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("url, is_ssh_url", ((k, URLS[k]["is_ssh_url"]) for k in sorted(URLS)))
|
||||
def test_is_ssh_url(url, is_ssh_url):
|
||||
assert known_hosts.is_ssh_url(url) == is_ssh_url
|
||||
|
||||
|
||||
@pytest.mark.parametrize("url, fqdn, port", ((k, URLS[k]["get_fqdn"], URLS[k]["port"]) for k in sorted(URLS)))
|
||||
def test_get_fqdn_and_port(url, fqdn, port):
|
||||
assert known_hosts.get_fqdn_and_port(url) == (fqdn, port)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fqdn, port, add_host_key_cmd",
|
||||
(
|
||||
(URLS[k]["get_fqdn"], URLS[k]["port"], URLS[k]["add_host_key_cmd"])
|
||||
for k in sorted(URLS)
|
||||
if URLS[k]["is_ssh_url"]
|
||||
),
|
||||
)
|
||||
def test_add_host_key(mocker, fqdn, port, add_host_key_cmd):
|
||||
am = mocker.MagicMock()
|
||||
|
||||
get_bin_path = mocker.MagicMock()
|
||||
get_bin_path.return_value = keyscan_cmd = "/custom/path/ssh-keyscan"
|
||||
am.get_bin_path = get_bin_path
|
||||
|
||||
run_command = mocker.MagicMock()
|
||||
run_command.return_value = (0, "Needs output, otherwise thinks ssh-keyscan timed out'", "")
|
||||
am.run_command = run_command
|
||||
|
||||
append_to_file = mocker.MagicMock()
|
||||
append_to_file.return_value = (None,)
|
||||
am.append_to_file = append_to_file
|
||||
|
||||
mocker.patch("os.path.isdir", return_value=True)
|
||||
mocker.patch("os.path.exists", return_value=True)
|
||||
|
||||
known_hosts.add_host_key(am, fqdn, port=port)
|
||||
run_command.assert_called_with(keyscan_cmd + add_host_key_cmd, environ_update={"LANGUAGE": "C", "LC_ALL": "C"})
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
# Copyright (c) 2019, Andrey Tuzhilin <andrei.tuzhilin@gmail.com>
|
||||
# Copyright (c) 2020, Andrew Klychkov (@Andersson007) <aaklychkov@mail.ru>
|
||||
# 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 annotations
|
||||
|
||||
import pytest
|
||||
|
||||
from ansible_collections.community.general.plugins.module_utils.saslprep import saslprep
|
||||
|
||||
VALID = [
|
||||
("", ""),
|
||||
("\u00a0", " "),
|
||||
("a", "a"),
|
||||
("й", "й"),
|
||||
("\u30de\u30c8\u30ea\u30c3\u30af\u30b9", "\u30de\u30c8\u30ea\u30c3\u30af\u30b9"),
|
||||
("The\u00adM\u00aatr\u2168", "TheMatrIX"),
|
||||
("I\u00adX", "IX"),
|
||||
("user", "user"),
|
||||
("USER", "USER"),
|
||||
("\u00aa", "a"),
|
||||
("\u2168", "IX"),
|
||||
("\u05be\u00a0\u05be", "\u05be\u0020\u05be"),
|
||||
]
|
||||
|
||||
INVALID = [
|
||||
(None, TypeError),
|
||||
(b"", TypeError),
|
||||
("\u0221", ValueError),
|
||||
("\u0007", ValueError),
|
||||
("\u0627\u0031", ValueError),
|
||||
("\ue0001", ValueError),
|
||||
("\ue0020", ValueError),
|
||||
("\ufff9", ValueError),
|
||||
("\ufdd0", ValueError),
|
||||
("\u0000", ValueError),
|
||||
("\u06dd", ValueError),
|
||||
("\uffffD", ValueError),
|
||||
("\ud800", ValueError),
|
||||
("\u200e", ValueError),
|
||||
("\u05be\u00aa\u05be", ValueError),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize("source,target", VALID)
|
||||
def test_saslprep_conversions(source, target):
|
||||
assert saslprep(source) == target
|
||||
|
||||
|
||||
@pytest.mark.parametrize("source,exception", INVALID)
|
||||
def test_saslprep_exceptions(source, exception):
|
||||
with pytest.raises(exception):
|
||||
saslprep(source)
|
||||
|
|
@ -7,52 +7,6 @@ anchors:
|
|||
environ_true: &env-def-true {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: true}
|
||||
environ_false: &env-def-false {environ_update: {LANGUAGE: C, LC_ALL: C}, check_rc: false}
|
||||
test_cases:
|
||||
- id: install_dancer_compatibility
|
||||
input:
|
||||
name: Dancer
|
||||
mode: compatibility
|
||||
output:
|
||||
changed: true
|
||||
cpanm_version: '1.7047'
|
||||
mocks:
|
||||
run_command:
|
||||
- command: [/testbin/cpanm, --version]
|
||||
environ: *env-def-true
|
||||
rc: 0
|
||||
out: |
|
||||
cpanm (App::cpanminus) version 1.7047 (/usr/local/bin/cpanm)
|
||||
perl version 5.041005 (/usr/local/bin/perl)
|
||||
err: ''
|
||||
- command: [/testbin/perl, -le, use Dancer;]
|
||||
environ: *env-def-false
|
||||
rc: 2
|
||||
out: ''
|
||||
err: error, not installed
|
||||
- command: [/testbin/cpanm, Dancer]
|
||||
environ: *env-def-true
|
||||
rc: 0
|
||||
out: ''
|
||||
err: ''
|
||||
- id: install_dancer_already_installed_compatibility
|
||||
input:
|
||||
name: Dancer
|
||||
mode: compatibility
|
||||
output:
|
||||
changed: false
|
||||
mocks:
|
||||
run_command:
|
||||
- command: [/testbin/cpanm, --version]
|
||||
environ: *env-def-true
|
||||
rc: 0
|
||||
out: |
|
||||
cpanm (App::cpanminus) version 1.7047 (/usr/local/bin/cpanm)
|
||||
perl version 5.041005 (/usr/local/bin/perl)
|
||||
err: ''
|
||||
- command: [/testbin/perl, -le, use Dancer;]
|
||||
environ: *env-def-false
|
||||
rc: 0
|
||||
out: ''
|
||||
err: ''
|
||||
- id: install_dancer
|
||||
input:
|
||||
name: Dancer
|
||||
|
|
@ -72,26 +26,6 @@ test_cases:
|
|||
rc: 0
|
||||
out: ''
|
||||
err: ''
|
||||
- id: install_distribution_file_compatibility
|
||||
input:
|
||||
name: MIYAGAWA/Plack-0.99_05.tar.gz
|
||||
mode: compatibility
|
||||
output:
|
||||
changed: true
|
||||
mocks:
|
||||
run_command:
|
||||
- command: [/testbin/cpanm, --version]
|
||||
environ: *env-def-true
|
||||
rc: 0
|
||||
out: |
|
||||
cpanm (App::cpanminus) version 1.7047 (/usr/local/bin/cpanm)
|
||||
perl version 5.041005 (/usr/local/bin/perl)
|
||||
err: ''
|
||||
- command: [/testbin/cpanm, MIYAGAWA/Plack-0.99_05.tar.gz]
|
||||
environ: *env-def-true
|
||||
rc: 0
|
||||
out: ''
|
||||
err: ''
|
||||
- id: install_distribution_file
|
||||
input:
|
||||
name: MIYAGAWA/Plack-0.99_05.tar.gz
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue