freeipa/ipatests/test_integration/test_server_del.py
Stanislav Levin 851f6d48ac pylint: Fix consider-using-dict-items
Pylint 2.9 introduced new check:
> New checker consider-using-dict-items. Emitted when iterating over
dictionary keys and then indexing the same dictionary with the key
within loop body.

Fixes: https://pagure.io/freeipa/issue/9117
Signed-off-by: Stanislav Levin <slev@altlinux.org>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
2022-03-11 13:37:08 -05:00

354 lines
11 KiB
Python

#
# Copyright (C) 2016 FreeIPA Contributors see COPYING for license
#
from itertools import permutations
import pytest
from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_ipa.integration import tasks
from ipatests.pytest_ipa.integration.firewall import Firewall
from ipalib.constants import DOMAIN_LEVEL_1, DOMAIN_SUFFIX_NAME, CA_SUFFIX_NAME
REMOVAL_ERR_TEMPLATE = ("Removal of '{hostname}' leads to disconnected "
"topology in suffix '{suffix}'")
def check_master_removal(host, hostname_to_remove,
force=False,
ignore_topology_disconnect=False,
ignore_last_of_role=False):
result = tasks.run_server_del(
host,
hostname_to_remove,
force=force,
ignore_topology_disconnect=ignore_topology_disconnect,
ignore_last_of_role=ignore_last_of_role)
assert result.returncode == 0
if force:
assert ("Forcing removal of {hostname}".format(
hostname=hostname_to_remove) in result.stderr_text)
if ignore_topology_disconnect:
assert "Ignoring topology connectivity errors." in result.stderr_text
if ignore_last_of_role:
assert ("Ignoring these warnings and proceeding with removal" in
result.stderr_text)
tasks.assert_error(
host.run_command(
['ipa', 'server-show', hostname_to_remove], raiseonerr=False
),
"{}: server not found".format(hostname_to_remove),
returncode=2
)
# Only run the pki command if there is a CA installed on the machine
result = host.run_command(
[
'ipa',
'server-role-find',
'--server', host.hostname,
'--status', 'enabled',
'--role', 'CA server',
],
raiseonerr=False,
)
if result.returncode == 0:
host.run_command(['pki', 'client', 'init', '--force'])
result = host.run_command(
['pki', 'securitydomain-host-find'],
stdin_text='y\n',
).stdout_text
assert hostname_to_remove not in result
def check_removal_disconnects_topology(
host, hostname_to_remove,
affected_suffixes=(DOMAIN_SUFFIX_NAME,)):
result = tasks.run_server_del(host, hostname_to_remove)
assert len(affected_suffixes) <= 2
err_messages_by_suffix = {
CA_SUFFIX_NAME: REMOVAL_ERR_TEMPLATE.format(
hostname=hostname_to_remove,
suffix=CA_SUFFIX_NAME
),
DOMAIN_SUFFIX_NAME: REMOVAL_ERR_TEMPLATE.format(
hostname=hostname_to_remove,
suffix=DOMAIN_SUFFIX_NAME
)
}
for suffix, err_str in err_messages_by_suffix.items():
if suffix in affected_suffixes:
tasks.assert_error(result, err_str, returncode=1)
else:
assert err_str not in result.stderr_text
class ServerDelBase(IntegrationTest):
num_replicas = 2
num_clients = 1
domain_level = DOMAIN_LEVEL_1
topology = 'star'
@classmethod
def install(cls, mh):
super(ServerDelBase, cls).install(mh)
cls.client = cls.clients[0]
cls.replica1 = cls.replicas[0]
cls.replica2 = cls.replicas[1]
class TestServerDel(ServerDelBase):
@classmethod
def install(cls, mh):
super(TestServerDel, cls).install(mh)
# prepare topologysegments for negative test cases
# it should look like this for DOMAIN_SUFFIX_NAME:
# master
# /
# /
# /
# replica1------- replica2
# and like this for CA_SUFFIX_NAME
# master
# \
# \
# \
# replica1------- replica2
tasks.create_segment(cls.client, cls.replica1, cls.replica2)
tasks.create_segment(cls.client, cls.replica1, cls.replica2,
suffix=CA_SUFFIX_NAME)
# try to delete all relevant segment connecting master and replica1/2
segment_name_fmt = '{p[0].hostname}-to-{p[1].hostname}'
for domain_pair in permutations((cls.master, cls.replica2)):
tasks.destroy_segment(
cls.client, segment_name_fmt.format(p=domain_pair))
for ca_pair in permutations((cls.master, cls.replica1)):
tasks.destroy_segment(
cls.client, segment_name_fmt.format(p=ca_pair),
suffix=CA_SUFFIX_NAME)
def test_removal_of_nonexistent_master_raises_error(self):
"""
tests that removal of non-existent master raises an error
"""
hostname = u'bogus-master.bogus.domain'
err_message = "{}: server not found".format(hostname)
tasks.assert_error(
tasks.run_server_del(self.client, hostname),
err_message,
returncode=2
)
def test_forced_removal_of_nonexistent_master(self):
"""
tests that removal of non-existent master with '--force' does not raise
an error
"""
hostname = u'bogus-master.bogus.domain'
result = tasks.run_server_del(self.client, hostname, force=True)
assert result.returncode == 0
assert ('Deleted IPA server "{}"'.format(hostname) in
result.stdout_text)
assert ("Server has already been deleted" in result.stderr_text)
def test_removal_of_replica1_disconnects_domain_topology(self):
"""
tests that given the used topology, attempted removal of replica1 fails
with disconnected DOMAIN topology but not CA
"""
check_removal_disconnects_topology(
self.client,
self.replica1.hostname,
affected_suffixes=(DOMAIN_SUFFIX_NAME,)
)
def test_removal_of_replica2_disconnects_ca_topology(self):
"""
tests that given the used topology, attempted removal of replica2 fails
with disconnected CA topology but not DOMAIN
"""
check_removal_disconnects_topology(
self.client,
self.replica2.hostname,
affected_suffixes=(CA_SUFFIX_NAME,)
)
def test_ignore_topology_disconnect_replica1(self):
"""
tests that removal of replica1 with '--ignore-topology-disconnect'
destroys master for good
"""
check_master_removal(
self.client,
self.replica1.hostname,
ignore_topology_disconnect=True
)
# reinstall the replica
tasks.uninstall_master(self.replica1)
tasks.install_replica(self.master, self.replica1, setup_ca=True)
def test_ignore_topology_disconnect_replica2(self):
"""
tests that removal of replica2 with '--ignore-topology-disconnect'
destroys master for good with verbose option for uninstallation
"""
check_master_removal(
self.client,
self.replica2.hostname,
ignore_topology_disconnect=True
)
# reinstall the replica
tasks.uninstall_master(self.replica2, verbose=True)
tasks.install_replica(self.master, self.replica2, setup_ca=True)
def test_removal_of_master_disconnects_both_topologies(self):
"""
tests that master removal will now raise errors in both suffixes.
"""
check_removal_disconnects_topology(
self.client,
self.master.hostname,
affected_suffixes=(CA_SUFFIX_NAME, DOMAIN_SUFFIX_NAME)
)
def test_removal_of_replica1(self):
"""
tests the removal of replica1 which should now pass without errors
"""
check_master_removal(
self.client,
self.replica1.hostname
)
def test_removal_of_replica2(self):
"""
tests the removal of replica2 which should now pass without errors
"""
check_master_removal(
self.client,
self.replica2.hostname
)
class TestLastServices(ServerDelBase):
"""
Test the checks for last services during server-del and their bypassing
using when forcing the removal
"""
num_replicas = 1
domain_level = DOMAIN_LEVEL_1
topology = 'line'
@pytest.fixture
def restart_ipa(self):
yield
self.master.run_command(['ipactl', 'start'])
@classmethod
def install(cls, mh):
tasks.install_topo(
cls.topology, cls.master, cls.replicas, [],
domain_level=cls.domain_level, setup_replica_cas=False)
def test_removal_of_master_raises_error_about_last_dns(self):
"""
Now server-del should complain about the removal of last DNS server
"""
tasks.assert_error(
tasks.run_server_del(self.replicas[0], self.master.hostname),
"Deleting this server will leave your installation "
"without a DNS.",
1
)
def test_install_dns_on_replica1_and_dnssec_on_master(self):
"""
install DNS server on replica and DNSSec on master
"""
tasks.install_dns(self.replicas[0])
args = [
"ipa-dns-install",
"--dnssec-master",
"--forwarder", self.master.config.dns_forwarder,
"-U",
]
self.master.run_command(args)
Firewall(self.master).enable_service("dns")
def test_removal_of_master_raises_error_about_dnssec(self):
tasks.assert_error(
tasks.run_server_del(self.replicas[0], self.master.hostname),
"Replica is active DNSSEC key master. Uninstall "
"could break your DNS system. Please disable or replace "
"DNSSEC key master first.",
1
)
def test_disable_dnssec_on_master(self):
"""
Disable DNSSec master so that it is not tested anymore. Normal way
would be to move the DNSSec master to replica, but that is tested in
DNSSec tests.
"""
args = [
"ipa-dns-install",
"--disable-dnssec-master",
"--forwarder", self.master.config.dns_forwarder,
"--force",
"-U",
]
self.master.run_command(args)
def test_removal_of_master_raises_error_about_last_ca(self):
"""
test that removal of master fails on the last
"""
tasks.assert_error(
tasks.run_server_del(self.replicas[0], self.master.hostname),
"Deleting this server is not allowed as it would leave your "
"installation without a CA.",
1
)
def test_removal_of_server_raises_error_about_last_kra(self, restart_ipa):
"""
test that removal of server fails on the last KRA
We shut it down to verify that it can be removed if it failed.
"""
tasks.install_kra(self.master)
self.master.run_command(['ipactl', 'stop'])
tasks.assert_error(
tasks.run_server_del(self.replicas[0], self.master.hostname),
"Deleting this server is not allowed as it would leave your "
"installation without a KRA.",
1
)
def test_forced_removal_of_master(self):
"""
Tests that we can still force remove the master using
'--ignore-last-of-role'
"""
check_master_removal(
self.replicas[0], self.master.hostname,
ignore_last_of_role=True
)