mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-05-07 05:42:50 +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:
@@ -1,6 +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
|
||||
|
||||
azp/posix/1
|
||||
needs/root
|
||||
@@ -1,179 +0,0 @@
|
||||
---
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# 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
|
||||
|
||||
- name: Creating a client if the directory doesn't exist should work
|
||||
sensu_client:
|
||||
subscriptions:
|
||||
- default
|
||||
|
||||
- name: Set variable for client file
|
||||
set_fact:
|
||||
client_file: "/etc/sensu/conf.d/client.json"
|
||||
|
||||
- name: Insert invalid JSON in the client file
|
||||
lineinfile:
|
||||
state: "present"
|
||||
create: "yes"
|
||||
path: "{{ client_file }}"
|
||||
line: "{'foo' = bar}"
|
||||
|
||||
- name: Configure Sensu client with an existing invalid file
|
||||
sensu_client:
|
||||
name: "client"
|
||||
state: "present"
|
||||
subscriptions:
|
||||
- default
|
||||
register: client
|
||||
|
||||
- name: Retrieve configuration file
|
||||
slurp:
|
||||
src: "{{ client_file }}"
|
||||
register: client_config
|
||||
|
||||
- name: Assert that client data was set successfully and properly
|
||||
assert:
|
||||
that:
|
||||
- "client is successful"
|
||||
- "client is changed"
|
||||
- "client['config']['name'] == 'client'"
|
||||
- "'default' in client['config']['subscriptions']"
|
||||
- "client['file'] == client_file"
|
||||
|
||||
- name: Assert that the client configuration file is actually configured properly
|
||||
vars:
|
||||
config: "{{ client_config.content | b64decode | from_json }}"
|
||||
assert:
|
||||
that:
|
||||
- "config['client']['keepalives'] == true"
|
||||
- "config['client']['name'] == 'client'"
|
||||
- "config['client']['safe_mode'] == false"
|
||||
- "'default' in config['client']['subscriptions']"
|
||||
|
||||
- name: Delete Sensu client configuration
|
||||
sensu_client:
|
||||
state: "absent"
|
||||
register: client_delete
|
||||
|
||||
- name: Delete Sensu client configuration (again)
|
||||
sensu_client:
|
||||
state: "absent"
|
||||
register: client_delete_twice
|
||||
|
||||
- name: Retrieve configuration file stat
|
||||
stat:
|
||||
path: "{{ client_file }}"
|
||||
register: client_stat
|
||||
|
||||
- name: Assert that client deletion was successful
|
||||
assert:
|
||||
that:
|
||||
- "client_delete is successful"
|
||||
- "client_delete is changed"
|
||||
- "client_delete_twice is successful"
|
||||
- "client_delete_twice is not changed"
|
||||
- "client_stat.stat.exists == false"
|
||||
|
||||
- name: Configuring a client without subscriptions should fail
|
||||
sensu_client:
|
||||
name: "failure"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert failure to create client
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'the following are missing: subscriptions' in failure['msg']"
|
||||
|
||||
- name: Configure a new client from scratch with custom parameters
|
||||
sensu_client:
|
||||
name: "custom"
|
||||
address: "host.fqdn"
|
||||
subscriptions:
|
||||
- "default"
|
||||
- "webserver"
|
||||
redact:
|
||||
- "password"
|
||||
socket:
|
||||
bind: "127.0.0.1"
|
||||
port: "3030"
|
||||
keepalive:
|
||||
thresholds:
|
||||
warning: "180"
|
||||
critical: "300"
|
||||
handlers:
|
||||
- "email"
|
||||
custom:
|
||||
- broadcast: "irc"
|
||||
occurrences: "3"
|
||||
register: client
|
||||
|
||||
- name: Configure a new client from scratch with custom parameters (twice)
|
||||
sensu_client:
|
||||
name: "custom"
|
||||
address: "host.fqdn"
|
||||
subscriptions:
|
||||
- "default"
|
||||
- "webserver"
|
||||
redact:
|
||||
- "password"
|
||||
socket:
|
||||
bind: "127.0.0.1"
|
||||
port: "3030"
|
||||
keepalive:
|
||||
thresholds:
|
||||
warning: "180"
|
||||
critical: "300"
|
||||
handlers:
|
||||
- "email"
|
||||
custom:
|
||||
- broadcast: "irc"
|
||||
occurrences: "3"
|
||||
register: client_twice
|
||||
|
||||
- name: Retrieve configuration file
|
||||
slurp:
|
||||
src: "{{ client_file }}"
|
||||
register: client_config
|
||||
|
||||
- name: Assert that client data was set successfully and properly
|
||||
assert:
|
||||
that:
|
||||
- "client is successful"
|
||||
- "client is changed"
|
||||
- "client_twice is successful"
|
||||
- "client_twice is not changed"
|
||||
- "client['config']['name'] == 'custom'"
|
||||
- "client['config']['address'] == 'host.fqdn'"
|
||||
- "'default' in client['config']['subscriptions']"
|
||||
- "'webserver' in client['config']['subscriptions']"
|
||||
- "'password' in client['config']['redact']"
|
||||
- "client['config']['keepalive']['thresholds']['warning'] == '180'"
|
||||
- "client['config']['keepalive']['thresholds']['critical'] == '300'"
|
||||
- "'email' in client['config']['keepalive']['handlers']"
|
||||
- "client['config']['keepalive']['occurrences'] == '3'"
|
||||
- "client['file'] == client_file"
|
||||
|
||||
- name: Assert that the client configuration file is actually configured properly
|
||||
vars:
|
||||
config: "{{ client_config.content | b64decode | from_json }}"
|
||||
assert:
|
||||
that:
|
||||
- "config['client']['name'] == 'custom'"
|
||||
- "config['client']['address'] == 'host.fqdn'"
|
||||
- "config['client']['keepalives'] == true"
|
||||
- "config['client']['safe_mode'] == false"
|
||||
- "'default' in config['client']['subscriptions']"
|
||||
- "'webserver' in config['client']['subscriptions']"
|
||||
- "'password' in config['client']['redact']"
|
||||
- "config['client']['keepalive']['thresholds']['warning'] == '180'"
|
||||
- "config['client']['keepalive']['thresholds']['critical'] == '300'"
|
||||
- "'email' in config['client']['keepalive']['handlers']"
|
||||
- "config['client']['keepalive']['occurrences'] == '3'"
|
||||
@@ -1,6 +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
|
||||
|
||||
azp/posix/1
|
||||
needs/root
|
||||
@@ -1,129 +0,0 @@
|
||||
---
|
||||
####################################################################
|
||||
# WARNING: These are designed specifically for Ansible tests #
|
||||
# and should not be used as examples of how to write Ansible roles #
|
||||
####################################################################
|
||||
|
||||
# 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
|
||||
|
||||
- name: Creating a handler if the directory doesn't exist should work
|
||||
sensu_handler:
|
||||
name: "handler"
|
||||
type: "pipe"
|
||||
command: "/bin/bash"
|
||||
state: "present"
|
||||
|
||||
- name: Insert junk JSON in a handlers file
|
||||
lineinfile:
|
||||
state: "present"
|
||||
create: "yes"
|
||||
path: "/etc/sensu/conf.d/handlers/handler.json"
|
||||
line: "{'foo' = bar}"
|
||||
|
||||
- name: Configure a handler with an existing invalid file
|
||||
sensu_handler:
|
||||
name: "handler"
|
||||
type: "pipe"
|
||||
command: "/bin/bash"
|
||||
state: "present"
|
||||
register: handler
|
||||
|
||||
- name: Configure a handler (again)
|
||||
sensu_handler:
|
||||
name: "handler"
|
||||
type: "pipe"
|
||||
command: "/bin/bash"
|
||||
state: "present"
|
||||
register: handler_twice
|
||||
|
||||
- name: Retrieve configuration file
|
||||
slurp:
|
||||
src: "{{ handler['file'] }}"
|
||||
register: handler_config
|
||||
|
||||
- name: Assert that handler data was set successfully and properly
|
||||
assert:
|
||||
that:
|
||||
- "handler is successful"
|
||||
- "handler is changed"
|
||||
- "handler_twice is successful"
|
||||
- "handler_twice is not changed"
|
||||
- "handler['name'] == 'handler'"
|
||||
- "handler['file'] == '/etc/sensu/conf.d/handlers/handler.json'"
|
||||
- "handler['config']['type'] == 'pipe'"
|
||||
- "handler['config']['command'] == '/bin/bash'"
|
||||
- "handler['config']['timeout'] == 10"
|
||||
- "handler['config']['handle_flapping'] == false"
|
||||
- "handler['config']['handle_silenced'] == false"
|
||||
|
||||
- name: Assert that the handler configuration file is actually configured properly
|
||||
vars:
|
||||
config: "{{ handler_config.content | b64decode | from_json }}"
|
||||
assert:
|
||||
that:
|
||||
- "'handler' in config['handlers']"
|
||||
- "config['handlers']['handler']['type'] == 'pipe'"
|
||||
- "config['handlers']['handler']['command'] == '/bin/bash'"
|
||||
- "config['handlers']['handler']['timeout'] == 10"
|
||||
- "config['handlers']['handler']['handle_flapping'] == false"
|
||||
- "config['handlers']['handler']['handle_silenced'] == false"
|
||||
|
||||
- name: Delete Sensu handler configuration
|
||||
sensu_handler:
|
||||
name: "handler"
|
||||
state: "absent"
|
||||
register: handler_delete
|
||||
|
||||
- name: Delete Sensu handler configuration (again)
|
||||
sensu_handler:
|
||||
name: "handler"
|
||||
state: "absent"
|
||||
register: handler_delete_twice
|
||||
|
||||
- name: Retrieve configuration file stat
|
||||
stat:
|
||||
path: "{{ handler['file'] }}"
|
||||
register: handler_stat
|
||||
|
||||
- name: Assert that handler deletion was successful
|
||||
assert:
|
||||
that:
|
||||
- "handler_delete is successful"
|
||||
- "handler_delete is changed"
|
||||
- "handler_delete_twice is successful"
|
||||
- "handler_delete_twice is not changed"
|
||||
- "handler_stat.stat.exists == false"
|
||||
|
||||
- name: Configuring a handler without a name should fail
|
||||
sensu_handler:
|
||||
type: "pipe"
|
||||
command: "/bin/bash"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that configuring a handler without a name fails
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'required arguments: name' in failure['msg']"
|
||||
|
||||
- name: Configuring a handler without a type should fail
|
||||
sensu_handler:
|
||||
name: "pipe"
|
||||
command: "/bin/bash"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that configuring a handler without a type fails
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'the following are missing: type' in failure['msg']"
|
||||
|
||||
- include_tasks: pipe.yml
|
||||
- include_tasks: tcp.yml
|
||||
- include_tasks: udp.yml
|
||||
- include_tasks: set.yml
|
||||
- include_tasks: transport.yml
|
||||
@@ -1,25 +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
|
||||
|
||||
# Note: Pipe handlers are also tested and used as part of basic main.yml coverage
|
||||
- name: Configuring a handler with missing pipe parameters should fail
|
||||
sensu_handler:
|
||||
name: "pipe"
|
||||
type: "pipe"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that configuring a handler with missing pipe parameters fails
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'the following are missing: command' in failure['msg']"
|
||||
|
||||
- name: Configure a handler with pipe parameters
|
||||
sensu_handler:
|
||||
name: "pipe"
|
||||
type: "pipe"
|
||||
command: "/bin/bash"
|
||||
register: handler
|
||||
@@ -1,53 +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
|
||||
|
||||
- name: Configuring a handler with missing set parameters should fail
|
||||
sensu_handler:
|
||||
name: "set"
|
||||
type: "set"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that configuring a handler with missing set parameters fails
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'the following are missing: handlers' in failure['msg']"
|
||||
|
||||
- name: Configure a set handler
|
||||
sensu_handler:
|
||||
name: "set"
|
||||
type: "set"
|
||||
handlers:
|
||||
- anotherhandler
|
||||
register: handler
|
||||
|
||||
- name: Retrieve configuration file
|
||||
slurp:
|
||||
src: "{{ handler['file'] }}"
|
||||
register: handler_config
|
||||
|
||||
- name: Validate set handler return data
|
||||
assert:
|
||||
that:
|
||||
- "handler is successful"
|
||||
- "handler is changed"
|
||||
- "handler['name'] == 'set'"
|
||||
- "handler['file'] == '/etc/sensu/conf.d/handlers/set.json'"
|
||||
- "handler['config']['type'] == 'set'"
|
||||
- "'anotherhandler' in handler['config']['handlers']"
|
||||
- "handler['config']['handle_flapping'] == false"
|
||||
- "handler['config']['handle_silenced'] == false"
|
||||
|
||||
- name: Assert that the handler configuration file is actually configured properly
|
||||
vars:
|
||||
config: "{{ handler_config.content | b64decode | from_json }}"
|
||||
assert:
|
||||
that:
|
||||
- "'set' in config['handlers']"
|
||||
- "config['handlers']['set']['type'] == 'set'"
|
||||
- "'anotherhandler' in config['handlers']['set']['handlers']"
|
||||
- "config['handlers']['set']['handle_flapping'] == false"
|
||||
- "config['handlers']['set']['handle_silenced'] == false"
|
||||
@@ -1,56 +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
|
||||
|
||||
- name: Configuring a handler with missing tcp parameters should fail
|
||||
sensu_handler:
|
||||
name: "tcp"
|
||||
type: "tcp"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that configuring a handler with missing tcp parameters fails
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'the following are missing: socket' in failure['msg']"
|
||||
|
||||
- name: Configure a tcp handler
|
||||
sensu_handler:
|
||||
name: "tcp"
|
||||
type: "tcp"
|
||||
socket:
|
||||
host: 127.0.0.1
|
||||
port: 8000
|
||||
register: handler
|
||||
|
||||
- name: Retrieve configuration file
|
||||
slurp:
|
||||
src: "{{ handler['file'] }}"
|
||||
register: handler_config
|
||||
|
||||
- name: Validate tcp handler return data
|
||||
assert:
|
||||
that:
|
||||
- "handler is successful"
|
||||
- "handler is changed"
|
||||
- "handler['name'] == 'tcp'"
|
||||
- "handler['file'] == '/etc/sensu/conf.d/handlers/tcp.json'"
|
||||
- "handler['config']['type'] == 'tcp'"
|
||||
- "handler['config']['socket']['host'] == '127.0.0.1'"
|
||||
- "handler['config']['socket']['port'] == 8000"
|
||||
- "handler['config']['handle_flapping'] == false"
|
||||
- "handler['config']['handle_silenced'] == false"
|
||||
|
||||
- name: Assert that the handler configuration file is actually configured properly
|
||||
vars:
|
||||
config: "{{ handler_config.content | b64decode | from_json }}"
|
||||
assert:
|
||||
that:
|
||||
- "'tcp' in config['handlers']"
|
||||
- "config['handlers']['tcp']['type'] == 'tcp'"
|
||||
- "config['handlers']['tcp']['socket']['host'] == '127.0.0.1'"
|
||||
- "config['handlers']['tcp']['socket']['port'] == 8000"
|
||||
- "config['handlers']['tcp']['handle_flapping'] == false"
|
||||
- "config['handlers']['tcp']['handle_silenced'] == false"
|
||||
@@ -1,56 +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
|
||||
|
||||
- name: Configuring a handler with missing transport parameters should fail
|
||||
sensu_handler:
|
||||
name: "transport"
|
||||
type: "transport"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that configuring a handler with missing transport parameters fails
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'the following are missing: pipe' in failure['msg']"
|
||||
|
||||
- name: Configure a transport handler
|
||||
sensu_handler:
|
||||
name: "transport"
|
||||
type: "transport"
|
||||
pipe:
|
||||
type: "topic"
|
||||
name: "transport_handler"
|
||||
register: handler
|
||||
|
||||
- name: Retrieve configuration file
|
||||
slurp:
|
||||
src: "{{ handler['file'] }}"
|
||||
register: handler_config
|
||||
|
||||
- name: Validate transport handler return data
|
||||
assert:
|
||||
that:
|
||||
- "handler is successful"
|
||||
- "handler is changed"
|
||||
- "handler['name'] == 'transport'"
|
||||
- "handler['file'] == '/etc/sensu/conf.d/handlers/transport.json'"
|
||||
- "handler['config']['type'] == 'transport'"
|
||||
- "handler['config']['pipe']['type'] == 'topic'"
|
||||
- "handler['config']['pipe']['name'] == 'transport_handler'"
|
||||
- "handler['config']['handle_flapping'] == false"
|
||||
- "handler['config']['handle_silenced'] == false"
|
||||
|
||||
- name: Assert that the handler configuration file is actually configured properly
|
||||
vars:
|
||||
config: "{{ handler_config.content | b64decode | from_json }}"
|
||||
assert:
|
||||
that:
|
||||
- "'transport' in config['handlers']"
|
||||
- "config['handlers']['transport']['type'] == 'transport'"
|
||||
- "config['handlers']['transport']['pipe']['type'] == 'topic'"
|
||||
- "config['handlers']['transport']['pipe']['name'] == 'transport_handler'"
|
||||
- "config['handlers']['transport']['handle_flapping'] == false"
|
||||
- "config['handlers']['transport']['handle_silenced'] == false"
|
||||
@@ -1,56 +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
|
||||
|
||||
- name: Configuring a handler with missing udp parameters should fail
|
||||
sensu_handler:
|
||||
name: "udp"
|
||||
type: "udp"
|
||||
register: failure
|
||||
ignore_errors: true
|
||||
|
||||
- name: Assert that configuring a handler with missing udp parameters fails
|
||||
assert:
|
||||
that:
|
||||
- failure is failed
|
||||
- "'the following are missing: socket' in failure['msg']"
|
||||
|
||||
- name: Configure a udp handler
|
||||
sensu_handler:
|
||||
name: "udp"
|
||||
type: "udp"
|
||||
socket:
|
||||
host: 127.0.0.1
|
||||
port: 8000
|
||||
register: handler
|
||||
|
||||
- name: Retrieve configuration file
|
||||
slurp:
|
||||
src: "{{ handler['file'] }}"
|
||||
register: handler_config
|
||||
|
||||
- name: Validate udp handler return data
|
||||
assert:
|
||||
that:
|
||||
- "handler is successful"
|
||||
- "handler is changed"
|
||||
- "handler['name'] == 'udp'"
|
||||
- "handler['file'] == '/etc/sensu/conf.d/handlers/udp.json'"
|
||||
- "handler['config']['type'] == 'udp'"
|
||||
- "handler['config']['socket']['host'] == '127.0.0.1'"
|
||||
- "handler['config']['socket']['port'] == 8000"
|
||||
- "handler['config']['handle_flapping'] == false"
|
||||
- "handler['config']['handle_silenced'] == false"
|
||||
|
||||
- name: Assert that the handler configuration file is actually configured properly
|
||||
vars:
|
||||
config: "{{ handler_config.content | b64decode | from_json }}"
|
||||
assert:
|
||||
that:
|
||||
- "'udp' in config['handlers']"
|
||||
- "config['handlers']['udp']['type'] == 'udp'"
|
||||
- "config['handlers']['udp']['socket']['host'] == '127.0.0.1'"
|
||||
- "config['handlers']['udp']['socket']['port'] == 8000"
|
||||
- "config['handlers']['udp']['handle_flapping'] == false"
|
||||
- "config['handlers']['udp']['handle_silenced'] == false"
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user