diff --git a/.freeipa-pr-ci.yaml b/.freeipa-pr-ci.yaml index abcf8c5b634..80656690080 120000 --- a/.freeipa-pr-ci.yaml +++ b/.freeipa-pr-ci.yaml @@ -1 +1 @@ -ipatests/prci_definitions/gating.yaml \ No newline at end of file +ipatests/prci_definitions/temp_commit.yaml \ No newline at end of file diff --git a/doc/designs/prci_checker.md b/doc/designs/prci_checker.md index 08dc62d4c06..a88f9fa5107 100644 --- a/doc/designs/prci_checker.md +++ b/doc/designs/prci_checker.md @@ -72,7 +72,8 @@ classes: - "RunPytest2" - "RunPytest3" - "RunWebuiTests" - - "RunADTests" + - "`RunADTests`" + - "RunMultiDomainPytest" # (Optional) Definition files that should contain the same number of jobs fixed_n_jobs: @@ -182,7 +183,7 @@ $ python3 ipatests/prci_definitions/prci_checker.py -f ipatests/prci_definitions BEGINNING PRCI JOB DEFINITIONS CHECKS [File] gating [Jobs] 24 ERROR: In job 'fedora-latest/test_installation_TestInstallMaster': - 'class' field should be defined with one of the supported: ['RunPytest', 'RunPytest2', 'RunPytest3', 'RunWebuiTests', 'RunADTests'] + 'class' field should be defined with one of the supported: ['RunPytest', 'RunPytest2', 'RunPytest3', 'RunWebuiTests', 'RunADTests', 'RunMultiDomainPytest'] CHECKS FINISHED WITH ERRORS ``` diff --git a/ipatests/prci_definitions/prci_jobs_spec.yaml b/ipatests/prci_definitions/prci_jobs_spec.yaml index 7bc99d8d9a2..8064e844628 100644 --- a/ipatests/prci_definitions/prci_jobs_spec.yaml +++ b/ipatests/prci_definitions/prci_jobs_spec.yaml @@ -9,6 +9,7 @@ classes: - "RunPytest3" - "RunWebuiTests" - "RunADTests" + - "RunMultiDomainPytest" # (Optional) Definition files that should contain the same number of jobs fixed_n_jobs: diff --git a/ipatests/prci_definitions/temp_commit.yaml b/ipatests/prci_definitions/temp_commit.yaml index 233cd5705f1..0c3d5b1b52e 100644 --- a/ipatests/prci_definitions/temp_commit.yaml +++ b/ipatests/prci_definitions/temp_commit.yaml @@ -69,10 +69,10 @@ jobs: requires: [fedora-latest/build] priority: 50 job: - class: RunPytest + class: RunMultiDomainPytest args: build_url: '{fedora-latest/build_url}' - test_suite: test_integration/test_REPLACEME.py + test_suite: test_integration/test_trusted_ipa.py template: *ci-master-latest timeout: 3600 topology: *master_1repl_1client diff --git a/ipatests/pytest_ipa/integration/__init__.py b/ipatests/pytest_ipa/integration/__init__.py index 34b6ef0fb1e..22c5b04ade8 100644 --- a/ipatests/pytest_ipa/integration/__init__.py +++ b/ipatests/pytest_ipa/integration/__init__.py @@ -386,45 +386,79 @@ def mh(request, class_integration_logs): """ cls = request.cls - domain_description = { - 'type': 'IPA', - 'hosts': { - 'master': 1, - 'replica': cls.num_replicas, - 'client': cls.num_clients, - }, - } - domain_description['hosts'].update( - {role: 1 for role in cls.required_extra_roles}) - - domain_descriptions = [domain_description] - for _i in range(cls.num_ad_domains): - domain_descriptions.append({ - 'type': 'AD', - 'hosts': {'ad': 1} - }) - for _i in range(cls.num_ad_subdomains): - domain_descriptions.append({ - 'type': 'AD_SUBDOMAIN', - 'hosts': {'ad_subdomain': 1} - }) - for _i in range(cls.num_ad_treedomains): - domain_descriptions.append({ - 'type': 'AD_TREEDOMAIN', - 'hosts': {'ad_treedomain': 1} - }) - - mh = make_multihost_fixture( - request, - domain_descriptions, - config_class=Config, - _config=get_global_config(), - ) - mh.domain = mh.config.domains[0] - [mh.master] = mh.domain.hosts_by_role('master') - mh.replicas = mh.domain.hosts_by_role('replica') - mh.clients = mh.domain.hosts_by_role('client') + if cls.num_trusted_domains == 1: + mh = make_multihost_fixture(request, descriptions=[ + { + 'type': 'IPA', + 'hosts': + { + 'master': 1, + 'replica': cls.num_replicas, + 'client': cls.num_clients, + } + }, + { + 'type': 'TRUSTED_IPA', + 'hosts': + { + 'trusted_master': 1, + 'trusted_replica': cls.num_trusted_replicas, + 'trusted_client': cls.num_trusted_clients, + + }, + }, + ], config_class=Config, _config=get_global_config(),) + else: + domain_description = { + 'type': 'IPA', + 'hosts': { + 'master': 1, + 'replica': cls.num_replicas, + 'client': cls.num_clients, + }, + } + domain_description['hosts'].update( + {role: 1 for role in cls.required_extra_roles}) + + domain_descriptions = [domain_description] + for _i in range(cls.num_ad_domains): + domain_descriptions.append({ + 'type': 'AD', + 'hosts': {'ad': 1} + }) + for _i in range(cls.num_ad_subdomains): + domain_descriptions.append({ + 'type': 'AD_SUBDOMAIN', + 'hosts': {'ad_subdomain': 1} + }) + for _i in range(cls.num_ad_treedomains): + domain_descriptions.append({ + 'type': 'AD_TREEDOMAIN', + 'hosts': {'ad_treedomain': 1} + }) + mh = make_multihost_fixture( + request, + domain_descriptions, + config_class=Config, + _config=get_global_config(), + ) + if cls.num_trusted_domains == 1: + mh.domain1 = mh.config.domains[0] + mh.domain2 = mh.config.domains[1] + + [mh.master] = mh.domain1.hosts_by_role('master') + mh.replicas = mh.domain1.hosts_by_role('replica') + mh.clients = mh.domain1.hosts_by_role('client') + [mh.trusted_master] = mh.domain2.hosts_by_role('trusted_master') + mh.trusted_replicas = mh.domain2.hosts_by_role('trusted_replica') + mh.trusted_clients = mh.domain2.hosts_by_role('trusted_client') + else: + mh.domain = mh.config.domains[0] + [mh.master] = mh.domain.hosts_by_role('master') + mh.replicas = mh.domain.hosts_by_role('replica') + mh.clients = mh.domain.hosts_by_role('client') + ad_domains = mh.config.ad_domains if ad_domains: mh.ads = [] @@ -477,11 +511,21 @@ def add_compat_attrs(cls, mh): This is deprecated in favor of the mh fixture. To be removed when no more tests using this. """ - cls.domain = mh.domain - cls.master = mh.master - cls.replicas = mh.replicas - cls.clients = mh.clients - cls.ad_domains = mh.config.ad_domains + if cls.num_trusted_domains == 1: + cls.domain1 = mh.domain1 + cls.domain2 = mh.domain2 + cls.master = mh.master + cls.replicas = mh.replicas + cls.clients = mh.clients + cls.trusted_master = mh.trusted_master + cls.trusted_replicas = mh.trusted_replicas + cls.trusted_clients = mh.trusted_clients + cls.ad_domains = mh.config.ad_domains + else: + cls.domain = mh.domain + cls.master = mh.master + cls.replicas = mh.replicas + cls.clients = mh.clients if cls.ad_domains: cls.ads = mh.ads cls.ad_subdomains = mh.ad_subdomains @@ -494,15 +538,30 @@ def del_compat_attrs(cls): This is deprecated in favor of the mh fixture. To be removed when no more tests using this. """ - del cls.master - del cls.replicas - del cls.clients - del cls.domain - if cls.ad_domains: - del cls.ads - del cls.ad_subdomains - del cls.ad_treedomains - del cls.ad_domains + if cls.num_trusted_domains == 1: + del cls.master + del cls.replicas + del cls.clients + del cls.trusted_master + del cls.trusted_replicas + del cls.trusted_clients + del cls.domain1 + del cls.domain2 + if cls.ad_domains: + del cls.ads + del cls.ad_subdomains + del cls.ad_treedomains + del cls.ad_domains + else: + del cls.master + del cls.replicas + del cls.clients + del cls.domain + if cls.ad_domains: + del cls.ads + del cls.ad_subdomains + del cls.ad_treedomains + del cls.ad_domains def skip_if_fips(reason='Not supported in FIPS mode', host='master'): diff --git a/ipatests/pytest_ipa/integration/config.py b/ipatests/pytest_ipa/integration/config.py index 1f4dff7f652..571d7b9baad 100644 --- a/ipatests/pytest_ipa/integration/config.py +++ b/ipatests/pytest_ipa/integration/config.py @@ -94,7 +94,7 @@ def get_all_hosts(self): yield host def get_all_ipa_hosts(self): - for ipa_domain in (d for d in self.domains if d.is_ipa_type): + for ipa_domain in (d for d in self.domains if d.is_ipa_type or d.is_trusted_ipa_type): for ipa_host in ipa_domain.hosts: yield ipa_host @@ -135,7 +135,7 @@ def __init__(self, config, name, domain_type): self.name = str(name) self.hosts = [] - assert self.is_ipa_type or self.is_ad_type + assert self.is_ipa_type or self.is_ad_type or self.is_trusted_ipa_type self.realm = self.name.upper() self.basedn = DN(*(('dc', p) for p in name.split('.'))) @@ -143,6 +143,10 @@ def __init__(self, config, name, domain_type): def is_ipa_type(self): return self.type == 'IPA' + @property + def is_trusted_ipa_type(self): + return self.type == 'TRUSTED_IPA' + @property def is_ad_type(self): return self.type == 'AD' or self.type.startswith('AD_') @@ -158,6 +162,8 @@ def static_roles(self): return ('ad_subdomain',) elif self.type == 'AD_TREEDOMAIN': return ('ad_treedomain',) + elif self.type == 'TRUSTED_IPA': + return ('trusted_master', 'trusted_replica', 'trusted_client') else: raise LookupError(self.type) @@ -168,6 +174,8 @@ def get_host_class(self, host_dict): return Host elif self.is_ad_type: return WinHost + elif self.is_trusted_ipa_type: + return Host else: raise LookupError(self.type) @@ -175,6 +183,10 @@ def get_host_class(self, host_dict): def master(self): return self.host_by_role('master') + @property + def trusted_master(self): + return self.host_by_role('trusted_master') + @property def masters(self): return self.hosts_by_role('master') @@ -183,10 +195,18 @@ def masters(self): def replicas(self): return self.hosts_by_role('replica') + @property + def trusted_replicas(self): + return self.hosts_by_role('trusted_replica') + @property def clients(self): return self.hosts_by_role('client') + @property + def trusted_clients(self): + return self.hosts_by_role('trusted_client') + @property def ads(self): return self.hosts_by_role('ad') diff --git a/ipatests/test_integration/base.py b/ipatests/test_integration/base.py index 4717667cb0c..b26adc5af11 100644 --- a/ipatests/test_integration/base.py +++ b/ipatests/test_integration/base.py @@ -32,7 +32,10 @@ class IntegrationTest: num_replicas = 0 num_clients = 0 + num_trusted_replicas = 0 + num_trusted_clients = 0 num_ad_domains = 0 + num_trusted_domains = 0 num_ad_subdomains = 0 num_ad_treedomains = 0 required_extra_roles = [] diff --git a/ipatests/test_integration/test_trusted_ipa.py b/ipatests/test_integration/test_trusted_ipa.py new file mode 100644 index 00000000000..02a9975aa2a --- /dev/null +++ b/ipatests/test_integration/test_trusted_ipa.py @@ -0,0 +1,90 @@ +import time +import pytest +from ipatests.pytest_ipa.integration import config +from ipatests.pytest_ipa.integration import tasks +from ipatests.test_integration.base import IntegrationTest +import os + +def install_multidomain(master, trusted_master): + for host in (master, trusted_master): + tasks.install_master(host, setup_dns=True) + user = "idmuser" + passwd = "Secret123" + group = "idmgroup" + tasks.kinit_admin(host) + tasks.create_active_user( + host, user, passwd, first=user, last=user + ) + tasks.kinit_admin(host) + tasks.group_add(host, group) + tasks.group_add_member(host, group, user) + +class TestMinimalConfig(IntegrationTest): + num_trusted_domains = 1 + num_clients = 1 + num_trusted_clients = 1 + + @classmethod + def install(cls, mh): + master1 = cls.master + master2 = cls.trusted_master + cls.client = cls.clients[0] + cls.trusted_client = cls.trusted_clients[0] + + master1.run_command(["hostname"]) + master2.run_command(["hostname"]) + + @classmethod + def uninstall(cls, mh): + pass + + def _parse_result(self, result): + # ipa CLI should get an --outform json option + info = {} + for line in result.stdout_text.split("\n"): + line = line.strip() + if line: + if ":" not in line: + continue + k, v = line.split(":", 1) + k = k.strip() + v = v.strip() + try: + v = int(v, 10) + except ValueError: + if v == "FALSE": + v = False + elif v == "TRUE": + v = True + info.setdefault(k.lower(), []).append(v) + + for k, v in info.items(): + if len(v) == 1: + info[k] = v[0] + else: + info[k] = set(v) + return info + + def test_multidomain_setup(self): + install_multidomain(self.master, self.trusted_master) + tasks.install_client(self.master, self.client) + tasks.install_client(self.trusted_master, self.trusted_client) + master1 = self.master + master2 = self.trusted_master + tasks.kinit_admin(master1) + tasks.kinit_admin(master2) + tasks.disable_dnssec_validation(master1) + tasks.disable_dnssec_validation(master2) + tasks.restart_named(master1) + master1.run_command( + ["ipa", "dnsforwardzone-add", master2.domain.name, + "--forwarder={0}".format(master2.ip), + "--forward-policy=only" + ] + ) + master2.run_command( + ["ipa", "dnsforwardzone-add", master1.domain.name, + "--forwarder={0}".format(master1.ip), + "--forward-policy=only" + ] + )