summaryrefslogtreecommitdiffstats
path: root/ansible_collections/theforeman/foreman/tests
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/theforeman/foreman/tests
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/theforeman/foreman/tests')
-rw-r--r--ansible_collections/theforeman/foreman/tests/__init__.py0
-rw-r--r--ansible_collections/theforeman/foreman/tests/callback/three_hosts4
-rw-r--r--ansible_collections/theforeman/foreman/tests/callback/three_hosts.yml71
-rw-r--r--ansible_collections/theforeman/foreman/tests/conftest.py112
-rw-r--r--ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhost.json108
-rw-r--r--ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostA.json53
-rw-r--r--ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostB.json53
-rw-r--r--ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhost.json414
-rw-r--r--ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostA.json133
-rw-r--r--ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostB.json133
-rw-r--r--ansible_collections/theforeman/foreman/tests/galaxy-importer.cfg2
-rw-r--r--ansible_collections/theforeman/foreman/tests/inventory/hosts3
-rw-r--r--ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin.foreman.yml8
-rw-r--r--ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin_ansible.foreman.yml10
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_callback.py96
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_crud.py69
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_foreman_spec_helper.py61
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_module_state.py18
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/activation_key.yml281
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/activation_keys_role.yml28
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/architecture.yml132
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/auth_source_ldap.yml82
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/auth_sources_ldap_role.yml26
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/bookmark.yml41
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/compute_attribute.yml88
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile.yml115
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile_ovirt.yml77
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profiles_role.yml92
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resource.yml136
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resources_role.yml72
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/config_group.yml75
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_credential.yml77
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_credentials_role.yml59
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_info.yml49
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_library.yml69
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_repository.yml65
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_version.yml84
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_rhel_role.yml32
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload.yml94
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_deb.yml65
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_ostree.yml67
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view.yml229
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter.yml210
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_info.yml325
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule.yml141
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule_info.yml298
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_info.yml93
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_publish_role.yml93
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version.yml156
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_cleanup_role.yml109
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_info.yml120
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/content_views_role.yml68
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/convert2rhel.yml31
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/ansible_hello.erb18
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/bear-4.1-1.noarch.rpmbin0 -> 2438 bytes
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/delete_file.erb13
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/file_repo_test.txt1
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/fixtures_small_repo.tarbin0 -> 30720 bytes
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key.asc19
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key2.asc30
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/manifest_foreman-ansible-modules.zipbin0 -> 141074 bytes
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/odin_1.0_ppc64.debbin0 -> 2192 bytes
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds-tailoring.xml21
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds.xml4015
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/data/test-srpm01-1.0-1.src.rpmbin0 -> 2255 bytes
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/discovery_rule.yml108
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/domain.yml183
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/domain_info.yml83
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/domains_role.yml61
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/external_usergroup.yml84
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/filters.yml17
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/global_parameter.yml169
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/hardware_model.yml63
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/host.yml573
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/host_collection.yml82
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/host_errata_info.yml99
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/host_info.yml101
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/host_interface_attributes.yml323
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/host_power.yml86
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup.yml636
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup_info.yml49
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroups_role.yml29
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/http_proxy.yml118
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/image.yml205
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/installation_medium.yml138
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin.yml25
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin_ansible.yml25
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/job_invocation.yml44
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/job_template.yml189
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/katello_hostgroup.yml175
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/katello_smart_proxy.yml112
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environment.yml112
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environments_role.yml31
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/location.yml216
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/luna_hostgroup.yml105
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/manifest_role.yml26
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/module_defaults.yml36
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystem.yml122
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystems_role.yml70
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/organization.yml135
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/organization_info.yml46
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/organizations_role.yml46
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/os_default_template.yml94
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/partition_table.yml182
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/product.yml132
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_template.yml158
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_templates_role.yml69
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/puppet_environment.yml63
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/puppetclasses_import.yml49
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/realm.yml37
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/redhat_manifest.yml45
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role.yml48
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role_deb.yml33
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repository.yml193
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repository_deb.yml92
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repository_info.yml76
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repository_ostree.yml73
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set.yml191
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set_info.yml66
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/repository_sync.yml56
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/resource_info.yml100
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/role.yml135
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/scap_content.yml109
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/scap_tailoring_file.yml109
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/scc_account.yml112
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product.yml54
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product_old.yml54
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/setting.yml68
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/setting_info.yml47
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/settings_role.yml46
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/smart_class_parameter.yml593
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/smart_proxy.yml72
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot.yml50
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot_info.yml31
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/status_info.yml20
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/subnet.yml276
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/subnet_info.yml99
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/subnets_role.yml91
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_info.yml66
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_manifest.yml78
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plan.yml89
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plans_role.yml45
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/_assert_diff.yml13
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/activation_key.yml38
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/architecture.yml19
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/auth_source_ldap.yml56
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/bookmark.yml25
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_attribute.yml22
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_profile.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_resource.yml28
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/config_group.yml20
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_credential.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_info.yml14
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_library.yml22
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_repository.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_show.yml29
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_version.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view.yml29
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_docker.yml31
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_date.yml38
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_id.yml31
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_modulemd.yml30
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package.yml39
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package_group.yml31
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_cleanup.yml346
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_containers.yml59
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_date.yml67
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_id.yml61
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_modulemd.yml244
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_package_groups.yml65
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_packages.yml98
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_version.yml27
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/discovery_rule.yml32
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/domain.yml26
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/environment.yml24
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/external_usergroup.yml21
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/global_parameter.yml25
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host.yml53
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_collection.yml27
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_power.yml17
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/hostgroup.yml49
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/http_proxy.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/image.yml26
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/installation_medium.yml36
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin.yml20
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_setup.yml107
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_tests.yml47
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template.yml40
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template_from_file.yml18
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/katello_sync.yml37
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/lifecycle_environment.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/location.yml29
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/model.yml22
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/operatingsystem.yml34
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/organization.yml25
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/os_default_template.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/product.yml28
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/provisioning_template.yml37
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/ptable.yml35
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/puppetclasses_import.yml17
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/realm.yml22
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/redhat_manifest.yml27
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository.yml44
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository_set.yml29
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/role.yml28
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_content.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_tailoring_file.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_account.yml37
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_product.yml17
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/search_facts.yml18
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting.yml23
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting_fact.yml16
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_class_parameter.yml31
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_proxy.yml25
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/snapshot.yml19
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/status_info.yml7
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subnet.yml45
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subscription_manifest.yml21
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/sync_plan.yml33
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/templates_import.yml26
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/upload.yml24
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/user.yml49
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/usergroup.yml24
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/templates_import.yml102
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/user.yml103
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/usergroup.yml139
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/compute_profile.yml62
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/domain.yml8
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/host.yml13
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/hostgroup.yml39
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/search_facts.yml7
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/server.yml.example30
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/subnet.yml12
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/templates_import.yml6
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_playbooks/vars/usergroup.yml9
-rw-r--r--ansible_collections/theforeman/foreman/tests/test_recursive_dict_keys.py7
-rw-r--r--ansible_collections/theforeman/foreman/tests/utils.py14
-rw-r--r--ansible_collections/theforeman/foreman/tests/vcr_python_wrapper.py197
238 files changed, 21801 insertions, 0 deletions
diff --git a/ansible_collections/theforeman/foreman/tests/__init__.py b/ansible_collections/theforeman/foreman/tests/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/__init__.py
diff --git a/ansible_collections/theforeman/foreman/tests/callback/three_hosts b/ansible_collections/theforeman/foreman/tests/callback/three_hosts
new file mode 100644
index 000000000..e7e0c6e94
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/callback/three_hosts
@@ -0,0 +1,4 @@
+[local]
+testhost ansible_connection=local ansible_python_interpreter="{{ ansible_playbook_python }}"
+testhostA ansible_connection=local ansible_python_interpreter="{{ ansible_playbook_python }}"
+testhostB ansible_connection=local ansible_python_interpreter="{{ ansible_playbook_python }}"
diff --git a/ansible_collections/theforeman/foreman/tests/callback/three_hosts.yml b/ansible_collections/theforeman/foreman/tests/callback/three_hosts.yml
new file mode 100644
index 000000000..cf9894faf
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/callback/three_hosts.yml
@@ -0,0 +1,71 @@
+---
+- hosts: testhost
+ gather_facts: false
+ vars:
+ foo: foo bar
+ tasks:
+ - name: Changed task
+ command: echo foo
+ changed_when: true
+ notify: test handlers
+
+ - name: Ok task
+ command: echo foo
+ changed_when: false
+
+ - name: Failed task
+ fail:
+ msg: no reason
+ ignore_errors: true
+
+ - name: Skipped task
+ command: echo foo
+ when: false
+
+ - name: Task with var in name ({{ foo }})
+ command: echo foo
+
+ - name: Loop task
+ command: echo foo
+ loop:
+ - 1
+ - 2
+ - 3
+ loop_control:
+ label: foo-{{ item }}
+
+ handlers:
+ - name: Test handler 1
+ command: echo foo
+ listen: test handlers
+
+ - name: Test handler 2
+ command: echo foo
+ changed_when: false
+ listen: test handlers
+
+ - name: Test handler 3
+ command: echo foo
+ listen: test handlers
+
+- hosts:
+ - testhostA
+ - testhostB
+ gather_facts: false
+ tasks:
+ - name: Changed task
+ command: echo foo
+ changed_when: true
+
+ - name: Ok task
+ command: echo foo
+ changed_when: false
+
+ - name: Failed task
+ fail:
+ msg: no reason
+ ignore_errors: true
+
+ - name: Skipped task
+ command: echo foo
+ when: false
diff --git a/ansible_collections/theforeman/foreman/tests/conftest.py b/ansible_collections/theforeman/foreman/tests/conftest.py
new file mode 100644
index 000000000..8a5b95830
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/conftest.py
@@ -0,0 +1,112 @@
+import json
+import os
+
+import ansible_runner
+import pkg_resources
+import pytest
+import py.path
+import yaml
+
+
+TEST_PLAYBOOKS_PATH = py.path.local(__file__).realpath() / '..' / 'test_playbooks'
+
+
+def find_all_test_playbooks():
+ excluded_playbooks = os.environ.get('FAM_TEST_EXCLUDE_PLAYBOOKS', '').split(',')
+ for playbook in TEST_PLAYBOOKS_PATH.listdir(sort=True):
+ playbook = playbook.basename
+ if playbook.endswith('.yml') and playbook not in excluded_playbooks:
+ yield playbook.replace('.yml', '')
+
+
+ALL_TEST_PLAYBOOKS = list(find_all_test_playbooks())
+TEST_PLAYBOOKS = sorted([playbook for playbook in ALL_TEST_PLAYBOOKS if not playbook.startswith('inventory_plugin')])
+INVENTORY_PLAYBOOKS = sorted(set(ALL_TEST_PLAYBOOKS) - set(TEST_PLAYBOOKS))
+
+
+def pytest_addoption(parser):
+ parser.addoption(
+ "--vcrmode",
+ action="store",
+ default="replay",
+ choices=["replay", "record", "live"],
+ help="mode for vcr recording; one of ['replay', 'record', 'live']",
+ )
+
+
+@pytest.fixture
+def vcrmode(request):
+ return request.config.getoption("vcrmode")
+
+
+def get_foreman_url():
+ server_yml = py.path.local(__file__).realpath() / '..' / 'test_playbooks/vars/server.yml'
+ with open(server_yml.strpath) as server_yml_file:
+ server_yml_content = yaml.safe_load(server_yml_file)
+
+ return server_yml_content['foreman_server_url']
+
+
+def run_playbook(module, extra_vars=None, limit=None, inventory=None, check_mode=False, extra_env=None):
+ # Assemble parameters for playbook call
+ os.environ['ANSIBLE_CONFIG'] = os.path.join(os.getcwd(), 'ansible.cfg')
+ if extra_env is not None:
+ os.environ.update(extra_env)
+ kwargs = {}
+ kwargs['playbook'] = os.path.join(os.getcwd(), 'tests', 'test_playbooks', '{}.yml'.format(module))
+ if inventory is None:
+ inventory = os.path.join(os.getcwd(), 'tests', 'inventory', 'hosts')
+ kwargs['inventory'] = inventory
+ kwargs['verbosity'] = 4
+ if extra_vars:
+ kwargs['extravars'] = extra_vars
+ if limit:
+ kwargs['limit'] = limit
+ if check_mode:
+ kwargs['cmdline'] = "--check"
+ return ansible_runner.run(**kwargs)
+
+
+def run_playbook_vcr(tmpdir, module, extra_vars=None, limit=None, inventory=None, record=False, check_mode=False, extra_env=None):
+ if extra_vars is None:
+ extra_vars = {}
+ if extra_env is None:
+ extra_env = {}
+ if record:
+ # Cassettes that are to be overwritten must be deleted first
+ record_mode = 'once'
+ extra_vars['recording'] = True
+ else:
+ # Never reach out to the internet
+ record_mode = 'none'
+ if limit is None:
+ # Only run the tests (skip fixtures)
+ limit = 'tests:container'
+
+ # Dump recording parameters to json-file and pass its name by environment
+ test_params = {'test_name': module, 'serial': 0, 'record_mode': record_mode, 'check_mode': check_mode}
+ params_file = tmpdir.join('{}_test_params.json'.format(module))
+ params_file.write(json.dumps(test_params), ensure=True)
+ extra_env['FAM_TEST_VCR_PARAMS_FILE'] = params_file.strpath
+
+ cache_dir = tmpdir.join('cache')
+ cache_dir.ensure(dir=True)
+ extra_env['XDG_CACHE_HOME'] = cache_dir.strpath
+ apypie_cache_folder = get_foreman_url().replace(':', '_').replace('/', '_')
+ json_cache = cache_dir / 'apypie' / apypie_cache_folder / 'v2/default.json'
+ json_cache.ensure()
+ apidoc = 'apidoc/{}.json'.format(module)
+ fixture_dir = py.path.local(__file__).realpath() / '..' / 'fixtures'
+ fixture_dir.join(apidoc).copy(json_cache)
+
+ return run_playbook(module, extra_vars=extra_vars, limit=limit, inventory=inventory, check_mode=check_mode, extra_env=extra_env)
+
+
+def get_ansible_version():
+ ansible_version = '2.14.0'
+ for ansible_name in ['ansible', 'ansible-base', 'ansible-core']:
+ try:
+ ansible_version = pkg_resources.get_distribution(ansible_name).version
+ except pkg_resources.DistributionNotFound:
+ pass
+ return ansible_version
diff --git a/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhost.json b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhost.json
new file mode 100644
index 000000000..bc03bdea9
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhost.json
@@ -0,0 +1,108 @@
+{
+ "config_report": {
+ "check_mode": false,
+ "host": "testhost",
+ "logs": [
+ {
+ "log": {
+ "level": "notice",
+ "messages": {
+ "message": "{\"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Changed task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "info",
+ "messages": {
+ "message": "{\"changed\": false, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Ok task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "err",
+ "messages": {
+ "message": "{\"changed\": false, \"failed\": true, \"module\": \"fail\", \"msg\": \"no reason\"}"
+ },
+ "sources": {
+ "source": "Failed task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "notice",
+ "messages": {
+ "message": "{\"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Task with var in name (foo bar)"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "notice",
+ "messages": {
+ "message": "{\"changed\": true, \"failed\": false, \"module\": \"command\", \"msg\": \"All items completed\", \"results\": [{\"_ansible_item_label\": \"foo-1\", \"ansible_loop_var\": \"item\", \"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"item\": 1, \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}, {\"_ansible_item_label\": \"foo-2\", \"ansible_loop_var\": \"item\", \"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"item\": 2, \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}, {\"_ansible_item_label\": \"foo-3\", \"ansible_loop_var\": \"item\", \"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"item\": 3, \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}]}"
+ },
+ "sources": {
+ "source": "Loop task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "notice",
+ "messages": {
+ "message": "{\"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Test handler 1"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "info",
+ "messages": {
+ "message": "{\"changed\": false, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Test handler 2"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "notice",
+ "messages": {
+ "message": "{\"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Test handler 3"
+ }
+ }
+ }
+ ],
+ "metrics": {
+ "time": {
+ "total": 1
+ }
+ },
+ "reported_at": "2000-01-01 12:00:00+00:00",
+ "reporter": "ansible",
+ "status": {
+ "applied": 5,
+ "failed": 0,
+ "skipped": 1
+ }
+ }
+} \ No newline at end of file
diff --git a/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostA.json b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostA.json
new file mode 100644
index 000000000..6e68c3ca8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostA.json
@@ -0,0 +1,53 @@
+{
+ "config_report": {
+ "check_mode": false,
+ "host": "testhostA",
+ "logs": [
+ {
+ "log": {
+ "level": "notice",
+ "messages": {
+ "message": "{\"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Changed task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "info",
+ "messages": {
+ "message": "{\"changed\": false, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Ok task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "err",
+ "messages": {
+ "message": "{\"changed\": false, \"failed\": true, \"module\": \"fail\", \"msg\": \"no reason\"}"
+ },
+ "sources": {
+ "source": "Failed task"
+ }
+ }
+ }
+ ],
+ "metrics": {
+ "time": {
+ "total": 1
+ }
+ },
+ "reported_at": "2000-01-01 12:00:00+00:00",
+ "reporter": "ansible",
+ "status": {
+ "applied": 1,
+ "failed": 0,
+ "skipped": 1
+ }
+ }
+} \ No newline at end of file
diff --git a/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostB.json b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostB.json
new file mode 100644
index 000000000..9a796252d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/foreman/testhostB.json
@@ -0,0 +1,53 @@
+{
+ "config_report": {
+ "check_mode": false,
+ "host": "testhostB",
+ "logs": [
+ {
+ "log": {
+ "level": "notice",
+ "messages": {
+ "message": "{\"changed\": true, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Changed task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "info",
+ "messages": {
+ "message": "{\"changed\": false, \"cmd\": [\"echo\", \"foo\"], \"delta\": \"12:00:00.0000\", \"end\": \"2000-01-01 12:00:00.0000\", \"failed\": false, \"invocation\": {\"module_args\": {\"_raw_params\": \"echo foo\", \"_uses_shell\": false, \"argv\": null, \"chdir\": null, \"creates\": null, \"executable\": null, \"removes\": null, \"stdin\": null, \"stdin_add_newline\": true, \"strip_empty_ends\": true}}, \"module\": \"command\", \"rc\": 0, \"start\": \"2000-01-01 12:00:00.0000\", \"stderr\": \"\", \"stderr_lines\": [], \"stdout\": \"foo\", \"stdout_lines\": [\"foo\"]}"
+ },
+ "sources": {
+ "source": "Ok task"
+ }
+ }
+ },
+ {
+ "log": {
+ "level": "err",
+ "messages": {
+ "message": "{\"changed\": false, \"failed\": true, \"module\": \"fail\", \"msg\": \"no reason\"}"
+ },
+ "sources": {
+ "source": "Failed task"
+ }
+ }
+ }
+ ],
+ "metrics": {
+ "time": {
+ "total": 1
+ }
+ },
+ "reported_at": "2000-01-01 12:00:00+00:00",
+ "reporter": "ansible",
+ "status": {
+ "applied": 1,
+ "failed": 0,
+ "skipped": 1
+ }
+ }
+} \ No newline at end of file
diff --git a/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhost.json b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhost.json
new file mode 100644
index 000000000..9a7ce00c7
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhost.json
@@ -0,0 +1,414 @@
+{
+ "check_mode": false,
+ "host": "testhost",
+ "metrics": {
+ "time": {
+ "total": 1
+ }
+ },
+ "reported_at": "2000-01-01 12:00:00+00:00",
+ "results": [
+ {
+ "failed": false,
+ "result": {
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "changed_when": [
+ true
+ ],
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "name": "Changed task",
+ "notify": [
+ "test handlers"
+ ],
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": false,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "changed_when": [
+ false
+ ],
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "name": "Ok task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": true,
+ "result": {
+ "changed": false
+ },
+ "task": {
+ "action": "fail",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "ignore_errors": true,
+ "name": "Failed task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "name": "Task with var in name (foo bar)",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": true,
+ "results": [
+ {
+ "_ansible_item_label": "foo-1",
+ "ansible_loop_var": "item",
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "failed": false,
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "item": 1,
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ {
+ "_ansible_item_label": "foo-2",
+ "ansible_loop_var": "item",
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "failed": false,
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "item": 2,
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ {
+ "_ansible_item_label": "foo-3",
+ "ansible_loop_var": "item",
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "failed": false,
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "item": 3,
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ }
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "loop": [
+ 1,
+ 2,
+ 3
+ ],
+ "name": "Loop task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "is_handler": true,
+ "listen": "test handlers",
+ "name": "Test handler 1",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": false,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "changed_when": [
+ false
+ ],
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "is_handler": true,
+ "listen": "test handlers",
+ "name": "Test handler 2",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "is_handler": true,
+ "listen": "test handlers",
+ "name": "Test handler 3",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ }
+ ],
+ "summary": {
+ "changed": 5,
+ "failures": 0,
+ "ignored": 1,
+ "ok": 8,
+ "rescued": 0,
+ "skipped": 1,
+ "unreachable": 0
+ }
+} \ No newline at end of file
diff --git a/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostA.json b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostA.json
new file mode 100644
index 000000000..5798dadb5
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostA.json
@@ -0,0 +1,133 @@
+{
+ "check_mode": false,
+ "host": "testhostA",
+ "metrics": {
+ "time": {
+ "total": 1
+ }
+ },
+ "reported_at": "2000-01-01 12:00:00+00:00",
+ "results": [
+ {
+ "failed": false,
+ "result": {
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "changed_when": [
+ true
+ ],
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "name": "Changed task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": false,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "changed_when": [
+ false
+ ],
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "name": "Ok task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": true,
+ "result": {
+ "changed": false
+ },
+ "task": {
+ "action": "fail",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "ignore_errors": true,
+ "name": "Failed task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ }
+ ],
+ "summary": {
+ "changed": 1,
+ "failures": 0,
+ "ignored": 1,
+ "ok": 3,
+ "rescued": 0,
+ "skipped": 1,
+ "unreachable": 0
+ }
+} \ No newline at end of file
diff --git a/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostB.json b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostB.json
new file mode 100644
index 000000000..a78950d0e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/fixtures/callback/dir_store/proxy/testhostB.json
@@ -0,0 +1,133 @@
+{
+ "check_mode": false,
+ "host": "testhostB",
+ "metrics": {
+ "time": {
+ "total": 1
+ }
+ },
+ "reported_at": "2000-01-01 12:00:00+00:00",
+ "results": [
+ {
+ "failed": false,
+ "result": {
+ "changed": true,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "changed_when": [
+ true
+ ],
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "name": "Changed task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": false,
+ "result": {
+ "changed": false,
+ "cmd": [
+ "echo",
+ "foo"
+ ],
+ "invocation": {
+ "module_args": {
+ "_raw_params": "echo foo",
+ "_uses_shell": false,
+ "stdin_add_newline": true,
+ "strip_empty_ends": true
+ }
+ },
+ "rc": 0,
+ "stderr": "",
+ "stdout": "foo",
+ "stdout_lines": [
+ "foo"
+ ]
+ },
+ "task": {
+ "action": "command",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "changed_when": [
+ false
+ ],
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "name": "Ok task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ },
+ {
+ "failed": true,
+ "result": {
+ "changed": false
+ },
+ "task": {
+ "action": "fail",
+ "any_errors_fatal": false,
+ "async": 0,
+ "async_val": 0,
+ "become": false,
+ "become_method": "sudo",
+ "check_mode": false,
+ "delay": 5,
+ "diff": false,
+ "finalized": true,
+ "ignore_errors": true,
+ "name": "Failed task",
+ "poll": 15,
+ "retries": 3,
+ "squashed": true,
+ "throttle": 0
+ }
+ }
+ ],
+ "summary": {
+ "changed": 1,
+ "failures": 0,
+ "ignored": 1,
+ "ok": 3,
+ "rescued": 0,
+ "skipped": 1,
+ "unreachable": 0
+ }
+} \ No newline at end of file
diff --git a/ansible_collections/theforeman/foreman/tests/galaxy-importer.cfg b/ansible_collections/theforeman/foreman/tests/galaxy-importer.cfg
new file mode 100644
index 000000000..6aa4ee837
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/galaxy-importer.cfg
@@ -0,0 +1,2 @@
+[galaxy-importer]
+CHECK_REQUIRED_TAGS = True
diff --git a/ansible_collections/theforeman/foreman/tests/inventory/hosts b/ansible_collections/theforeman/foreman/tests/inventory/hosts
new file mode 100644
index 000000000..7dea42490
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/inventory/hosts
@@ -0,0 +1,3 @@
+localhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python"
+container ansible_connection=local ansible_python_interpreter="/usr/bin/env python"
+tests ansible_connection=local ansible_python_interpreter="/usr/bin/env python ../vcr_python_wrapper.py"
diff --git a/ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin.foreman.yml b/ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin.foreman.yml
new file mode 100644
index 000000000..cc737d7a6
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin.foreman.yml
@@ -0,0 +1,8 @@
+plugin: theforeman.foreman.foreman
+url: http://localhost:3000/
+user: admin
+password: changeme
+validate_certs: false
+want_params: true
+want_facts: true
+use_reports_api: false
diff --git a/ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin_ansible.foreman.yml b/ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin_ansible.foreman.yml
new file mode 100644
index 000000000..90d1d6a47
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/inventory/inventory_plugin_ansible.foreman.yml
@@ -0,0 +1,10 @@
+plugin: theforeman.foreman.foreman
+url: http://localhost:3001/
+user: admin
+password: changeme
+validate_certs: false
+want_params: true
+want_facts: true
+want_content_facet_attributes: false
+want_hostcollections: false
+use_reports_api: true
diff --git a/ansible_collections/theforeman/foreman/tests/test_callback.py b/ansible_collections/theforeman/foreman/tests/test_callback.py
new file mode 100644
index 000000000..91a7b9540
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_callback.py
@@ -0,0 +1,96 @@
+import os
+import re
+import json
+
+try:
+ from ansible.module_utils.compat.version import LooseVersion
+except ImportError:
+ from distutils.version import LooseVersion
+
+from .conftest import run_playbook, get_ansible_version
+
+
+def run_playbook_callback(tmpdir, report_type):
+ extra_env = {}
+ ansible_version = get_ansible_version()
+ if LooseVersion(ansible_version) < LooseVersion('2.11'):
+ extra_env['ANSIBLE_CALLBACK_WHITELIST'] = "theforeman.foreman.foreman"
+ extra_env['ANSIBLE_COMMAND_WARNINGS'] = "0"
+ else:
+ extra_env['ANSIBLE_CALLBACKS_ENABLED'] = "theforeman.foreman.foreman"
+ # No connection is actually performed during the test
+ extra_env['FOREMAN_REPORT_TYPE'] = report_type
+ extra_env['FOREMAN_URL'] = "http://localhost"
+ if report_type == "proxy":
+ extra_env['FOREMAN_PROXY_URL'] = "http://localhost"
+ extra_env['FOREMAN_SSL_CERT'] = "/dev/zero"
+ extra_env['FOREMAN_SSL_KEY'] = "/dev/zero"
+ extra_env['FOREMAN_DIR_STORE'] = tmpdir.strpath
+ playbook = os.path.join('..', 'callback', 'three_hosts')
+ inventory = os.path.join(os.getcwd(), 'tests', 'callback', 'three_hosts')
+ return run_playbook(playbook, inventory=inventory, extra_env=extra_env)
+
+
+def drop_incompatible_items(d):
+ """
+ Recursively drop report items that vary on invocations
+ and versions and cannot be reasonably fixed
+ """
+ dd = {}
+ for k, v in d.items():
+ if k in ['msg', 'start', 'end', 'delta', 'uuid', 'timeout', '_ansible_no_log', 'warn', 'connection',
+ 'extended_allitems', 'loop_control', 'expand_argument_vars']:
+ continue
+
+ if isinstance(v, dict):
+ dd[k] = drop_incompatible_items(v)
+ elif isinstance(v, (list, set, tuple)):
+ dd[k] = type(v)(drop_incompatible_items(vv) if isinstance(vv, dict) else vv
+ for vv in v)
+ else:
+ dd[k] = v
+
+ return dd
+
+
+def run_callback(tmpdir, report_type, vcrmode):
+ run = run_playbook_callback(tmpdir, report_type)
+ assert run.rc == 0
+ assert len(tmpdir.listdir()) > 0, "Directory with results is empty"
+ for real_file in tmpdir.listdir(sort=True):
+ contents = real_file.read()
+ contents = re.sub(r"\d+-\d+-\d+ \d+:\d+:\d+\+\d+:\d+", "2000-01-01 12:00:00+00:00", contents)
+ contents = re.sub(r"\d+-\d+-\d+[ T]\d+:\d+:\d+\.\d+", "2000-01-01 12:00:00.0000", contents)
+ contents = re.sub(r"\d+:\d+:\d+\.\d+", "12:00:00.0000", contents)
+ if report_type == "foreman":
+ # drop_incompatible_items cannot be used for the legacy format
+ contents = re.sub(r", \\\"msg\\\": \\\"\\\"", "", contents)
+ contents = re.sub(r"\\\"_ansible_no_log\\\": [^,]+, ", "", contents)
+ contents = re.sub(r", \\\"warn\\\": false", "", contents)
+ contents = re.sub(r", \\\"expand_argument_vars\\\": true", "", contents)
+ real_contents = json.loads(contents)
+ if report_type == "foreman":
+ real_contents['config_report']['metrics']['time']['total'] = 1
+ else:
+ real_contents['metrics']['time']['total'] = 1
+ real_contents = drop_incompatible_items(real_contents)
+ fixture_name = real_file.basename
+ fixture = os.path.join(os.getcwd(), 'tests', 'fixtures', 'callback', 'dir_store', report_type, fixture_name)
+ if vcrmode == "record":
+ print("Writing: ", str(fixture))
+ with open(fixture, 'w') as f:
+ json.dump(real_contents, f, indent=2, sort_keys=True)
+ else:
+ with open(fixture, 'r') as f:
+ expected_contents = json.load(f)
+ expected_contents = drop_incompatible_items(expected_contents)
+ real_contents = drop_incompatible_items(real_contents)
+ assert expected_contents == real_contents, "Fixture {fixture_name} differs, run with -vvvv to see the diff".format(fixture_name=fixture_name)
+
+
+def test_callback_foreman(tmpdir, vcrmode):
+ run_callback(tmpdir, "foreman", vcrmode)
+
+
+def test_callback_proxy(tmpdir, vcrmode):
+ run_callback(tmpdir, "proxy", vcrmode)
diff --git a/ansible_collections/theforeman/foreman/tests/test_crud.py b/ansible_collections/theforeman/foreman/tests/test_crud.py
new file mode 100644
index 000000000..8dad7cdee
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_crud.py
@@ -0,0 +1,69 @@
+import os
+import sys
+
+import pytest
+try:
+ from ansible.module_utils.compat.version import LooseVersion
+except ImportError:
+ from distutils.version import LooseVersion
+
+from .conftest import TEST_PLAYBOOKS, INVENTORY_PLAYBOOKS, run_playbook, run_playbook_vcr, get_ansible_version
+
+IGNORED_WARNINGS = [
+ "Activation Key 'Test Activation Key Copy' already exists.",
+ "You have configured a plain HTTP server URL. All communication will happen unencrypted.",
+]
+
+ANSIBLE_SUPPORTS_MODULE_DEFAULTS = LooseVersion(get_ansible_version()) >= LooseVersion('2.12')
+
+if sys.version_info[0] == 2:
+ for envvar in os.environ.keys():
+ try:
+ os.environ[envvar] = os.environ[envvar].decode('utf-8').encode('ascii', 'ignore')
+ except UnicodeError:
+ os.environ.pop(envvar)
+
+
+@pytest.mark.parametrize('module', TEST_PLAYBOOKS)
+def test_crud(tmpdir, module, vcrmode):
+ if module in ['module_defaults'] and not ANSIBLE_SUPPORTS_MODULE_DEFAULTS:
+ pytest.skip("Module defaults only work with Ansible 2.12+")
+ if vcrmode == "live":
+ run = run_playbook(module)
+ else:
+ record = vcrmode == "record"
+ run = run_playbook_vcr(tmpdir, module, record=record)
+ assert run.rc == 0
+
+ _assert_no_warnings(run)
+
+
+@pytest.mark.parametrize('module', TEST_PLAYBOOKS)
+def test_check_mode(tmpdir, module):
+ if module in ['subscription_manifest', 'templates_import', 'puppetclasses_import', 'content_rhel_role']:
+ pytest.skip("This module does not support check_mode.")
+ if module in ['module_defaults'] and not ANSIBLE_SUPPORTS_MODULE_DEFAULTS:
+ pytest.skip("Module defaults only work with Ansible 2.12+")
+ run = run_playbook_vcr(tmpdir, module, check_mode=True)
+ assert run.rc == 0
+
+ _assert_no_warnings(run)
+
+
+@pytest.mark.parametrize('module', INVENTORY_PLAYBOOKS)
+def test_inventory(tmpdir, module):
+ inventory = [os.path.join(os.getcwd(), 'tests', 'inventory', inv) for inv in ['hosts', "{}.foreman.yml".format(module)]]
+ run = run_playbook(module, inventory=inventory)
+ assert run.rc == 0
+
+ _assert_no_warnings(run)
+
+
+def _assert_no_warnings(run):
+ for event in run.events:
+ # check for play level warnings
+ assert not event.get('event_data', {}).get('warning', False)
+
+ # check for task level warnings
+ event_warnings = [warning for warning in event.get('event_data', {}).get('res', {}).get('warnings', []) if warning not in IGNORED_WARNINGS]
+ assert [] == event_warnings, str(event_warnings)
diff --git a/ansible_collections/theforeman/foreman/tests/test_foreman_spec_helper.py b/ansible_collections/theforeman/foreman/tests/test_foreman_spec_helper.py
new file mode 100644
index 000000000..8069fc2cf
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_foreman_spec_helper.py
@@ -0,0 +1,61 @@
+from plugins.module_utils.foreman_helper import _foreman_spec_helper
+
+
+def test_empty_entity():
+ spec = {}
+ foreman_spec, argument_spec = _foreman_spec_helper(spec)
+ assert spec == {}
+ assert foreman_spec == {}
+ assert argument_spec == {}
+
+
+def test_full_entity():
+ spec = {
+ 'name': {},
+ 'count': {'type': 'int', 'aliases': ['number']},
+ 'facilities': {'type': 'list'},
+ 'street': {'type': 'entity', 'flat_name': 'street_id'},
+ 'quarter': {'type': 'entity', 'resource_type': 'edges'},
+ 'houses': {'type': 'entity_list', 'flat_name': 'house_ids'},
+ 'prices': {'type': 'nested_list', 'foreman_spec': {
+ 'value': {'type': 'int'},
+ }},
+ 'tenant': {'invisible': True},
+ }
+ foreman_spec, argument_spec = _foreman_spec_helper(spec)
+ assert spec == {
+ 'name': {},
+ 'count': {'type': 'int', 'aliases': ['number']},
+ 'facilities': {'type': 'list'},
+ 'street': {'type': 'entity', 'flat_name': 'street_id'},
+ 'quarter': {'type': 'entity', 'resource_type': 'edges'},
+ 'houses': {'type': 'entity_list', 'flat_name': 'house_ids'},
+ 'prices': {'type': 'nested_list', 'foreman_spec': {
+ 'value': {'type': 'int'},
+ }},
+ 'tenant': {'invisible': True},
+ }
+ assert foreman_spec == {
+ 'name': {},
+ 'count': {'type': 'int'},
+ 'facilities': {'type': 'list'},
+ 'street': {'type': 'entity', 'flat_name': 'street_id', 'resource_type': 'streets'},
+ 'street_id': {},
+ 'quarter': {'type': 'entity', 'flat_name': 'quarter_id', 'resource_type': 'edges'},
+ 'quarter_id': {},
+ 'houses': {'type': 'entity_list', 'flat_name': 'house_ids', 'resource_type': 'houses'},
+ 'house_ids': {'type': 'list'},
+ 'prices': {'type': 'nested_list', 'foreman_spec': {'value': {'type': 'int'}}, 'ensure': False},
+ 'tenant': {},
+ }
+ assert argument_spec == {
+ 'name': {},
+ 'count': {'type': 'int', 'aliases': ['number']},
+ 'facilities': {'type': 'list'},
+ 'street': {},
+ 'quarter': {},
+ 'houses': {'type': 'list', 'elements': 'str'},
+ 'prices': {'type': 'list', 'elements': 'dict', 'options': {
+ 'value': {'type': 'int'},
+ }},
+ }
diff --git a/ansible_collections/theforeman/foreman/tests/test_module_state.py b/ansible_collections/theforeman/foreman/tests/test_module_state.py
new file mode 100644
index 000000000..50fe20f1a
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_module_state.py
@@ -0,0 +1,18 @@
+import pytest
+
+from .conftest import TEST_PLAYBOOKS
+from .utils import ALL_MODULES, MODULES_PATH
+
+
+def _module_file_path(module):
+ module_file_name = "{}.py".format(module)
+ return MODULES_PATH / module_file_name
+
+
+def _module_is_tested(module):
+ return module in TEST_PLAYBOOKS
+
+
+@pytest.mark.parametrize('module', ALL_MODULES)
+def test_module_is_tested(module):
+ assert _module_is_tested(module)
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/activation_key.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/activation_key.yml
new file mode 100644
index 000000000..133dab304
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/activation_key.yml
@@ -0,0 +1,281 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ tags:
+ - setup
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_state: present
+ - include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ - include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ activation_key_name: Test Activation Key Copy
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ tags:
+ - test
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: create minimal AK
+ include_tasks: tasks/activation_key.yml
+ vars:
+ expected_change: true
+ - name: create minimal AK again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ expected_change: false
+ - name: remove minimal AK
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+
+ - name: create AK with subs
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_lifecycle_environment: "Library"
+ activation_key_content_view: "Default Organization View"
+ activation_key_subscriptions:
+ - name: "Test Product"
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "subscriptions.*\\[\\]"
+ expected_diff_after: "subscriptions.*\\[[^\\]]"
+ - name: create AK with subs again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_lifecycle_environment: "Library"
+ activation_key_content_view: "Default Organization View"
+ activation_key_subscriptions:
+ - name: "Test Product"
+ expected_change: false
+ - name: remove AK with subs
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+
+ - name: create AK with content overrides set to disabled
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_lifecycle_environment: "Library"
+ activation_key_content_view: "Default Organization View"
+ activation_key_subscriptions:
+ - name: "Test Product"
+ activation_key_content_overrides:
+ - label: "Test_Organization_Test_Product_Test_Repository"
+ override: disabled
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "content_overrides.*{}"
+ expected_diff_after: "Test_Organization_Test_Product_Test_Repository.*false"
+ - name: create AK with content overrides set to disabled again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_content_overrides:
+ - label: "Test_Organization_Test_Product_Test_Repository"
+ override: disabled
+ expected_change: false
+ - name: update AK with content overrides set to default
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_content_overrides:
+ - label: "Test_Organization_Test_Product_Test_Repository"
+ override: default
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "Test_Organization_Test_Product_Test_Repository.*false"
+ expected_diff_after: "content_overrides.*{}"
+ - name: update AK with content overrides set to default again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_content_overrides:
+ - label: "Test_Organization_Test_Product_Test_Repository"
+ override: default
+ expected_change: false
+ - name: update AK with content overrides set to enabled
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_content_overrides:
+ - label: "Test_Organization_Test_Product_Test_Repository"
+ override: enabled
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "content_overrides.*{}"
+ expected_diff_after: "Test_Organization_Test_Product_Test_Repository.*true"
+ - name: update AK with content overrides set to enabled again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_content_overrides:
+ - label: "Test_Organization_Test_Product_Test_Repository"
+ override: enabled
+ expected_change: false
+ - name: remove AK with content overrides
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+
+ - name: create AK with auto_attach=true
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_auto_attach: true
+ expected_change: true
+ - name: create AK with auto_attach=true again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_auto_attach: true
+ expected_change: false
+ - name: remove AK with auto_attach=true
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+
+ - name: create AK with auto_attach=false
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_auto_attach: false
+ expected_change: true
+ - name: create AK with auto_attach=false again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_auto_attach: false
+ expected_change: false
+ - name: remove AK with auto_attach=false
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+
+ - name: create AK with unlimited_hosts=false
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_unlimited_hosts: false
+ activation_key_max_hosts: 10
+ expected_change: true
+ - name: create AK with unlimited_hosts=false again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_unlimited_hosts: false
+ activation_key_max_hosts: 10
+ expected_change: false
+ - name: remove AK with unlimited_hosts=false
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+
+ - name: create AK with host_collections
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_host_collections:
+ - "TheAnswer"
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: ""
+ expected_diff_after: "activation_keys/host_collections"
+ - name: create AK with host_collections again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_host_collections:
+ - "TheAnswer"
+ expected_change: false
+ - name: remove host_collections from AK
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_host_collections: []
+ expected_change: true
+ - name: remove AK with host_collectione
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+
+ - name: create minimal AK with state=present_with_defaults
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: present_with_defaults
+ expected_change: true
+ - name: try to update an AK with state=present_with_defaults, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_lifecycle_environment: "Library"
+ activation_key_content_view: "Default Organization View"
+ activation_key_subscriptions:
+ - name: "Test Product"
+ activation_key_content_overrides:
+ - label: "Test_Organization_Test_Product_Test_Repository"
+ override: disabled
+ activation_key_state: present_with_defaults
+ expected_change: false
+
+ - name: copy AK
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_new_name: "Test Activation Key Copy"
+ activation_key_state: copied
+ expected_change: true
+ - name: copy AK again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_new_name: "Test Activation Key Copy"
+ activation_key_state: copied
+ expected_change: false
+ - name: remove copied AK
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_name: "Test Activation Key Copy"
+ activation_key_state: absent
+ expected_change: true
+
+ - name: remove AK
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: true
+ - name: remove AK again, no change
+ include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ tags:
+ - teardown
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/activation_keys_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/activation_keys_role.yml
new file mode 100644
index 000000000..e2fec6c41
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/activation_keys_role.yml
@@ -0,0 +1,28 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: activation_keys
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_activation_keys:
+ - name: Testkey1
+ - name: Testkey2
+ auto_attach: false
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/architecture.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/architecture.yml
new file mode 100644
index 000000000..2e73518a8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/architecture.yml
@@ -0,0 +1,132 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "TestOS1"
+ operatingsystem_minor: 0
+ operatingsystem_description: "TestOS1"
+ operatingsystem_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "TestOS1"
+ operatingsystem_minor: 1
+ operatingsystem_description: "TestOS1 SP1"
+ operatingsystem_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "TestOS2"
+ operatingsystem_state: present
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "TestOS1"
+ architecture_state: present
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "TestOS1"
+ architecture_state: present
+ expected_change: false
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "TestOS1"
+ - "TestOS1 SP1"
+ architecture_state: present
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "TestOS1"
+ architecture_state: present
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "TestOS2"
+ architecture_state: present
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "TestOS2"
+ architecture_state: present
+ expected_change: false
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "aarch64"
+ architecture_state: present
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "aarch64"
+ architecture_updated_name: "aarch64-2"
+ architecture_state: present
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "aarch64-2"
+ architecture_state: present
+ expected_change: false
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "aarch64-2"
+ architecture_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "{{ item }}"
+ operatingsystem_state: absent
+ loop:
+ - "TestOS1"
+ - "TestOS1 SP1"
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "TestOS2"
+ operatingsystem_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/auth_source_ldap.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/auth_source_ldap.yml
new file mode 100644
index 000000000..45c59e43c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/auth_source_ldap.yml
@@ -0,0 +1,82 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/domain.yml
+ tasks:
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "present"
+ with_items: "{{ domain_locations }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "present"
+ with_items: "{{ domain_organizations }}"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: present
+ auth_source_ldap_account_password: changeme
+ expected_change: true
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: present
+ expected_change: false
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: present
+ auth_source_ldap_account: test
+ expected_change: true
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: present
+ auth_source_ldap_netgroups: true
+ expected_change: true
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: present
+ auth_source_ldap_netgroups: true
+ expected_change: false
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: absent
+ expected_change: true
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/domain.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "absent"
+ with_items: "{{ domain_locations | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ with_items: "{{ domain_organizations }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/auth_sources_ldap_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/auth_sources_ldap_role.yml
new file mode 100644
index 000000000..1a513b023
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/auth_sources_ldap_role.yml
@@ -0,0 +1,26 @@
+---
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: auth_sources_ldap
+ vars:
+ foreman_auth_sources_ldap:
+ - name: "Example LDAP"
+ host: "ldap.example.org"
+ onthefly_register: true
+ account: uid=ansible,cn=sysaccounts,cn=etc,dc=example,dc=com
+ account_password: secret
+ base_dn: dc=example,dc=com
+ groups_base: cn=groups,cn=accounts, dc=example,dc=com
+ server_type: free_ipa
+ attr_login: uid
+ attr_firstname: givenName
+ attr_lastname: sn
+ attr_mail: mail
+ attr_photo: jpegPhoto
+ state: present
+ expected_change: true
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/bookmark.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/bookmark.yml
new file mode 100644
index 000000000..02ca8fd29
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/bookmark.yml
@@ -0,0 +1,41 @@
+---
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/bookmark.yml
+ vars:
+ bookmark_state: present_with_defaults
+ expected_change: true
+ - include_tasks: tasks/bookmark.yml
+ vars:
+ bookmark_state: present
+ expected_change: false
+
+ - include_tasks: tasks/bookmark.yml
+ vars:
+ bookmark_state: present_with_defaults
+ bookmark_query: "started_at > 12 hours ago"
+ expected_change: false
+ - include_tasks: tasks/bookmark.yml
+ vars:
+ bookmark_state: present
+ bookmark_query: "started_at > 12 hours ago"
+ expected_change: true
+ - include_tasks: tasks/bookmark.yml
+ vars:
+ bookmark_state: present
+ bookmark_public: false
+ expected_change: true
+ - include_tasks: tasks/bookmark.yml
+ vars:
+ bookmark_state: absent
+ expected_change: true
+ - include_tasks: tasks/bookmark.yml
+ vars:
+ bookmark_state: absent
+ expected_change: false
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_attribute.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_attribute.yml
new file mode 100644
index 000000000..785c5f57c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_attribute.yml
@@ -0,0 +1,88 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: present
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_organizations: "{{ libvirt.compute_resource.organizations }}"
+ compute_resource_locations: "{{ libvirt.compute_resource.locations }}"
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params: "{{ libvirt.compute_resource.params }}"
+ compute_resource_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ tasks:
+ - name: Load server config
+ include_vars:
+ file: vars/server.yml
+
+ - include_tasks: tasks/compute_attribute.yml
+ vars:
+ vm_attrs:
+ memory: 2147483648
+ cpus: 2
+ compute_attribute_state: present
+ expected_change: true
+
+ - include_tasks: tasks/compute_attribute.yml
+ vars:
+ vm_attrs:
+ memory: 2147483648
+ cpus: 2
+ compute_attribute_state: present
+ expected_change: false
+
+ - include_tasks: tasks/compute_attribute.yml
+ vars:
+ vm_attrs:
+ memory_mb: 1073741824
+ cpu: 1
+ compute_attribute_state: present
+ expected_change: true
+
+ - include_tasks: tasks/compute_attribute.yml
+ vars:
+ vm_attrs:
+ memory_mb: 1073741824
+ cpu: 1
+ compute_attribute_state: present
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: absent
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile.yml
new file mode 100644
index 000000000..6eb908346
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile.yml
@@ -0,0 +1,115 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "{{ libvirt.compute_resource.name }}"
+ compute_resource_organizations: "{{ libvirt.compute_resource.organizations }}"
+ compute_resource_locations: "{{ libvirt.compute_resource.locations }}"
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params: "{{ libvirt.compute_resource.params }}"
+ compute_resource_state: present
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: absent
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: app-small
+ compute_profile_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: present
+ expected_change: true
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: present
+ expected_change: false
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: absent
+ expected_change: true
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: absent
+ expected_change: false
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: app-small
+ compute_profile_attributes:
+ - compute_resource: "{{ libvirt.compute_resource.name }}"
+ vm_attrs: "{{ libvirt.compute_profile.attrs }}"
+ compute_profile_state: present
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "{}"
+ expected_diff_after: "model.*virtio"
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: app-small
+ compute_profile_attributes:
+ - compute_resource: "{{ libvirt.compute_resource.name }}"
+ vm_attrs: "{{ libvirt.compute_profile.attrs }}"
+ compute_profile_state: present
+ expected_change: false
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: app-small
+ compute_profile_attributes:
+ - compute_resource: "{{ libvirt.compute_resource.name }}"
+ vm_attrs: "{{ libvirt.compute_profile.attrs | combine({'cpus':2}) }}"
+ compute_profile_state: present
+ expected_change: true
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: app-small
+ compute_profile_attributes:
+ - compute_resource: "{{ libvirt.compute_resource.name }}"
+ vm_attrs: "{{ libvirt.compute_profile.attrs | combine({'cpus':2}) }}"
+ compute_profile_state: present
+ expected_change: false
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: app-small
+ compute_profile_state: absent
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "{{ libvirt.compute_resource.name }}"
+ compute_resource_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile_ovirt.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile_ovirt.yml
new file mode 100644
index 000000000..6ec69e26b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profile_ovirt.yml
@@ -0,0 +1,77 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "{{ ovirt.compute_resource.name }}"
+ compute_resource_organizations: "{{ ovirt.compute_resource.organizations }}"
+ compute_resource_locations: "{{ ovirt.compute_resource.locations }}"
+ compute_resource_provider: 'ovirt'
+ compute_resource_provider_params: "{{ ovirt.compute_resource.params }}"
+ compute_resource_state: present_with_defaults
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: present
+ compute_profile_attributes:
+ - compute_resource: "{{ ovirt.compute_resource.name }}"
+ vm_attrs: "{{ ovirt.compute_profile.attrs }}"
+ expected_change: true
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: present
+ compute_profile_attributes:
+ - compute_resource: "{{ ovirt.compute_resource.name }}"
+ vm_attrs: "{{ ovirt.compute_profile.attrs }}"
+ expected_change: false
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: absent
+ expected_change: true
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "{{ ovirt.compute_resource.name }}"
+ compute_resource_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profiles_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profiles_role.yml
new file mode 100644
index 000000000..3fa5408c4
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_profiles_role.yml
@@ -0,0 +1,92 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - name: ensure test location
+ include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+ - name: ensure operating system
+ include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "RedHat-8.4"
+ operatingsystem_major: "8"
+ operatingsystem_family: Redhat
+ operatingsystem_state: present
+ - name: ensure compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt"
+ compute_resource_organizations:
+ - Test Organization
+ compute_resource_locations:
+ - Test Location
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu:///system
+ compute_resource_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: compute_profiles
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_compute_profiles:
+ - name: "app-small"
+ compute_attributes:
+ - compute_resource: "libvirt"
+ vm_attrs:
+ cpus: 1
+ memory: 2147483648
+ nics_attributes:
+ 0:
+ type: bridge
+ bridge: ""
+ model: virtio
+ volumes_attributes:
+ 0:
+ pool_name: default
+ capacity: 10G
+ allocation: 0G
+ format_type: raw
+ state: present
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "RedHat-8.4"
+ operatingsystem_state: absent
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt"
+ compute_resource_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resource.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resource.yml
new file mode 100644
index 000000000..5331ebe90
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resource.yml
@@ -0,0 +1,136 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: 'Libvirt compute resource'
+ block:
+ - name: Create libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr01"
+ compute_resource_description: 'Libvirt compute resource'
+ compute_resource_organizations:
+ - Test Organization
+ compute_resource_locations:
+ - Test Location
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ compute_resource_state: present
+ expected_change: true
+ - name: Update libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr01"
+ compute_resource_description: 'Libvirt compute resource'
+ compute_resource_organizations:
+ - Test Organization
+ compute_resource_locations:
+ - Test Location
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ compute_resource_state: present
+ expected_change: false
+ - name: Update libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr01"
+ compute_resource_updated_name: "libvirt-cr"
+ compute_resource_description: 'A compute_resource with an updated description'
+ compute_resource_organizations:
+ - Test Organization
+ compute_resource_locations:
+ - Test Location
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ compute_resource_state: present
+ expected_change: true
+ - name: Update libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr"
+ compute_resource_description: 'A compute_resource with an updated description'
+ compute_resource_organizations:
+ - Test Organization
+ compute_resource_locations:
+ - Test Location
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ compute_resource_state: present
+ expected_change: false
+ - name: Update libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr"
+ compute_resource_description: 'A compute_resource with an updated description and params'
+ compute_resource_organizations:
+ - Test Organization
+ compute_resource_locations:
+ - Test Location
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ display_type: spice
+ compute_resource_state: present
+ expected_change: true
+ - name: Update libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr"
+ compute_resource_description: 'A compute_resource with an updated description and params'
+ compute_resource_organizations:
+ - Test Organization
+ compute_resource_locations:
+ - Test Location
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ display_type: spice
+ compute_resource_state: present
+ expected_change: false
+ - name: Delete libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr"
+ compute_resource_state: absent
+ expected_change: true
+ - name: Delete libvirt compute resource
+ include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "libvirt-cr"
+ compute_resource_state: absent
+ expected_change: false
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resources_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resources_role.yml
new file mode 100644
index 000000000..ee7e615e3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/compute_resources_role.yml
@@ -0,0 +1,72 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - name: ensure test location
+ include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+ - name: ensure operating system
+ include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "RedHat-8.4"
+ operatingsystem_major: "8"
+ operatingsystem_family: Redhat
+ operatingsystem_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: compute_resources
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_compute_resources:
+ - name: "libvirt-cr01"
+ description: 'Libvirt compute resource'
+ organizations:
+ - Test Organization
+ locations:
+ - Test Location
+ provider: 'libvirt'
+ provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ images:
+ - name: "RHEL-8.4"
+ operatingsystem: "RedHat-8.4"
+ architecture: "x86_64"
+ user_data: true
+ image_username: "root"
+ image_password: "changeme"
+ uuid: "rhel-8.4-template"
+ state: present
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/config_group.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/config_group.yml
new file mode 100644
index 000000000..5eb7c522c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/config_group.yml
@@ -0,0 +1,75 @@
+---
+#
+# Disclaimer: You have to import puppetlabs-ntp module in your foreman instance
+# before running config_group tests
+#
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_state: present
+ expected_change: true
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_state: present
+ config_group_puppetclasses: []
+ expected_change: false
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_puppetclasses: ['ntp', 'ntp::config']
+ config_group_state: present
+ expected_change: true
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_puppetclasses: ['ntp', 'ntp::config']
+ config_group_state: present
+ expected_change: false
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_puppetclasses: []
+ config_group_state: present
+ expected_change: true
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_name: "config group 1"
+ config_group_puppetclasses: []
+ config_group_state: present
+ expected_change: true
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_name: "config group 1"
+ config_group_updated_name: "config group 2"
+ config_group_puppetclasses: []
+ config_group_state: present
+ expected_change: true
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_name: "config group 2"
+ config_group_puppetclasses: []
+ config_group_state: present
+ expected_change: false
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_name: "config group 2"
+ config_group_puppetclasses: []
+ config_group_state: absent
+ expected_change: true
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_puppetclasses: []
+ config_group_state: present
+ expected_change: false
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_state: absent
+ expected_change: true
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_state: absent
+ expected_change: false
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_credential.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_credential.yml
new file mode 100644
index 000000000..fa2fd0629
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_credential.yml
@@ -0,0 +1,77 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: 'Test GPG key'
+ block:
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: present
+ content_credential_type: "gpg_key"
+ content_credential_content: "{{ lookup('file', 'data/gpg_key.asc') }}"
+ expected_change: true
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: present
+ content_credential_type: "gpg_key"
+ content_credential_content: "{{ lookup('file', 'data/gpg_key.asc') }}"
+ expected_change: false
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_content: "{{ lookup('file', 'data/gpg_key2.asc') }}"
+ content_credential_state: present
+ expected_change: true
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: absent
+ expected_change: true
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: absent
+ expected_change: false
+ - name: 'Test Certs'
+ block:
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: present
+ content_credential_name: Test cert
+ content_credential_content: "{{ lookup('file', 'data/gpg_key.asc') }}"
+ content_credential_type: cert
+ expected_change: true
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: Test cert
+ content_credential_state: absent
+ expected_change: true
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: Test cert
+ content_credential_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_credentials_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_credentials_role.yml
new file mode 100644
index 000000000..914015f89
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_credentials_role.yml
@@ -0,0 +1,59 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: content_credentials
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_content_credentials:
+ - name: RPM-GPG-KEY-foreman
+ content_type: gpg_key
+ content: "{{ lookup('url', 'https://yum.theforeman.org/releases/2.4/RPM-GPG-KEY-foreman', split_lines=False) }}"
+ - name: RPM-GPG-KEY-my-repo2
+ content_type: gpg_key
+ content: |
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
+ mQINBGAX2bIBEADuTGNExTEST0hOcpJ13XS1BEwuhzo7r16QaI0hP1vRxZeLJgeC
+ b2KWRvHHfepr2jdAoAeOVhERrMz5EpMcgPEs7NUE+vbYr+K9LFzw5gmUC00CCuQ+
+ RCJRRXYNV8F41y4dTGOkE/ON52ljDvVyFb3DbUUYPH9ZfOE0Z6kMIcJo6eYsDAdK
+ EjoQ1jQkVaRa8I4+YZ9XEFkPqVUkY1+tMfipqqQuNbvN2xgQSk8dc6uEouyC8FBA
+ GPugplbCaEZNFWt48xQU9vP1JblQ6z9cynLKFxxWkgr9DKRRh1kw2pIQyGhl1RhI
+ uvedY9OeJlqxuBsBvko7JULcX622HcHUkhzQD+ss0L9nE3lZuO5ywpZdTYln296E
+ 7awNEr0ER9Xqx9pMp5JeXNSHjlleFN01vLG5Xa7WNc32fvDtn2JhkzTU/dlIA2F+
+ w5Tlg5ROY8olWc+jHKmvTQwxZ9s9XQuHmBpNbOijHg4Ekr0TGo6d3rjHZKiisZBG
+ mAbHe1pWLOmeRpjqc6xmIpDMrsx75U0WgkwjBtbfxUcDYEzzJOcO87Q3s8kH+ie3
+ 5eSClT7coImWUmVKIoFSvxj8JgUT6P81v7CW4AlVDpRjBtYmc82NsGuSEgAykuQo
+ VRguqU/w3QTU3rEcWfLVmyfyEKC4tBUCAhGShii/rLrtCspBT+uVpcDkQwARAQAB
+ tD1Gb3JlbWFuIEF1dG9tYXRpYyBTaWduaW5nIEtleSAoMi40KSA8cGFja2FnZXNA
+ dGhlZm9yZW1hbi5vcmc+iQJUBBMBCAA+FiEEZDJT9xuCsb6vLh1PpDm9Vawq2fEF
+ AmAX2bICGy8FCQHhM4AFCwkIBwIGFQoJCAsCBBYCAwECHgECF4AACgkQpDm9Vawq
+ 2fHMBQ//ffbTmU0Bl9Im8dDCzebhO6/D3iyshoceAfUjJrwvuhzSlil2cjWiLdmP
+ CjBhUB8eDRhSQ+LlfJe9C0PKEyC72rzTsfUZj4NBKNQGT2P+peJ1l8PUAAlk7jZl
+ QZcDER9Nju7/d+VTqF6PXkcbnIo1GVD/EX+R9mKphIbu9qaxBqGhCVay1D7jNxzH
+ OBaMse5hf1hJ0WzcyK6pRLMU9JeuLEdhwJqSP0+/E8R31El92EO1+selLy6hD3ro
+ NX3iehtcQVKdQ/5rflP6K7ZbDDj76lgRBbOY+UT1tft1nvdgKIoRPMqlBc2tMLNT
+ jzJrw/AW7C9pRUTvox2uFKw0Eo/0pnSR4qllBCGE67VpJLXeMQFjwOLcaKX57civ
+ X1z7nGTg4K+Ye5BM33Pq0Df24M0qLeqD6vLhB0Ny2JFiivw4zWJu448RELb1Omai
+ aNipdHQDN8D345mjctUDcc/2T7q6bcu5ErrFT8GK/FPdwpgDIPN20gxEMR9vG83n
+ AMkzSNrMefNlJoyTdgthokPb99LmN6Foybk6VNoKy4u/mID6uprWGMIl1/LX2wu1
+ xRxRy1YznHnmtGqTYOikyAp0e+4tDfHMZ58yC9/XGztxJvj6vvwwf9n5ZO4MC4Kj
+ XQVHErcrTa8cZWW87pLrNvILegPA6v778BV0GLV5PqnWhl9Y1sY=
+ =SrzP
+ -----END PGP PUBLIC KEY BLOCK-----
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_info.yml
new file mode 100644
index 000000000..d0bf2d5c8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_info.yml
@@ -0,0 +1,49 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+
+ - include_tasks: tasks/content_export_library.yml # Full export
+ vars:
+ incremental: false
+ destination_server: "airgapped.example.com"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_export_info.yml
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_library.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_library.yml
new file mode 100644
index 000000000..160f8fc89
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_library.yml
@@ -0,0 +1,69 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_export_library.yml # Full export
+ vars:
+ expected_change: true
+ incremental: false
+ destination_server: "airgapped.example.com"
+ register: result
+ - include_tasks: tasks/content_export_library.yml # Incremental export
+ vars:
+ expected_change: true
+ incremental: true
+ # from_history_id: "{{ result.task.output.export_history_id }}" # (not required; will use most recent export by default)
+ destination_server: "airgapped.example.com"
+ tags: library-export
+ register: result
+ - include_tasks: tasks/content_export_show.yml
+ vars:
+ id: "{{ result['task']['output']['export_history_id'] | default(12345) }}"
+ destination_server: "airgapped.example.com"
+ when:
+ # when in check mode, no export has been done, so we can't check it
+ - not ansible_check_mode
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: Clean up metadata.json
+ ansible.builtin.file:
+ path: ./metadata.json
+ state: absent
+
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_repository.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_repository.yml
new file mode 100644
index 000000000..15c8316c7
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_repository.yml
@@ -0,0 +1,65 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Export Test Product"
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Export Test Product"
+ repository_name: "TestRepo"
+ repository_state: present
+ register: result
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_export_repository.yml # Full export
+ vars:
+ product: "Export Test Product"
+ repository: "TestRepo"
+ expected_change: true
+ incremental: false
+ - include_tasks: tasks/content_export_repository.yml # Incremental export
+ vars:
+ product: "Export Test Product"
+ repository: "TestRepo"
+ expected_change: true
+ incremental: true
+ - include_tasks: tasks/content_export_show.yml
+ vars:
+ id: "{{ result['task']['output']['export_history_id'] | default(12345) }}"
+ when:
+ - not ansible_check_mode
+- hosts: localhost # Teardown
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Export Test Product"
+ repository_name: "TestRepo"
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Export Test Product"
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_version.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_version.yml
new file mode 100644
index 000000000..11321c542
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_export_version.yml
@@ -0,0 +1,84 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Export Test Product"
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Export Test Product"
+ repository_name: "TestRepo"
+ repository_state: present
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ repositories:
+ - name: "TestRepo"
+ product: "Export Test Product"
+ - include_tasks: tasks/content_view_version.yml
+ vars:
+ version: 1.0
+ state: present
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_export_version.yml # Full export
+ vars:
+ destination_server: "airgapped.example.com"
+ content_view: "Test Content View"
+ content_view_version: "1.0"
+ incremental: false
+ register: result
+
+ - include_tasks: tasks/content_export_version.yml # Incremental export
+ vars:
+ expected_change: true
+ incremental: true
+ content_view: "Test Content View"
+ content_view_version: "1.0"
+ destination_server: "airgapped.example.com"
+ - include_tasks: tasks/content_export_show.yml
+ vars:
+ id: "{{ result['task']['output']['export_history_id'] | default(12345) }}"
+ destination_server: "airgapped.example.com"
+ when:
+ - not ansible_check_mode
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_view_version.yml
+ vars:
+ state: absent
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Export Test Product"
+ repository_name: "TestRepo"
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Export Test Product"
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_rhel_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_rhel_role.yml
new file mode 100644
index 000000000..5ae94abbe
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_rhel_role.yml
@@ -0,0 +1,32 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: content_rhel
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_validate_certs: false
+ foreman_manifest_download: false
+ foreman_manifest_path: "{{ subscription_manifest_path }}"
+ foreman_sync_plan_name: "RHEL Sync Plan"
+ foreman_sync_plan_interval: daily
+ foreman_sync_plan_sync_date: 2021-02-02 00:00:00 UTC
+ foreman_activation_key_name: "basic_rhel_key"
+ foreman_content_rhel_wait_for_syncs: true
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload.yml
new file mode 100644
index 000000000..701ff90d6
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload.yml
@@ -0,0 +1,94 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: "Test File Repository"
+ repository_content_type: "file"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: "Test File Repository"
+ repository_content_type: "file"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: upload RPM
+ include_tasks: tasks/upload.yml
+ vars:
+ expected_change: true
+ - name: upload RPM again, no change
+ include_tasks: tasks/upload.yml
+ vars:
+ expected_change: false
+
+ - name: upload SRPM
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/test-srpm01-1.0-1.src.rpm"
+ expected_change: true
+ - name: upload SRPM again, no change
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/test-srpm01-1.0-1.src.rpm"
+ expected_change: false
+
+ - name: upload File
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/file_repo_test.txt"
+ upload_repository: "Test File Repository"
+ expected_change: true
+ - name: upload File again, no change
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/file_repo_test.txt"
+ upload_repository: "Test File Repository"
+ expected_change: false
+
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: "Test File Repository"
+ repository_content_type: "file"
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_deb.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_deb.yml
new file mode 100644
index 000000000..b89f32d97
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_deb.yml
@@ -0,0 +1,65 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: "Test Deb Repository"
+ repository_content_type: "deb"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: "Test Deb Repository"
+ repository_content_type: "deb"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+
+ - name: upload deb package
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/odin_1.0_ppc64.deb"
+ upload_repository: "Test Deb Repository"
+ expected_change: true
+ - name: upload deb package again, no change
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/odin_1.0_ppc64.deb"
+ upload_repository: "Test Deb Repository"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: "Test Deb Repository"
+ repository_content_type: "deb"
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_ostree.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_ostree.yml
new file mode 100644
index 000000000..5fc5fb3ec
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_upload_ostree.yml
@@ -0,0 +1,67 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: "Test OStree Repository"
+ repository_content_type: "ostree"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: "Test OStree Repository"
+ repository_content_type: "ostree"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+
+ - name: upload ostree archive
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/fixtures_small_repo.tar"
+ upload_repository: "Test OStree Repository"
+ upload_ostree_repository_name: "small"
+ expected_change: true
+ - name: upload ostree archive again, change due to API limitations
+ include_tasks: tasks/upload.yml
+ vars:
+ upload_src: "{{ playbook_dir }}/data/fixtures_small_repo.tar"
+ upload_repository: "Test OStree Repository"
+ upload_ostree_repository_name: "small"
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: "Test OStree Repository"
+ repository_content_type: "ostree"
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view.yml
new file mode 100644
index 000000000..c687ca639
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view.yml
@@ -0,0 +1,229 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Test Product 2"
+ repository_state: present
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: absent
+ - import_tasks: tasks/content_view_version.yml
+ vars:
+ state: absent
+ version: "1.0"
+ ignore_errors: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ expected_change: true
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ expected_diff: true
+ expected_diff_before: "{}"
+ expected_diff_after: "Test Content View"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ expected_change: false
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ expected_change: true
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ expected_change: false
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ expected_change: true
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+
+ - include_tasks: tasks/content_view_version.yml
+ vars:
+ version: "1.0"
+
+ # Composite Content Views
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: true
+ composite: true
+ components:
+ - content_view: Test Content View
+ version: "1.0"
+ expected_diff: true
+ expected_diff_before: "content_view_components.*\\[\\]"
+ expected_diff_after: "content_view_version_id"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: false
+ composite: true
+ components:
+ - content_view: Test Content View
+ version: "1.0"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: true
+ composite: true
+ auto_publish: true
+ components:
+ - content_view: Test Content View
+ version: "1.0"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: false
+ composite: true
+ auto_publish: true
+ components:
+ - content_view: Test Content View
+ version: "1.0"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: true
+ composite: true
+ auto_publish: true
+ components:
+ - content_view: Test Content View
+ latest: true
+ expected_diff: true
+ expected_diff_before: "latest.*false"
+ expected_diff_after: "latest.*true"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: false
+ composite: true
+ auto_publish: true
+ components:
+ - content_view: Test Content View
+ latest: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: false
+ composite: true
+ auto_publish: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: true
+ composite: true
+ components: []
+ auto_publish: true
+ expected_diff: true
+ expected_diff_before: "content_view_version_id"
+ expected_diff_after: "content_view_components.*\\[\\]"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: false
+ composite: true
+ components: []
+ auto_publish: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: present
+ expected_change: false
+ composite: true
+ auto_publish: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: absent
+ expected_change: true
+ composite: true
+ auto_publish: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: absent
+ expected_change: false
+ composite: true
+ auto_publish: true
+
+ # Remove the original CV again
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ expected_change: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Test Product 2"
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter.yml
new file mode 100644
index 000000000..66044ae26
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter.yml
@@ -0,0 +1,210 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_url: "https://repos.fedorapeople.org/pulp/pulp/demo_repos/zoo/"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+ repository_url: https://registry.hub.docker.com
+ repository_docker_upstream_name: library/busybox
+ - include_tasks: tasks/katello_sync.yml
+ - include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: Test Docker Repository
+ - include_tasks: tasks/content_view.yml
+ vars:
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - include_tasks: tasks/content_view_filter_modulemd.yml
+ vars:
+ filter_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: Test Content View Filter Package
+ block:
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ expected_change: false
+
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ original_packages: true
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ original_packages: true
+ expected_change: false
+
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ original_packages: false
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ original_packages: false
+ expected_change: false
+
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ version: 1
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ version: 1
+ expected_change: false
+
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ max_version: 1
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ max_version: 1
+ expected_change: false
+
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ min_version: 1
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ min_version: 1
+ expected_change: false
+
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ inclusion: true
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package.yml
+ vars:
+ filter_state: absent
+ rule_state: absent
+ expected_change: true
+
+ - name: Test Content View Filter Errata ID
+ block:
+ - include_tasks: tasks/content_view_filter_errata_id.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_errata_id.yml
+ vars:
+ expected_change: false
+ - include_tasks: tasks/content_view_filter_errata_id.yml
+ vars:
+ filter_state: absent
+ rule_state: absent
+ expected_change: true
+
+ - name: Test Content View Filter Errata Date
+ block:
+ - include_tasks: tasks/content_view_filter_errata_date.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_errata_date.yml
+ vars:
+ expected_change: false
+ - include_tasks: tasks/content_view_filter_errata_date.yml
+ vars:
+ date_type: issued
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_errata_date.yml
+ vars:
+ types: security
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_errata_date.yml
+ vars:
+ filter_state: absent
+ rule_state: absent
+ expected_change: true
+
+ - name: Test Content View Filter Package Groups
+ block:
+ - include_tasks: tasks/content_view_filter_package_group.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_package_group.yml
+ vars:
+ expected_change: false
+ - include_tasks: tasks/content_view_filter_package_group.yml
+ vars:
+ filter_state: absent
+ rule_state: absent
+ expected_change: true
+
+ - name: Test Content View Filter Docker
+ block:
+ - include_tasks: tasks/content_view_filter_docker.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_docker.yml
+ vars:
+ expected_change: false
+ - include_tasks: tasks/content_view_filter_docker.yml
+ vars:
+ filter_state: absent
+ rule_state: absent
+ expected_change: true
+
+ - name: Test Content View Filter modulemd
+ block:
+ - include_tasks: tasks/content_view_filter_modulemd.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/content_view_filter_modulemd.yml
+ vars:
+ expected_change: false
+ - include_tasks: tasks/content_view_filter_modulemd.yml
+ vars:
+ filter_state: absent
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_name: Test Docker Repository
+ repository_state: absent
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_info.yml
new file mode 100644
index 000000000..9f9787ca9
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_info.yml
@@ -0,0 +1,325 @@
+---
+- name: "Setup content_view_filter_info test prerequisites"
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Create Test Organization"
+ ansible.builtin.include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+
+ - name: "Create Test Product"
+ ansible.builtin.include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+
+ - name: "Create Test Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+
+ - name: "Create Additional Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_url: "https://repos.fedorapeople.org/pulp/pulp/demo_repos/zoo/"
+
+ - name: "Create Module repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: "Test Modular Repository"
+ repository_content_type: yum
+ repository_url: "https://dl.fedoraproject.org/pub/epel/8/Modular/x86_64"
+
+ - name: "Create Container Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+ repository_url: https://registry.access.redhat.com
+ repository_docker_upstream_name: ubi9
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: Test Docker Repository
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: Test Modular Repository
+
+ - name: "Create Content View"
+ ansible.builtin.include_tasks: tasks/content_view.yml
+ vars:
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - name: "Test Docker Repository"
+ product: "Test Product"
+ - name: "Test Modular Repository"
+ product: "Test Product"
+
+ - name: "Create content view filters"
+ ansible.builtin.include_tasks: tasks/content_view_filter.yml
+
+
+- name: "Test content_view_filter info"
+ hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Fetch content_view_filter_info - rpm original packages"
+ vars:
+ content_view_filter_name: "Test Content View Filter - AllRPMsNoErrata"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - AllRPMsNoErrata"
+ - result['content_view_filter']['type'] == "rpm"
+ - result['content_view_filter']['inclusion'] == True
+ - result['content_view_filter']['original_packages'] == True
+
+
+ - name: "Fetch content_view_filter_info - modulemd original streams"
+ vars:
+ content_view_filter_name: "Test Content View Filter - AllModuleStreamsNoErrata"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - AllModuleStreamsNoErrata"
+ - result['content_view_filter']['type'] == "modulemd"
+ - result['content_view_filter']['inclusion'] == True
+ - result['content_view_filter']['original_module_streams'] == True
+
+
+ - name: "Fetch content_view_filter_info - rpm exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - rpm"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - rpm"
+ - result['content_view_filter']['type'] == "rpm"
+ - result['content_view_filter']['inclusion'] == False
+ - result['content_view_filter']['original_packages'] == False
+
+
+ - name: "Fetch content_view_filter_info - package_group exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - package_group"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - package_group"
+ - result['content_view_filter']['type'] == "package_group"
+ - result['content_view_filter']['inclusion'] == False
+
+
+ - name: "Fetch content_view_filter_info - erratum_by_id exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_id"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - erratum_by_id"
+ - result['content_view_filter']['type'] == "erratum"
+ - result['content_view_filter']['inclusion'] == False
+
+
+ - name: "Fetch content_view_filter_info - erratum_by_date exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_date"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - erratum_by_date"
+ - result['content_view_filter']['type'] == "erratum"
+ - result['content_view_filter']['inclusion'] == False
+
+
+ - name: "Fetch content_view_filter_info - container exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - docker"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - docker"
+ - result['content_view_filter']['type'] == "docker"
+ - result['content_view_filter']['inclusion'] == False
+
+
+ - name: "Fetch content_view_filter_info - modulemd exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter']['name'] == "Test Content View Filter - modulemd"
+ - result['content_view_filter']['type'] == "modulemd"
+ - result['content_view_filter']['inclusion'] == False
+
+
+
+- name: "Clean up test dependencies"
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+
+ - name: "Cleanup Content View Filters"
+ ansible.builtin.include_tasks: tasks/content_view_filter.yml
+ vars:
+ filter_state: absent
+
+ - name: Clean up the content view
+ ansible.builtin.include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_name: Test Modular Repository
+ repository_state: absent
+
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_name: Test Docker Repository
+ repository_state: absent
+
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+
+ - name: "Clean up products"
+ ansible.builtin.include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+
+ - name: "Clean up Organizations"
+ ansible.builtin.include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule.yml
new file mode 100644
index 000000000..108ab6589
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule.yml
@@ -0,0 +1,141 @@
+---
+- name: "Create test dependencies"
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Create Test Organization"
+ ansible.builtin.include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+
+ - name: "Create Test Product"
+ ansible.builtin.include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+
+ - name: "Create Test Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+
+ - name: "Create Addititional Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_url: "https://repos.fedorapeople.org/pulp/pulp/demo_repos/zoo/"
+
+ - name: "Create Module repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: "Test Modular Repository"
+ repository_content_type: yum
+ repository_url: "https://dl.fedoraproject.org/pub/epel/8/Modular/x86_64"
+
+ - name: "Create Container repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+ repository_url: https://registry.access.redhat.com
+ repository_docker_upstream_name: ubi8
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: Test Docker Repository
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: Test Modular Repository
+
+ - name: "Create Content View"
+ ansible.builtin.include_tasks: tasks/content_view.yml
+ vars:
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - name: "Test Docker Repository"
+ product: "Test Product"
+ - name: "Test Modular Repository"
+ product: "Test Product"
+
+ - name: "Create content view filters"
+ ansible.builtin.include_tasks: tasks/content_view_filter.yml
+
+- name: "Test content_view_filter_rule"
+ hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Create Content View Filter Rule for packages"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_packages.yml
+
+ - name: "Create Content View Filter Rule for package groups"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_package_groups.yml
+ vars:
+ expected_change: true
+
+ - name: "Create Content View Filter Rule for errata_id"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_errata_by_id.yml
+ vars:
+ expected_change: true
+
+ - name: "Create Content View Filter Rule for errata_by_date"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_errata_by_date.yml
+ vars:
+ expected_change: true
+
+ - name: "Create Content View Filter Rule for containers"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_containers.yml
+ vars:
+ expected_change: true
+
+ - name: "Create Content View Filter Rule for module_streams"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_modulemd.yml
+ vars:
+ expected_change: true
+
+ - name: "Cleanup Content View Filter Rules"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_cleanup.yml
+ vars:
+ expected_change: true
+
+- name: "Clean up test dependencies"
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_name: Test Docker Repository
+ repository_state: absent
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - name: "Clean up products"
+ ansible.builtin.include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - name: "Clean up Organizations"
+ ansible.builtin.include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule_info.yml
new file mode 100644
index 000000000..55b7f2a93
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_filter_rule_info.yml
@@ -0,0 +1,298 @@
+---
+- name: "Setup content_view_filter_info test prerequisites"
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Create Test Organization"
+ ansible.builtin.include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+
+ - name: "Create Test Product"
+ ansible.builtin.include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+
+ - name: "Create Test Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+
+ - name: "Create Additional Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_url: "https://repos.fedorapeople.org/pulp/pulp/demo_repos/zoo/"
+
+ - name: "Create Module repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: "Test Modular Repository"
+ repository_content_type: yum
+ repository_url: "https://dl.fedoraproject.org/pub/epel/8/Modular/x86_64"
+
+ - name: "Create Container Repository"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+ repository_url: https://registry.access.redhat.com
+ repository_docker_upstream_name: ubi9
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: Test Docker Repository
+
+ - name: "Sync content"
+ ansible.builtin.include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: Test Modular Repository
+
+ - name: "Create Content View"
+ ansible.builtin.include_tasks: tasks/content_view.yml
+ vars:
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+
+ - name: "Create Content View"
+ ansible.builtin.include_tasks: tasks/content_view.yml
+ vars:
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - name: "Test Docker Repository"
+ product: "Test Product"
+ - name: "Test Modular Repository"
+ product: "Test Product"
+
+ - name: "Create content view filters"
+ ansible.builtin.include_tasks: tasks/content_view_filter.yml
+
+ - name: "Create Content View Filter Rule for packages"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_packages.yml
+
+ - name: "Create Content View Filter Rule for package groups"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_package_groups.yml
+
+ - name: "Create Content View Filter Rule for errata_id"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_errata_by_id.yml
+
+ - name: "Create Content View Filter Rule for errata_by_date"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_errata_by_date.yml
+
+ - name: "Create Content View Filter Rule for containers"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_containers.yml
+
+ - name: "Create Content View Filter Rule for module_streams"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_modulemd.yml
+
+- name: "Test content_view_filter_rule_info"
+ hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Fetch content_view_filter_info - rpm exlude"
+ vars:
+ content_view_filter_rule_name: "bear"
+ content_view_filter_name: "Test Content View Filter - rpm"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_rule_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ content_view_filter_rule_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule info is valid failed!"
+ that:
+ - result['content_view_filter_rule']['name'] == "bear"
+
+
+ - name: "Fetch content_view_filter_info - package_group exlude"
+ vars:
+ content_view_filter_rule_name: "birds"
+ content_view_filter_name: "Test Content View Filter - package_group"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_rule_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ content_view_filter_rule_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter_rule']['name'] == "birds"
+ - result['content_view_filter_rule']['uuid'] != ""
+
+
+ - name: "Fetch content_view_filter_info - erratum_by_id exlude"
+ vars:
+ content_view_filter_rule_name: "RHEA-2012:0004"
+ content_view_filter_name: "Test Content View Filter - erratum_by_id"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_rule_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ errata_id: "{{ content_view_filter_rule_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter_rules'][0]['errata_id'] == "RHEA-2012:0004"
+
+
+ - name: "Fetch content_view_filter_info - erratum_by_date exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_date"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_rule_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ # name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter_rules'][0]['end_date'] == "2019-01-03"
+ - result['content_view_filter_rules'][0]['start_date'] == "2017-01-03"
+ - result['content_view_filter_rules'][0]['date_type'] == "updated"
+
+ - name: "Fetch content_view_filter_info - container exlude"
+ vars:
+ content_view_filter_rule_name: "8.7-929"
+ content_view_filter_name: "Test Content View Filter - docker"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_rule_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ content_view_filter_rule_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - result['content_view_filter_rule']['name'] == "8.7-929"
+
+
+ - name: "Fetch content_view_filter_info - modulemd exlude"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ content_view_filter_rule_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ # name: "{{ content_view_filter_name }}"
+ register: result
+
+ - name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter info is valid failed!"
+ that:
+ - "{{ result['content_view_filter_rules']|length }} != 0"
+
+- name: "Clean up test dependencies"
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "Cleanup Content View Filter Rules"
+ ansible.builtin.include_tasks: tasks/content_view_filter_rule_cleanup.yml
+
+ - name: "Cleanup Content View Filters"
+ ansible.builtin.include_tasks: tasks/content_view_filter.yml
+ vars:
+ filter_state: absent
+
+ - name: Clean up the content view
+ ansible.builtin.include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_name: Test Modular Repository
+ repository_state: absent
+
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_name: Test Docker Repository
+ repository_state: absent
+
+ - name: "Clean up repositories"
+ ansible.builtin.include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+
+ - name: "Clean up products"
+ ansible.builtin.include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+
+ - name: "Clean up Organizations"
+ ansible.builtin.include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_info.yml
new file mode 100644
index 000000000..01d888f45
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_info.yml
@@ -0,0 +1,93 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Test Product 2"
+ repository_state: present
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: absent
+ - name: Create content view
+ include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ expected_change: true
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch content_view info
+ content_view_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "Test Content View"
+ register: content_view_info
+ - name: check content_view details
+ assert:
+ that:
+ - content_view_info['content_view']['name'] == "Test Content View"
+ - content_view_info['content_view']['repositories'][0]['name'] == "Test Repository"
+
+ - name: search content_view info
+ content_view_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ search: 'name = "Test Content View"'
+ register: content_view_info
+ - name: check content_view details
+ assert:
+ that:
+ - content_view_info['content_views'][0]['name'] == "Test Content View"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Test Product 2"
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_publish_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_publish_role.yml
new file mode 100644
index 000000000..227994f8e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_publish_role.yml
@@ -0,0 +1,93 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Test Product 2"
+ repository_state: present
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: absent
+ - import_tasks: tasks/content_view_version.yml
+ vars:
+ state: absent
+ version: "1.0"
+ ignore_errors: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: content_view_publish
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_content_views:
+ - Test Content View
+ post_tasks:
+ - name: search content view version info
+ content_view_version_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ content_view: "Test Content View"
+ search: 'version = "1.0"'
+ register: content_view_version_info
+ - name: check content_view details
+ assert:
+ that:
+ - content_view_version_info['content_view_versions'][0]['version'] == "1.0"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ - include_tasks: tasks/repository.yml
+ vars:
+ product_name: "Test Product 2"
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version.yml
new file mode 100644
index 000000000..fdeb29000
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version.yml
@@ -0,0 +1,156 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_name: "{{ item.name }}"
+ lifecycle_environment_label: "{{ item.label }}"
+ lifecycle_environment_prior: "{{ item.prior }}"
+ loop:
+ - name: Test
+ label: test
+ prior: Library
+ - name: QA
+ label: qa
+ prior: Test
+ - name: Prod
+ label: prod
+ prior: QA
+ - import_tasks: tasks/content_view_version.yml
+ vars:
+ state: absent
+ version: 1.0
+ ignore_errors: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: publish CV version 1.0
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ description: version-1.0
+ version: 1.0
+ expected_change: true
+ - name: publish CV version 1.0 again, no change
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ description: version-1.0
+ version: 1.0
+ lifecycle_environments:
+ - Library
+ expected_change: false
+ - name: publish CV to Library again, no change
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ description: version-1.0
+ version: 1.0
+ lifecycle_environments:
+ - Library
+ expected_change: false
+ - name: publish CV version 2.0
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ description: version-2.0
+ version: 2.0
+ expected_change: true
+ - name: remove cv version 1.0
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ version: 1.0
+ state: absent
+ expected_change: true
+ - name: remove cv version 1.0 again, no change
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ version: 1.0
+ state: absent
+ expected_change: false
+ - name: promote CV from Library to Test
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ current_lifecycle_environment: Library
+ lifecycle_environments:
+ - Library
+ - Test
+ expected_change: true
+ - name: promote CV from Library to Test again, no change
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ current_lifecycle_environment: Library
+ lifecycle_environments:
+ - Library
+ - Test
+ expected_change: false
+ - name: force promote CV from Test to Prod
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ current_lifecycle_environment: Test
+ lifecycle_environments:
+ - Library
+ - Test
+ - Prod
+ force_promote: true
+ expected_change: true
+ - name: force promote CV from Test to Prod again, no change
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ current_lifecycle_environment: Test
+ lifecycle_environments:
+ - Library
+ - Test
+ - Prod
+ force_promote: true
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_view_version.yml
+ vars:
+ state: absent
+ version: 1.0
+ ignore_errors: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ ignore_errors: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ ignore_errors: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ ignore_errors: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_cleanup_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_cleanup_role.yml
new file mode 100644
index 000000000..13253d28b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_cleanup_role.yml
@@ -0,0 +1,109 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "cleanup-testcv"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "cleanup-testccv"
+ composite: true
+ components:
+ - content_view: cleanup-testcv
+ latest: true
+ - include_tasks: tasks/content_view_version.yml
+ vars:
+ content_view_name: "cleanup-testcv"
+ version: "{{ item }}"
+ loop:
+ - "1.0"
+ - "2.0"
+ - "3.0"
+ - "4.0"
+ - "5.0"
+ - include_tasks: tasks/content_view_version.yml
+ vars:
+ content_view_name: "cleanup-testccv"
+ version: "{{ item }}"
+ loop:
+ - "1.0"
+ - "2.0"
+ - "3.0"
+ - "4.0"
+ - "5.0"
+
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: clean up all but two unused CVs
+ include_role:
+ name: content_view_version_cleanup
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_content_view_version_cleanup_keep: 2
+ foreman_content_view_version_cleanup_search: "name ~ cleanup"
+ - name: find remaining content view versions
+ theforeman.foreman.resource_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ resource: content_views
+ search: "name ~ cleanup"
+ register: remaining_cvs
+ - name: check remaining content view versions
+ assert:
+ that:
+ - remaining_cvs.resources[0].versions|map(attribute='version')|list == ['3.0', '4.0', '5.0']
+ - remaining_cvs.resources[1].versions|map(attribute='version')|list == ['3.0', '4.0', '5.0']
+ - name: clean up all unused CVs
+ include_role:
+ name: content_view_version_cleanup
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_content_view_version_cleanup_keep: 0
+ foreman_content_view_version_cleanup_search: "name ~ cleanup"
+ - name: find remaining content view versions
+ theforeman.foreman.resource_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ resource: content_views
+ search: "name ~ cleanup"
+ register: remaining_cvs
+ - name: check remaining content view versions
+ assert:
+ that:
+ - remaining_cvs.resources[0].versions|map(attribute='version')|list == ['5.0']
+ - remaining_cvs.resources[1].versions|map(attribute='version')|list == ['5.0']
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: remove test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "absent"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_info.yml
new file mode 100644
index 000000000..03c462048
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_view_version_info.yml
@@ -0,0 +1,120 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_name: "{{ item.name }}"
+ lifecycle_environment_label: "{{ item.label }}"
+ lifecycle_environment_prior: "{{ item.prior }}"
+ loop:
+ - name: Test
+ label: test
+ prior: Library
+ - name: QA
+ label: qa
+ prior: Test
+ - name: Prod
+ label: prod
+ prior: QA
+ - import_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ ignore_errors: true
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: present
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - name: publish CV version 1.0
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ description: version-1.0
+ version: 1.0
+ - name: promote CV from Library to Test
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ current_lifecycle_environment: Library
+ lifecycle_environments:
+ - Library
+ - Test
+ - name: publish CV version 2.0
+ include_tasks: tasks/content_view_version.yml
+ vars:
+ description: version-2.0
+ version: 2.0
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch all content view versions
+ content_view_version_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ content_view: "Test Content View"
+ register: content_view_version_info
+ - name: check content_view_version details
+ assert:
+ that:
+ - content_view_version_info['content_view_versions'][0]['version'] == "2.0"
+ - content_view_version_info['content_view_versions'][1]['version'] == "1.0"
+
+ - name: search content view version info
+ content_view_version_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ content_view: "Test Content View"
+ search: 'version = "1.0"'
+ register: content_view_version_info
+ - name: check content_view details
+ assert:
+ that:
+ - content_view_version_info['content_view_versions'][0]['version'] == "1.0"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+ ignore_errors: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ ignore_errors: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ ignore_errors: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/content_views_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_views_role.yml
new file mode 100644
index 000000000..cc88a90ea
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/content_views_role.yml
@@ -0,0 +1,68 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_name: "Test Composite Content View"
+ content_view_state: absent
+ - include_tasks: tasks/content_view.yml
+ vars:
+ content_view_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: content_views
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_content_views:
+ - name: "Test Content View"
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ - name: "Test Composite Content View"
+ components:
+ - content_view: Test Content View
+ latest: true
+ - name: "Test Content View with Filter"
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ filters:
+ - name: "Test Package Content View Filter"
+ filter_state: "present"
+ filter_type: "rpm"
+ rule_name: "bear"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "absent"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/convert2rhel.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/convert2rhel.yml
new file mode 100644
index 000000000..29f215efb
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/convert2rhel.yml
@@ -0,0 +1,31 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: convert2rhel
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_validate_certs: false
+ foreman_convert2rhel_manage_subscription: false
+ foreman_content_rhel_wait_for_syncs: false
+ foreman_content_rhel_enable_rhel7: true
+ foreman_content_rhel_enable_rhel8: true
+ foreman_convert2rhel_enable_oracle7: true
+ foreman_convert2rhel_enable_oracle8: true
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ansible_hello.erb b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ansible_hello.erb
new file mode 100644
index 000000000..19c70f668
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ansible_hello.erb
@@ -0,0 +1,18 @@
+<%#
+name: Ansible Roles - Hello World
+job_category: Ansible Playbook
+description_format: Test Ansible Roles
+feature: ansible_run_host
+snippet: false
+provider_type: Ansible
+kind: job_template
+model: JobTemplate
+%>
+
+---
+- hosts: all
+ tasks:
+ - name: Hello
+ debug:
+ msg: Hello World
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/bear-4.1-1.noarch.rpm b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/bear-4.1-1.noarch.rpm
new file mode 100644
index 000000000..1bd252ef7
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/bear-4.1-1.noarch.rpm
Binary files differ
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/delete_file.erb b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/delete_file.erb
new file mode 100644
index 000000000..2488c1db8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/delete_file.erb
@@ -0,0 +1,13 @@
+<%#
+kind: job_template
+name: delete file
+job_category: Commands
+description_format: "delete %{file}"
+provider_type: SSH
+template_inputs:
+- name: file
+ description: file to delete
+ input_type: user
+ required: true
+%>
+rm -rf --no-preserve-root <%= input("file") %>
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/file_repo_test.txt b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/file_repo_test.txt
new file mode 100644
index 000000000..e22494549
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/file_repo_test.txt
@@ -0,0 +1 @@
+This file is used for testing file repository upload.
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/fixtures_small_repo.tar b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/fixtures_small_repo.tar
new file mode 100644
index 000000000..12b1379e4
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/fixtures_small_repo.tar
Binary files differ
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key.asc b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key.asc
new file mode 100644
index 000000000..f996df18f
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key.asc
@@ -0,0 +1,19 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.5 (GNU/Linux)
+
+mQENBFVMupABCAC9AiPd5+NBtEed8BG4hf4dt94dqJ4B+Lnnv7sVdoqO3tNHA8GW
+QayAPQRN+kAkCzZ+BoqMi7rKTwMyRvUGBpkFhuVCRbQdDIJuvP1S8liP42sPMhVY
++mb7frXQE7EUZ0MH7PfxrvgcxiFi/awmBjQZkrYYbiYZPc7NJFshoJeLe5f6ZXqX
+m9GoX5MVxwC4iRNrHxQKTywvxTURt4wTx4+ZipUmrAjUcknW+g/try61dHJhLCWi
+qH8QYZLNnSgmbK9y8BoL0wxDTeos8sGbvVSd1sVoTiktyGOROjEAUlzC7PhUMjLF
+X9ECWS2q7NoysmheJwVeZxzMxXfvg83HoLyjABEBAAG0JkthdGVsbG8gPGZvcmVt
+YW4tZGV2QGdvb2dsZWdyb3Vwcy5jb20+iQE8BBMBAgAmBQJVTLqQAhsDBQkFo5qA
+BgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQCC1M07xi0T/8+Af/b4KfwT51wFWm
+3bN/LVEYKrfSE32PnlxAVX3jY+eSRnf3Cah+QH5eAGtDIn+hb2JXr5K+CEBnmupS
+Rp57oZJQnqjxK4BRY2WstABxjSXG1gx8iC/vLq6dUV3lK5LSe9hfmXMKr3vos1x1
+b2ehiNstDj264aByokU9R9J3FDtwiEc/xaA7x66SSkWILYtRBYzUlu+lUmox3wJw
+0bCCWPF9PV0IpmzSKwqHLqaV985HtVovH34n//vQiMVnVmXYiiN5WQUrJs5VBmwy
+zXXOdEGqVA/0n4y7nG+hpFWgNb2G0/eSrIg4XWseMYXIc4tJF8zX0dU263A8fP/Q
+eyRp696I2g==
+=5p62
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key2.asc b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key2.asc
new file mode 100644
index 000000000..bd863d8e2
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/gpg_key2.asc
@@ -0,0 +1,30 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+Version: GnuPG v1.4.5 (GNU/Linux)
+
+mQINBE4P06MBEACqn48FZgYkG2QrtUAVDV58H6LpDYEcTcv4CIFSkgs6dJ9TavCW
+NyPBZRpM2R+Rg5eVqlborp7TmktBP/sSsxc8eJ+3P2aQWSWc5ol74Y0OznJUCrBr
+bIdypJllsD9Fe+h7gLBXTh3vdBEWr2lR+xA+Oou8UlO2gFbVFQqMafUgU1s0vqaE
+/hHH0TzwD0/tJ6eqIbHwVR/Bu6kHFK4PwePovhfvyYD9Y+C0vOYd5Ict2vbLHz1f
+QBDZObv4M6KN3j7nzme47hKtdMd+LwFqxM5cXfM6b5doDulWPmuGV78VoX6OR7el
+x1tlfpuiFeuXYnImm5nTawArcQ1UkXUSYcTUKShJebRDLR3BycxR39Q9jtbOQ29R
+FumHginovEhdUcinRr22eRXgcmzpR00zFIWoFCwHh/OCtG14nFhefuZ8Z80qbVhW
+2J9+/O4tksv9HtQBmQNOK5S8C4HNF2M8AfOWNTr8esFSDc0YA5/cxzdfOOtWam/w
+lBpNcUUSSgddRsBwijPuWhVA3NmA/uQlJtAo4Ji5vo8cj5MTPG3+U+rfNqRxu1Yc
+ioXRo4LzggPscaTZX6V24n0fzw0J2k7TT4sX007k+7YXwEMqmHpcMYbDNzdCzUer
+Zilh5hihJwvGfdi234W3GofttoO+jaAZjic7a3p6cO1ICMgfVqrbZCUQVQARAQAB
+tEZDZW50T1MtNiBLZXkgKENlbnRPUyA2IE9mZmljaWFsIFNpZ25pbmcgS2V5KSA8
+Y2VudG9zLTYta2V5QGNlbnRvcy5vcmc+iQI8BBMBAgAmBQJOD9OjAhsDBQkSzAMA
+BgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQCUb8osEFud6ajRAAnb6d+w6Y/v/d
+MSy7UEy4rNquArix8xhqBwwjoGXpa37OqTvvcJrftZ1XgtzmTbkqXc+9EFch0C+w
+ST10f+H0SPTUGuPwqLkg27snUkDAv1B8laub+l2L9erzCaRriH8MnFyxt5v1rqWA
+mVlRymzgXK+EQDr+XOgMm1CvxVY3OwdjdoHNox4TdVQWlZl83xdLXBxkd5IRciNm
+sg5fJAzAMeg8YsoDee3m4khg9gEm+/Rj5io8Gfk0nhQpgGGeS1HEXl5jzTb44zQW
+qudkfcLEdUMOECbu7IC5Z1wrcj559qcp9C94IwQQO+LxLwg4kHffvZjCaOXDRiya
+h8KGsEDuiqwjU9HgGq9fa0Ceo3OyUazUi+WnOxBLVIQ8cUZJJ2Ia5PDnEsz59kCp
+JmBZaYPxUEteMtG3yDTa8c8jUnJtMPpkwpSkeMBeNr/rEH4YcBoxuFjppHzQpJ7G
+hZRbOfY8w97TgJbfDElwTX0/xX9ypsmBezgGoOvOkzP9iCy9YUBc9q/SNnflRWPO
+sMVrjec0vc6ffthu2xBdigBXhL7x2bphWzTXf2T067k+JOdoh5EGney6LhQzcp8m
+YCTENStCR+L/5XwrvNgRBnoXe4e0ZHet1CcCuBCBvSmsPHp5ml21ahsephnHx+rl
+JNGtzulnNP07RyfzQcpCNFH7W4lXzqM=
+=jrWY
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/manifest_foreman-ansible-modules.zip b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/manifest_foreman-ansible-modules.zip
new file mode 100644
index 000000000..e7222168c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/manifest_foreman-ansible-modules.zip
Binary files differ
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/odin_1.0_ppc64.deb b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/odin_1.0_ppc64.deb
new file mode 100644
index 000000000..0915c62c5
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/odin_1.0_ppc64.deb
Binary files differ
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds-tailoring.xml b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds-tailoring.xml
new file mode 100644
index 000000000..517a69c64
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds-tailoring.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xccdf:Tailoring xmlns:xccdf="http://checklists.nist.gov/xccdf/1.2" id="xccdf_scap-workbench_tailoring_default">
+ <xccdf:benchmark href="/tmp/scap-workbench-nlKqUD/ssg-firefox-ds.xml"/>
+ <xccdf:version time="2020-03-26T20:20:49">1</xccdf:version>
+ <xccdf:Profile id="xccdf_org.theforeman_profile_fam_test_fixtures" extends="xccdf_org.ssgproject.content_profile_stig">
+ <xccdf:title xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US" override="true">Upstream Firefox STIG [CUSTOMIZED]</xccdf:title>
+ <xccdf:description xmlns:xhtml="http://www.w3.org/1999/xhtml" xml:lang="en-US" override="true">This profile is developed under the DoD consensus model and DISA FSO Vendor STIG process,
+serving as the upstream development environment for the Firefox STIG.
+
+As a result of the upstream/downstream relationship between the SCAP Security Guide project
+and the official DISA FSO STIG baseline, users should expect variance between SSG and DISA FSO content.
+For official DISA FSO STIG content, refer to https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance.
+
+While this profile is packaged by Red Hat as part of the SCAP Security Guide package, please note
+that commercial support of this SCAP content is NOT available. This profile is provided as example
+SCAP content with no endorsement for suitability or production readiness. Support for this
+profile is provided by the upstream SCAP Security Guide community on a best-effort basis. The
+upstream project homepage is https://www.open-scap.org/security-policies/scap-security-guide/.</xccdf:description>
+ <xccdf:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-home_page" selected="false"/>
+ </xccdf:Profile>
+</xccdf:Tailoring>
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds.xml b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds.xml
new file mode 100644
index 000000000..1bd0ed1c8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/ssg-firefox-ds.xml
@@ -0,0 +1,4015 @@
+<?xml version="1.0"?>
+<ns0:data-stream-collection xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:ns0="http://scap.nist.gov/schema/scap/source/1.2" xmlns:ns1="http://www.w3.org/1999/xlink" xmlns:ns12="http://cpe.mitre.org/dictionary/2.0" xmlns:ns2="urn:oasis:names:tc:entity:xmlns:xml:catalog" xmlns:ns3="http://oval.mitre.org/XMLSchema/oval-definitions-5" xmlns:ns5="http://oval.mitre.org/XMLSchema/oval-common-5" xmlns:ns6="http://oval.mitre.org/XMLSchema/oval-definitions-5#independent" xmlns:ns7="http://oval.mitre.org/XMLSchema/oval-definitions-5#linux" xmlns:ns8="http://scap.nist.gov/schema/ocil/2.0" xmlns:ns9="http://checklists.nist.gov/xccdf/1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" id="scap_org.open-scap_collection_from_xccdf_ssg-firefox-xccdf-1.2.xml" schematron-version="1.3">
+ <ns0:data-stream id="scap_org.open-scap_datastream_from_xccdf_ssg-firefox-xccdf-1.2.xml" scap-version="1.3" use-case="OTHER">
+ <ns0:dictionaries>
+ <ns0:component-ref id="scap_org.open-scap_cref_ssg-firefox-cpe-dictionary.xml" ns1:href="#scap_org.open-scap_comp_ssg-firefox-cpe-dictionary.xml">
+ <ns2:catalog>
+ <ns2:uri name="ssg-firefox-cpe-oval.xml" uri="#scap_org.open-scap_cref_ssg-firefox-cpe-oval.xml"/>
+ </ns2:catalog>
+ </ns0:component-ref>
+ </ns0:dictionaries>
+ <ns0:checklists>
+ <ns0:component-ref id="scap_org.open-scap_cref_ssg-firefox-xccdf-1.2.xml" ns1:href="#scap_org.open-scap_comp_ssg-firefox-xccdf-1.2.xml">
+ <ns2:catalog>
+ <ns2:uri name="ssg-firefox-oval.xml" uri="#scap_org.open-scap_cref_ssg-firefox-oval.xml"/>
+ <ns2:uri name="ssg-firefox-ocil.xml" uri="#scap_org.open-scap_cref_ssg-firefox-ocil.xml"/>
+ </ns2:catalog>
+ </ns0:component-ref>
+ </ns0:checklists>
+ <ns0:checks>
+ <ns0:component-ref id="scap_org.open-scap_cref_ssg-firefox-oval.xml" ns1:href="#scap_org.open-scap_comp_ssg-firefox-oval.xml"/>
+ <ns0:component-ref id="scap_org.open-scap_cref_ssg-firefox-ocil.xml" ns1:href="#scap_org.open-scap_comp_ssg-firefox-ocil.xml"/>
+ <ns0:component-ref id="scap_org.open-scap_cref_ssg-firefox-cpe-oval.xml" ns1:href="#scap_org.open-scap_comp_ssg-firefox-cpe-oval.xml"/>
+ </ns0:checks>
+ </ns0:data-stream>
+ <ns0:component id="scap_org.open-scap_comp_ssg-firefox-oval.xml" timestamp="2020-01-16T13:55:21">
+ <ns3:oval_definitions xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-common-5 oval-common-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5 oval-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#independent independent-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#unix unix-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#linux linux-definitions-schema.xsd">
+ <ns3:generator>
+ <ns5:product_name>combine_ovals.py from SCAP Security Guide</ns5:product_name>
+ <ns5:product_version>ssg: [0, 1, 48], python: 3.7.6</ns5:product_version>
+ <ns5:schema_version>5.11</ns5:schema_version>
+ <ns5:timestamp>2020-01-16T13:51:04</ns5:timestamp>
+ </ns3:generator>
+ <ns3:definitions>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-verification:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Enable Certificate Verification</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>When a web site asks for a certificate for user authentication, Firefox must be configured to have the user choose which certificate to present. Websites within DOD require user authentication for access which increases security for DoD information. Access will be denied to the user if certificate management is not configured</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-verification" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="verification installed" test_ref="oval:ssg-test_firefox_preferences-verification:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-ssl_protocol_tls:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Enable TLS Usage in Firefox</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>DoD implementations of SSL must use TLS 1.0 in accordance with
+ the Network Infrastructure STIG.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-ssl_protocol_tls" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="TLS is enabled" test_ref="oval:ssg-test_firefox_preferences-ssl_protocol_tls:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-javascript_context_menus:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable JavaScript Context Menus</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox should be configured to not allow JavaScript to
+ disable or replace context menus.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-javascript_context_menus" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="disable javaScript context menus" test_ref="oval:ssg-test_firefox_preferences-javascript_context_menus:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-javascript_window_changes:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable JavaScript's Raise Or Lower Windows Capability</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox should be configured to not allow JavaScript to
+ raise or lower windows.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-javascript_window_changes" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="raise or lower windows disabled" test_ref="oval:ssg-test_firefox_preferences-javascript_window_changes:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-home_page:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Default Firefox Home Page Configured</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>The default homepage for Firefox is set and cannot be changed.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-home_page" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="home page configured" test_ref="oval:ssg-test_firefox_preferences-home_page:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-pop-up_windows:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Enable Firefox Pop-up Blocker</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>The Firefox Pop-up blocker should be enabled as windows may be
+ used to launch an attack within a new browser window with altered settings.
+ </ns3:description>
+ <ns3:reference ref_id="firefox_preferences-pop-up_windows" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="pop-up_windows installed" test_ref="oval:ssg-test_firefox_preferences-pop-up_windows:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-installed_firefox_version_supported:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Supported Version of Firefox Installed</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Use of versions of an application which are not
+ supported by the vendor are not permitted. Vendors respond to
+ security flaws with updates and patches. These updates are not
+ available for unsupported versions which can leave the application
+ vulnerable to attack.</ns3:description>
+ <ns3:reference ref_id="installed_firefox_version_supported" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="installed version of firefox supported" test_ref="oval:ssg-test_supported_version_of_firefox:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-search_update:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable Installed Search Plugins Update Checking</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Search plugins can be automatically configured to check for
+ updates. Updates need to be controlled and installed from authorized and
+ trusted servers.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-search_update" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="Disable search plugin update capability" test_ref="oval:ssg-test_firefox_preferences-search_update:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-non-secure_page_warning:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Enable Non-Secure Page Warnings</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox is not configured to provide warnings when a user switches
+ from a secure (SSL-enabled) to a non-secure page.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-non-secure_page_warning" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="non-secure page warning configured" test_ref="oval:ssg-test_firefox_preferences-non-secure_page_warning:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-auto-download_actions:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable Automatic Downloads of MIME Types</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox automatically executes or downloads MIME types which are
+ not authorized for auto-download.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-auto-download_actions" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="Auto download actions of mime type is disabled" test_ref="oval:ssg-test_firefox_preferences-auto-download_actions:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-javascript_window_resizing:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable JavaScript's Moving Or Resizing Windows Capability</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>FireFox should not be configured to allow JavaScript to move
+ or resize windows.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-javascript_window_resizing" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="move or resize windows disabled" test_ref="oval:ssg-test_firefox_preferences-javascript_window_resizing:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-shell_protocol:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable Firefox Access to Shell Protocols</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox can be configured to access systems shells which
+ could potentially allow Firefox and other users to access to the
+ underlying system.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-shell_protocol" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="Disable Firefox Shell Protocol Access" test_ref="oval:ssg-test_firefox_preferences-shell_protocol:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-password_store:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable the Firefox Password Store</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>The Firefox password store should be disabled.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-password_store" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="password_store disabled" test_ref="oval:ssg-test_firefox_preferences-password_store:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-open_confirmation:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Enable Downloading and Opening File Confirmation</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox is not configured to prompt user before downloading and
+ opening required file types.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-open_confirmation" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="open_confirmation configured" test_ref="oval:ssg-test_firefox_preferences-open_confirmation:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-ssl_version_3:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable SSL Version 3 in Firefox</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Earlier versions of SSL have known security vulnerabilities
+ and are not authorized for use in DOD.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-ssl_version_3" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="SSL V3 installed" test_ref="oval:ssg-test_firefox_preferences-ssl_version_3:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-addons_plugin_updates:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable Addons Plugin Updates</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox automatically updates installed
+ add-ons and plugins.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-addons_plugin_updates" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="addons plugin updates configured" test_ref="oval:ssg-test_firefox_preferences-addons_plugin_updates:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-ssl_version_2:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable SSL Version 2.0 in Firefox</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>SSL 2.0 and SSL 3.0 contain a number of security flaws.
+ Therefore, SSL 2.0 should be disabled.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-ssl_version_2" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="SSL 2.0 protocol disabled" test_ref="oval:ssg-test_firefox_preferences-ssl_version_2:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-autofill_passwords:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable User Ability To Autofill Passwords</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox should not be configured to autofill passwords.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-autofill_passwords" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="autofill_passwords disabled" test_ref="oval:ssg-test_firefox_preferences-autofill_passwords:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-javascript_status_bar_changes:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable JavaScript's Ability To Change The Status Bar</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox should be configured to not allow JavaScript to
+ hide or change the status bar.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-javascript_status_bar_changes" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="disable hiding or changing status bar menus" test_ref="oval:ssg-test_firefox_preferences-javascript_status_bar_changes:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-javascript_status_bar_text:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable JavaScript's Ability To Modify The Browser Appearance</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox should be configured not to allow JavaScript
+ to change the status bar text.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-javascript_status_bar_text" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="disable changing the status bar text" test_ref="oval:ssg-test_firefox_preferences-javascript_status_bar_text:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-auto-update_of_firefox:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable Firefox Auto-Update Capability</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox should not be able to automatically
+ update itself.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-auto-update_of_firefox" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="auto-update is disabled" test_ref="oval:ssg-test_firefox_preferences-auto-update_of_firefox:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-autofill_forms:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable Autofill Form Assistance</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Firefox formfill assistance option is disabled.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-autofill_forms" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="autofill_forms disabled" test_ref="oval:ssg-test_firefox_preferences-autofill_forms:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-cookies_clear:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Clear Cookies And Other Data When Firefox Closes</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Set browser preferences to perform a Clear Private Data
+ operation when closing the browser in order to clear cookies and other
+ data installed by websites visited during the session.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-cookies_clear" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="enabled sanitizeOnShutdown" test_ref="oval:ssg-test_firefox_preferences-cookies_shutdown_sanitize:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-cookies_user_notice:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Disable User Prompt For Clearing Cookies And Other Data</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Users should not be prompted about data and cookies being
+ cleared when the browser is closed.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-cookies_user_notice" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="disable promptOnSanitize" test_ref="oval:ssg-test_firefox_preferences-cookies_sanitize_prompt:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-lock_settings_obscure:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Prevent Users from Changing Firefox Configuration Settings</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Locked settings prevents users from accessing about:config and
+ changing the security settings set by the system administrator.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-lock_settings_obscure" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="Do not obscure locked file content with ROT-13" test_ref="oval:ssg-test_firefox_preferences-obscure_value:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="compliance" id="oval:ssg-firefox_preferences-lock_settings_config_file:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Prevent Users from Changing Firefox Configuration Settings</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>Locked settings prevents users from accessing about:config and
+ changing the security settings set by the system administrator.</ns3:description>
+ <ns3:reference ref_id="firefox_preferences-lock_settings_config_file" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="Configuration file is set" test_ref="oval:ssg-test_firefox_preferences-config_filename:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="inventory" id="oval:ssg-installed_app_is_firefox:def:1" version="2">
+ <ns3:metadata>
+ <ns3:title>Mozilla Firefox</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:reference ref_id="cpe:/a:mozilla:firefox" source="CPE"/>
+ <ns3:description>The application installed on the system is firefox.</ns3:description>
+ <ns3:reference ref_id="installed_app_is_firefox" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria operator="AND">
+ <ns3:extend_definition comment="Installed OS is part of the Unix family" definition_ref="oval:ssg-installed_OS_is_part_of_Unix_family:def:1"/>
+ <ns3:criterion comment="Firefox is installed" test_ref="oval:ssg-test_firefox:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="inventory" id="oval:ssg-installed_OS_is_part_of_Unix_family:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Installed operating system is part of the Unix family</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>The operating system installed on the system is part of the Unix OS family</ns3:description>
+ <ns3:reference ref_id="installed_OS_is_part_of_Unix_family" source="ssg"/>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="Installed operating system is part of the unix family" test_ref="oval:ssg-test_unix_family:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ </ns3:definitions>
+ <ns3:tests>
+ <ns6:textfilecontent54_test check="all" comment="Enable Certification verification" id="oval:ssg-test_firefox_preferences-verification:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-verification:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check if TLS is enabled" id="oval:ssg-test_firefox_preferences-ssl_protocol_tls:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-ssl_protocol_tls:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for disable javaScript context menu is disabled" id="oval:ssg-test_firefox_preferences-javascript_context_menus:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-javascript_context_menus:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="raise or lower windows is disabled" id="oval:ssg-test_firefox_preferences-javascript_window_changes:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-javascript_window_changes:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for home page configured" id="oval:ssg-test_firefox_preferences-home_page:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-home_page:obj:1"/>
+ <ns6:state state_ref="oval:ssg-state_firefox_preferences-home_page:ste:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for pop-up_windows installed" id="oval:ssg-test_firefox_preferences-pop-up_windows:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-pop-up_windows:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns7:rpminfo_test check="all" check_existence="any_exist" comment="Installed version of firefox is greater than ESR 31.5" id="oval:ssg-test_supported_version_of_firefox:tst:1" version="1">
+ <ns7:object object_ref="oval:ssg-obj_supported_version_of_firefox:obj:1"/>
+ <ns7:state state_ref="oval:ssg-state_supported_version_of_firefox:ste:1"/>
+ </ns7:rpminfo_test>
+ <ns6:textfilecontent54_test check="all" comment="Check search plugin update capability is disabled" id="oval:ssg-test_firefox_preferences-search_update:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-search_update:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for non-secure page warning configured" id="oval:ssg-test_firefox_preferences-non-secure_page_warning:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-non-secure_page_warning:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for Auto download Actions installed" id="oval:ssg-test_firefox_preferences-auto-download_actions:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-auto-download_actions:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for move or resize windows disabled" id="oval:ssg-test_firefox_preferences-javascript_window_resizing:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-javascript_window_resizing:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check that the hell_protocol is disabled" id="oval:ssg-test_firefox_preferences-shell_protocol:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-shell_protocol:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check that the password_store is disabled" id="oval:ssg-test_firefox_preferences-password_store:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-password_store:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for open_confirmation configured" id="oval:ssg-test_firefox_preferences-open_confirmation:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-open_confirmation:obj:1"/>
+ <ns6:state state_ref="oval:ssg-state_firefox_preferences-open_confirmation:ste:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for SSL Version 3 preferences" id="oval:ssg-test_firefox_preferences-ssl_version_3:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-ssl_version_3:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for addons plugin updates" id="oval:ssg-test_firefox_preferences-addons_plugin_updates:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-addons_plugin_updates:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check SSL 2.0 protocol disabled" id="oval:ssg-test_firefox_preferences-ssl_version_2:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-ssl_version_2:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for autofill_passwords disabled" id="oval:ssg-test_firefox_preferences-autofill_passwords:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-autofill_passwords:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check that hiding or changing status bar is disabled" id="oval:ssg-test_firefox_preferences-javascript_status_bar_changes:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-javascript_status_bar_changes:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check that changing the status bar text is disabled" id="oval:ssg-test_firefox_preferences-javascript_status_bar_text:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-javascript_status_bar_text:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check that auto-update of firefox is disabled" id="oval:ssg-test_firefox_preferences-auto-update_of_firefox:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-auto-update_of_firefox:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for autofill_forms disabled" id="oval:ssg-test_firefox_preferences-autofill_forms:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-autofill_forms:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for sanitizeOnShutdown enabled" id="oval:ssg-test_firefox_preferences-cookies_shutdown_sanitize:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-cookies_shutdown_sanitize:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for promptOnSanitize disabled" id="oval:ssg-test_firefox_preferences-cookies_sanitize_prompt:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-cookies_sanitize_prompt:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for obscure_value" id="oval:ssg-test_firefox_preferences-obscure_value:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-obscure_value:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns6:textfilecontent54_test check="all" comment="Check for configuration filename" id="oval:ssg-test_firefox_preferences-config_filename:tst:1" version="2">
+ <ns6:object object_ref="oval:ssg-object_firefox_preferences-config_filename:obj:1"/>
+ </ns6:textfilecontent54_test>
+ <ns7:rpminfo_test check="all" check_existence="at_least_one_exists" comment="Firefox is installed" id="oval:ssg-test_firefox:tst:1" version="1">
+ <ns7:object object_ref="oval:ssg-obj_firefox:obj:1"/>
+ </ns7:rpminfo_test>
+ <ns6:family_test check="all" check_existence="at_least_one_exists" comment="Test installed OS is part of the unix family" id="oval:ssg-test_unix_family:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_unix_family:obj:1"/>
+ <ns6:state state_ref="oval:ssg-state_unix_family:ste:1"/>
+ </ns6:family_test>
+ </ns3:tests>
+ <ns3:objects>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-verification:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("security.default_personal_cert",[\s]+"Ask Every Time"\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-ssl_protocol_tls:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("security.enable_tls",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-javascript_context_menus:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("dom.event.contextmenu.enabled",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-javascript_window_changes:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("dom.disable_window_flip",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-home_page:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("browser.startup.homepage",[\s]+"(\S+)"\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-pop-up_windows:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("dom.disable_window_open_feature.status",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns7:rpminfo_object id="oval:ssg-obj_supported_version_of_firefox:obj:1" version="1">
+ <ns7:name>firefox</ns7:name>
+ </ns7:rpminfo_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-search_update:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("browser.search.update",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-non-secure_page_warning:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("security.warn_leaving_secure",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-auto-download_actions:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("browser.helperApps.alwaysAsk.force",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-javascript_window_resizing:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("dom.disable_window_move_resize",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-shell_protocol:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("network.protocol-handler.external.shell",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-password_store:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("signon.rememberSignons",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-open_confirmation:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("plugin.disable_full_page_plugin_for_types",[\s]+"(\S+)"\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-ssl_version_3:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("security.enable_ssl3",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-addons_plugin_updates:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("extensions.update.enabled",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-ssl_version_2:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("security.enable_ssl2",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-autofill_passwords:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("signon.prefillForms",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-javascript_status_bar_changes:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("dom.disable_window_status_change",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-javascript_status_bar_text:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("dom.disable_window_open_feature.status",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-auto-update_of_firefox:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("app.update.enabled",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-autofill_forms:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("browser.formfill.enable",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-cookies_shutdown_sanitize:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("privacy.sanitize.sanitizeOnShutdown",[\s]+true\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-cookies_sanitize_prompt:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.cfg$</ns6:filename>
+ <ns6:pattern operation="pattern match">^lockPref\("privacy.sanitize.promptOnSanitize",[\s]+false\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-obscure_value:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox\/defaults\/(preferences|pref)</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.js$</ns6:filename>
+ <ns6:pattern operation="pattern match">^pref\("general.config.obscure_value",[\s]+0\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns6:textfilecontent54_object id="oval:ssg-object_firefox_preferences-config_filename:obj:1" version="1">
+ <ns6:path operation="pattern match">^\/usr\/(|local\/)lib(|64)\/firefox\/defaults\/(preferences|pref)</ns6:path>
+ <ns6:filename operation="pattern match">^.*\.js$</ns6:filename>
+ <ns6:pattern operation="pattern match">^pref\("general.config.filename",[\s]+"(\S+)\.cfg"\);$</ns6:pattern>
+ <ns6:instance datatype="int">1</ns6:instance>
+ </ns6:textfilecontent54_object>
+ <ns7:rpminfo_object id="oval:ssg-obj_firefox:obj:1" version="1">
+ <ns7:name>firefox</ns7:name>
+ </ns7:rpminfo_object>
+ <ns6:family_object id="oval:ssg-object_unix_family:obj:1" version="1"/>
+ </ns3:objects>
+ <ns3:states>
+ <ns6:textfilecontent54_state id="oval:ssg-state_firefox_preferences-home_page:ste:1" version="1">
+ <ns6:subexpression datatype="string" operation="equals" var_check="all" var_ref="oval:ssg-var_default_home_page:var:1"/>
+ </ns6:textfilecontent54_state>
+ <ns7:rpminfo_state id="oval:ssg-state_supported_version_of_firefox:ste:1" version="1">
+ <ns7:evr datatype="evr_string" operation="greater than">3.0.0</ns7:evr>
+ </ns7:rpminfo_state>
+ <ns6:textfilecontent54_state id="oval:ssg-state_firefox_preferences-open_confirmation:ste:1" version="1">
+ <ns6:subexpression operation="equals" var_check="all" var_ref="oval:ssg-var_required_file_types:var:1"/>
+ </ns6:textfilecontent54_state>
+ <ns6:family_state id="oval:ssg-state_unix_family:ste:1" version="1">
+ <ns6:family>unix</ns6:family>
+ </ns6:family_state>
+ </ns3:states>
+ <ns3:variables>
+ <ns3:external_variable comment="Expected default home page" datatype="string" id="oval:ssg-var_default_home_page:var:1" version="1"/>
+ <ns3:external_variable comment="Expected file types" datatype="string" id="oval:ssg-var_required_file_types:var:1" version="1"/>
+ </ns3:variables>
+ </ns3:oval_definitions>
+ </ns0:component>
+ <ns0:component id="scap_org.open-scap_comp_ssg-firefox-ocil.xml" timestamp="2020-01-16T13:55:21">
+ <ns8:ocil>
+ <ns8:generator>
+ <ns8:product_name>xccdf-create-ocil.xslt from SCAP Security Guide</ns8:product_name>
+ <ns8:product_version>ssg: 0.1.48</ns8:product_version>
+ <ns8:schema_version>2.0</ns8:schema_version>
+ <ns8:timestamp>2020-01-16T00:00:00Z</ns8:timestamp>
+ </ns8:generator>
+ <ns8:questionnaires>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-home_page_ocil:questionnaire:1">
+ <ns8:title>Default Firefox Home Page Configured</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-home_page_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-non-secure_page_warning_ocil:questionnaire:1">
+ <ns8:title>Enable Non-Secure Page Warnings</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-non-secure_page_warning_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-ssl_version_3_ocil:questionnaire:1">
+ <ns8:title>Disable SSL Version 3.0 in Firefox</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-ssl_version_3_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-password_store_ocil:questionnaire:1">
+ <ns8:title>Disable the Firefox Password Store</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-password_store_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-installed_firefox_version_supported_ocil:questionnaire:1">
+ <ns8:title>Supported Version of Firefox Installed</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-installed_firefox_version_supported_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-auto-download_actions_ocil:questionnaire:1">
+ <ns8:title>Disable Automatic Downloads of MIME Types</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-auto-download_actions_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-javascript_context_menus_ocil:questionnaire:1">
+ <ns8:title>Disable JavaScript Context Menus</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-javascript_context_menus_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-open_confirmation_ocil:questionnaire:1">
+ <ns8:title>Enable Downloading and Opening File Confirmation</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-open_confirmation_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-verification_ocil:questionnaire:1">
+ <ns8:title>Enable Certificate Verification</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-verification_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-javascript_window_resizing_ocil:questionnaire:1">
+ <ns8:title>Disable JavaScript's Moving Or Resizing Windows Capability</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-javascript_window_resizing_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-search_update_ocil:questionnaire:1">
+ <ns8:title>Disable Installed Search Plugins Update Checking</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-search_update_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-autofill_forms_ocil:questionnaire:1">
+ <ns8:title>Disable Autofill Form Assistance</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-autofill_forms_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-shell_protocol_ocil:questionnaire:1">
+ <ns8:title>Disable Firefox Access to Shell Protocols</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-shell_protocol_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-addons_plugin_updates_ocil:questionnaire:1">
+ <ns8:title>Disable Addons Plugin Updates</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-addons_plugin_updates_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-autofill_passwords_ocil:questionnaire:1">
+ <ns8:title>Disable User Ability To Autofill Passwords</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-autofill_passwords_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-ssl_version_2_ocil:questionnaire:1">
+ <ns8:title>Disable SSL Version 2.0 in Firefox</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-ssl_version_2_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-ssl_protocol_tls_ocil:questionnaire:1">
+ <ns8:title>Enable TLS Usage in Firefox</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-ssl_protocol_tls_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-javascript_status_bar_text_ocil:questionnaire:1">
+ <ns8:title>Disable JavaScript's Ability To Modify The Browser Appearance</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-javascript_status_bar_text_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-javascript_window_changes_ocil:questionnaire:1">
+ <ns8:title>Disable JavaScript's Raise Or Lower Windows Capability</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-javascript_window_changes_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-javascript_status_bar_changes_ocil:questionnaire:1">
+ <ns8:title>Disable JavaScript's Ability To Change The Status Bar</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-javascript_status_bar_changes_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-auto-update_of_firefox_ocil:questionnaire:1">
+ <ns8:title>Disable Firefox Auto-Update Capability</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-auto-update_of_firefox_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-pop-up_windows_ocil:questionnaire:1">
+ <ns8:title>Enable Firefox Pop-up Blocker</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-pop-up_windows_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-lock_settings_config_file_ocil:questionnaire:1">
+ <ns8:title>Set Firefox Configuration File Location</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-lock_settings_config_file_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-lock_settings_obscure_ocil:questionnaire:1">
+ <ns8:title>Disable Firefox Configuration File ROT-13 Encoding</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-lock_settings_obscure_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-enable_ca_trust_ocil:questionnaire:1">
+ <ns8:title>Enable Shared System Certificates</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-enable_ca_trust_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-dod_root_certificate_installed_ocil:questionnaire:1">
+ <ns8:title>The DoD Root Certificate Exists</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-dod_root_certificate_installed_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-cookies_clear_ocil:questionnaire:1">
+ <ns8:title>Clear Data When Firefox Closes</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-cookies_clear_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ <ns8:questionnaire id="ocil:ssg-firefox_preferences-cookies_user_notice_ocil:questionnaire:1">
+ <ns8:title>Disable User Prompt When Data Is Cleared</ns8:title>
+ <ns8:actions>
+ <ns8:test_action_ref>ocil:ssg-firefox_preferences-cookies_user_notice_action:testaction:1</ns8:test_action_ref>
+ </ns8:actions>
+ </ns8:questionnaire>
+ </ns8:questionnaires>
+ <ns8:test_actions>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-home_page_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-home_page_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-non-secure_page_warning_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-non-secure_page_warning_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-ssl_version_3_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-ssl_version_3_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-password_store_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-password_store_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-installed_firefox_version_supported_action:testaction:1" question_ref="ocil:ssg-installed_firefox_version_supported_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-auto-download_actions_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-auto-download_actions_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-javascript_context_menus_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-javascript_context_menus_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-open_confirmation_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-open_confirmation_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-verification_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-verification_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-javascript_window_resizing_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-javascript_window_resizing_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-search_update_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-search_update_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-autofill_forms_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-autofill_forms_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-shell_protocol_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-shell_protocol_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-addons_plugin_updates_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-addons_plugin_updates_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-autofill_passwords_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-autofill_passwords_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-ssl_version_2_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-ssl_version_2_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-ssl_protocol_tls_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-ssl_protocol_tls_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-javascript_status_bar_text_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-javascript_status_bar_text_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-javascript_window_changes_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-javascript_window_changes_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-javascript_status_bar_changes_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-javascript_status_bar_changes_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-auto-update_of_firefox_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-auto-update_of_firefox_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-pop-up_windows_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-pop-up_windows_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-lock_settings_config_file_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-lock_settings_config_file_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-lock_settings_obscure_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-lock_settings_obscure_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-enable_ca_trust_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-enable_ca_trust_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-dod_root_certificate_installed_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-dod_root_certificate_installed_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-cookies_clear_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-cookies_clear_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ <ns8:boolean_question_test_action id="ocil:ssg-firefox_preferences-cookies_user_notice_action:testaction:1" question_ref="ocil:ssg-firefox_preferences-cookies_user_notice_question:question:1">
+ <ns8:when_true>
+ <ns8:result>PASS</ns8:result>
+ </ns8:when_true>
+ <ns8:when_false>
+ <ns8:result>FAIL</ns8:result>
+ </ns8:when_false>
+ </ns8:boolean_question_test_action>
+ </ns8:test_actions>
+ <ns8:questions>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-home_page_question:question:1">
+ <ns8:question_text>To verify that default home page is set,
+run the following command:
+$ grep 'browser.startup.homepage' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("browser.startup.homepage", "");
+ Is it the case that it is not configured?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-non-secure_page_warning_question:question:1">
+ <ns8:question_text>To verify that non-secure page warnings are enabled,
+run the following command:
+$ grep 'security.warn_leaving_secure' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("security.warn_leaving_secure", "true");
+ Is it the case that it is not enabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-ssl_version_3_question:question:1">
+ <ns8:question_text>To verify that SSL version 3 is disabled,
+run the following command:
+$ grep 'security.enable_ssl3' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("security.enable_ssl3", "false");
+ Is it the case that it is not enabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-password_store_question:question:1">
+ <ns8:question_text>To verify that the password store is disabled,
+run the following command:
+$ grep 'signon.rememberSignons' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("signon.rememberSignons", "false");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-installed_firefox_version_supported_question:question:1">
+ <ns8:question_text>If the system is joined to the Red Hat Network, a Red Hat Satellite Server, or
+a yum server which provides updates, invoking the following command will
+indicate if updates are available:
+$ sudo yum check-update
+If the system is not configured to update from one of these sources,
+run the following command to list when each package was last updated:
+$ rpm -qa -last
+Compare this to Red Hat Security Advisories (RHSA) listed at
+
+ https://access.redhat.com/security/updates/active/https://access.redhat.com/security/updates/active/
+to determine if the system is missing applicable updates.
+ Is it the case that it is not updated?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-auto-download_actions_question:question:1">
+ <ns8:question_text>To verify that user interaction is required for the downloading of MIME types,
+run the following command:
+$ grep 'browser.helperApps.alwaysAsk.force' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("browser.helperApps.alwaysAsk.force", "true");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-javascript_context_menus_question:question:1">
+ <ns8:question_text>To verify that JavaScript cannot change context menus,
+run the following command:
+$ grep 'dom.event.contextmenu.enabled' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("dom.event.contextmenu.enabled", "false");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-open_confirmation_question:question:1">
+ <ns8:question_text>To verify that downloading and opening file confirmation is enabled,
+run the following command:
+$ grep 'plugin.disable_full_page_plugin_for_types' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("plugin.disable_full_page_plugin_for_types", "");
+ Is it the case that it is not set or application listing is incorrect?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-verification_question:question:1">
+ <ns8:question_text>To verify that certificate verification is enabled, run the following command:
+$ grep 'security.default_personal_cert' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("security.default_personal_cert", "Ask Every Time");
+ Is it the case that it is not enabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-javascript_window_resizing_question:question:1">
+ <ns8:question_text>To verify that JavaScript cannot change windows sizing,
+run the following command:
+$ grep 'dom.disable_window_move_resize' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("dom.disable_window_move_resize", "true");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-search_update_question:question:1">
+ <ns8:question_text>To verify that search plugins cannot automatically update,
+run the following command:
+$ grep 'browser.search.update' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("browser.search.update", "false");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-autofill_forms_question:question:1">
+ <ns8:question_text>To verify that Autofill Form Assistance is disabled,
+run the following command:
+$ grep 'browser.formfill.enable' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("browser.formfill.enable", false);
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-shell_protocol_question:question:1">
+ <ns8:question_text>To verify that the shell protocol access is disabled,
+run the following command:
+$ grep 'network.protocol-handler.external.shell' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("network.protocol-handler.external.shell", "false");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-addons_plugin_updates_question:question:1">
+ <ns8:question_text>To verify that add-ons and plugins cannot automatically update,
+run the following command:
+$ grep 'extensions.update.enabled' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("extensions.update.enabled", false);
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-autofill_passwords_question:question:1">
+ <ns8:question_text>To verify that password autofill is disabled,
+run the following command:
+$ grep 'signon.prefillForms' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("signon.prefillForms", false);
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-ssl_version_2_question:question:1">
+ <ns8:question_text>To verify that SSL version 2.0 is disabled,
+run the following command:
+$ grep 'security.enable_ssl2' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("security.enable_ssl2", "false");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-ssl_protocol_tls_question:question:1">
+ <ns8:question_text>To verify that TLS is enabled, run the following command:
+$ grep 'security.enable_tls' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("security.enable_tls", "true");
+ Is it the case that it is not enabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-javascript_status_bar_text_question:question:1">
+ <ns8:question_text>To verify that JavaScript cannot change the browser appearance,
+run the following command:
+$ grep 'dom.disable_window_open_feature.status' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("dom.disable_window_open_feature.status", "true");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-javascript_window_changes_question:question:1">
+ <ns8:question_text>To verify that JavaScript cannot change windows sizing,
+run the following command:
+$ grep 'dom.disable_window_flip' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("dom.disable_window_flip", "true");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-javascript_status_bar_changes_question:question:1">
+ <ns8:question_text>To verify that JavaScript cannot change the status bar,
+run the following command:
+$ grep 'dom.disable_window_status_change' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("dom.disable_window_status_change", "true");
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-auto-update_of_firefox_question:question:1">
+ <ns8:question_text>To verify that Firefox cannot auto-update,
+run the following command:
+$ grep 'app.update.enable' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("app.update.enable", false);
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-pop-up_windows_question:question:1">
+ <ns8:question_text>To verify that pop-up blocker is enabled,
+run the following command:
+$ grep 'dom.disable_window_open_feature.status' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("dom.disable_window_open_feature.status", "true");
+ Is it the case that it is not enabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-lock_settings_config_file_question:question:1">
+ <ns8:question_text>To verify that configuration filename is set, run the following command:
+$ grep 'filename' FIREFOX_INSTALL_DIR/defaults/preferences/*.js
+The output should return something similar to:
+pref("general.config.filename", "mozilla.cfg");
+ Is it the case that users can change mandatory settings?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-lock_settings_obscure_question:question:1">
+ <ns8:question_text>To verify that ROT-13 encoding is disabled, run the following command:
+$ grep 'obscure_value' FIREFOX_INSTALL_DIR/defaults/preferences/*.js
+The output should return something similar to:
+pref("general.config.obscure_value", 0);
+ Is it the case that users can change mandatory settings?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-enable_ca_trust_question:question:1">
+ <ns8:question_text>To verify that the central system cerificate authority store is enabled,
+run the following command:
+$ ls -l /etc/alternatives/libnssckbi.so.x86_64
+The output should return something similar to:
+lrwxrwxrwx. 1 root root 34 Apr 30 09:19 /etc/alternatives/libnssckbi.so.x86_64 -&gt; /usr/lib64/pkcs11/p11-kit-trust.so
+ Is it the case that it is not enabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-dod_root_certificate_installed_question:question:1">
+ <ns8:question_text>To verify that the DoD root certificate is installed,
+list all certificates in /etc/pki/ca-trust/source/anchors
+and compare them to the DoD root certificate. If there is a match
+to the DoD root certificate, then the DoD root certificate is
+installed.
+ Is it the case that it is not installed?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-cookies_clear_question:question:1">
+ <ns8:question_text>To verify that Firefox clears data on exit,
+run the following command:
+$ grep 'privacy.sanitize.sanitizeOnShutdown' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("privacy.sanitize.sanitizeOnShutdown", true);
+ Is it the case that it is not set to clear?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ <ns8:boolean_question id="ocil:ssg-firefox_preferences-cookies_user_notice_question:question:1">
+ <ns8:question_text>To verify that Firefox does not prompt users about data being cleared,
+run the following command:
+$ grep 'privacy.sanitize.promptOnSanitize' FIREFOX_INSTALL_DIR/*.cfg
+The output should return:
+lockPref("privacy.sanitize.promptOnSanitize", false);
+ Is it the case that it is not disabled?
+ </ns8:question_text>
+ </ns8:boolean_question>
+ </ns8:questions>
+ </ns8:ocil>
+ </ns0:component>
+ <ns0:component id="scap_org.open-scap_comp_ssg-firefox-xccdf-1.2.xml" timestamp="2020-01-16T13:55:38">
+ <ns9:Benchmark id="xccdf_org.ssgproject.content_benchmark_FIREFOX" resolved="1" style="SCAP_1.2" xml:lang="en-US">
+ <ns9:status date="2020-01-16">draft</ns9:status>
+ <ns9:title xml:lang="en-US">Guide to the Secure Configuration of Firefox</ns9:title>
+ <ns9:description xml:lang="en-US">This guide presents a catalog of security-relevant
+configuration settings for Firefox. It is a rendering of
+content structured in the eXtensible Configuration Checklist Description Format (XCCDF)
+in order to support security automation. The SCAP content is
+is available in the <html:code>scap-security-guide</html:code> package which is developed at
+
+ <html:a href="https://www.open-scap.org/security-policies/scap-security-guide">https://www.open-scap.org/security-policies/scap-security-guide</html:a>.
+<html:br/><html:br/>
+Providing system administrators with such guidance informs them how to securely
+configure systems under their control in a variety of network roles. Policy
+makers and baseline creators can use this catalog of settings, with its
+associated references to higher-level security control catalogs, in order to
+assist them in security baseline creation. This guide is a <html:em>catalog, not a
+checklist</html:em>, and satisfaction of every item is not likely to be possible or
+sensible in many operational scenarios. However, the XCCDF format enables
+granular selection and adjustment of settings, and their association with OVAL
+and OCIL content provides an automated checking capability. Transformations of
+this document, and its associated automated checking content, are capable of
+providing baselines that meet a diverse set of policy objectives. Some example
+XCCDF <html:em>Profiles</html:em>, which are selections of items that form checklists and
+can be used as baselines, are available with this guide. They can be
+processed, in an automated fashion, with tools that support the Security
+Content Automation Protocol (SCAP). The DISA STIG for Firefox,
+which provides required settings for US Department of Defense systems, is
+one example of a baseline created from this guidance.
+</ns9:description>
+ <ns9:notice id="terms_of_use" xml:lang="en-US">Do not attempt to implement any of the settings in
+this guide without first testing them in a non-operational environment. The
+creators of this guidance assume no responsibility whatsoever for its use by
+other parties, and makes no guarantees, expressed or implied, about its
+quality, reliability, or any other characteristic.
+</ns9:notice>
+ <ns9:front-matter xml:lang="en-US">The SCAP Security Guide Project<html:br/>
+
+ <html:a href="https://www.open-scap.org/security-policies/scap-security-guide">https://www.open-scap.org/security-policies/scap-security-guide</html:a>
+</ns9:front-matter>
+ <ns9:rear-matter xml:lang="en-US">Red Hat and Red Hat Enterprise Linux are either registered
+trademarks or trademarks of Red Hat, Inc. in the United States and other
+countries. All other names are registered trademarks or trademarks of their
+respective companies.
+</ns9:rear-matter>
+ <ns9:platform idref="cpe:/a:mozilla:firefox"/>
+ <ns9:version update="https://github.com/OpenSCAP/scap-security-guide/releases/latest">0.1.48</ns9:version>
+ <ns9:metadata>
+ <dc:publisher>SCAP Security Guide Project</dc:publisher>
+ <dc:creator>SCAP Security Guide Project</dc:creator>
+ <dc:contributor>Frank J Cameron (CAM1244) &lt;cameron@ctc.com&gt;</dc:contributor>
+ <dc:contributor>0x66656c6978 &lt;0x66656c6978@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Gabe Alford &lt;redhatrises@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Firas AlShafei &lt;firas.alshafei@us.abb.com&gt;</dc:contributor>
+ <dc:contributor>Christopher Anderson &lt;cba@fedoraproject.org&gt;</dc:contributor>
+ <dc:contributor>angystardust &lt;angystardust@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Chuck Atkins &lt;chuck.atkins@kitware.com&gt;</dc:contributor>
+ <dc:contributor>Ryan Ballanger &lt;root@rballang-admin-2.fastenal.com&gt;</dc:contributor>
+ <dc:contributor>Alex Baranowski &lt;alex@euro-linux.com&gt;</dc:contributor>
+ <dc:contributor>Molly Jo Bault &lt;Molly.Jo.Bault@ballardtech.com&gt;</dc:contributor>
+ <dc:contributor>Gabriel Becker &lt;ggasparb@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Alexander Bergmann &lt;abergmann@suse.com&gt;</dc:contributor>
+ <dc:contributor>Jose Luis BG &lt;bgjoseluis@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Joseph Bisch &lt;joseph.bisch@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Jeffrey Blank &lt;blank@eclipse.ncsc.mil&gt;</dc:contributor>
+ <dc:contributor>Olivier Bonhomme &lt;ptitoliv@ptitoliv.net&gt;</dc:contributor>
+ <dc:contributor>Ted Brunell &lt;tbrunell@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Blake Burkhart &lt;blake.burkhart@us.af.mil&gt;</dc:contributor>
+ <dc:contributor>Patrick Callahan &lt;pmc@patrickcallahan.com&gt;</dc:contributor>
+ <dc:contributor>Nick Carboni &lt;ncarboni@redhat.com&gt;</dc:contributor>
+ <dc:contributor>James Cassell &lt;james.cassell@ll.mit.edu&gt;</dc:contributor>
+ <dc:contributor>Frank Caviggia &lt;fcaviggi@ra.iad.redhat.com&gt;</dc:contributor>
+ <dc:contributor>Eric Christensen &lt;echriste@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Jayson Cofell &lt;1051437+70k10@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Caleb Cooper &lt;coopercd@ornl.gov&gt;</dc:contributor>
+ <dc:contributor>Deric Crago &lt;deric.crago@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Maura Dailey &lt;maura@eclipse.ncsc.mil&gt;</dc:contributor>
+ <dc:contributor>Klaas Demter &lt;demter@atix.de&gt;</dc:contributor>
+ <dc:contributor>dhanushkar-wso2 &lt;dhanushkar@wso2.com&gt;</dc:contributor>
+ <dc:contributor>Andrew DiPrinzio &lt;andrew.diprinzio@jhuapl.edu&gt;</dc:contributor>
+ <dc:contributor>dom &lt;dominique.blaze@devinci.fr&gt;</dc:contributor>
+ <dc:contributor>Jean-Baptiste Donnette &lt;jean-baptiste.donnette@epita.fr&gt;</dc:contributor>
+ <dc:contributor>drax &lt;applezip@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Sebastian Dunne &lt;sdunne@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Greg Elin &lt;gregelin@gitmachines.com&gt;</dc:contributor>
+ <dc:contributor>Alexis Facques &lt;alexis.facques@mythalesgroup.io&gt;</dc:contributor>
+ <dc:contributor>Leah Fisher &lt;lfisher047@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Alijohn Ghassemlouei &lt;alijohn.ghassemlouei@sapns2.com&gt;</dc:contributor>
+ <dc:contributor>ghylock &lt;ghylock@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Andrew Gilmore &lt;agilmore2@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Joshua Glemza &lt;jglemza@nasa.gov&gt;</dc:contributor>
+ <dc:contributor>Loren Gordon &lt;lorengordon@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Patrik Greco &lt;sikevux@sikevux.se&gt;</dc:contributor>
+ <dc:contributor>Steve Grubb &lt;sgrubb@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Marek Haicman &lt;mhaicman@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Rebekah Hayes &lt;rhayes@corp.rivierautilities.com&gt;</dc:contributor>
+ <dc:contributor>Trey Henefield &lt;thenefield@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Henning Henkel &lt;henning.henkel@helvetia.ch&gt;</dc:contributor>
+ <dc:contributor>hex2a &lt;hex2a@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>John Hooks &lt;jhooks@starscream.pa.jhbcomputers.com&gt;</dc:contributor>
+ <dc:contributor>Jakub Hrozek &lt;jhrozek@redhat.com&gt;</dc:contributor>
+ <dc:contributor>De Huo &lt;De.Huo@windriver.com&gt;</dc:contributor>
+ <dc:contributor>Robin Price II &lt;robin@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Yasir Imam &lt;yimam@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Jiri Jaburek &lt;jjaburek@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Keith Jackson &lt;keithkjackson@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Jeremiah Jahn &lt;jeremiah@goodinassociates.com&gt;</dc:contributor>
+ <dc:contributor>Stephan Joerrens &lt;Stephan.Joerrens@fiduciagad.de&gt;</dc:contributor>
+ <dc:contributor>Jono &lt;jono@ubuntu-18.localdomain&gt;</dc:contributor>
+ <dc:contributor>Kai Kang &lt;kai.kang@windriver.com&gt;</dc:contributor>
+ <dc:contributor>Charles Kernstock &lt;charles.kernstock@ultra-ats.com&gt;</dc:contributor>
+ <dc:contributor>Yuli Khodorkovskiy &lt;ykhodorkovskiy@tresys.com&gt;</dc:contributor>
+ <dc:contributor>Nathan Kinder &lt;nkinder@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Lee Kinser &lt;lee.kinser@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Evgeny Kolesnikov &lt;ekolesni@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Peter 'Pessoft' Kol&#xED;nek &lt;github@pessoft.com&gt;</dc:contributor>
+ <dc:contributor>Luke Kordell &lt;luke.t.kordell@lmco.com&gt;</dc:contributor>
+ <dc:contributor>Malte Kraus &lt;malte.kraus@suse.com&gt;</dc:contributor>
+ <dc:contributor>kspargur &lt;kspargur@kspargur.csb&gt;</dc:contributor>
+ <dc:contributor>Amit Kumar &lt;amitkuma@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Fen Labalme &lt;fen@civicactions.com&gt;</dc:contributor>
+ <dc:contributor>Ian Lee &lt;lee1001@llnl.gov&gt;</dc:contributor>
+ <dc:contributor>Jarrett Lee &lt;jarrettl@umd.edu&gt;</dc:contributor>
+ <dc:contributor>Jan Lieskovsky &lt;jlieskov@redhat.com&gt;</dc:contributor>
+ <dc:contributor>&#x160;imon Luka&#x161;&#xED;k &lt;slukasik@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Milan Lysonek &lt;mlysonek@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Fredrik Lys&#xE9;n &lt;fredrik@pipemore.se&gt;</dc:contributor>
+ <dc:contributor>Matus Marhefka &lt;mmarhefk@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Jamie Lorwey Martin &lt;jlmartin@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Robert McAllister &lt;rmcallis@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Michael McConachie &lt;michael@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Khary Mendez &lt;kharyam@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Rodney Mercer &lt;rmercer@harris.com&gt;</dc:contributor>
+ <dc:contributor>Matt Micene &lt;nzwulfin@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Brian Millett &lt;bmillett@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Mixer9 &lt;35545791+Mixer9@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>mmosel &lt;mmosel@kde.example.com&gt;</dc:contributor>
+ <dc:contributor>Zbynek Moravec &lt;zmoravec@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Kazuo Moriwaka &lt;moriwaka@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Michael Moseley &lt;michael@eclipse.ncsc.mil&gt;</dc:contributor>
+ <dc:contributor>Joe Nall &lt;joe@nall.com&gt;</dc:contributor>
+ <dc:contributor>Neiloy &lt;neiloy@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Axel Nennker &lt;axel@nennker.de&gt;</dc:contributor>
+ <dc:contributor>Michele Newman &lt;mnewman@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Sean O'Keeffe &lt;seanokeeffe797@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Ilya Okomin &lt;ilya.okomin@oracle.com&gt;</dc:contributor>
+ <dc:contributor>Kaustubh Padegaonkar &lt;theTuxRacer@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Michael Palmiotto &lt;mpalmiotto@tresys.com&gt;</dc:contributor>
+ <dc:contributor>Max R.D. Parmer &lt;maxp@trystero.is&gt;</dc:contributor>
+ <dc:contributor>Jan Pazdziora &lt;jpazdziora@redhat.com&gt;</dc:contributor>
+ <dc:contributor>pcactr &lt;paul.c.arnold4.ctr@mail.mil&gt;</dc:contributor>
+ <dc:contributor>Kenneth Peeples &lt;kennethwpeeples@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Nathan Peters &lt;Nathaniel.Peters@ca.com&gt;</dc:contributor>
+ <dc:contributor>Frank Lin PIAT &lt;fpiat@klabs.be&gt;</dc:contributor>
+ <dc:contributor>Stefan Pietsch &lt;mail.ipv4v6+gh@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Vojtech Polasek &lt;vpolasek@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Martin Preisler &lt;mpreisle@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Wesley Ceraso Prudencio &lt;wcerasop@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Raphael Sanchez Prudencio &lt;rsprudencio@redhat.com&gt;</dc:contributor>
+ <dc:contributor>T.O. Radzy Radzykewycz &lt;radzy@windriver.com&gt;</dc:contributor>
+ <dc:contributor>Kenyon Ralph &lt;kenyon@kenyonralph.com&gt;</dc:contributor>
+ <dc:contributor>Mike Ralph &lt;mralph@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Rick Renshaw &lt;Richard_Renshaw@xtoenergy.com&gt;</dc:contributor>
+ <dc:contributor>Chris Reynolds &lt;c.reynolds82@gmail.com&gt;</dc:contributor>
+ <dc:contributor>rhayes &lt;rhayes@rivierautilities.com&gt;</dc:contributor>
+ <dc:contributor>Pat Riehecky &lt;riehecky@fnal.gov&gt;</dc:contributor>
+ <dc:contributor>rlucente-se-jboss &lt;rlucente@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Jesse Roland &lt;j.roland277@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Joshua Roys &lt;roysjosh@gmail.com&gt;</dc:contributor>
+ <dc:contributor>rrenshaw &lt;bofh69@yahoo.com&gt;</dc:contributor>
+ <dc:contributor>Chris Ruffalo &lt;chris.ruffalo@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Ray Shaw (Cont ARL/CISD) rvshaw &lt;rvshaw@esme.arl.army.mil&gt;</dc:contributor>
+ <dc:contributor>Willy Santos &lt;wsantos@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Gautam Satish &lt;gautams@hpe.com&gt;</dc:contributor>
+ <dc:contributor>Watson Sato &lt;wsato@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Satoru SATOH &lt;satoru.satoh@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Alexander Scheel &lt;ascheel@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Bryan Schneiders &lt;pschneiders@trisept.com&gt;</dc:contributor>
+ <dc:contributor>shaneboulden &lt;shane.boulden@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Spencer Shimko &lt;sshimko@tresys.com&gt;</dc:contributor>
+ <dc:contributor>Mark Shoger &lt;mshoger@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Thomas Sj&#xF6;gren &lt;konstruktoid@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Francisco Slavin &lt;fslavin@tresys.com&gt;</dc:contributor>
+ <dc:contributor>David Smith &lt;dsmith@eclipse.ncsc.mil&gt;</dc:contributor>
+ <dc:contributor>Kevin Spargur &lt;kspargur@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Kenneth Stailey &lt;kstailey.lists@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Leland Steinke &lt;leland.j.steinke.ctr@mail.mil&gt;</dc:contributor>
+ <dc:contributor>Justin Stephenson &lt;jstephen@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Brian Stinson &lt;brian@bstinson.com&gt;</dc:contributor>
+ <dc:contributor>Jake Stookey &lt;jakestookey@gmail.com&gt;</dc:contributor>
+ <dc:contributor>Jonathan Sturges &lt;jsturges@jsturges.remote.csb&gt;</dc:contributor>
+ <dc:contributor>Philippe Thierry &lt;phil@reseau-libre.net&gt;</dc:contributor>
+ <dc:contributor>Derek Thurston &lt;thegrit@gmail.com&gt;</dc:contributor>
+ <dc:contributor>tianzhenjia &lt;jiatianzhen@cmss.chinamobile.com&gt;</dc:contributor>
+ <dc:contributor>Paul Tittle &lt;ptittle@cmf.nrl.navy.mil&gt;</dc:contributor>
+ <dc:contributor>tomas.hudik &lt;tomas.hudik@embedit.cz&gt;</dc:contributor>
+ <dc:contributor>Jeb Trayer &lt;jeb.d.trayer@uscg.mil&gt;</dc:contributor>
+ <dc:contributor>Mat&#x11B;j T&#xFD;&#x10D; &lt;matyc@redhat.com&gt;</dc:contributor>
+ <dc:contributor>VadimDor &lt;29509093+VadimDor@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Shawn Wells &lt;shawn@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Daniel E. White &lt;linuxdan@users.noreply.github.com&gt;</dc:contributor>
+ <dc:contributor>Roy Williams &lt;roywilli@roywilli.redhat.com&gt;</dc:contributor>
+ <dc:contributor>Rob Wilmoth &lt;rwilmoth@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Lucas Yamanishi &lt;lucas.yamanishi@onyxpoint.com&gt;</dc:contributor>
+ <dc:contributor>Xirui Yang &lt;xirui.yang@oracle.com&gt;</dc:contributor>
+ <dc:contributor>Kevin Zimmerman &lt;kevin.zimmerman@kitware.com&gt;</dc:contributor>
+ <dc:contributor>Jan &#x10C;ern&#xFD; &lt;jcerny@redhat.com&gt;</dc:contributor>
+ <dc:contributor>Michal &#x160;ruba&#x159; &lt;msrubar@redhat.com&gt;</dc:contributor>
+ <dc:source>https://github.com/OpenSCAP/scap-security-guide/releases/latest</dc:source>
+ </ns9:metadata>
+ <ns9:model system="urn:xccdf:scoring:default"/>
+ <ns9:Profile id="xccdf_org.ssgproject.content_profile_stig">
+ <ns9:title override="true" xml:lang="en-US">Upstream Firefox STIG</ns9:title>
+ <ns9:description override="true" xml:lang="en-US">This profile is developed under the DoD consensus model and DISA FSO Vendor STIG process,
+serving as the upstream development environment for the Firefox STIG.
+
+As a result of the upstream/downstream relationship between the SCAP Security Guide project
+and the official DISA FSO STIG baseline, users should expect variance between SSG and DISA FSO content.
+For official DISA FSO STIG content, refer to https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance.
+
+While this profile is packaged by Red Hat as part of the SCAP Security Guide package, please note
+that commercial support of this SCAP content is NOT available. This profile is provided as example
+SCAP content with no endorsement for suitability or production readiness. Support for this
+profile is provided by the upstream SCAP Security Guide community on a best-effort basis. The
+upstream project homepage is https://www.open-scap.org/security-policies/scap-security-guide/.</ns9:description>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-dod_root_certificate_installed" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-enable_ca_trust" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-addons_plugin_updates" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-auto-download_actions" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-autofill_forms" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-autofill_passwords" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-auto-update_of_firefox" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-cookies_clear" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-cookies_user_notice" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-lock_settings_obscure" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-lock_settings_config_file" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-open_confirmation" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-password_store" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-search_update" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-shell_protocol" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-ssl_version_2" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-ssl_protocol_tls" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-verification" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-ssl_version_3" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-home_page" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_installed_firefox_version_supported" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_status_bar_text" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_context_menus" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_status_bar_changes" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_window_resizing" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_window_changes" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-non-secure_page_warning" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_rule_firefox_preferences-pop-up_windows" selected="true"/>
+ <ns9:select idref="xccdf_org.ssgproject.content_group_remediation_functions" selected="false"/>
+ <ns9:refine-value idref="xccdf_org.ssgproject.content_value_var_default_home_page" selector="about_blank"/>
+ </ns9:Profile>
+ <ns9:Group id="xccdf_org.ssgproject.content_group_remediation_functions">
+ <ns9:title xml:lang="en-US">Remediation functions used by the SCAP Security Guide Project</ns9:title>
+ <ns9:description xml:lang="en-US">XCCDF form of the various remediation functions as used by remediation scripts from the SCAP Security Guide Project.</ns9:description>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_include_merge_files_by_lines" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function include_merge_files_by_lines</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value>function include_merge_files_by_lines {
+ :
+}
+
+# 1: Filename of the "master" file
+# 2: Filename of the newly created file
+function create_empty_file_like {
+ local lines_count
+ lines_count=$(cat "$1" | wc -l)
+ for _ in $(seq 1 "$lines_count"); do
+ printf '\n' &gt;&gt; "$2"
+ done
+}
+
+
+# 1: Filename of the "master" file
+# 2: Filename of sample flie
+function second_file_is_same_except_newlines {
+ local lines_of_master lines_of_sample len_of_master line_number i
+ readarray -t lines_of_master &lt; "$1"
+ readarray -t lines_of_sample &lt; "$2"
+
+ len_of_master="${#lines_of_master[@]}"
+ if test "$len_of_master" != "${#lines_of_sample[@]}"; then
+ echo "Files '$1' and '$2' have different number of lines, $len_of_master and ${#lines_of_sample[@]} respectively."
+ return 1
+ fi
+
+ for line_number in $(seq 1 "$len_of_master"); do
+ i=$((line_number - 1))
+ test -n "${lines_of_sample[$i]}" || continue
+ if test "${lines_of_master[$i]}" != "${lines_of_sample[$i]}"; then
+ echo "Line $line_number is different in files '$1' and '$2'."
+ return 1
+ fi
+ done
+}
+
+
+# 1: Filename of the "master" file
+# 2: Filename of sample flie
+# 3: List of indices (1-based, space-separated string)
+function merge_first_lines_to_second_on_indices {
+ local lines_of_master lines_of_sample line_number i
+ test -f "$2" || create_empty_file_like "$1" "$2"
+
+ readarray -t lines_of_master &lt; "$1"
+ readarray -t lines_of_sample &lt; "$2"
+
+ error_msg="$(second_file_is_same_except_newlines "$1" "$2")"
+ if test $? != 0; then
+ echo "Error merging lines into '$2': $error_msg" &gt;&amp;2
+ return 1
+ fi
+
+ for line_number in $3; do
+ i=$((line_number - 1))
+ lines_of_sample[$i]="${lines_of_master[$i]}"
+ done
+
+ printf "%s\n" "${lines_of_sample[@]}" &gt; "$2"
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_perform_audit_adjtimex_settimeofday_stime_remediation" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function perform_audit_adjtimex_settimeofday_stime_remediation</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value># Function to fix syscall audit rule for given system call. It is
+# based on example audit syscall rule definitions as outlined in
+# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
+# package. It will combine multiple system calls belonging to the same
+# syscall group into one audit rule (rather than to create audit rule per
+# different system call) to avoid audit infrastructure performance penalty
+# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
+#
+# https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
+#
+# for further details.
+#
+# Expects five arguments (each of them is required) in the form of:
+# * audit tool tool used to load audit rules,
+# either 'auditctl', or 'augenrules
+# * audit rules' pattern audit rule skeleton for same syscall
+# * syscall group greatest common string this rule shares
+# with other rules from the same group
+# * architecture architecture this rule is intended for
+# * full form of new rule to add expected full form of audit rule as to be
+# added into audit.rules file
+#
+# Note: The 2-th up to 4-th arguments are used to determine how many existing
+# audit rules will be inspected for resemblance with the new audit rule
+# (5-th argument) the function is going to add. The rule's similarity check
+# is performed to optimize audit.rules definition (merge syscalls of the same
+# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
+# penalty.
+#
+# Example call:
+#
+# See e.g. 'audit_rules_file_deletion_events.sh' remediation script
+#
+function fix_audit_syscall_rule {
+
+# Load function arguments into local variables
+local tool="$1"
+local pattern="$2"
+local group="$3"
+local arch="$4"
+local full_rule="$5"
+
+# Check sanity of the input
+if [ $# -ne "5" ]
+then
+ echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
+ echo "Aborting."
+ exit 1
+fi
+
+# Create a list of audit *.rules files that should be inspected for presence and correctness
+# of a particular audit rule. The scheme is as follows:
+#
+# -----------------------------------------------------------------------------------------
+# Tool used to load audit rules | Rule already defined | Audit rules file to inspect |
+# -----------------------------------------------------------------------------------------
+# auditctl | Doesn't matter | /etc/audit/audit.rules |
+# -----------------------------------------------------------------------------------------
+# augenrules | Yes | /etc/audit/rules.d/*.rules |
+# augenrules | No | /etc/audit/rules.d/$key.rules |
+# -----------------------------------------------------------------------------------------
+#
+declare -a files_to_inspect
+
+retval=0
+
+# First check sanity of the specified audit tool
+if [ "$tool" != 'auditctl' ] &amp;&amp; [ "$tool" != 'augenrules' ]
+then
+ echo "Unknown audit rules loading tool: $1. Aborting."
+ echo "Use either 'auditctl' or 'augenrules'!"
+ return 1
+# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
+# file to the list of files to be inspected
+elif [ "$tool" == 'auditctl' ]
+then
+ files_to_inspect+=('/etc/audit/audit.rules' )
+# If audit tool is 'augenrules', then check if the audit rule is defined
+# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
+# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
+elif [ "$tool" == 'augenrules' ]
+then
+ # Extract audit $key from audit rule so we can use it later
+ key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
+ readarray -t matches &lt; &lt;(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+ for match in "${matches[@]}"
+ do
+ files_to_inspect+=("${match}")
+ done
+ # Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
+ if [ ${#files_to_inspect[@]} -eq "0" ]
+ then
+ file_to_inspect="/etc/audit/rules.d/$key.rules"
+ files_to_inspect=("$file_to_inspect")
+ if [ ! -e "$file_to_inspect" ]
+ then
+ touch "$file_to_inspect"
+ chmod 0640 "$file_to_inspect"
+ fi
+ fi
+fi
+
+#
+# Indicator that we want to append $full_rule into $audit_file by default
+local append_expected_rule=0
+
+for audit_file in "${files_to_inspect[@]}"
+do
+ # Filter existing $audit_file rules' definitions to select those that:
+ # * follow the rule pattern, and
+ # * meet the hardware architecture requirement, and
+ # * are current syscall group specific
+ readarray -t existing_rules &lt; &lt;(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d" "$audit_file")
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+
+ # Process rules found case-by-case
+ for rule in "${existing_rules[@]}"
+ do
+ # Found rule is for same arch &amp; key, but differs (e.g. in count of -S arguments)
+ if [ "${rule}" != "${full_rule}" ]
+ then
+ # If so, isolate just '(-S \w)+' substring of that rule
+ rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
+ # Check if list of '-S syscall' arguments of that rule is subset
+ # of '-S syscall' list of expected $full_rule
+ if grep -q -- "$rule_syscalls" &lt;&lt;&lt; "$full_rule"
+ then
+ # Rule is covered (i.e. the list of -S syscalls for this rule is
+ # subset of -S syscalls of $full_rule =&gt; existing rule can be deleted
+ # Thus delete the rule from audit.rules &amp; our array
+ sed -i -e "\;${rule};d" "$audit_file"
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+ existing_rules=("${existing_rules[@]//$rule/}")
+ else
+ # Rule isn't covered by $full_rule - it besides -S syscall arguments
+ # for this group contains also -S syscall arguments for other syscall
+ # group. Example: '-S lchown -S fchmod -S fchownat' =&gt; group='chown'
+ # since 'lchown' &amp; 'fchownat' share 'chown' substring
+ # Therefore:
+ # * 1) delete the original rule from audit.rules
+ # (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
+ # * 2) delete the -S syscall arguments for this syscall group, but
+ # keep those not belonging to this syscall group
+ # (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
+ # * 3) append the modified (filtered) rule again into audit.rules
+ # if the same rule not already present
+ #
+ # 1) Delete the original rule
+ sed -i -e "\;${rule};d" "$audit_file"
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+
+ # 2) Delete syscalls for this group, but keep those from other groups
+ # Convert current rule syscall's string into array splitting by '-S' delimiter
+ IFS_BKP="$IFS"
+ IFS=$'-S'
+ read -a rule_syscalls_as_array &lt;&lt;&lt; "$rule_syscalls"
+ # Reset IFS back to default
+ IFS="$IFS_BKP"
+ # Splitting by "-S" can't be replaced by the readarray functionality easily
+
+ # Declare new empty string to hold '-S syscall' arguments from other groups
+ new_syscalls_for_rule=''
+ # Walk through existing '-S syscall' arguments
+ for syscall_arg in "${rule_syscalls_as_array[@]}"
+ do
+ # Skip empty $syscall_arg values
+ if [ "$syscall_arg" == '' ]
+ then
+ continue
+ fi
+ # If the '-S syscall' doesn't belong to current group add it to the new list
+ # (together with adding '-S' delimiter back for each of such item found)
+ if grep -q -v -- "$group" &lt;&lt;&lt; "$syscall_arg"
+ then
+ new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
+ fi
+ done
+ # Replace original '-S syscall' list with the new one for this rule
+ updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
+ # Squeeze repeated whitespace characters in rule definition (if any) into one
+ updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
+ # 3) Append the modified / filtered rule again into audit.rules
+ # (but only in case it's not present yet to prevent duplicate definitions)
+ if ! grep -q -- "$updated_rule" "$audit_file"
+ then
+ echo "$updated_rule" &gt;&gt; "$audit_file"
+ fi
+ fi
+ else
+ # $audit_file already contains the expected rule form for this
+ # architecture &amp; key =&gt; don't insert it second time
+ append_expected_rule=1
+ fi
+ done
+
+ # We deleted all rules that were subset of the expected one for this arch &amp; key.
+ # Also isolated rules containing system calls not from this system calls group.
+ # Now append the expected rule if it's not present in $audit_file yet
+ if [[ ${append_expected_rule} -eq "0" ]]
+ then
+ echo "$full_rule" &gt;&gt; "$audit_file"
+ fi
+done
+
+return $retval
+
+}
+
+
+# Function to perform remediation for the 'adjtimex', 'settimeofday', and 'stime' audit
+# system calls on RHEL, Fedora or OL systems.
+# Remediation performed for both possible tools: 'auditctl' and 'augenrules'.
+#
+# Note: 'stime' system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
+# therefore excluded from the list of time group system calls to be audited on this arch
+#
+# Example Call:
+#
+# perform_audit_adjtimex_settimeofday_stime_remediation
+#
+function perform_audit_adjtimex_settimeofday_stime_remediation {
+
+# Retrieve hardware architecture of the underlying system
+[ "$(getconf LONG_BIT)" = "32" ] &amp;&amp; RULE_ARCHS=("b32") || RULE_ARCHS=("b32" "b64")
+
+for ARCH in "${RULE_ARCHS[@]}"
+do
+
+ PATTERN="-a always,exit -F arch=${ARCH} -S .* -k *"
+ # Create expected audit group and audit rule form for particular system call &amp; architecture
+ if [ ${ARCH} = "b32" ]
+ then
+ # stime system call is known at 32-bit arch (see e.g "$ ausyscall i386 stime" 's output)
+ # so append it to the list of time group system calls to be audited
+ GROUP="\(adjtimex\|settimeofday\|stime\)"
+ FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -S stime -k audit_time_rules"
+ elif [ ${ARCH} = "b64" ]
+ then
+ # stime system call isn't known at 64-bit arch (see "$ ausyscall x86_64 stime" 's output)
+ # therefore don't add it to the list of time group system calls to be audited
+ GROUP="\(adjtimex\|settimeofday\)"
+ FULL_RULE="-a always,exit -F arch=${ARCH} -S adjtimex -S settimeofday -k audit_time_rules"
+ fi
+ # Perform the remediation for both possible tools: 'auditctl' and 'augenrules'
+ fix_audit_syscall_rule "auditctl" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
+ fix_audit_syscall_rule "augenrules" "$PATTERN" "$GROUP" "$ARCH" "$FULL_RULE"
+done
+
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_fix_audit_watch_rule" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function fix_audit_watch_rule</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value># Function to fix audit file system object watch rule for given path:
+# * if rule exists, also verifies the -w bits match the requirements
+# * if rule doesn't exist yet, appends expected rule form to $files_to_inspect
+# audit rules file, depending on the tool which was used to load audit rules
+#
+# Expects four arguments (each of them is required) in the form of:
+# * audit tool tool used to load audit rules,
+# either 'auditctl', or 'augenrules'
+# * path value of -w audit rule's argument
+# * required access bits value of -p audit rule's argument
+# * key value of -k audit rule's argument
+#
+# Example call:
+#
+# fix_audit_watch_rule "auditctl" "/etc/localtime" "wa" "audit_time_rules"
+#
+function fix_audit_watch_rule {
+
+# Load function arguments into local variables
+local tool="$1"
+local path="$2"
+local required_access_bits="$3"
+local key="$4"
+
+# Check sanity of the input
+if [ $# -ne "4" ]
+then
+ echo "Usage: fix_audit_watch_rule 'tool' 'path' 'bits' 'key'"
+ echo "Aborting."
+ exit 1
+fi
+
+# Create a list of audit *.rules files that should be inspected for presence and correctness
+# of a particular audit rule. The scheme is as follows:
+#
+# -----------------------------------------------------------------------------------------
+# Tool used to load audit rules | Rule already defined | Audit rules file to inspect |
+# -----------------------------------------------------------------------------------------
+# auditctl | Doesn't matter | /etc/audit/audit.rules |
+# -----------------------------------------------------------------------------------------
+# augenrules | Yes | /etc/audit/rules.d/*.rules |
+# augenrules | No | /etc/audit/rules.d/$key.rules |
+# -----------------------------------------------------------------------------------------
+declare -a files_to_inspect
+files_to_inspect=()
+
+# Check sanity of the specified audit tool
+if [ "$tool" != 'auditctl' ] &amp;&amp; [ "$tool" != 'augenrules' ]
+then
+ echo "Unknown audit rules loading tool: $1. Aborting."
+ echo "Use either 'auditctl' or 'augenrules'!"
+ exit 1
+# If the audit tool is 'auditctl', then add '/etc/audit/audit.rules'
+# into the list of files to be inspected
+elif [ "$tool" == 'auditctl' ]
+then
+ files_to_inspect+=('/etc/audit/audit.rules')
+# If the audit is 'augenrules', then check if rule is already defined
+# If rule is defined, add '/etc/audit/rules.d/*.rules' to list of files for inspection.
+# If rule isn't defined, add '/etc/audit/rules.d/$key.rules' to list of files for inspection.
+elif [ "$tool" == 'augenrules' ]
+then
+ readarray -t matches &lt; &lt;(grep -P "[\s]*-w[\s]+$path" /etc/audit/rules.d/*.rules)
+
+ # For each of the matched entries
+ for match in "${matches[@]}"
+ do
+ # Extract filepath from the match
+ rulesd_audit_file=$(echo $match | cut -f1 -d ':')
+ # Append that path into list of files for inspection
+ files_to_inspect+=("$rulesd_audit_file")
+ done
+ # Case when particular audit rule isn't defined yet
+ if [ "${#files_to_inspect[@]}" -eq "0" ]
+ then
+ # Append '/etc/audit/rules.d/$key.rules' into list of files for inspection
+ local key_rule_file="/etc/audit/rules.d/$key.rules"
+ # If the $key.rules file doesn't exist yet, create it with correct permissions
+ if [ ! -e "$key_rule_file" ]
+ then
+ touch "$key_rule_file"
+ chmod 0640 "$key_rule_file"
+ fi
+
+ files_to_inspect+=("$key_rule_file")
+ fi
+fi
+
+# Finally perform the inspection and possible subsequent audit rule
+# correction for each of the files previously identified for inspection
+for audit_rules_file in "${files_to_inspect[@]}"
+do
+
+ # Check if audit watch file system object rule for given path already present
+ if grep -q -P -- "[\s]*-w[\s]+$path" "$audit_rules_file"
+ then
+ # Rule is found =&gt; verify yet if existing rule definition contains
+ # all of the required access type bits
+
+ # Escape slashes in path for use in sed pattern below
+ local esc_path=${path//$'/'/$'\/'}
+ # Define BRE whitespace class shortcut
+ local sp="[[:space:]]"
+ # Extract current permission access types (e.g. -p [r|w|x|a] values) from audit rule
+ current_access_bits=$(sed -ne "s/$sp*-w$sp\+$esc_path$sp\+-p$sp\+\([rxwa]\{1,4\}\).*/\1/p" "$audit_rules_file")
+ # Split required access bits string into characters array
+ # (to check bit's presence for one bit at a time)
+ for access_bit in $(echo "$required_access_bits" | grep -o .)
+ do
+ # For each from the required access bits (e.g. 'w', 'a') check
+ # if they are already present in current access bits for rule.
+ # If not, append that bit at the end
+ if ! grep -q "$access_bit" &lt;&lt;&lt; "$current_access_bits"
+ then
+ # Concatenate the existing mask with the missing bit
+ current_access_bits="$current_access_bits$access_bit"
+ fi
+ done
+ # Propagate the updated rule's access bits (original + the required
+ # ones) back into the /etc/audit/audit.rules file for that rule
+ sed -i "s/\($sp*-w$sp\+$esc_path$sp\+-p$sp\+\)\([rxwa]\{1,4\}\)\(.*\)/\1$current_access_bits\3/" "$audit_rules_file"
+ else
+ # Rule isn't present yet. Append it at the end of $audit_rules_file file
+ # with proper key
+
+ echo "-w $path -p $required_access_bits -k $key" &gt;&gt; "$audit_rules_file"
+ fi
+done
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_set_faillock_option_to_value_in_pam_file" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function set_faillock_option_to_value_in_pam_file</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value>function set_faillock_option_to_value_in_pam_file {
+ # If invoked with no arguments, exit. This is an intentional behavior.
+ [ $# -gt 1 ] || return 0
+ [ $# -ge 3 ] || die "$0 requires exactly zero, three, or four arguments"
+ [ $# -le 4 ] || die "$0 requires exactly zero, three, or four arguments"
+ local _pamFile="$1" _option="$2" _value="$3" _insert_lines_callback="$4"
+ # pam_faillock.so already present?
+ if grep -q "^auth.*pam_faillock.so.*" "$_pamFile"; then
+
+ # pam_faillock.so present, is the option present?
+ if grep -q "^auth.*[default=die].*pam_faillock.so.*authfail.*$_option=" "$_pamFile"; then
+
+ # both pam_faillock.so &amp; option present, just correct option to the right value
+ sed -i --follow-symlinks "s/\(^auth.*required.*pam_faillock.so.*preauth.*silent.*\)\($_option *= *\).*/\1\2$_value/" "$_pamFile"
+ sed -i --follow-symlinks "s/\(^auth.*[default=die].*pam_faillock.so.*authfail.*\)\($_option *= *\).*/\1\2$_value/" "$_pamFile"
+
+ # pam_faillock.so present, but the option not yet
+ else
+
+ # append correct option value to appropriate places
+ sed -i --follow-symlinks "/^auth.*required.*pam_faillock.so.*preauth.*silent.*/ s/$/ $_option=$_value/" "$_pamFile"
+ sed -i --follow-symlinks "/^auth.*[default=die].*pam_faillock.so.*authfail.*/ s/$/ $_option=$_value/" "$_pamFile"
+ fi
+
+ # pam_faillock.so not present yet
+ else
+ test -z "$_insert_lines_callback" || "$_insert_lines_callback" "$_option" "$_value" "$_pamFile"
+ # insert pam_faillock.so preauth &amp; authfail rows with proper value of the option in question
+ fi
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_create_audit_remediation_unsuccessful_file_modification_detailed" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function create_audit_remediation_unsuccessful_file_modification_detailed</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value>function create_audit_remediation_unsuccessful_file_modification_detailed {
+ mkdir -p "$(dirname "$1")"
+ # The - option to mark a here document limit string (&lt;&lt;-EOF) suppresses leading tabs (but not spaces) in the output.
+ cat &lt;&lt;-EOF &gt; "$1"
+ ## This content is a section of an Audit config snapshot recommended for RHEL8 sytems that target OSPP compliance.
+ ## The following content has been retreived on 2019-03-11 from: https://github.com/linux-audit/audit-userspace/blob/master/rules/30-ospp-v42.rules
+
+ ## The purpose of these rules is to meet the requirements for Operating
+ ## System Protection Profile (OSPP)v4.2. These rules depends on having
+ ## 10-base-config.rules, 11-loginuid.rules, and 43-module-load.rules installed.
+
+ ## Unsuccessful file creation (open with O_CREAT)
+ -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&amp;0100 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&amp;0100 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b32 -S open -F a1&amp;0100 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b64 -S open -F a1&amp;0100 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&amp;0100 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&amp;0100 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b32 -S open -F a1&amp;0100 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b64 -S open -F a1&amp;0100 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b32 -S creat -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b64 -S creat -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b32 -S creat -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+ -a always,exit -F arch=b64 -S creat -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-create
+
+ ## Unsuccessful file modifications (open for write or truncate)
+ -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&amp;01003 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&amp;01003 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b32 -S open -F a1&amp;01003 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b64 -S open -F a1&amp;01003 -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b32 -S openat,open_by_handle_at -F a2&amp;01003 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b64 -S openat,open_by_handle_at -F a2&amp;01003 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b32 -S open -F a1&amp;01003 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b64 -S open -F a1&amp;01003 -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b32 -S truncate,ftruncate -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+ -a always,exit -F arch=b64 -S truncate,ftruncate -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-modification
+
+ ## Unsuccessful file access (any other opens) This has to go last.
+ -a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-access
+ -a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EACCES -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-access
+ -a always,exit -F arch=b32 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-access
+ -a always,exit -F arch=b64 -S open,creat,truncate,ftruncate,openat,open_by_handle_at -F exit=-EPERM -F auid&gt;=1000 -F auid!=unset -F key=unsuccesful-access
+ EOF
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_perform_audit_rules_privileged_commands_remediation" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function perform_audit_rules_privileged_commands_remediation</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value># Function to perform remediation for 'audit_rules_privileged_commands' rule
+#
+# Expects two arguments:
+#
+# audit_tool tool used to load audit rules
+# One of 'auditctl' or 'augenrules'
+#
+# min_auid Minimum original ID the user logged in with
+# '500' for RHEL-6 and before, '1000' for RHEL-7 and after.
+#
+# Example Call(s):
+#
+# perform_audit_rules_privileged_commands_remediation "auditctl" "500"
+# perform_audit_rules_privileged_commands_remediation "augenrules" "1000"
+#
+function perform_audit_rules_privileged_commands_remediation {
+#
+# Load function arguments into local variables
+local tool="$1"
+local min_auid="$2"
+
+# Check sanity of the input
+if [ $# -ne "2" ]
+then
+ echo "Usage: perform_audit_rules_privileged_commands_remediation 'auditctl | augenrules' '500 | 1000'"
+ echo "Aborting."
+ exit 1
+fi
+
+declare -a files_to_inspect=()
+
+# Check sanity of the specified audit tool
+if [ "$tool" != 'auditctl' ] &amp;&amp; [ "$tool" != 'augenrules' ]
+then
+ echo "Unknown audit rules loading tool: $1. Aborting."
+ echo "Use either 'auditctl' or 'augenrules'!"
+ exit 1
+# If the audit tool is 'auditctl', then:
+# * add '/etc/audit/audit.rules'to the list of files to be inspected,
+# * specify '/etc/audit/audit.rules' as the output audit file, where
+# missing rules should be inserted
+elif [ "$tool" == 'auditctl' ]
+then
+ files_to_inspect=("/etc/audit/audit.rules")
+ output_audit_file="/etc/audit/audit.rules"
+#
+# If the audit tool is 'augenrules', then:
+# * add '/etc/audit/rules.d/*.rules' to the list of files to be inspected
+# (split by newline),
+# * specify /etc/audit/rules.d/privileged.rules' as the output file, where
+# missing rules should be inserted
+elif [ "$tool" == 'augenrules' ]
+then
+ readarray -t files_to_inspect &lt; &lt;(find /etc/audit/rules.d -maxdepth 1 -type f -name '*.rules' -print)
+ output_audit_file="/etc/audit/rules.d/privileged.rules"
+fi
+
+# Obtain the list of SUID/SGID binaries on the particular system (split by newline)
+# into privileged_binaries array
+readarray -t privileged_binaries &lt; &lt;(find / -xdev -type f -perm -4000 -o -type f -perm -2000 2&gt;/dev/null)
+
+# Keep list of SUID/SGID binaries that have been already handled within some previous iteration
+declare -a sbinaries_to_skip=()
+
+# For each found sbinary in privileged_binaries list
+for sbinary in "${privileged_binaries[@]}"
+do
+
+ # Check if this sbinary wasn't already handled in some of the previous sbinary iterations
+ # Return match only if whole sbinary definition matched (not in the case just prefix matched!!!)
+ if [[ $(sed -ne "\|${sbinary}|p" &lt;&lt;&lt; "${sbinaries_to_skip[*]}") ]]
+ then
+ # If so, don't process it second time &amp; go to process next sbinary
+ continue
+ fi
+
+ # Reset the counter of inspected files when starting to check
+ # presence of existing audit rule for new sbinary
+ local count_of_inspected_files=0
+
+ # Define expected rule form for this binary
+ expected_rule="-a always,exit -F path=${sbinary} -F perm=x -F auid&gt;=${min_auid} -F auid!=unset -k privileged"
+
+ # If list of audit rules files to be inspected is empty, just add new rule and move on to next binary
+ if [[ ${#files_to_inspect[@]} -eq 0 ]]; then
+ echo "$expected_rule" &gt;&gt; "$output_audit_file"
+ continue
+ fi
+
+ # Replace possible slash '/' character in sbinary definition so we could use it in sed expressions below
+ sbinary_esc=${sbinary//$'/'/$'\/'}
+
+ # For each audit rules file from the list of files to be inspected
+ for afile in "${files_to_inspect[@]}"
+ do
+
+ # Search current audit rules file's content for match. Match criteria:
+ # * existing rule is for the same SUID/SGID binary we are currently processing (but
+ # can contain multiple -F path= elements covering multiple SUID/SGID binaries)
+ # * existing rule contains all arguments from expected rule form (though can contain
+ # them in arbitrary order)
+
+ base_search=$(sed -e '/-a always,exit/!d' -e '/-F path='"${sbinary_esc}"'/!d' \
+ -e '/-F path=[^[:space:]]\+/!d' -e '/-F perm=.*/!d' \
+ -e '/-F auid&gt;='"${min_auid}"'/!d' -e '/-F auid!=\(4294967295\|unset\)/!d' \
+ -e '/-k \|-F key=/!d' "$afile")
+
+ # Increase the count of inspected files for this sbinary
+ count_of_inspected_files=$((count_of_inspected_files + 1))
+
+ # Require execute access type to be set for existing audit rule
+ exec_access='x'
+
+ # Search current audit rules file's content for presence of rule pattern for this sbinary
+ if [[ $base_search ]]
+ then
+
+ # Current audit rules file already contains rule for this binary =&gt;
+ # Store the exact form of found rule for this binary for further processing
+ concrete_rule=$base_search
+
+ # Select all other SUID/SGID binaries possibly also present in the found rule
+
+ readarray -t handled_sbinaries &lt; &lt;(grep -o -e "-F path=[^[:space:]]\+" &lt;&lt;&lt; "$concrete_rule")
+ handled_sbinaries=("${handled_sbinaries[@]//-F path=/}")
+
+ # Merge the list of such SUID/SGID binaries found in this iteration with global list ignoring duplicates
+ readarray -t sbinaries_to_skip &lt; &lt;(for i in "${sbinaries_to_skip[@]}" "${handled_sbinaries[@]}"; do echo "$i"; done | sort -du)
+
+ # Separate concrete_rule into three sections using hash '#'
+ # sign as a delimiter around rule's permission section borders
+ concrete_rule="$(echo "$concrete_rule" | sed -n "s/\(.*\)\+\(-F perm=[rwax]\+\)\+/\1#\2#/p")"
+
+ # Split concrete_rule into head, perm, and tail sections using hash '#' delimiter
+
+ rule_head=$(cut -d '#' -f 1 &lt;&lt;&lt; "$concrete_rule")
+ rule_perm=$(cut -d '#' -f 2 &lt;&lt;&lt; "$concrete_rule")
+ rule_tail=$(cut -d '#' -f 3 &lt;&lt;&lt; "$concrete_rule")
+
+ # Extract already present exact access type [r|w|x|a] from rule's permission section
+ access_type=${rule_perm//-F perm=/}
+
+ # Verify current permission access type(s) for rule contain 'x' (execute) permission
+ if ! grep -q "$exec_access" &lt;&lt;&lt; "$access_type"
+ then
+
+ # If not, append the 'x' (execute) permission to the existing access type bits
+ access_type="$access_type$exec_access"
+ # Reconstruct the permissions section for the rule
+ new_rule_perm="-F perm=$access_type"
+ # Update existing rule in current audit rules file with the new permission section
+ sed -i "s#${rule_head}\(.*\)${rule_tail}#${rule_head}${new_rule_perm}${rule_tail}#" "$afile"
+
+ fi
+
+ # If the required audit rule for particular sbinary wasn't found yet, insert it under following conditions:
+ #
+ # * in the "auditctl" mode of operation insert particular rule each time
+ # (because in this mode there's only one file -- /etc/audit/audit.rules to be inspected for presence of this rule),
+ #
+ # * in the "augenrules" mode of operation insert particular rule only once and only in case we have already
+ # searched all of the files from /etc/audit/rules.d/*.rules location (since that audit rule can be defined
+ # in any of those files and if not, we want it to be inserted only once into /etc/audit/rules.d/privileged.rules file)
+ #
+ elif [ "$tool" == "auditctl" ] || [[ "$tool" == "augenrules" &amp;&amp; $count_of_inspected_files -eq "${#files_to_inspect[@]}" ]]
+ then
+
+ # Check if this sbinary wasn't already handled in some of the previous afile iterations
+ # Return match only if whole sbinary definition matched (not in the case just prefix matched!!!)
+ if [[ ! $(sed -ne "\|${sbinary}|p" &lt;&lt;&lt; "${sbinaries_to_skip[*]}") ]]
+ then
+ # Current audit rules file's content doesn't contain expected rule for this
+ # SUID/SGID binary yet =&gt; append it
+ echo "$expected_rule" &gt;&gt; "$output_audit_file"
+ fi
+
+ continue
+ fi
+
+ done
+
+done
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_fix_audit_syscall_rule" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function fix_audit_syscall_rule</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value># Function to fix syscall audit rule for given system call. It is
+# based on example audit syscall rule definitions as outlined in
+# /usr/share/doc/audit-2.3.7/stig.rules file provided with the audit
+# package. It will combine multiple system calls belonging to the same
+# syscall group into one audit rule (rather than to create audit rule per
+# different system call) to avoid audit infrastructure performance penalty
+# in the case of 'one-audit-rule-definition-per-one-system-call'. See:
+#
+# https://www.redhat.com/archives/linux-audit/2014-November/msg00009.html
+#
+# for further details.
+#
+# Expects five arguments (each of them is required) in the form of:
+# * audit tool tool used to load audit rules,
+# either 'auditctl', or 'augenrules
+# * audit rules' pattern audit rule skeleton for same syscall
+# * syscall group greatest common string this rule shares
+# with other rules from the same group
+# * architecture architecture this rule is intended for
+# * full form of new rule to add expected full form of audit rule as to be
+# added into audit.rules file
+#
+# Note: The 2-th up to 4-th arguments are used to determine how many existing
+# audit rules will be inspected for resemblance with the new audit rule
+# (5-th argument) the function is going to add. The rule's similarity check
+# is performed to optimize audit.rules definition (merge syscalls of the same
+# group into one rule) to avoid the "single-syscall-per-audit-rule" performance
+# penalty.
+#
+# Example call:
+#
+# See e.g. 'audit_rules_file_deletion_events.sh' remediation script
+#
+function fix_audit_syscall_rule {
+
+# Load function arguments into local variables
+local tool="$1"
+local pattern="$2"
+local group="$3"
+local arch="$4"
+local full_rule="$5"
+
+# Check sanity of the input
+if [ $# -ne "5" ]
+then
+ echo "Usage: fix_audit_syscall_rule 'tool' 'pattern' 'group' 'arch' 'full rule'"
+ echo "Aborting."
+ exit 1
+fi
+
+# Create a list of audit *.rules files that should be inspected for presence and correctness
+# of a particular audit rule. The scheme is as follows:
+#
+# -----------------------------------------------------------------------------------------
+# Tool used to load audit rules | Rule already defined | Audit rules file to inspect |
+# -----------------------------------------------------------------------------------------
+# auditctl | Doesn't matter | /etc/audit/audit.rules |
+# -----------------------------------------------------------------------------------------
+# augenrules | Yes | /etc/audit/rules.d/*.rules |
+# augenrules | No | /etc/audit/rules.d/$key.rules |
+# -----------------------------------------------------------------------------------------
+#
+declare -a files_to_inspect
+
+retval=0
+
+# First check sanity of the specified audit tool
+if [ "$tool" != 'auditctl' ] &amp;&amp; [ "$tool" != 'augenrules' ]
+then
+ echo "Unknown audit rules loading tool: $1. Aborting."
+ echo "Use either 'auditctl' or 'augenrules'!"
+ return 1
+# If audit tool is 'auditctl', then add '/etc/audit/audit.rules'
+# file to the list of files to be inspected
+elif [ "$tool" == 'auditctl' ]
+then
+ files_to_inspect+=('/etc/audit/audit.rules' )
+# If audit tool is 'augenrules', then check if the audit rule is defined
+# If rule is defined, add '/etc/audit/rules.d/*.rules' to the list for inspection
+# If rule isn't defined yet, add '/etc/audit/rules.d/$key.rules' to the list for inspection
+elif [ "$tool" == 'augenrules' ]
+then
+ # Extract audit $key from audit rule so we can use it later
+ key=$(expr "$full_rule" : '.*-k[[:space:]]\([^[:space:]]\+\)' '|' "$full_rule" : '.*-F[[:space:]]key=\([^[:space:]]\+\)')
+ readarray -t matches &lt; &lt;(sed -s -n -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d;F" /etc/audit/rules.d/*.rules)
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+ for match in "${matches[@]}"
+ do
+ files_to_inspect+=("${match}")
+ done
+ # Case when particular rule isn't defined in /etc/audit/rules.d/*.rules yet
+ if [ ${#files_to_inspect[@]} -eq "0" ]
+ then
+ file_to_inspect="/etc/audit/rules.d/$key.rules"
+ files_to_inspect=("$file_to_inspect")
+ if [ ! -e "$file_to_inspect" ]
+ then
+ touch "$file_to_inspect"
+ chmod 0640 "$file_to_inspect"
+ fi
+ fi
+fi
+
+#
+# Indicator that we want to append $full_rule into $audit_file by default
+local append_expected_rule=0
+
+for audit_file in "${files_to_inspect[@]}"
+do
+ # Filter existing $audit_file rules' definitions to select those that:
+ # * follow the rule pattern, and
+ # * meet the hardware architecture requirement, and
+ # * are current syscall group specific
+ readarray -t existing_rules &lt; &lt;(sed -e "\;${pattern};!d" -e "/${arch}/!d" -e "/${group}/!d" "$audit_file")
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+
+ # Process rules found case-by-case
+ for rule in "${existing_rules[@]}"
+ do
+ # Found rule is for same arch &amp; key, but differs (e.g. in count of -S arguments)
+ if [ "${rule}" != "${full_rule}" ]
+ then
+ # If so, isolate just '(-S \w)+' substring of that rule
+ rule_syscalls=$(echo "$rule" | grep -o -P '(-S \w+ )+')
+ # Check if list of '-S syscall' arguments of that rule is subset
+ # of '-S syscall' list of expected $full_rule
+ if grep -q -- "$rule_syscalls" &lt;&lt;&lt; "$full_rule"
+ then
+ # Rule is covered (i.e. the list of -S syscalls for this rule is
+ # subset of -S syscalls of $full_rule =&gt; existing rule can be deleted
+ # Thus delete the rule from audit.rules &amp; our array
+ sed -i -e "\;${rule};d" "$audit_file"
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+ existing_rules=("${existing_rules[@]//$rule/}")
+ else
+ # Rule isn't covered by $full_rule - it besides -S syscall arguments
+ # for this group contains also -S syscall arguments for other syscall
+ # group. Example: '-S lchown -S fchmod -S fchownat' =&gt; group='chown'
+ # since 'lchown' &amp; 'fchownat' share 'chown' substring
+ # Therefore:
+ # * 1) delete the original rule from audit.rules
+ # (original '-S lchown -S fchmod -S fchownat' rule would be deleted)
+ # * 2) delete the -S syscall arguments for this syscall group, but
+ # keep those not belonging to this syscall group
+ # (original '-S lchown -S fchmod -S fchownat' would become '-S fchmod'
+ # * 3) append the modified (filtered) rule again into audit.rules
+ # if the same rule not already present
+ #
+ # 1) Delete the original rule
+ sed -i -e "\;${rule};d" "$audit_file"
+ if [ $? -ne 0 ]
+ then
+ retval=1
+ fi
+
+ # 2) Delete syscalls for this group, but keep those from other groups
+ # Convert current rule syscall's string into array splitting by '-S' delimiter
+ IFS_BKP="$IFS"
+ IFS=$'-S'
+ read -a rule_syscalls_as_array &lt;&lt;&lt; "$rule_syscalls"
+ # Reset IFS back to default
+ IFS="$IFS_BKP"
+ # Splitting by "-S" can't be replaced by the readarray functionality easily
+
+ # Declare new empty string to hold '-S syscall' arguments from other groups
+ new_syscalls_for_rule=''
+ # Walk through existing '-S syscall' arguments
+ for syscall_arg in "${rule_syscalls_as_array[@]}"
+ do
+ # Skip empty $syscall_arg values
+ if [ "$syscall_arg" == '' ]
+ then
+ continue
+ fi
+ # If the '-S syscall' doesn't belong to current group add it to the new list
+ # (together with adding '-S' delimiter back for each of such item found)
+ if grep -q -v -- "$group" &lt;&lt;&lt; "$syscall_arg"
+ then
+ new_syscalls_for_rule="$new_syscalls_for_rule -S $syscall_arg"
+ fi
+ done
+ # Replace original '-S syscall' list with the new one for this rule
+ updated_rule=${rule//$rule_syscalls/$new_syscalls_for_rule}
+ # Squeeze repeated whitespace characters in rule definition (if any) into one
+ updated_rule=$(echo "$updated_rule" | tr -s '[:space:]')
+ # 3) Append the modified / filtered rule again into audit.rules
+ # (but only in case it's not present yet to prevent duplicate definitions)
+ if ! grep -q -- "$updated_rule" "$audit_file"
+ then
+ echo "$updated_rule" &gt;&gt; "$audit_file"
+ fi
+ fi
+ else
+ # $audit_file already contains the expected rule form for this
+ # architecture &amp; key =&gt; don't insert it second time
+ append_expected_rule=1
+ fi
+ done
+
+ # We deleted all rules that were subset of the expected one for this arch &amp; key.
+ # Also isolated rules containing system calls not from this system calls group.
+ # Now append the expected rule if it's not present in $audit_file yet
+ if [[ ${append_expected_rule} -eq "0" ]]
+ then
+ echo "$full_rule" &gt;&gt; "$audit_file"
+ fi
+done
+
+return $retval
+
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_populate" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function populate</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value># The populate function isn't directly used by SSG at the moment but it can be
+# used for testing purposes and will be used in SSG Testsuite in the future.
+
+function populate {
+# code to populate environment variables needed (for unit testing)
+if [ -z "${!1}" ]; then
+ echo "$1 is not defined. Exiting."
+ exit
+fi
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_include_mount_options_functions" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function include_mount_options_functions</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value>function include_mount_options_functions {
+ :
+}
+
+# $1: type of filesystem
+# $2: new mount point option
+# $3: filesystem of new mount point (used when adding new entry in fstab)
+# $4: mount type of new mount point (used when adding new entry in fstab)
+function ensure_mount_option_for_vfstype {
+ local _vfstype="$1" _new_opt="$2" _filesystem=$3 _type=$4 _vfstype_points=()
+ readarray -t _vfstype_points &lt; &lt;(grep -E "[[:space:]]${_vfstype}[[:space:]]" /etc/fstab | awk '{print $2}')
+
+ for _vfstype_point in "${_vfstype_points[@]}"
+ do
+ ensure_mount_option_in_fstab "$_vfstype_point" "$_new_opt" "$_filesystem" "$_type"
+ done
+}
+
+# $1: mount point
+# $2: new mount point option
+# $3: device or virtual string (used when adding new entry in fstab)
+# $4: mount type of mount point (used when adding new entry in fstab)
+function ensure_mount_option_in_fstab {
+ local _mount_point="$1" _new_opt="$2" _device=$3 _type=$4
+ local _mount_point_match_regexp="" _previous_mount_opts=""
+ _mount_point_match_regexp="$(get_mount_point_regexp "$_mount_point")"
+
+ if [ "$(grep -c "$_mount_point_match_regexp" /etc/fstab)" -eq 0 ]; then
+ # runtime opts without some automatic kernel/userspace-added defaults
+ _previous_mount_opts=$(grep "$_mount_point_match_regexp" /etc/mtab | head -1 | awk '{print $4}' \
+ | sed -E "s/(rw|defaults|seclabel|${_new_opt})(,|$)//g;s/,$//")
+ [ "$_previous_mount_opts" ] &amp;&amp; _previous_mount_opts+=","
+ echo "${_device} ${_mount_point} ${_type} defaults,${_previous_mount_opts}${_new_opt} 0 0" &gt;&gt; /etc/fstab
+ elif [ "$(grep "$_mount_point_match_regexp" /etc/fstab | grep -c "$_new_opt")" -eq 0 ]; then
+ _previous_mount_opts=$(grep "$_mount_point_match_regexp" /etc/fstab | awk '{print $4}')
+ sed -i "s|\(${_mount_point_match_regexp}.*${_previous_mount_opts}\)|\1,${_new_opt}|" /etc/fstab
+ fi
+}
+
+# $1: mount point
+function get_mount_point_regexp {
+ printf "[[:space:]]%s[[:space:]]" "$1"
+}
+
+# $1: mount point
+function assert_mount_point_in_fstab {
+ local _mount_point_match_regexp
+ _mount_point_match_regexp="$(get_mount_point_regexp "$1")"
+ grep "$_mount_point_match_regexp" -q /etc/fstab \
+ || { echo "The mount point '$1' is not even in /etc/fstab, so we can't set up mount options" &gt;&amp;2; return 1; }
+}
+
+# $1: mount point
+function remove_defaults_from_fstab_if_overriden {
+ local _mount_point_match_regexp
+ _mount_point_match_regexp="$(get_mount_point_regexp "$1")"
+ if grep "$_mount_point_match_regexp" /etc/fstab | grep -q "defaults,"
+ then
+ sed -i "s|\(${_mount_point_match_regexp}.*\)defaults,|\1|" /etc/fstab
+ fi
+}
+
+# $1: mount point
+function ensure_partition_is_mounted {
+ local _mount_point="$1"
+ mkdir -p "$_mount_point" || return 1
+ if mountpoint -q "$_mount_point"; then
+ mount -o remount --target "$_mount_point"
+ else
+ mount --target "$_mount_point"
+ fi
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_replace_or_append" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function replace_or_append</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value># Function to replace configuration setting in config file or add the configuration setting if
+# it does not exist.
+#
+# Expects arguments:
+#
+# config_file: Configuration file that will be modified
+# key: Configuration option to change
+# value: Value of the configuration option to change
+# cce: The CCE identifier or '@CCENUM@' if no CCE identifier exists
+# format: The printf-like format string that will be given stripped key and value as arguments,
+# so e.g. '%s=%s' will result in key=value subsitution (i.e. without spaces around =)
+#
+# Optional arugments:
+#
+# format: Optional argument to specify the format of how key/value should be
+# modified/appended in the configuration file. The default is key = value.
+#
+# Example Call(s):
+#
+# With default format of 'key = value':
+# replace_or_append '/etc/sysctl.conf' '^kernel.randomize_va_space' '2' '@CCENUM@'
+#
+# With custom key/value format:
+# replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' 'disabled' '@CCENUM@' '%s=%s'
+#
+# With a variable:
+# replace_or_append '/etc/sysconfig/selinux' '^SELINUX=' $var_selinux_state '@CCENUM@' '%s=%s'
+#
+function replace_or_append {
+ local default_format='%s = %s' case_insensitive_mode=yes sed_case_insensitive_option='' grep_case_insensitive_option=''
+ local config_file=$1
+ local key=$2
+ local value=$3
+ local cce=$4
+ local format=$5
+
+ if [ "$case_insensitive_mode" = yes ]; then
+ sed_case_insensitive_option="i"
+ grep_case_insensitive_option="-i"
+ fi
+ [ -n "$format" ] || format="$default_format"
+ # Check sanity of the input
+ [ $# -ge "3" ] || { echo "Usage: replace_or_append &lt;config_file_location&gt; &lt;key_to_search&gt; &lt;new_value&gt; [&lt;CCE number or literal '@CCENUM@' if unknown&gt;] [printf-like format, default is '$default_format']" &gt;&amp;2; exit 1; }
+
+ # Test if the config_file is a symbolic link. If so, use --follow-symlinks with sed.
+ # Otherwise, regular sed command will do.
+ sed_command=('sed' '-i')
+ if test -L "$config_file"; then
+ sed_command+=('--follow-symlinks')
+ fi
+
+ # Test that the cce arg is not empty or does not equal @CCENUM@.
+ # If @CCENUM@ exists, it means that there is no CCE assigned.
+ if [ -n "$cce" ] &amp;&amp; [ "$cce" != '@CCENUM@' ]; then
+ cce="${cce}"
+ else
+ cce="CCE"
+ fi
+
+ # Strip any search characters in the key arg so that the key can be replaced without
+ # adding any search characters to the config file.
+ stripped_key=$(sed 's/[\^=\$,;+]*//g' &lt;&lt;&lt; "$key")
+
+ # shellcheck disable=SC2059
+ printf -v formatted_output "$format" "$stripped_key" "$value"
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ # We search for the key string followed by a word boundary (matched by \&gt;),
+ # so if we search for 'setting', 'setting2' won't match.
+ if LC_ALL=C grep -q -m 1 $grep_case_insensitive_option -e "${key}\\&gt;" "$config_file"; then
+ "${sed_command[@]}" "s/${key}\\&gt;.*/$formatted_output/g$sed_case_insensitive_option" "$config_file"
+ else
+ # \n is precaution for case where file ends without trailing newline
+ printf '\n# Per %s: Set %s in %s\n' "$cce" "$formatted_output" "$config_file" &gt;&gt; "$config_file"
+ printf '%s\n' "$formatted_output" &gt;&gt; "$config_file"
+ fi
+}</ns9:value>
+ </ns9:Value>
+ <ns9:Value hidden="true" id="xccdf_org.ssgproject.content_value_function_die" operator="equals" prohibitChanges="true" type="string">
+ <ns9:title xml:lang="en-US">Remediation function die</ns9:title>
+ <ns9:description xml:lang="en-US">Shared bash remediation function. Not intended to be changed by tailoring.</ns9:description>
+ <ns9:value># Print a message to stderr and exit the shell
+# $1: The message to print.
+# $2: The error code (optional, default is 1)
+function die {
+ local _message="$1" _rc="${2:-1}"
+ printf '%s\n' "$_message" &gt;&amp;2
+ exit "$_rc"
+}</ns9:value>
+ </ns9:Value>
+ </ns9:Group>
+ <ns9:Group id="xccdf_org.ssgproject.content_group_firefox">
+ <ns9:title xml:lang="en-US">Firefox</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox is an open-source web browser and developed by Mozilla.
+Web browsers such as Firefox are used for a number of reasons. This section
+provides settings for configuring Firefox policies to meet compliance
+settings for Firefox running on Red Hat Enterprise Linux systems.
+
+<html:ul>Refer to <html:li><html:a href="http://kb.mozillazine.org/Firefox_:_FAQs_:_About:config_Entries">http://kb.mozillazine.org/Firefox_:_FAQs_:_About:config_Entries</html:a></html:li>
+for a list of currently supported Firefox settings.</html:ul></ns9:description>
+ <ns9:Value id="xccdf_org.ssgproject.content_value_var_required_file_types" type="string">
+ <ns9:title xml:lang="en-US">The Default Required Firefox File Types</ns9:title>
+ <ns9:description xml:lang="en-US">The default required file types that need to request usage
+confirmation in Firefox.</ns9:description>
+ <ns9:value>application/pdf,application/doc,application/xls,application/bat,application/ppt,application/mdb,application/mde,application/fdf,application/xfdf,application/lsl,application/lso,appliation/lss,application/iqy,application/rqy,application/xlk,application/pot,application/pps,application/dot,application/wbk,application/ps,application/eps,application/wch,application/wcm,application/wbi,application/wb1,application/wb3,application/rtf,application/wch,application/wcm,application/ad,application/adp,application/xlt,application/dos,application/wks</ns9:value>
+ </ns9:Value>
+ <ns9:Value id="xccdf_org.ssgproject.content_value_var_default_home_page" type="string">
+ <ns9:title xml:lang="en-US">The Default Firefox Home Page</ns9:title>
+ <ns9:description xml:lang="en-US">The default home page for Firefox users.</ns9:description>
+ <ns9:value selector="about_blank">about:blank</ns9:value>
+ <ns9:value>None</ns9:value>
+ </ns9:Value>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-home_page" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Default Firefox Home Page Configured</ns9:title>
+ <ns9:description xml:lang="en-US">The default home page is set to a vendor's defined website or
+Firefox's own website. This can be changed to an organizationally defined website
+or <html:code>about:blank</html:code>. To set the default home page, set
+<html:code>browser.startup.homepage</html:code> to <html:code><ns9:sub idref="xccdf_org.ssgproject.content_value_var_default_home_page" use="legacy"/></html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF017</ns9:reference>
+ <ns9:rationale xml:lang="en-US">The browser home page parameter specifies the web page that is to be
+displayed when the browser is started explicitly and when product-specific
+buttons or key sequences for the home page are accessed. This helps to
+mitigate the possibility of automatic inadvertent execution of scripts
+added to a previously safe site.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-home_page" system="urn:xccdf:fix:script:sh">
+var_default_home_page="<ns9:sub idref="xccdf_org.ssgproject.content_value_var_default_home_page" use="legacy"/>"
+
+
+firefox_cfg="stig.cfg"
+value="\"${var_default_home_page}\""
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("browser.startup.homepage", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("browser.startup.homepage".*/lockPref("browser.startup.homepage", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("browser.startup.homepage", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-export export-name="oval:ssg-var_default_home_page:var:1" value-id="xccdf_org.ssgproject.content_value_var_default_home_page"/>
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-home_page:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-home_page_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-non-secure_page_warning" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Enable Non-Secure Page Warnings</ns9:title>
+ <ns9:description xml:lang="en-US">When users browse websites, web pages can switch in between secure and
+non-secure protocols. Users can be warned each time by
+setting <html:code>security.warn_leaving_secure</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF130</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Users may not be aware that the information being viewed under secure
+conditions in a previous page are not currently being viewed under
+the same security settings.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-non-secure_page_warning" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("security.warn_leaving_secure", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("security.warn_leaving_secure".*/lockPref("security.warn_leaving_secure", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("security.warn_leaving_secure", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-non-secure_page_warning:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-non-secure_page_warning_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-ssl_version_3" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable SSL Version 3.0 in Firefox</ns9:title>
+ <ns9:description xml:lang="en-US">SSL version 3.0 is vulnerable and should be disabled by setting
+<html:code>security.enable_ssl3</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF020</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Earlier versions of SSL have known security vulnerabilities and are not
+authorized for use in DOD.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-ssl_version_3" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("security.enable_ssl3", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("security.enable_ssl3".*/lockPref("security.enable_ssl3", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("security.enable_ssl3", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-ssl_version_3:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-ssl_version_3_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-password_store" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable the Firefox Password Store</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox allows users to store passwords whether or not a master password
+is set for the password store. To disable the storing of passwords, set
+<html:code>signon.rememberSignons</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF160</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Autofill of a password can be enabled when a site is visited. This feature could also
+be used to autofill the certificate pin which could lead to compromise of DoD information.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-password_store" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("signon.rememberSignons", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("signon.rememberSignons".*/lockPref("signon.rememberSignons", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("signon.rememberSignons", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-password_store:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-password_store_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_installed_firefox_version_supported" selected="false" severity="high">
+ <ns9:title xml:lang="en-US">Supported Version of Firefox Installed</ns9:title>
+ <ns9:description xml:lang="en-US">If the system is joined to the Red Hat Network, a Red Hat Satellite Server,
+or a yum server, run the following command to install updates:
+<html:pre>$ sudo yum update</html:pre>
+If the system is not configured to use one of these sources, updates (in the form of RPM packages)
+can be manually downloaded and installed using <html:code>rpm</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">DCMC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF003</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Use of versions of an application which are not supported by the vendor
+are not permitted. Vendors respond to security flaws with updates and
+patches. These updates are not available for unsupported version which
+can leave the application vulnerable to attack.</ns9:rationale>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-installed_firefox_version_supported:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-installed_firefox_version_supported_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-auto-download_actions" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable Automatic Downloads of MIME Types</ns9:title>
+ <ns9:description xml:lang="en-US">MIME type files are automatically downloaded or executed in Firefox. This
+can be disabled by setting <html:code>browser.helperApps.alwaysAsk.force</html:code> to
+<html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">DCMC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF100</ns9:reference>
+ <ns9:rationale xml:lang="en-US">The default action for file types for which a plugin is installed is to
+automatically download and execute the file using the associated plugin.
+Firefox allows users to change the specified download action so that the
+file is opened with a selected external application or saved to disk
+instead.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-auto-download_actions" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("browser.helperApps.alwaysAsk.force", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("browser.helperApps.alwaysAsk.force".*/lockPref("browser.helperApps.alwaysAsk.force", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("browser.helperApps.alwaysAsk.force", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-auto-download_actions:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-auto-download_actions_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_context_menus" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable JavaScript Context Menus</ns9:title>
+ <ns9:description xml:lang="en-US">JavaScript can configure and make changes to the web browser's appearance by
+specifically disabling or replacing context menus. This can be disabled by
+setting <html:code>dom.event.contextmenu.enabled</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF183</ns9:reference>
+ <ns9:rationale xml:lang="en-US">A website may execute JavaScript that can make changes to these
+context menus. This can help disguise an attack.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-javascript_context_menus" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("dom.event.contextmenu.enabled", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("dom.event.contextmenu.enabled".*/lockPref("dom.event.contextmenu.enabled", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("dom.event.contextmenu.enabled", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-javascript_context_menus:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-javascript_context_menus_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-open_confirmation" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Enable Downloading and Opening File Confirmation</ns9:title>
+ <ns9:description xml:lang="en-US">To have an action dialog box appear promping users what action to take when
+certain types of files are downloaded or opened, set
+<html:code>plugin.disable_full_page_plugin_for_types</html:code> to
+<html:code><ns9:sub idref="xccdf_org.ssgproject.content_value_var_required_file_types" use="legacy"/></html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF110</ns9:reference>
+ <ns9:rationale xml:lang="en-US">When the user receives a dialog box asking if they want to save the file
+or open it with a specified application, this indicates that a plugin does
+not exist. Also, the user has not previously selected a download action or helper
+application to automatically use for that type of file. When prompted, if the user
+checks the option to 'Do this automatically for files like this from now on', then
+an entry will appear for that type of file in the plugins listing, and this file
+type is automatically opened in the future. This can be a security issue. New file
+types cannot be added directly to the Application plugin listing.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-open_confirmation" system="urn:xccdf:fix:script:sh">
+var_required_file_types="<ns9:sub idref="xccdf_org.ssgproject.content_value_var_required_file_types" use="legacy"/>"
+
+
+firefox_cfg="stig.cfg"
+value="\"${var_required_file_types}\""
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("plugin.disable_full_page_plugin_for_types", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's|lockPref("plugin.disable_full_page_plugin_for_types".*|lockPref("plugin.disable_full_page_plugin_for_types", '"$value)"';|g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("plugin.disable_full_page_plugin_for_types", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-export export-name="oval:ssg-var_required_file_types:var:1" value-id="xccdf_org.ssgproject.content_value_var_required_file_types"/>
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-open_confirmation:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-open_confirmation_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-verification" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Enable Certificate Verification</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox can be configured to prompt the user to choose a certificate
+to present to a website when asked. To enable certificate verification,
+set <html:code>security.default_personal_cert</html:code> to <html:code>Ask Every Time</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF050</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Websites within DoD require user authentication for access which increases
+security for DoD information. Access will be denied to the user if
+certificate management is not configured.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-verification" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="\"Ask Every Time\""
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("security.default_personal_cert", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("security.default_personal_cert".*/lockPref("security.default_personal_cert", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("security.default_personal_cert", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-verification:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-verification_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_window_resizing" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable JavaScript's Moving Or Resizing Windows Capability</ns9:title>
+ <ns9:description xml:lang="en-US">JavaScript can configure and make changes to the web browser's appearance by
+specifically moving and resizing browser windows. This can be disabled by
+setting <html:code>dom.disable_window_move_resize</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF181</ns9:reference>
+ <ns9:rationale xml:lang="en-US">JavaScript can make changes to the browser&#x2019;s appearance. This activity
+can help disguise an attack taking place in a minimized background window.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-javascript_window_resizing" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("dom.disable_window_move_resize", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("dom.disable_window_move_resize".*/lockPref("dom.disable_window_move_resize", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("dom.disable_window_move_resize", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-javascript_window_resizing:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-javascript_window_resizing_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-search_update" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable Installed Search Plugins Update Checking</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox automatically checks for updated versions of search plugins.
+To disable the automatic updates of plugins, set
+<html:code>browser.search.update</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF085</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Updates need to be controlled and installed from authorized and trusted servers.
+This setting overrides a number of other settings which may direct the application
+to access external URLs.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-search_update" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("browser.search.update", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("browser.search.update".*/lockPref("browser.search.update", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("browser.search.update", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-search_update:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-search_update_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-autofill_forms" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable Autofill Form Assistance</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox provides tools to auto-fill forms from prefilled information.
+This can be disabled by setting <html:code>browser.formfill.enable</html:code> to
+<html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF140</ns9:reference>
+ <ns9:rationale xml:lang="en-US">In order to protect privacy and sensitive data, Firefox provides
+the ability to configure Firefox such that data entered into forms
+is not saved. This mitigates the risk of a website gleaning private
+information from prefilled information.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-autofill_forms" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("browser.formfill.enable", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("browser.formfill.enable".*/lockPref("browser.formfill.enable", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("browser.formfill.enable", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-autofill_forms:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-autofill_forms_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-shell_protocol" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable Firefox Access to Shell Protocols</ns9:title>
+ <ns9:description xml:lang="en-US">Access to the shell is disabled by default but can be changed.
+To prevent shell access from being enabled, set
+<html:code>network.protocol-handler.external.shell</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF105</ns9:reference>
+ <ns9:rationale xml:lang="en-US">If enabled, this setting would allow the browser to access the Windows shell.
+This could allow access to the underlying system.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-shell_protocol" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("network.protocol-handler.external.shell", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("network.protocol-handler.external.shell".*/lockPref("network.protocol-handler.external.shell", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("network.protocol-handler.external.shell", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-shell_protocol:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-shell_protocol_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-addons_plugin_updates" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable Addons Plugin Updates</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox automatically updates installed add-ons and plugins which
+can be disabled by setting <html:code>extensions.update.enabled</html:code> to
+<html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF090</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Automatic updates from untrusted sites puts the enclave at
+risk of attack and may override security settings.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-addons_plugin_updates" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("extensions.update.enabled", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("extensions.update.enabled".*/lockPref("extensions.update.enabled", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("extensions.update.enabled", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-addons_plugin_updates:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-addons_plugin_updates_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-autofill_passwords" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable User Ability To Autofill Passwords</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox automatically allows users to save passwords to be auto-filled
+into password forms. This can be disabled by setting
+<html:code>signon.prefillForms</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF150</ns9:reference>
+ <ns9:rationale xml:lang="en-US">While on the internet, it may be possible for an attacker to view
+the saved password files and gain access to the user's accounts on
+various hosts.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-autofill_passwords" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("signon.prefillForms", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("signon.prefillForms".*/lockPref("signon.prefillForms", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("signon.prefillForms", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-autofill_passwords:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-autofill_passwords_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-ssl_version_2" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable SSL Version 2.0 in Firefox</ns9:title>
+ <ns9:description xml:lang="en-US">SSL version 2 is not enabled by default and should not be enabled.
+To prevent SSL version 2 from being enabled set
+<html:code>security.enable_ssl2</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF010</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Use of versions prior to TLS 1.0 are not permitted because these versions are
+non-standard. SSL 2.0 and SSL 3.0 contain a number of security flaws.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-ssl_version_2" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("security.enable_ssl2", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("security.enable_ssl2".*/lockPref("security.enable_ssl2", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("security.enable_ssl2", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-ssl_version_2:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-ssl_version_2_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-ssl_protocol_tls" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Enable TLS Usage in Firefox</ns9:title>
+ <ns9:description xml:lang="en-US">To enable TLS, set <html:code>security.enable_tls</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF030</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Earlier versions of SSL have known security vulnerabilities and are not
+authorized for use in DOD environments.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-ssl_protocol_tls" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("security.enable_tls", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("security.enable_tls".*/lockPref("security.enable_tls", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("security.enable_tls", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-ssl_protocol_tls:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-ssl_protocol_tls_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_status_bar_text" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable JavaScript's Ability To Modify The Browser Appearance</ns9:title>
+ <ns9:description xml:lang="en-US">JavaScript can configure and make changes to the web browser's appearance by
+specifically hiding the status bar from view. This can disabled by
+setting <html:code>dom.disable_window_open_feature.status</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF185</ns9:reference>
+ <ns9:rationale xml:lang="en-US">JavaScript can make changes to the browser&#x2019;s appearance. This activity
+can help disguise an attack taking place in a minimized background window.
+Webpage authors can disable many features of a popup window that they open.
+This setting prevents the status bar from being hidden.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-javascript_status_bar_text" system="urn:xccdf:fix:script:sh">
+
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("dom.disable_window_open_feature.status", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("dom.disable_window_open_feature.status".*/lockPref("dom.disable_window_open_feature.status", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("dom.disable_window_open_feature.status", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-javascript_status_bar_text:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-javascript_status_bar_text_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_window_changes" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable JavaScript's Raise Or Lower Windows Capability</ns9:title>
+ <ns9:description xml:lang="en-US">JavaScript can configure and make changes to the web browser's appearance by
+specifically raising and lowering windows. This can be disabled by
+setting <html:code>dom.disable_window_flip</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF182</ns9:reference>
+ <ns9:rationale xml:lang="en-US">JavaScript can make changes to the browser&#x2019;s appearance. Allowing a website
+to use JavaScript to raise and lower browser windows may disguise an attack.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-javascript_window_changes" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("dom.disable_window_flip", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("dom.disable_window_flip".*/lockPref("dom.disable_window_flip", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("dom.disable_window_flip", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-javascript_window_changes:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-javascript_window_changes_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-javascript_status_bar_changes" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable JavaScript's Ability To Change The Status Bar</ns9:title>
+ <ns9:description xml:lang="en-US">JavaScript can configure and make changes to the web browser's appearance by
+specifically hiding or changing the status bar. This can be disabled by
+setting <html:code>dom.disable_window_status_change</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF184</ns9:reference>
+ <ns9:rationale xml:lang="en-US">When a user visits some webpages, JavaScript can hide or make changes
+to the browser&#x2019;s appearance to hide unauthorized activity. This activity
+can help disguise an attack taking place in a minimized background window.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-javascript_status_bar_changes" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("dom.disable_window_status_change", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("dom.disable_window_status_change".*/lockPref("dom.disable_window_status_change", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("dom.disable_window_status_change", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-javascript_status_bar_changes:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-javascript_status_bar_changes_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-auto-update_of_firefox" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable Firefox Auto-Update Capability</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox can be set to automatically update as new updates. This can be
+disabled by setting <html:code>app.update.enable</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF080</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Allowing software updates from non-trusted sites can introduce settings
+that will override a secured installation of the application. This can
+place DoD information at risk. If this setting is enabled, then there are
+many other default settings which point to untrusted sites which must be
+changed to point to an authorized update site that is not publicly accessible.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-auto-update_of_firefox" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("app.update.enabled", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("app.update.enabled".*/lockPref("app.update.enabled", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("app.update.enabled", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-auto-update_of_firefox:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-auto-update_of_firefox_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-pop-up_windows" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Enable Firefox Pop-up Blocker</ns9:title>
+ <ns9:description xml:lang="en-US">The pop-up blocker can be enabled by setting
+<html:code>dom.disable_window_open_feature.status</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF180</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Popup windows may be used to launch an attack within a new browser window
+with altered settings.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-pop-up_windows" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("dom.disable_window_open_feature.status", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("dom.disable_window_open_feature.status".*/lockPref("dom.disable_window_open_feature.status", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("dom.disable_window_open_feature.status", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-pop-up_windows:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-pop-up_windows_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Group id="xccdf_org.ssgproject.content_group_firefox_preferences-lock_settings">
+ <ns9:title xml:lang="en-US">Prevent Users from Changing Firefox Configuration Settings</ns9:title>
+ <ns9:description xml:lang="en-US">Firefox required security preferences cannot be changed by users.</ns9:description>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-lock_settings_config_file" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Set Firefox Configuration File Location</ns9:title>
+ <ns9:description xml:lang="en-US">Specify the Firefox configuration file location by setting
+<html:code>general.config.filename</html:code> to the configuration (i.e. <html:code>mozilla.cfg</html:code>)
+filename that contains the Firefox security preferences.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF070</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Locked settings prevents users from accessing about:config and changing
+the security settings set by the system administrator.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-lock_settings_config_file" system="urn:xccdf:fix:script:sh">
+
+value="\"stig.cfg\""
+firefox_js="stig_settings.js"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+firefox_pref="/defaults/pref"
+firefox_preferences="/defaults/preferences"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Different versions of Firefox have different preferences directories, check for them and set the right one
+ if [ -d "${firefox_dir}/${firefox_pref}" ] ; then
+ firefox_pref_dir="${firefox_dir}/${firefox_pref}"
+ elif [ -d "${firefox_dir}/${firefox_preferences}" ] ; then
+ firefox_pref_dir="${firefox_dir}/${firefox_preferences}"
+ else
+ mkdir -m 755 -p "${firefox_dir}/${firefox_preferences}"
+ firefox_pref_dir="${firefox_dir}/${firefox_preferences}"
+ fi
+
+ # Make sure the Firefox .js file exists and has the appropriate permissions
+ if ! [ -f "${firefox_pref_dir}/${firefox_js}" ] ; then
+ touch "${firefox_pref_dir}/${firefox_js}"
+ chmod 644 "${firefox_pref_dir}/${firefox_js}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^pref("general.config.filename", ' "${firefox_pref_dir}/${firefox_js}"; then
+ sed -i 's/pref("general.config.filename".*/pref("general.config.filename", '"$value)"';/g' "${firefox_pref_dir}/${firefox_js}"
+ else
+ echo 'pref("general.config.filename", '"$value"');' &gt;&gt; "${firefox_pref_dir}/${firefox_js}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-lock_settings_config_file:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-lock_settings_config_file_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-lock_settings_obscure" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable Firefox Configuration File ROT-13 Encoding</ns9:title>
+ <ns9:description xml:lang="en-US">Disable ROT-13 encoding by setting <html:code>general.config.obscure_value</html:code>
+to <html:code>0</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF070</ns9:reference>
+ <ns9:rationale xml:lang="en-US">ROT-13 encoded prevents system adminstrators from easily configuring
+and deploying Firefox configuration settings. It also prevents validating
+settings easily from automated security tools.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-lock_settings_obscure" system="urn:xccdf:fix:script:sh">
+
+value="0"
+firefox_js="stig_settings.js"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+firefox_pref="/defaults/pref"
+firefox_preferences="/defaults/preferences"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Different versions of Firefox have different preferences directories, check for them and set the right one
+ if [ -d "${firefox_dir}/${firefox_pref}" ] ; then
+ firefox_pref_dir="${firefox_dir}/${firefox_pref}"
+ elif [ -d "${firefox_dir}/${firefox_preferences}" ] ; then
+ firefox_pref_dir="${firefox_dir}/${firefox_preferences}"
+ else
+ mkdir -m 755 -p "${firefox_dir}/${firefox_preferences}"
+ firefox_pref_dir="${firefox_dir}/${firefox_preferences}"
+ fi
+
+ # Make sure the Firefox .js file exists and has the appropriate permissions
+ if ! [ -f "${firefox_pref_dir}/${firefox_js}" ] ; then
+ touch "${firefox_pref_dir}/${firefox_js}"
+ chmod 644 "${firefox_pref_dir}/${firefox_js}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^pref("general.config.obscure_value", ' "${firefox_pref_dir}/${firefox_js}"; then
+ sed -i 's/pref("general.config.obscure_value".*/pref("general.config.obscure_value", '"$value)"';/g' "${firefox_pref_dir}/${firefox_js}"
+ else
+ echo 'pref("general.config.obscure_value", '"$value"');' &gt;&gt; "${firefox_pref_dir}/${firefox_js}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-lock_settings_obscure:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-lock_settings_obscure_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ </ns9:Group>
+ <ns9:Group id="xccdf_org.ssgproject.content_group_firefox_preferences-dod_root_certificate">
+ <ns9:title xml:lang="en-US">The DoD Root Certificate Is Required</ns9:title>
+ <ns9:description xml:lang="en-US">The Shared System Certificates store contains certificates that
+applications can access for a single certificate repository.
+If enabled, Firefox can access that single system certificate
+repository. If the DoD root certificate is also installed into
+the shared system certificate repository, Firefox will see and
+use the DoD root certificate as a valid certificate authority.</ns9:description>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-enable_ca_trust" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Enable Shared System Certificates</ns9:title>
+ <ns9:description xml:lang="en-US">The Shared System Certificates store makes NSS, GnuTLS, OpenSSL, and Java
+share a default source for retrieving system certificate anchors and blacklist
+information. Firefox has the capability of using this centralized store for its
+CA certificates. If the Shared System Certificates store is disabled, it can
+be enabled by running the following command:
+<html:pre>$ sudo update-ca-trust enable</html:pre></ns9:description>
+ <ns9:reference href="https://public.cyber.mil/stigs/cci/">CCI-000054</ns9:reference>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">AC-10</ns9:reference>
+ <ns9:rationale xml:lang="en-US">The DOD root certificate will ensure that the trust chain is
+established for server certificates issued from the DOD CA.</ns9:rationale>
+ <ns9:ident system="https://nvd.nist.gov/cce/index.cfm">CCE-82057-1</ns9:ident>
+ <ns9:fix id="firefox_preferences-enable_ca_trust" system="urn:xccdf:fix:script:sh">P11=$(readlink /etc/alternatives/libnssckbi.so*)
+P11LIB="/usr/lib/pkcs11/p11-kit-trust.so"
+P11LIB64="/usr/lib64/pkcs11/p11-kit-trust.so"
+
+if ! [[ ${P11} == "${P11LIB64}" ]] || ! [[ ${P11} == "${P11LIB}" ]] ; then
+ /usr/bin/update-ca-trust enable
+fi
+</ns9:fix>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-enable_ca_trust_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-dod_root_certificate_installed" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">The DoD Root Certificate Exists</ns9:title>
+ <ns9:description xml:lang="en-US">The DoD root certificate should be installed in the Shared System Certificates store
+for Firefox to be able to access the DoD certificate. To install the root certificated
+into the Shared System Certificates store, copy the DoD root certificate into
+<html:code>/etc/pki/ca-trust/source/anchors</html:code>. Once the file is copied, run the following
+command:
+<html:pre>$ sudo update-ca-trust extract</html:pre></ns9:description>
+ <ns9:reference href="https://public.cyber.mil/stigs/cci/">CCI-000054</ns9:reference>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">AC-10</ns9:reference>
+ <ns9:rationale xml:lang="en-US">The DOD root certificate will ensure that the trust chain is
+established for server certificates issued from the DOD CA.</ns9:rationale>
+ <ns9:ident system="https://nvd.nist.gov/cce/index.cfm">CCE-82056-3</ns9:ident>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-dod_root_certificate_installed_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ </ns9:Group>
+ <ns9:Group id="xccdf_org.ssgproject.content_group_firefox_preferences-cookies">
+ <ns9:title xml:lang="en-US">Clearing Cookies And Other Data</ns9:title>
+ <ns9:description xml:lang="en-US">Browser preferences should be set to perform a Clear Private Data
+operation when closing the browser in order to clear cookies and other
+data installed by websites visited during the session.</ns9:description>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-cookies_clear" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Clear Data When Firefox Closes</ns9:title>
+ <ns9:description xml:lang="en-US">When a user browses to a website, cookies and other types of data
+get stored on the system. This can be disabled by setting
+<html:code>privacy.sanitize.sanitizeOnShutdown</html:code> to <html:code>true</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF170</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Cookies can help websites perform better but can also be part of spyware.
+To mitigate this risk, set browser preferences to perform a Clear Private
+Data operation when closing the browser in order to clear cookies and
+other data installed by websites visited during the session.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-cookies_clear" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="true"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("privacy.sanitize.sanitizeOnShutdown", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("privacy.sanitize.sanitizeOnShutdown".*/lockPref("privacy.sanitize.sanitizeOnShutdown", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("privacy.sanitize.sanitizeOnShutdown", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-cookies_clear:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-cookies_clear_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ <ns9:Rule id="xccdf_org.ssgproject.content_rule_firefox_preferences-cookies_user_notice" selected="false" severity="medium">
+ <ns9:title xml:lang="en-US">Disable User Prompt When Data Is Cleared</ns9:title>
+ <ns9:description xml:lang="en-US">By default, users are asked if it is okay to clear out cookies and data
+when Firefox closes. This can be disabled by
+setting <html:code>privacy.sanitize.promptOnSanitize</html:code> to <html:code>false</html:code>.</ns9:description>
+ <ns9:reference href="http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-53r4.pdf">ECSC-1</ns9:reference>
+ <ns9:reference href="https://public.cyber.mil/stigs/downloads/?_dl_facet_stigs=app-security%2Cbrowser-guidance">FIREFOX-DTBF170</ns9:reference>
+ <ns9:rationale xml:lang="en-US">Cookies can help websites perform better but can also be part of spyware.
+To mitigate this risk, set browser preferences to perform a Clear Private
+Data operation when closing the browser in order to clear cookies and
+other data installed by websites visited during the session.</ns9:rationale>
+ <ns9:fix id="firefox_preferences-cookies_user_notice" system="urn:xccdf:fix:script:sh">
+
+firefox_cfg="stig.cfg"
+value="false"
+firefox_dirs="/usr/lib/firefox /usr/lib64/firefox /usr/local/lib/firefox /usr/local/lib64/firefox"
+
+# Check the possible Firefox install directories
+for firefox_dir in ${firefox_dirs}; do
+ # If the Firefox directory exists, then Firefox is installed
+ if [ -d "${firefox_dir}" ]; then
+ # Make sure the Firefox .cfg file exists and has the appropriate permissions
+ if ! [ -f "${firefox_dir}/${firefox_cfg}" ] ; then
+ touch "${firefox_dir}/${firefox_cfg}"
+ chmod 644 "${firefox_dir}/${firefox_cfg}"
+ fi
+
+ # If the key exists, change it. Otherwise, add it to the config_file.
+ if LC_ALL=C grep -m 1 -q '^lockPref("privacy.sanitize.promptOnSanitize", ' "${firefox_dir}/${firefox_cfg}"; then
+ sed -i 's/lockPref("privacy.sanitize.promptOnSanitize".*/lockPref("privacy.sanitize.promptOnSanitize", '"$value)"';/g' "${firefox_dir}/${firefox_cfg}"
+ else
+ echo 'lockPref("privacy.sanitize.promptOnSanitize", '"$value"');' &gt;&gt; "${firefox_dir}/${firefox_cfg}"
+ fi
+ fi
+done
+</ns9:fix>
+ <ns9:check system="http://oval.mitre.org/XMLSchema/oval-definitions-5">
+ <ns9:check-content-ref href="ssg-firefox-oval.xml" name="oval:ssg-firefox_preferences-cookies_user_notice:def:1"/>
+ </ns9:check>
+ <ns9:check system="http://scap.nist.gov/schema/ocil/2">
+ <ns9:check-content-ref href="ssg-firefox-ocil.xml" name="ocil:ssg-firefox_preferences-cookies_user_notice_ocil:questionnaire:1"/>
+ </ns9:check>
+ </ns9:Rule>
+ </ns9:Group>
+ </ns9:Group>
+ </ns9:Benchmark>
+ </ns0:component>
+ <ns0:component id="scap_org.open-scap_comp_ssg-firefox-cpe-oval.xml" timestamp="2020-01-16T13:51:05">
+ <ns3:oval_definitions xsi:schemaLocation="http://oval.mitre.org/XMLSchema/oval-common-5 oval-common-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5 oval-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#independent independent-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#unix unix-definitions-schema.xsd http://oval.mitre.org/XMLSchema/oval-definitions-5#linux linux-definitions-schema.xsd">
+ <ns3:generator>
+ <ns5:product_name>combine_ovals.py from SCAP Security Guide</ns5:product_name>
+ <ns5:product_version>ssg: [0, 1, 48], python: 3.7.6</ns5:product_version>
+ <ns5:schema_version>5.11</ns5:schema_version>
+ <ns5:timestamp>2020-01-16T13:51:04</ns5:timestamp>
+ </ns3:generator>
+ <ns3:definitions>
+ <ns3:definition class="inventory" id="oval:ssg-installed_app_is_firefox:def:1" version="2">
+ <ns3:metadata>
+ <ns3:title>Mozilla Firefox</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:reference ref_id="cpe:/a:mozilla:firefox" source="CPE"/>
+ <ns3:description>The application installed on the system is firefox.</ns3:description>
+ </ns3:metadata>
+ <ns3:criteria operator="AND">
+ <ns3:extend_definition comment="Installed OS is part of the Unix family" definition_ref="oval:ssg-installed_OS_is_part_of_Unix_family:def:1"/>
+ <ns3:criterion comment="Firefox is installed" test_ref="oval:ssg-test_firefox:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ <ns3:definition class="inventory" id="oval:ssg-installed_OS_is_part_of_Unix_family:def:1" version="1">
+ <ns3:metadata>
+ <ns3:title>Installed operating system is part of the Unix family</ns3:title>
+ <ns3:affected family="unix">
+ <ns3:product>Firefox</ns3:product>
+ </ns3:affected>
+ <ns3:description>The operating system installed on the system is part of the Unix OS family</ns3:description>
+ </ns3:metadata>
+ <ns3:criteria>
+ <ns3:criterion comment="Installed operating system is part of the unix family" test_ref="oval:ssg-test_unix_family:tst:1"/>
+ </ns3:criteria>
+ </ns3:definition>
+ </ns3:definitions>
+ <ns3:tests>
+ <ns7:rpminfo_test check="all" check_existence="at_least_one_exists" comment="Firefox is installed" id="oval:ssg-test_firefox:tst:1" version="1">
+ <ns7:object object_ref="oval:ssg-obj_firefox:obj:1"/>
+ </ns7:rpminfo_test>
+ <ns6:family_test check="all" check_existence="at_least_one_exists" comment="Test installed OS is part of the unix family" id="oval:ssg-test_unix_family:tst:1" version="1">
+ <ns6:object object_ref="oval:ssg-object_unix_family:obj:1"/>
+ <ns6:state state_ref="oval:ssg-state_unix_family:ste:1"/>
+ </ns6:family_test>
+ </ns3:tests>
+ <ns3:objects>
+ <ns7:rpminfo_object id="oval:ssg-obj_firefox:obj:1" version="1">
+ <ns7:name>firefox</ns7:name>
+ </ns7:rpminfo_object>
+ <ns6:family_object id="oval:ssg-object_unix_family:obj:1" version="1"/>
+ </ns3:objects>
+ <ns3:states>
+ <ns6:family_state id="oval:ssg-state_unix_family:ste:1" version="1">
+ <ns6:family>unix</ns6:family>
+ </ns6:family_state>
+ </ns3:states>
+ </ns3:oval_definitions>
+ </ns0:component>
+ <ns0:component id="scap_org.open-scap_comp_ssg-firefox-cpe-dictionary.xml" timestamp="2020-01-16T13:51:05">
+ <ns12:cpe-list xsi:schemaLocation="http://cpe.mitre.org/dictionary/2.0 http://cpe.mitre.org/files/cpe-dictionary_2.1.xsd">
+ <ns12:cpe-item name="cpe:/a:mozilla:firefox">
+ <ns12:title xml:lang="en-us">Mozilla Firefox</ns12:title>
+ <ns12:check href="ssg-firefox-cpe-oval.xml" system="http://oval.mitre.org/XMLSchema/oval-definitions-5">oval:ssg-installed_app_is_firefox:def:1</ns12:check>
+ </ns12:cpe-item>
+ </ns12:cpe-list>
+ </ns0:component>
+</ns0:data-stream-collection>
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/data/test-srpm01-1.0-1.src.rpm b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/test-srpm01-1.0-1.src.rpm
new file mode 100644
index 000000000..36cb62390
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/data/test-srpm01-1.0-1.src.rpm
Binary files differ
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/discovery_rule.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/discovery_rule.yml
new file mode 100644
index 000000000..ccdf338f0
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/discovery_rule.yml
@@ -0,0 +1,108 @@
+---
+## To record cassettes using this playbook (record_discovery_rule)
+## you need to have the discovery plugin active
+## $ foreman-installer --enable-foreman-plugin-discovery
+##
+## You also need the proxy to be setup with the DNS feature:
+## $ foreman-installer --foreman-proxy-dns true
+##
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: present
+ with_items: "{{ hostgroup.locations }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: present
+ with_items: "{{ hostgroup.organizations }}"
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Discovery hostgroup"
+ hostgroup_description: "Discovery hostgroup"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_state: present
+ - include_tasks: tasks/discovery_rule.yml
+ vars:
+ discovery_rule_name: 'New-discovery-rule'
+ discovery_rule_state: 'absent'
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/discovery_rule.yml
+ vars:
+ discovery_rule_name: 'New-discovery-rule'
+ discovery_rule_search: 'mac = aa:aa:aa:aa:aa:aa'
+ discovery_rule_hostgroup: 'Discovery hostgroup'
+ discovery_rule_hostname: 'discovered-host'
+ discovery_rule_max_count: '1'
+ discovery_rule_organizations: "{{ hostgroup.organizations }}"
+ discovery_rule_locations: "{{ hostgroup.locations }}"
+ discovery_rule_state: 'present'
+ expected_change: true
+
+ - include_tasks: tasks/discovery_rule.yml
+ vars:
+ discovery_rule_name: 'New-discovery-rule'
+ discovery_rule_search: 'mac = aa:aa:aa:aa:aa:aa'
+ discovery_rule_hostgroup: 'Discovery hostgroup'
+ discovery_rule_hostname: 'discovered-host'
+ discovery_rule_max_count: '1'
+ discovery_rule_organizations: "{{ hostgroup.organizations }}"
+ discovery_rule_locations: "{{ hostgroup.locations }}"
+ discovery_rule_state: 'present'
+ expected_change: false
+
+ - include_tasks: tasks/discovery_rule.yml
+ vars:
+ discovery_rule_name: 'New-discovery-rule'
+ discovery_rule_state: 'absent'
+ expected_change: true
+
+ - include_tasks: tasks/discovery_rule.yml
+ vars:
+ discovery_rule_name: 'New-discovery-rule'
+ discovery_rule_state: 'absent'
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Discovery hostgroup"
+ hostgroup_description: "Discovery hostgroup"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: absent
+ with_items: "{{ hostgroup.locations | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: absent
+ with_items: "{{ hostgroup.organizations }}"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/domain.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/domain.yml
new file mode 100644
index 000000000..3e44e24b4
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/domain.yml
@@ -0,0 +1,183 @@
+---
+## Need to enable proxy on the foreman-server with:
+## foreman-installer --foreman-proxy-dns true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/domain.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "present"
+ with_items: "{{ domain_locations }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "present"
+ with_items: "{{ domain_organizations }}"
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "absent"
+ #TODO create smart_proxy, when ansible-module exists
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/domain.yml
+ tasks:
+ - name: create domain
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ expected_change: true
+ - name: create domain again, no change
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ expected_change: false
+ - name: assign dns_proxy
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ domain_dns_proxy: "{{ foreman_proxy }}"
+ expected_change: true
+ - name: assign dns_proxy again, no change
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ domain_dns_proxy: "{{ foreman_proxy }}"
+ expected_change: false
+ - name: unset dns_proxy
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ domain_dns_proxy: ""
+ expected_change: true
+ - name: unset dns_proxy again, no change
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ domain_dns_proxy: ""
+ expected_change: false
+ - name: delete domain
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "absent"
+ expected_change: true
+
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_locations: []
+ domain_organizations: []
+ domain_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ domain_state: "present"
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "{}"
+ expected_diff_after: "subnet_param1"
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ expected_change: true
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ domain_state: "present"
+ expected_change: false
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_parameters:
+ - name: subnet_param1
+ value: new_value1
+ - name: subnet_param3
+ value: value3
+ domain_state: "present"
+ expected_change: true
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_parameters:
+ - name: subnet_param1
+ value: new_value1
+ - name: subnet_param3
+ value: value3
+ domain_state: "present"
+ expected_change: false
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_parameters: []
+ domain_state: "present"
+ expected_change: true
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_parameters: []
+ domain_state: "present"
+ expected_change: false
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "foobar.example.com"
+ domain_state: "present"
+ expected_change: true
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "foobar.example.com"
+ domain_updated_name: "barbaz.example.com"
+ domain_state: "present"
+ expected_change: true
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "barbaz.example.com"
+ domain_state: "present"
+ expected_change: false
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "barbaz.example.com"
+ domain_state: "absent"
+ expected_change: true
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "absent"
+ expected_change: true
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "absent"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/domain.yml
+ tasks:
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "absent"
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "absent"
+ with_items: "{{ domain_locations | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ with_items: "{{ domain_organizations }}"
+ #TODO remove smart_proxy, when ansible-module exists
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/domain_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/domain_info.yml
new file mode 100644
index 000000000..f7b802101
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/domain_info.yml
@@ -0,0 +1,83 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/domain.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "present"
+ with_items: "{{ domain_locations }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "present"
+ with_items: "{{ domain_organizations }}"
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "absent"
+ - name: create domain
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "present"
+ expected_change: true
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch domain info
+ domain_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "example.com"
+ register: domain_info
+ - name: check domain details
+ assert:
+ that:
+ - domain_info['domain']['name'] == "example.com"
+
+ - name: search domain info
+ domain_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ search: "name = example.com"
+ register: domain_info
+ - name: check domain details
+ assert:
+ that:
+ - domain_info['domains'][0]['name'] == "example.com"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/domain.yml
+ tasks:
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_state: "absent"
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "absent"
+ with_items: "{{ domain_locations | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ with_items: "{{ domain_organizations }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/domains_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/domains_role.yml
new file mode 100644
index 000000000..a0fe46085
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/domains_role.yml
@@ -0,0 +1,61 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - name: ensure test location
+ include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "example.org"
+ domain_state: "absent"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: domains
+ vars:
+ foreman_domains:
+ - name: "example.org"
+ description: 'Example Domain'
+ organizations:
+ - Test Organization
+ locations:
+ - Test Location
+ state: present
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "example.org"
+ domain_state: "absent"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/external_usergroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/external_usergroup.yml
new file mode 100644
index 000000000..0813dcf14
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/external_usergroup.yml
@@ -0,0 +1,84 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "present"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "present"
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "internal_group"
+ usergroup_state: present
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: present
+ auth_source_ldap_attr_login: dc=vagrant,dc=vm
+ auth_source_ldap_groups_base: cn=groups,cn=accounts,dc=vagrant,dc=vm
+ auth_source_ldap_tls: false
+ - include_tasks: tasks/external_usergroup.yml
+ vars:
+ external_usergroup_state: absent
+ auth_source_ldap: "Example LDAP"
+ usergroup: "internal_group"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/external_usergroup.yml
+ vars:
+ external_usergroup_state: present
+ auth_source_ldap: "Example LDAP"
+ usergroup: "internal_group"
+ expected_change: true
+ - include_tasks: tasks/external_usergroup.yml
+ vars:
+ external_usergroup_state: present
+ auth_source_ldap: "Example LDAP"
+ usergroup: "internal_group"
+ expected_change: false
+ - include_tasks: tasks/external_usergroup.yml
+ vars:
+ external_usergroup_state: absent
+ auth_source_ldap: "Example LDAP"
+ usergroup: "internal_group"
+ expected_change: true
+ - include_tasks: tasks/external_usergroup.yml
+ vars:
+ external_usergroup_state: absent
+ auth_source_ldap: "Example LDAP"
+ usergroup: "internal_group"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ tags:
+ - teardown
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "internal_group"
+ usergroup_state: "absent"
+ - include_tasks: tasks/auth_source_ldap.yml
+ vars:
+ auth_source_ldap_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "absent"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/filters.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/filters.yml
new file mode 100644
index 000000000..70c67f21e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/filters.yml
@@ -0,0 +1,17 @@
+---
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ tags:
+ - test
+ gather_facts: false
+ tasks:
+ - debug:
+ msg: "{{ 'Test__String)' | theforeman.foreman.cp_label }}"
+ - assert:
+ that:
+ - "{{ 'Test String' | theforeman.foreman.cp_label == 'Test_String' }}"
+ - "{{ 'Test__String' | theforeman.foreman.cp_label == 'Test__String' }}"
+ - "{{ 'Test--String' | theforeman.foreman.cp_label == 'Test--String' }}"
+ - "{{ 'Test (String) 1234' | theforeman.foreman.cp_label == 'Test_String_1234' }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/global_parameter.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/global_parameter.yml
new file mode 100644
index 000000000..457483981
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/global_parameter.yml
@@ -0,0 +1,169 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_state: absent
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_name: "my_param"
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_name: "my_param"
+ global_parameter_updated_name: "my_param2"
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_name: "my_param2"
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_name: "my_param2"
+ global_parameter_state: absent
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: integer
+ global_parameter_hidden_value: true
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: integer
+ global_parameter_hidden_value: true
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: integer
+ global_parameter_hidden_value: false
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: real
+ global_parameter_value: 3.14
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: real
+ global_parameter_value: 3.14
+ global_parameter_hidden_value: false
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: string
+ global_parameter_value: ""
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: string
+ global_parameter_value: ""
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: boolean
+ global_parameter_value: true
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: boolean
+ global_parameter_value: true
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: string
+ global_parameter_value: "'"
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: string
+ global_parameter_value: "'"
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: hash
+ global_parameter_value: {'a': 2, '1': 'b'}
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: hash
+ global_parameter_value:
+ a: 2
+ 1: b
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: array
+ global_parameter_value: ['a', 2, true, 1.e-3]
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: array
+ global_parameter_value:
+ - 'a'
+ - 2
+ - true
+ - 0.001
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: yaml
+ global_parameter_value:
+ - alpha
+ - beta:
+ - a
+ - 1
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: yaml
+ global_parameter_value:
+ - alpha
+ - beta:
+ - a
+ - 1
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: json
+ global_parameter_value: {"name": "test", "value": 4, "tags": ["a", "b", "c"]}
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: json
+ global_parameter_value:
+ name: "test"
+ value: 4
+ tags: ['a', 'b', 'c']
+ expected_change: false
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_state: absent
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_type: json
+ global_parameter_value: {"name": "test", "value": 4, "tags": ["a", "b", "c"]}
+ expected_change: true
+ - include_tasks: tasks/global_parameter.yml
+ vars:
+ global_parameter_state: absent
+ expected_change: true
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/hardware_model.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/hardware_model.yml
new file mode 100644
index 000000000..f1875b41a
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/hardware_model.yml
@@ -0,0 +1,63 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/model.yml
+ vars:
+ model_state: "absent"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: create model
+ include_tasks: tasks/model.yml
+ vars:
+ model_state: "present"
+ expected_change: true
+ - name: create model again, no change
+ include_tasks: tasks/model.yml
+ vars:
+ model_state: "present"
+ expected_change: false
+ - name: update model
+ include_tasks: tasks/model.yml
+ vars:
+ model_state: "present"
+ model_info: "fancy laptop for ACME"
+ expected_change: true
+ - name: update model again, no change
+ include_tasks: tasks/model.yml
+ vars:
+ model_state: "present"
+ model_info: "fancy laptop for ACME"
+ expected_change: false
+ - name: delete model
+ include_tasks: tasks/model.yml
+ vars:
+ model_state: "absent"
+ expected_change: true
+ - name: delete model again, no change
+ include_tasks: tasks/model.yml
+ vars:
+ model_state: "absent"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/model.yml
+ vars:
+ model_state: "absent"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/host.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/host.yml
new file mode 100644
index 000000000..57c1e3956
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/host.yml
@@ -0,0 +1,573 @@
+---
+- hosts: foreman
+ become: true
+ tasks:
+ - name: install puppet-prometheus
+ command: /opt/puppetlabs/bin/puppet module install puppet-prometheus
+ args:
+ creates: /etc/puppetlabs/code/environments/production/modules/prometheus/
+ - name: import puppet modules into Foreman
+ command: hammer proxy import-classes --puppet-environment production --name {{ ansible_fqdn }}
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }}"
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }}"
+ location_organizations:
+ - "{{ host.organization }}"
+ location_state: present
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }} Secondary"
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }} Secondary"
+ location_organizations:
+ - "{{ host.organization }} Secondary"
+ location_state: present
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ host.domain }}"
+ domain_locations:
+ - "{{ host.location }}"
+ domain_organizations:
+ - "{{ host.organization }}"
+ domain_state: present
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }}"
+ subnet_mask: '255.255.255.224'
+ subnet_domains:
+ - "{{ host.domain }}"
+ subnet_locations:
+ - "{{ host.location }}"
+ subnet_organizations:
+ - "{{ host.organization }}"
+ subnet_state: present
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "{{ host.hostgroup }}"
+ hostgroup_domain: "{{ host.domain }}"
+ hostgroup_locations:
+ - "{{ host.location }}"
+ hostgroup_organizations:
+ - "{{ host.organization }}"
+ hostgroup_state: present
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "{{ host.hostgroup }}/child_group"
+ hostgroup_domain: "{{ host.domain }}"
+ hostgroup_locations:
+ - "{{ host.location }}"
+ hostgroup_organizations:
+ - "{{ host.organization }}"
+ hostgroup_state: present
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: present
+ user_password: password
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_state: present
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "{{ host.arch }}"
+ architecture_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "{{ host.os.name }}"
+ operatingsystem_major: "{{ host.os.major }}"
+ operatingsystem_minor: "{{ host.os.minor }}"
+ operatingsystem_family: "{{ host.os.family }}"
+ operatingsystem_architectures:
+ - "{{ host.arch }}"
+ operatingsystem_state: present
+ - include_tasks: tasks/environment.yml
+ vars:
+ environment_state: present
+ environment_name: "production"
+ environment_locations:
+ - "{{ host.location }}"
+ environment_organizations:
+ - "{{ host.organization }}"
+ - include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - name: create host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ expected_change: true
+
+ - name: create host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ expected_change: false
+
+ - name: update host, set owner to a user
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_owner: test
+ expected_change: true
+
+ - name: update host, set owner to a user again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_owner: test
+ expected_change: false
+
+ - name: update host, set owner to a usergroup
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_owner_group: testgroup
+ expected_change: true
+
+ - name: update host, set owner to a usergroup again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_owner_group: testgroup
+ expected_change: false
+
+ - name: Add subnet to host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_subnet: "{{ host.subnet }}"
+ host_managed: false
+ expected_change: true
+
+ - name: Add subnet to host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_subnet: "{{ host.subnet }}"
+ host_managed: false
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+ - name: delete host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: false
+
+ - name: create host with hostgroup
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_hostgroup: "{{ host.hostgroup }}"
+ host_managed: false
+ host_build: false
+ expected_change: true
+
+ - name: create host again with hostgroup, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_hostgroup: "{{ host.hostgroup }}"
+ host_managed: false
+ host_build: false
+ expected_change: false
+
+ - name: move host to child hostgroup
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_hostgroup: "{{ host.hostgroup }}/child_group"
+ host_managed: false
+ host_build: false
+ expected_change: true
+
+ - name: move host again to child hostgroup, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_hostgroup: "{{ host.hostgroup }}/child_group"
+ host_managed: false
+ host_build: false
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+ - name: delete host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: false
+
+ - name: create host with nested hostgroup
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_hostgroup: "{{ host.hostgroup }}/child_group"
+ host_managed: false
+ host_build: false
+ expected_change: true
+
+ - name: create host again with nested hostgroup, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_hostgroup: "{{ host.hostgroup }}/child_group"
+ host_managed: false
+ host_build: false
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+ - name: delete host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: false
+
+ - name: create host with ip and mac
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_ip: "192.0.2.23"
+ host_mac: "EE:FF:00:00:00:01"
+ host_managed: false
+ host_build: false
+ expected_change: true
+
+ - name: create host again with ip and mac
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_ip: "192.0.2.23"
+ host_mac: "EE:FF:00:00:00:01"
+ host_managed: false
+ host_build: false
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+ - name: create host with os and arch
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_operatingsystem: "{{ host.os.name }}"
+ host_architecture: "{{ host.arch }}"
+ expected_change: true
+
+ - name: create host with os and arch again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_operatingsystem: "{{ host.os.name }}"
+ host_architecture: "{{ host.arch }}"
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+ - name: create host with puppetclasses
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_environment: production
+ host_puppetclasses:
+ - "prometheus::redis_exporter"
+ expected_change: true
+
+ - name: create host with puppetclasses again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_environment: production
+ host_puppetclasses:
+ - "prometheus::redis_exporter"
+ expected_change: false
+
+ - name: update host with puppetclasses
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_environment: production
+ host_puppetclasses:
+ - "prometheus::haproxy_exporter"
+ expected_change: true
+
+ - name: update host with puppetclasses again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_environment: production
+ host_puppetclasses:
+ - "prometheus::haproxy_exporter"
+ expected_change: false
+
+ - name: update host with puppetclasses and description
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_description: nice host
+ host_environment: production
+ host_puppetclasses:
+ - "prometheus::redis_exporter"
+ expected_change: true
+
+ - name: update host with puppetclasses and description again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_description: nice host
+ host_environment: production
+ host_puppetclasses:
+ - "prometheus::redis_exporter"
+ expected_change: false
+
+ - name: remove puppetclasses from host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_puppetclasses: []
+ expected_change: true
+
+ - name: remove puppetclasses from host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ host_puppetclasses: []
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+ - name: create host in first org/loc
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_build: false
+ expected_change: true
+
+ - name: move host to second org/loc
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }} Secondary"
+ host_location: "{{ host.location }} Secondary"
+ host_managed: false
+ host_build: false
+ expected_change: true
+
+ - name: move host to second org/loc again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }} Secondary"
+ host_location: "{{ host.location }} Secondary"
+ host_managed: false
+ host_build: false
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: absent
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_state: absent
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "{{ host.hostgroup }}/child_group"
+ hostgroup_state: absent
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "{{ host.hostgroup }}"
+ hostgroup_state: absent
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }}"
+ subnet_mask: '255.255.255.224'
+ subnet_domains: []
+ subnet_state: present
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }}"
+ subnet_mask: '255.255.255.224'
+ subnet_state: absent
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ host.domain }}"
+ domain_state: absent
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "{{ host.os.name }}"
+ operatingsystem_state: absent
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "{{ host.arch }}"
+ architecture_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }} Secondary"
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }} Secondary"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }}"
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }}"
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/host_collection.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_collection.yml
new file mode 100644
index 000000000..2c21577d5
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_collection.yml
@@ -0,0 +1,82 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_state: present
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: ""
+ expected_diff_after: "name.*TheAnswer"
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_state: present
+ expected_change: false
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_name: "mycollection"
+ host_collection_state: present
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: ""
+ expected_diff_after: "name.*mycollection"
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_name: "mycollection"
+ host_collection_updated_name: "mycollection2"
+ host_collection_state: present
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "name.*mycollection"
+ expected_diff_after: "name.*mycollection2"
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_name: "mycollection2"
+ host_collection_state: present
+ expected_change: false
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_name: "mycollection2"
+ host_collection_state: present
+ expected_change: false
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_name: "mycollection2"
+ host_collection_state: absent
+ expected_change: true
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_state: absent
+ expected_change: true
+ - include_tasks: tasks/host_collection.yml
+ vars:
+ host_collection_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/host_errata_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_errata_info.yml
new file mode 100644
index 000000000..5f6f47177
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_errata_info.yml
@@ -0,0 +1,99 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_name: errata_key
+ activation_key_content_view: Default Organization View
+ activation_key_lifecycle_environment: Library
+ activation_key_subscriptions:
+ - name: "Test Product"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_url: "https://jlsherrill.fedorapeople.org/fake-repos/needed-errata/"
+ - name: sync product
+ include_tasks: tasks/katello_sync.yml
+
+- hosts: foreman
+ become: true
+ tasks:
+ - name: install katello-ca-consumer
+ package:
+ name: http://localhost/pub/katello-ca-consumer-latest.noarch.rpm
+ - name: subscribe to katello
+ command: subscription-manager register --org="Test_Organization" --activationkey="errata_key"
+ - name: install buggy walrus
+ package:
+ name: walrus-0.71-1
+
+- hosts: tests
+ gather_facts: false
+ collections:
+ - theforeman.foreman
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: get errata info
+ host_errata_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ host: "{{ foreman_host }}"
+ register: errata
+ - name: check results
+ assert:
+ that:
+ - errata.host_errata | length == 1
+ - errata.host_errata[0]['errata_id'] == 'RHEA-2012:0055'
+
+ - name: get errata info with CV and LCE
+ host_errata_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ host: "{{ foreman_host }}"
+ content_view: "Default Organization View"
+ lifecycle_environment: "Library"
+ register: errata
+ - name: check results
+ assert:
+ that:
+ - errata.host_errata | length == 1
+ - errata.host_errata[0]['errata_id'] == 'RHEA-2012:0055'
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/activation_key.yml
+ vars:
+ activation_key_name: errata_key
+ activation_key_state: absent
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/host_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_info.yml
new file mode 100644
index 000000000..78b0eb4ab
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_info.yml
@@ -0,0 +1,101 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }}"
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }}"
+ location_organizations:
+ - "{{ host.organization }}"
+ location_state: present
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ host.domain }}"
+ domain_locations:
+ - "{{ host.location }}"
+ domain_organizations:
+ - "{{ host.organization }}"
+ domain_state: present
+ - name: create host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - name: fetch host info
+ host_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "test-host.{{ host.domain }}"
+ organization: "{{ host.organization }}"
+ location: "{{ host.location }}"
+ register: host_info
+ - name: check host details
+ assert:
+ that:
+ - host_info['host']['name'] == "test-host.{{ host.domain }}"
+ - host_info['host']['domain_name'] == host.domain
+
+ - name: search host info
+ host_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ search: "name = test-host.{{ host.domain }}"
+ organization: "{{ host.organization }}"
+ location: "{{ host.location }}"
+ register: host_info
+ - name: check host details
+ assert:
+ that:
+ - host_info['hosts'][0]['name'] == "test-host.{{ host.domain }}"
+ - host_info['hosts'][0]['domain_name'] == host.domain
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ host.domain }}"
+ domain_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }}"
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }}"
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/host_interface_attributes.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_interface_attributes.yml
new file mode 100644
index 000000000..36f304b82
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_interface_attributes.yml
@@ -0,0 +1,323 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }}"
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }}"
+ location_organizations:
+ - "{{ host.organization }}"
+ location_state: present
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ host.domain }}"
+ domain_locations:
+ - "{{ host.location }}"
+ domain_organizations:
+ - "{{ host.organization }}"
+ domain_state: present
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }}"
+ subnet_network: '192.0.2.0'
+ subnet_mask: '255.255.255.0'
+ subnet_domains:
+ - "{{ host.domain }}"
+ subnet_locations:
+ - "{{ host.location }}"
+ subnet_organizations:
+ - "{{ host.organization }}"
+ subnet_state: present
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }} Secondary"
+ subnet_network: '198.51.100.0'
+ subnet_mask: '255.255.255.0'
+ subnet_domains:
+ - "{{ host.domain }}"
+ subnet_locations:
+ - "{{ host.location }}"
+ subnet_organizations:
+ - "{{ host.organization }}"
+ subnet_state: present
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "{{ host.hostgroup }}"
+ hostgroup_domain: "{{ host.domain }}"
+ hostgroup_locations:
+ - "{{ host.location }}"
+ hostgroup_organizations:
+ - "{{ host.organization }}"
+ hostgroup_state: present
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "{{ host.arch }}"
+ architecture_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "{{ host.os.name }}"
+ operatingsystem_major: "{{ host.os.major }}"
+ operatingsystem_minor: "{{ host.os.minor }}"
+ operatingsystem_family: "{{ host.os.family }}"
+ operatingsystem_architectures:
+ - "{{ host.arch }}"
+ operatingsystem_state: present
+ - include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - name: create host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - type: "interface"
+ identifier: "fam01"
+ ip: "192.0.2.23"
+ mac: "EE:FF:00:00:00:01"
+ subnet: "{{ host.subnet }}"
+ expected_change: true
+
+ - name: create host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - type: "interface"
+ identifier: "fam01"
+ ip: "192.0.2.23"
+ mac: "EE:FF:00:00:00:01"
+ subnet: "{{ host.subnet }}"
+ expected_change: false
+
+ - name: update host, add new interface
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - type: "interface"
+ identifier: "fam01"
+ ip: "192.0.2.23"
+ mac: "EE:FF:00:00:00:01"
+ subnet: "{{ host.subnet }}"
+ - type: "interface"
+ identifier: "fam02"
+ ip: "198.51.100.42"
+ mac: "EE:FF:00:00:00:02"
+ subnet: "{{ host.subnet }} Secondary"
+ expected_change: true
+
+ - name: update host, add new interface again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - type: "interface"
+ identifier: "fam01"
+ ip: "192.0.2.23"
+ mac: "EE:FF:00:00:00:01"
+ subnet: "{{ host.subnet }}"
+ - type: "interface"
+ identifier: "fam02"
+ ip: "198.51.100.42"
+ mac: "EE:FF:00:00:00:02"
+ subnet: "{{ host.subnet }} Secondary"
+ expected_change: false
+
+ - name: update host, delete interface
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - type: "interface"
+ identifier: "fam02"
+ ip: "198.51.100.42"
+ mac: "EE:FF:00:00:00:02"
+ subnet: "{{ host.subnet }} Secondary"
+ expected_change: true
+
+ - name: update host, delete interface again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - type: "interface"
+ identifier: "fam02"
+ ip: "198.51.100.42"
+ mac: "EE:FF:00:00:00:02"
+ subnet: "{{ host.subnet }} Secondary"
+ expected_change: false
+
+ - name: update host, make interfaces bond
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - identifier: eth0
+ mac: aa:bb:cc:dd:ee:ff
+ type: interface
+ managed: true
+ primary: false
+ provision: false
+ - identifier: eth1
+ mac: aa:bb:cc:dd:ee:ee
+ type: interface
+ managed: true
+ primary: false
+ provision: false
+ - identifier: bond0
+ mac: aa:bb:cc:dd:ee:ff
+ type: bond
+ managed: true
+ primary: true
+ provision: true
+ mode: 802.3ad
+ attached_devices:
+ - eth0
+ - eth1
+ bond_options: "miimon=100 lacp_rate=1"
+ ip: "192.0.2.100"
+ expected_change: true
+
+ - name: update host, make interfaces bond again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_organization: "{{ host.organization }}"
+ host_location: "{{ host.location }}"
+ host_managed: false
+ host_interfaces_attributes:
+ - identifier: eth0
+ mac: aa:bb:cc:dd:ee:ff
+ type: interface
+ managed: true
+ primary: false
+ provision: false
+ - identifier: eth1
+ mac: aa:bb:cc:dd:ee:ee
+ type: interface
+ managed: true
+ primary: false
+ provision: false
+ - identifier: bond0
+ mac: aa:bb:cc:dd:ee:ff
+ type: bond
+ managed: true
+ primary: true
+ provision: true
+ mode: 802.3ad
+ attached_devices:
+ - eth0
+ - eth1
+ bond_options: "miimon=100 lacp_rate=1"
+ ip: "192.0.2.100"
+ expected_change: false
+
+ - name: delete host
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: true
+
+ - name: delete host again, no change
+ include_tasks: tasks/host.yml
+ vars:
+ host_name: "test-host.{{ host.domain }}"
+ host_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/host.yml
+ tasks:
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "{{ host.hostgroup }}"
+ hostgroup_state: absent
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }}"
+ subnet_mask: '255.255.255.224'
+ subnet_domains: []
+ subnet_state: present
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }} Secondary"
+ subnet_mask: '255.255.255.224'
+ subnet_domains: []
+ subnet_state: present
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }}"
+ subnet_mask: '255.255.255.224'
+ subnet_state: absent
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ host.subnet }} Secondary"
+ subnet_mask: '255.255.255.224'
+ subnet_state: absent
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ host.domain }}"
+ domain_state: absent
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "{{ host.os.name }}"
+ operatingsystem_state: absent
+ - include_tasks: tasks/architecture.yml
+ vars:
+ architecture_name: "{{ host.arch }}"
+ architecture_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ host.location }}"
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ host.organization }}"
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/host_power.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_power.yml
new file mode 100644
index 000000000..1b8a127be
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/host_power.yml
@@ -0,0 +1,86 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ vars:
+ host_name: vm01.example.com
+ tasks:
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "off"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ vars:
+ host_name: vm01.example.com
+ tasks:
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "state"
+ expected_change: false
+ expected_power_state: "off"
+
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_hostname: "{{ host_name }}"
+ host_power_state: "state"
+ expected_change: false
+ expected_power_state: "off"
+
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "on"
+ expected_change: true
+
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "on"
+ expected_change: false
+
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "start"
+ expected_change: false
+
+ # Sometime host power state change is not reflected instantaneously
+ # and make this playbook fail when recording tests
+ - pause:
+ seconds: 5
+ when: recording is defined
+
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "off"
+ expected_change: true
+
+ # Sometime host power state change is not reflected instantaneously
+ # and make this playbook fail when recording tests
+ - pause:
+ seconds: 5
+ when: recording is defined
+
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "off"
+ expected_change: false
+
+ - include_tasks: tasks/host_power.yml
+ vars:
+ host_power_name: "{{ host_name }}"
+ host_power_state: "stop"
+ expected_change: false
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup.yml
new file mode 100644
index 000000000..88fa34835
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup.yml
@@ -0,0 +1,636 @@
+---
+## To record cassettes using this playbook (record_hostgroup)
+## some puppet classes need to be imported.
+## See comments in #582 for details. To import the classes run:
+##
+## $ puppet module install puppet-prometheus
+## $ hammer proxy import-classes --puppet-environment production --name $(hostname -f)
+##
+## You also need the libvirt compute resource support enabled:
+## $ foreman-installer --enable-foreman-compute-libvirt
+## And libvirt up and running:
+## $ dnf install libvirt
+## $ systemctl enable --now libvirtd
+## $ usermod -aG libvirt foreman
+##
+## You also need the proxy to be setup with the DNS feature:
+## $ foreman-installer --foreman-proxy-dns true
+##
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ - vars/compute_profile.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: present
+ with_items: "{{ hostgroup.locations }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: present
+ with_items: "{{ hostgroup.organizations }}"
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_organizations: "{{ hostgroup.organizations }}"
+ domain_locations: "{{ hostgroup.locations }}"
+ domain_name: "{{ item }}"
+ domain_dns_proxy: "{{ hostgroup.dns_proxy }}"
+ domain_state: present
+ with_items: "{{ hostgroup.domains }}"
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ hostgroup.subnet }}"
+ subnet_mask: '255.255.255.224'
+ subnet_domains: "{{ hostgroup.domains }}"
+ subnet_state: present
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: "{{ hostgroup.ptable }}"
+ ptable_os_family: "{{ hostgroup.os.family }}"
+ ptable_locations: "{{ hostgroup.locations }}"
+ ptable_organizations: "{{ hostgroup.organizations }}"
+ ptable_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "{{ hostgroup.os.name }}"
+ operatingsystem_major: "{{ hostgroup.os.major }}"
+ operatingsystem_minor: "{{ hostgroup.os.minor }}"
+ operatingsystem_family: "{{ hostgroup.os.family }}"
+ operatingsystem_architectures:
+ - "{{ hostgroup.arch }}"
+ operatingsystem_ptables:
+ - "{{ hostgroup.ptable }}"
+ operatingsystem_state: present
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: "{{ hostgroup.os.name }} Mirror"
+ installation_medium_operatingsystems:
+ - "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ installation_medium_locations: "{{ hostgroup.locations }}"
+ installation_medium_organizations: "{{ hostgroup.organizations }}"
+ installation_medium_state: present
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "{{ hostgroup.compute_resource.name }}"
+ compute_resource_organizations: "{{ hostgroup.organizations }}"
+ compute_resource_locations: "{{ hostgroup.locations }}"
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params: "{{ hostgroup.compute_resource.params }}"
+ compute_resource_state: present
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: "{{ hostgroup.compute_profile.name }}"
+ compute_profile_attributes:
+ - compute_resource: "{{ hostgroup.compute_resource.name }}"
+ vm_attrs: "{{ libvirt.compute_profile.attrs }}"
+ compute_profile_state: present
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_name: "{{ item }}"
+ config_group_state: present
+ with_items: "{{ hostgroup.config_groups }}"
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_compute_resource: "{{ hostgroup.compute_resource.name }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with puppet classes"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_compute_resource: "{{ hostgroup.compute_resource.name }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_puppetclasses:
+ - "prometheus::redis_exporter"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with puppet classes"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_puppetclasses:
+ - "prometheus::redis_exporter"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with puppet classes"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_puppetclasses:
+ - "prometheus::redis_exporter"
+ - "prometheus::statsd_exporter"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with puppet classes"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_puppetclasses:
+ - "prometheus::statsd_exporter"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with puppet classes"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_puppetclasses:
+ - "prometheus::statsd_exporter"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with puppet classes"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_puppetclasses:
+ - "prometheus::statsd_exporter"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_description: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ # The foreman api does not report the compute_resource_id/name; we cannot test this
+ # See also https://projects.theforeman.org/issues/27460
+ # hostgroup_compute_resource: "{{ hostgroup.compute_resource.name }}"
+ hostgroup_compute_profile: "{{ hostgroup.compute_profile.name }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_environment: "production"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_config_groups: "{{ hostgroup.config_groups }}"
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Nested New host group"
+ hostgroup_description: "Nested group"
+ hostgroup_parent: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Nested New host group"
+ hostgroup_description: "Nested group"
+ hostgroup_parent: "New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with nested parent"
+ hostgroup_description: "Nested group"
+ hostgroup_parent: "New host group/Nested New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group with nested parent"
+ hostgroup_description: "Nested group"
+ hostgroup_parent: "New host group/Nested New host group"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_domain: "{{ hostgroup.domains | first }}"
+ hostgroup_subnet: "{{ hostgroup.subnet }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "Grub2 UEFI"
+ hostgroup_puppet_proxy: "{{ hostgroup.puppet_server }}"
+ hostgroup_puppet_ca_proxy: "{{ hostgroup.puppet_ca }}"
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 2"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "PXELinux BIOS"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 2"
+ hostgroup_architecture: "{{ hostgroup.arch }}"
+ hostgroup_operatingsystem: "{{ hostgroup.os.name }} {{ hostgroup.os.major }}.{{ hostgroup.os.minor }}"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_installation_medium: "{{ hostgroup.os.name }} Mirror"
+ hostgroup_ptable: "{{ hostgroup.ptable }}"
+ hostgroup_pxe_loader: "PXELinux BIOS"
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: new_value1
+ - name: subnet_param3
+ value: value3
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_parameters:
+ - name: subnet_param1
+ value: new_value1
+ - name: subnet_param3
+ value: value3
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Super New host group"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Super New host group"
+ hostgroup_updated_name: "Super New host group 2"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Super New host group 2"
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 1"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 1"
+ hostgroup_updated_name: "Nested New host group 10"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 10"
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 10"
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 2"
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group 2"
+ hostgroup_state: absent
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group/New host group with nested parent"
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Nested New host group/New host group with nested parent"
+ hostgroup_state: absent
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Nested New host group"
+ hostgroup_parent: "New host group"
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "Nested New host group"
+ hostgroup_parent: "New host group"
+ hostgroup_state: absent
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_root_pass: "changeme"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_root_pass: "changeme"
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group/Whatever Child"
+ hostgroup_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/config_group.yml
+ vars:
+ config_group_name: "{{ item }}"
+ config_group_state: absent
+ with_items: "{{ hostgroup.config_groups }}"
+ # There is chicken and egg problem with subnet-domains relation, so we have to
+ # dissociate subnets and domains before delete
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ hostgroup.subnet }}"
+ subnet_domains: []
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_organizations: "{{ hostgroup.organizations }}"
+ domain_locations: "{{ hostgroup.locations }}"
+ domain_name: "{{ item }}"
+ domain_state: absent
+ with_items: "{{ hostgroup.domains }}"
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "{{ hostgroup.subnet }}"
+ subnet_mask: '255.255.255.224'
+ subnet_state: absent
+ - include_tasks: tasks/compute_profile.yml
+ vars:
+ compute_profile_name: "{{ hostgroup.compute_profile.name }}"
+ compute_profile_state: absent
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_profile_name: "{{ hostgroup.compute_profile.name }}"
+ compute_resource_provider: 'libvirt'
+ compute_resource_state: absent
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "{{ hostgroup.os.name }}"
+ operatingsystem_major: "{{ hostgroup.os.major }}"
+ operatingsystem_minor: "{{ hostgroup.os.minor }}"
+ operatingsystem_state: absent
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: "{{ hostgroup.ptable }}"
+ ptable_state: absent
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: "{{ hostgroup.os.name }} Mirror"
+ installation_medium_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "absent"
+ with_items: "{{ hostgroup.locations | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ with_items: "{{ hostgroup.organizations }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup_info.yml
new file mode 100644
index 000000000..3ded0bf1e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroup_info.yml
@@ -0,0 +1,49 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars:
+ test_hostgroup: "test_hostgroup"
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch hostgroup info
+ hostgroup_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ test_hostgroup }}"
+ register: hostgroup_info
+ - debug: var=hostgroup_info
+ - name: check hostgroup details
+ assert:
+ that:
+ - hostgroup_info['hostgroup']['name'] == test_hostgroup
+ - "'name' in hostgroup_info['hostgroup']"
+
+ - name: search hostgroup info
+ hostgroup_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ search: "name ~ {{ test_hostgroup }}"
+ register: hostgroup_info
+ - name: check hostgroup details
+ assert:
+ that:
+ - hostgroup_info['hostgroups'][0]['name'] == test_hostgroup
+ - "'name' in hostgroup_info['hostgroups'][0]"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroups_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroups_role.yml
new file mode 100644
index 000000000..5b45b4e01
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/hostgroups_role.yml
@@ -0,0 +1,29 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: hostgroups
+ vars:
+ foreman_hostgroups:
+ - name: Hostgroup1
+ - name: Hostgroup2
+ parent: Hostgroup1
+ - name: Hostgroup3
+ architecture: "x86_64"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/http_proxy.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/http_proxy.yml
new file mode 100644
index 000000000..20ca7d5e3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/http_proxy.yml
@@ -0,0 +1,118 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: "present"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: create http_proxy
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "present"
+ http_proxy_name: "example.org Proxy"
+ http_proxy_url: "http://example.org:3128"
+ expected_change: true
+ - name: create http_proxy again, no change
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "present"
+ http_proxy_name: "example.org Proxy"
+ http_proxy_url: "http://example.org:3128"
+ expected_change: false
+ - name: delete http_proxy
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "absent"
+ http_proxy_name: "example.org Proxy"
+ expected_change: true
+ - name: delete http_proxy again, no change
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "absent"
+ http_proxy_name: "example.org Proxy"
+ expected_change: false
+
+ - name: create http_proxy with user/pass
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "present"
+ http_proxy_name: "example.org Proxy"
+ http_proxy_url: "http://example.org:3128"
+ http_proxy_username: "proxyuser"
+ http_proxy_password: "proxypass"
+ expected_change: true
+ - name: create http_proxy with user again, no change
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "present"
+ http_proxy_name: "example.org Proxy"
+ http_proxy_url: "http://example.org:3128"
+ http_proxy_username: "proxyuser"
+ # don't set http_proxy_password here
+ expected_change: false
+ - name: update http_proxy with org/loc
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "present"
+ http_proxy_name: "example.org Proxy"
+ http_proxy_organizations:
+ - "Test Organization"
+ http_proxy_locations:
+ - "Test Location"
+ expected_change: true
+ - name: update http_proxy with org/loc, no change
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "present"
+ http_proxy_name: "example.org Proxy"
+ http_proxy_organizations:
+ - "Test Organization"
+ http_proxy_locations:
+ - "Test Location"
+ expected_change: false
+ - name: delete http_proxy
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "absent"
+ http_proxy_name: "example.org Proxy"
+ expected_change: true
+ - name: delete http_proxy again, no change
+ include_tasks: tasks/http_proxy.yml
+ vars:
+ http_proxy_state: "absent"
+ http_proxy_name: "example.org Proxy"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "absent"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/image.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/image.yml
new file mode 100644
index 000000000..4f30fd937
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/image.yml
@@ -0,0 +1,205 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "MYCR"
+ compute_resource_state: present
+ compute_resource_provider: libvirt
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "MYOS SP1"
+ operatingsystem_name: "MYOS"
+ operatingsystem_minor: 1
+ operatingsystem_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "MY2NDOS"
+ operatingsystem_name: "MY2NDOS"
+ operatingsystem_minor: 1
+ operatingsystem_state: present
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "MYOS SP1"
+ - "MY2NDOS"
+ architecture_name: "MY1024"
+ architecture_state: present
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "MYCR"
+ compute_resource_description: 'A compute_resource'
+ compute_resource_provider: 'libvirt'
+ compute_resource_provider_params:
+ url: qemu+ssh://root@libvirt.example.com/system
+ display_type: spice
+ compute_resource_state: present
+ - include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MYOStemplate"
+ image_username: "myosadmin"
+ image_operatingsystem: "MYOS SP1"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: absent
+ - include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MY2NDOStemplate"
+ image_username: "myosadmin"
+ image_operatingsystem: "MY2NDOS"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: absent
+
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: 'MYIMAGE'
+ block:
+ - name: Create MYIMAGE
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MYOStemplate"
+ image_username: "myosadmin"
+ image_operatingsystem: "MYOS SP1"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: present
+ expected_change: true
+ - name: Do not change MYIMAGE
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MYOStemplate"
+ image_username: "myosadmin"
+ image_operatingsystem: "MYOS SP1"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: present
+ expected_change: false
+ - name: Modify MYIMAGE
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MYOStemplate-new"
+ image_username: "myosadmin"
+ image_operatingsystem: "MYOS SP1"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_user_data: true
+ image_state: present
+ expected_change: true
+ - name: Create MY2NDIMAGE with same name
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MY2NDOStemplate"
+ image_username: "myosadmin"
+ image_operatingsystem: "MY2NDOS"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: present
+ expected_change: true
+ - name: Do not change MY2NDIMAGE
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MY2NDOStemplate"
+ image_username: "myosadmin"
+ image_operatingsystem: "MY2NDOS"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: present
+ expected_change: false
+ - name: Do not change MYIMAGE
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MYOStemplate-new"
+ image_username: "myosadmin"
+ image_operatingsystem: "MYOS SP1"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: present
+ expected_change: false
+ - name: Delete MYIMAGE
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MYOStemplate"
+ image_username: "myosadmin"
+ image_operatingsystem: "MYOS SP1"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_user_data: false
+ image_state: absent
+ expected_change: true
+ - name: Delete MY2NDIMAGE
+ include_tasks: tasks/image.yml
+ vars:
+ image_name: "MYOS 1"
+ image_uuid: "MY2NDOStemplate-new"
+ image_username: "myosadmin"
+ image_operatingsystem: "MY2NDOS"
+ image_compute_resource: "MYCR"
+ image_architecture: "MY1024"
+ image_state: absent
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/architecture.yml
+ vars:
+ operatingsystems:
+ - "MYOS SP1"
+ - "MY2NDOS"
+ architecture_name: "MY1024"
+ architecture_state: absent
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "MYOS SP1"
+ operatingsystem_minor: 1
+ operatingsystem_state: absent
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "MY2NDOS"
+ operatingsystem_minor: 1
+ operatingsystem_state: absent
+ - include_tasks: tasks/compute_resource.yml
+ vars:
+ compute_resource_name: "MYCR"
+ compute_resource_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/installation_medium.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/installation_medium.yml
new file mode 100644
index 000000000..bf10b4aee
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/installation_medium.yml
@@ -0,0 +1,138 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ operatingsystem_name: "TempleOS"
+
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_state: present
+ expected_change: true
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_state: present
+ installation_medium_os_family: Debian
+ expected_change: false
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: "SuperOS OS 1.0"
+ installation_medium_path: "https://superos.org/"
+ installation_medium_state: present
+ expected_change: true
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: "SuperOS OS 1.0"
+ installation_medium_updated_name: "SuperOS-NG OS 1.0"
+ installation_medium_path: "https://superos.org/"
+ installation_medium_state: present
+ expected_change: true
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: "SuperOS-NG OS 1.0"
+ installation_medium_path: "https://superos.org/"
+ installation_medium_state: present
+ expected_change: false
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: "SuperOS-NG OS 1.0"
+ installation_medium_state: absent
+ expected_change: true
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: 'another os'
+ installation_medium_path: 'http://example.org/another.iso'
+ installation_medium_locations: "{{ omit }}"
+ installation_medium_state: present
+ expected_change: true
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_path: 'http://example.org/iso'
+ installation_medium_state: present
+ expected_change: true
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_state: absent
+ expected_change: true
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_state: absent
+ expected_change: false
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: '*'
+ installation_medium_operatingsystems: "{{ omit }}"
+ installation_medium_organizations: "{{ omit }}"
+ installation_medium_path: "{{ omit }}"
+ installation_medium_state: present
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: ""
+ expected_diff_after: "location_ids"
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: '*'
+ installation_medium_operatingsystems: "{{ omit }}"
+ installation_medium_organizations: "{{ omit }}"
+ installation_medium_path: "{{ omit }}"
+ installation_medium_state: present
+ expected_change: false
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: '*'
+ installation_medium_operatingsystems: "{{ omit }}"
+ installation_medium_locations: "{{ omit }}"
+ installation_medium_organizations: "{{ omit }}"
+ installation_medium_path: "{{ omit }}"
+ installation_medium_state: absent
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "name"
+ expected_diff_after: "{}"
+ - include_tasks: tasks/installation_medium.yml
+ vars:
+ installation_medium_name: '*'
+ installation_medium_operatingsystems: "{{ omit }}"
+ installation_medium_locations: "{{ omit }}"
+ installation_medium_organizations: "{{ omit }}"
+ installation_medium_path: "{{ omit }}"
+ installation_medium_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin.yml
new file mode 100644
index 000000000..d9cf9915b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin.yml
@@ -0,0 +1,25 @@
+---
+- hosts: container
+ vars:
+ foreman_groups:
+ - name: group_a
+ - name: group_b
+ - name: group_c
+ label: group_b/group_c
+ parent: group_b
+ foreman_hosts:
+ testhost1.example.com: group_a
+ testhost2.example.com: group_b/group_c
+ foreman_container: "quay.io/foreman/foreman"
+ foreman_version: "2.3-stable"
+ foreman_host: "foreman"
+ foreman_port: "3000"
+ postgres_version: "12"
+ postgres_host: "postgres"
+ postgres_port: 5432
+ collections:
+ - community.docker
+ - theforeman.foreman
+ tasks:
+ - name: test inventory
+ include_tasks: tasks/inventory_plugin.yml
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin_ansible.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin_ansible.yml
new file mode 100644
index 000000000..40029a3b3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/inventory_plugin_ansible.yml
@@ -0,0 +1,25 @@
+---
+- hosts: container
+ vars:
+ foreman_groups:
+ - name: group_a
+ - name: group_b
+ - name: group_c
+ label: group_b/group_c
+ parent: group_b
+ foreman_hosts:
+ testhost1.example.com: group_a
+ testhost2.example.com: group_b/group_c
+ foreman_container: "quay.io/evgeni/foreman-ansible"
+ foreman_version: "2.3-ansible"
+ foreman_host: "foremanansible"
+ foreman_port: "3001"
+ postgres_version: "12"
+ postgres_host: "postgresansible"
+ postgres_port: 5433
+ collections:
+ - community.docker
+ - theforeman.foreman
+ tasks:
+ - name: test inventory
+ include_tasks: tasks/inventory_plugin.yml
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/job_invocation.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/job_invocation.yml
new file mode 100644
index 000000000..de146e7c5
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/job_invocation.yml
@@ -0,0 +1,44 @@
+# registered host expected
+
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch status
+ include_tasks: tasks/status_info.yml
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ vars:
+ tasks:
+ - name: "Run remote command on a single host once"
+ job_invocation:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ search_query: "{{ foreman_host }}"
+ command: 'ls'
+ job_template: 'Run Command - SSH Default'
+ validate_certs: "{{ foreman_validate_certs }}"
+
+ - name: "Run Ansible command on active hosts once a day"
+ job_invocation:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ command: 'pwd'
+ bookmark: 'ok hosts'
+ job_template: 'Run Command - Ansible Default'
+ validate_certs: "{{ foreman_validate_certs }}"
+ recurrence:
+ cron_line: "30 2 * * *"
+ concurrency_control:
+ concurrency_level: 2
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/job_template.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/job_template.yml
new file mode 100644
index 000000000..912c48f0b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/job_template.yml
@@ -0,0 +1,189 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_state: absent
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_name: "{{ item }}"
+ job_template_state: absent
+ loop:
+ - "configure flux compensator"
+ - "Ansible Roles - Hello World"
+ - "delete file"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_state: present
+ job_template_audit_comment: "create job template"
+ expected_change: true
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_state: present
+ job_template_audit_comment: "don't update job template"
+ expected_change: false
+ - include_tasks: tasks/job_template.yml
+ vars:
+ template_inputs:
+ - name: "newer input"
+ input_type: "user"
+ job_template_state: present
+ expected_change: true
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_template: 'A job template with an template'
+ job_template_state: present
+ expected_change: true
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_state: absent
+ expected_change: true
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_state: absent
+ expected_change: false
+
+ - include_tasks: tasks/job_template_from_file.yml
+ vars:
+ job_template_state: present
+ job_template_file_name: "data/delete_file.erb"
+ job_template_locations:
+ - "Test Location"
+ job_template_organizations:
+ - "Test Organization"
+ expected_change: true
+
+ - name: Add the same template input via direct input
+ include_tasks: tasks/job_template.yml
+ vars:
+ job_template_name: delete file
+ job_template_job_category: Commands
+ job_template_description_format: "delete %{file}"
+ job_template_provider_type: SSH
+ template_inputs:
+ - name: file
+ description: file to delete
+ input_type: user
+ required: true
+ job_template_template: |
+ <%#
+ kind: job_template
+ name: delete file
+ job_category: Commands
+ description_format: "delete %{file}"
+ provider_type: SSH
+ template_inputs:
+ - name: file
+ description: file to delete
+ input_type: user
+ required: true
+ %>
+ rm -rf --no-preserve-root <%= input("file") %>
+ job_template_state: present
+ expected_change: false
+
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_name: delete file
+ job_template_state: absent
+ expected_change: true
+
+ - name: Add Ansible template with implicit provider_type
+ include_tasks: tasks/job_template_from_file.yml
+ vars:
+ job_template_state: present
+ job_template_file_name: "data/ansible_hello.erb"
+ job_template_locations:
+ - "Test Location"
+ expected_change: true
+
+ - name: Add the same template input via direct input with explicit provider_type
+ include_tasks: tasks/job_template.yml
+ vars:
+ job_template_name: Ansible Roles - Hello World
+ job_template_job_category: Ansible Playbook
+ job_template_description_format: "Test Ansible Roles"
+ job_template_provider_type: Ansible
+ job_template_organizations: "{{ omit }}"
+ template_inputs:
+ job_template_template: |
+ <%#
+ name: Ansible Roles - Hello World
+ job_category: Ansible Playbook
+ description_format: Test Ansible Roles
+ feature: ansible_run_host
+ snippet: false
+ provider_type: Ansible
+ kind: job_template
+ model: JobTemplate
+ %>
+
+ ---
+ - hosts: all
+ tasks:
+ - name: Hello
+ debug:
+ msg: Hello World
+ ...
+ job_template_state: present
+ expected_change: false
+ - name: assign all job templates the same organization
+ include_tasks: tasks/job_template.yml
+ vars:
+ job_template_name: '*'
+ job_template_locations: "{{ omit }}"
+ job_template_provider_type: "{{ omit }}"
+ job_template_template: "{{ omit }}"
+ template_inputs: "{{ omit }}"
+ job_template_state: present
+ expected_change: true
+ - name: assign all job templates the same organization
+ include_tasks: tasks/job_template.yml
+ vars:
+ job_template_name: '*'
+ job_template_locations: "{{ omit }}"
+ job_template_provider_type: "{{ omit }}"
+ job_template_template: "{{ omit }}"
+ template_inputs: "{{ omit }}"
+ job_template_state: present
+ expected_change: false
+
+ - include_tasks: tasks/job_template.yml
+ vars:
+ job_template_name: Ansible Roles - Hello World
+ job_template_state: absent
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/katello_hostgroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/katello_hostgroup.yml
new file mode 100644
index 000000000..224b5282d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/katello_hostgroup.yml
@@ -0,0 +1,175 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: present
+ with_items: "{{ hostgroup.locations }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: present
+ with_items: "{{ hostgroup.organizations }}"
+ - include_tasks: tasks/content_view.yml
+ vars:
+ organization_name: "{{ hostgroup.organizations | first }}"
+ content_view_name: "{{ hostgroup.content_view.name }}"
+ - include_tasks: tasks/content_view_version.yml
+ vars:
+ organization_name: "{{ hostgroup.organizations | first }}"
+ content_view_name: "{{ hostgroup.content_view.name }}"
+ lifecycle_environments: "{{ hostgroup.lifecycle_environment }}"
+ version: "{{ hostgroup.content_view.version }}"
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - name: create HG
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_organization: "{{ hostgroup.organizations | first }}"
+ hostgroup_content_source: "{{ hostgroup.content_source }}"
+ hostgroup_lifecycle_environment: "{{ hostgroup.lifecycle_environment }}"
+ hostgroup_content_view: "{{ hostgroup.content_view.name }}"
+ hostgroup_parameters:
+ - name: test_param_one
+ parameter_type: string
+ value: oneoneone
+ hostgroup_activation_keys: key_one
+ hostgroup_state: present
+ expected_change: true
+
+ - name: create HG again, no change
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_organization: "{{ hostgroup.organizations | first }}"
+ hostgroup_content_source: "{{ hostgroup.content_source }}"
+ hostgroup_lifecycle_environment: "{{ hostgroup.lifecycle_environment }}"
+ hostgroup_content_view: "{{ hostgroup.content_view.name }}"
+ hostgroup_parameters:
+ - name: test_param_one
+ parameter_type: string
+ value: oneoneone
+ hostgroup_activation_keys: key_one
+ hostgroup_state: present
+ expected_change: false
+
+ - name: only set AK, HG should not lose params, no change
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_organization: "{{ hostgroup.organizations | first }}"
+ hostgroup_activation_keys: key_one
+ hostgroup_state: present
+ expected_change: false
+
+ - name: only set params, HG should not lose AK, no change
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_organization: "{{ hostgroup.organizations | first }}"
+ hostgroup_parameters:
+ - name: test_param_one
+ parameter_type: string
+ value: oneoneone
+ hostgroup_state: present
+ expected_change: false
+
+ - name: only set AK via params
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_organization: "{{ hostgroup.organizations | first }}"
+ hostgroup_parameters:
+ - name: kt_activation_keys
+ parameter_type: string
+ value: new_key
+ hostgroup_state: present
+ expected_change: true
+
+ - name: only set AK via params, again, no change
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_organization: "{{ hostgroup.organizations | first }}"
+ hostgroup_parameters:
+ - name: kt_activation_keys
+ parameter_type: string
+ value: new_key
+ hostgroup_state: present
+ expected_change: false
+
+ - name: delete HG
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+ expected_change: true
+
+ - name: delete HG again, no change
+ include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ # There is no way for now to un publish content view version via ansible
+ # so we cannot cleanup content related stuff
+ # - include_tasks: tasks/content_view_version.yml
+ # vars:
+ # organization_name: "{{ hostgroup.organizations | first }}"
+ # content_view_name: "{{ hostgroup.content_view.name }}"
+ # version: "{{ hostgroup.content_view.version }}"
+ # state: absent
+ # - include_tasks: tasks/content_view.yml
+ # vars:
+ # organization_name: "{{ hostgroup.organizations | first }}"
+ # content_view_name: "{{ hostgroup.content_view.name }}"
+ # content_view_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "absent"
+ with_items: "{{ hostgroup.locations | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ # As we cannot cleanup content stuff we have to let the org used for it in place
+ #with_items: "{{ hostgroup.organizations }}"
+ with_items: "{{ hostgroup.organizations | difference([hostgroup.organizations | first]) }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/katello_smart_proxy.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/katello_smart_proxy.yml
new file mode 100644
index 000000000..437a9f7c3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/katello_smart_proxy.yml
@@ -0,0 +1,112 @@
+---
+# Do not do this on a production machine!
+#
+# To run recording for this test, you need to:
+# - run a smart proxy box (e.g. centos7-foreman-proxy-3.17)
+# - configure /etc/hosts on both machines
+# o foreman.example.com -> main foreman server
+# o foreman-proxy.example.com -> smart proxy
+# - configure your smart proxy to listen to http on 8000
+# - configure your smart proxy to trust anything
+# - restart your smart proxy
+# - disable selinux enforcing
+# - record before puppet takes back those changes
+#
+# setenforce 0
+# foreman-installer --foreman-proxy-http true --foreman-proxy-http-port 8000 --disable-system-checks \
+# --foreman-proxy-trusted-hosts=EMPTY_ARRAY
+#
+# Do not do this on a production machine!
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: "present"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_name: "{{ item.name }}"
+ lifecycle_environment_label: "{{ item.label }}"
+ lifecycle_environment_prior: "{{ item.prior }}"
+ loop:
+ - name: Dev
+ label: dev
+ prior: Library
+ - name: Test
+ label: test
+ prior: Dev
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: present
+ smart_proxy_lifecycle_environments:
+ - 'Dev'
+ expected_change: true
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: present
+ smart_proxy_lifecycle_environments:
+ - 'Dev'
+ expected_change: false
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: present
+ smart_proxy_lifecycle_environments:
+ - 'Test'
+ expected_change: true
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: present
+ smart_proxy_lifecycle_environments:
+ - 'Test'
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_download_policy: background
+ smart_proxy_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_download_policy: background
+ smart_proxy_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+ expected_change: true
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environment.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environment.yml
new file mode 100644
index 000000000..4dd30dfb2
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environment.yml
@@ -0,0 +1,112 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: absent
+ lifecycle_environment_name: "{{ item }}"
+ lifecycle_environment_label:
+ loop:
+ - Production
+ - Test
+ - Dev
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_label: "dev"
+ lifecycle_environment_description: "The dev environment"
+ expected_change: true
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ expected_change: false
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_name: "Test"
+ lifecycle_environment_label: "test"
+ lifecycle_environment_prior: "Dev"
+ lifecycle_environment_description: "The test environment"
+ expected_change: true
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_name: "Test"
+ lifecycle_environment_label: "test"
+ lifecycle_environment_prior: "Dev"
+ expected_change: false
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_name: "Production"
+ lifecycle_environment_label: "production"
+ lifecycle_environment_prior: "Test"
+ lifecycle_environment_description: "The prod environment"
+ expected_change: true
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: present
+ lifecycle_environment_name: "Test"
+ lifecycle_environment_description: "The new test environment"
+ expected_change: true
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: absent
+ lifecycle_environment_name: "Production"
+ expected_change: true
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: absent
+ lifecycle_environment_name: "Test"
+ expected_change: true
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: absent
+ lifecycle_environment_name: "Test"
+ expected_change: false
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: absent
+ lifecycle_environment_name: "Dev"
+ expected_change: true
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: absent
+ lifecycle_environment_name: "Dev"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/lifecycle_environment.yml
+ vars:
+ lifecycle_environment_state: absent
+ lifecycle_environment_name: "{{ item }}"
+ loop:
+ - Production
+ - Test
+ - Dev
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environments_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environments_role.yml
new file mode 100644
index 000000000..4234225e8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/lifecycle_environments_role.yml
@@ -0,0 +1,31 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: lifecycle_environments
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_lifecycle_environments:
+ - name: "Dev"
+ prior: "Library"
+ - name: "Test"
+ prior: "Dev"
+ - name: "Prod"
+ prior: "Test"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/location.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/location.yml
new file mode 100644
index 000000000..3b674a1ca
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/location.yml
@@ -0,0 +1,216 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: absent
+ with_items:
+ - Test Location/Sub Location 1/Sub Location 2
+ - Test Location/Sub Location 1
+ - Test Location/Sub Location 2
+ - Test Location
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Test Location
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Test Location
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Sub Location 1
+ location_parent: Test Location
+ location_organizations:
+ - Test Organization
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Sub Location 1
+ location_parent: Test Location
+ location_organizations:
+ - Test Organization
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Sub Location 2
+ location_parent: Test Location/Sub Location 1
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Sub Location 2
+ location_parent: Test Location/Sub Location 1
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Test Location/Sub Location 1/Sub Location 2
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Test Location/Sub Location 1/Sub Location 2
+ location_organizations:
+ - Test Organization
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ location_name: Test Location/Sub Location 2
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ location_name: Test Location
+ # TODO checkmode does not realize the impossibility of removing the parent
+ expected_change: "{{ ansible_check_mode }}"
+ expected_error: "{{ not ansible_check_mode }}"
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ location_name: Test Location/Sub Location 1/Sub Location 2
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ location_name: Sub Location 1
+ location_parent: Test Location
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ location_name: Test Location/Sub Location 2
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ location_name: Sub Location 1
+ location_parent: Test Location
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ location_name: Test Location/Sub Location 2
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ location_name: Test Location
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_parameters:
+ - name: my_param
+ value: my value
+ - name: my_param2
+ parameter_type: string
+ value: my other value
+ - name: my_param3
+ parameter_type: array
+ value:
+ - array
+ - value
+ location_state: present
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_parameters:
+ - name: my_param
+ value: my value
+ - name: my_param2
+ parameter_type: string
+ value: my other value
+ - name: my_param3
+ parameter_type: array
+ value:
+ - array
+ - value
+ location_state: present
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_parameters:
+ - name: my_param
+ value: my value
+ location_state: present
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_parameters:
+ - name: my_param
+ value: my value
+ location_state: present
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_parameters: []
+ location_state: present
+ expected_change: true
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ expected_change: false
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ expected_change: true
+
+ - name: Try to delete location with not existing parent
+ include_tasks: tasks/location.yml
+ vars:
+ location_name: NonExistant/SubLocation
+ location_state: absent
+ expected_change: false
+ expected_error: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: absent
+ with_items:
+ - Test Location/Sub Location 1/Sub Location 2
+ - Test Location/Sub Location 1
+ - Test Location/Sub Location 2
+ - Test Location
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/luna_hostgroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/luna_hostgroup.yml
new file mode 100644
index 000000000..dad059b67
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/luna_hostgroup.yml
@@ -0,0 +1,105 @@
+# `ansible-galaxy role install thulium_drake.motd -p /usr/share/ansible/roles`
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: present
+ with_items: "{{ hostgroup.locations }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: present
+ with_items: "{{ hostgroup.organizations }}"
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_openscap_proxy: "{{ hostgroup.openscap_proxy }}"
+ hostgroup_ansible_roles:
+ - thulium_drake.motd
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_openscap_proxy: "{{ hostgroup.openscap_proxy }}"
+ hostgroup_ansible_roles:
+ - thulium_drake.motd
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_openscap_proxy: "{{ hostgroup.openscap_proxy }}"
+ hostgroup_ansible_roles: []
+ hostgroup_state: present
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_locations: "{{ hostgroup.locations }}"
+ hostgroup_organizations: "{{ hostgroup.organizations }}"
+ hostgroup_openscap_proxy: "{{ hostgroup.openscap_proxy }}"
+ hostgroup_ansible_roles: []
+ hostgroup_state: present
+ expected_change: false
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: "New host group"
+ hostgroup_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/hostgroup.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "absent"
+ with_items: "{{ hostgroup.locations | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ with_items: "{{ hostgroup.organizations }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/manifest_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/manifest_role.yml
new file mode 100644
index 000000000..23d727814
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/manifest_role.yml
@@ -0,0 +1,26 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: manifest
+ vars:
+ foreman_manifest_download: false
+ foreman_manifest_path: "{{ subscription_manifest_path }}"
+ foreman_organization: "Test Organization"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/module_defaults.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/module_defaults.yml
new file mode 100644
index 000000000..4544a4a10
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/module_defaults.yml
@@ -0,0 +1,36 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch status
+ include_tasks: tasks/status_info.yml
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ module_defaults:
+ group/theforeman.foreman.foreman:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ tasks:
+ - name: fetch status info (no FQCN)
+ status_info:
+
+ - name: fetch setting info (FQCN)
+ theforeman.foreman.setting_info:
+ name: "login_text"
+ register: setting_info
+ - name: check setting details
+ assert:
+ that:
+ - setting_info['setting']['name'] == "login_text"
+ - setting_info['setting']['value'] == ''
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystem.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystem.yml
new file mode 100644
index 000000000..b0188f45f
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystem.yml
@@ -0,0 +1,122 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: absent
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "{{ operatingsystem_name}} SP1"
+ operatingsystem_minor: "1"
+ operatingsystem_state: absent
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "{{ operatingsystem_name}} SP1"
+ operatingsystem_minor: "1"
+ operatingsystem_state: present
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ expected_change: false
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ operatingsystem_parameters:
+ - name: param1
+ value: value1
+ - name: param2
+ value: '{"value2":"value2"}'
+ parameter_type: json
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ operatingsystem_parameters:
+ - name: param1
+ value: value1
+ - name: param2
+ value: '{"value2":"value2"}'
+ parameter_type: json
+ expected_change: false
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ operatingsystem_parameters:
+ - name: param1
+ value: new_value1
+ - name: param3
+ value: '{"value3":"value3"}'
+ parameter_type: json
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ operatingsystem_parameters:
+ - name: param1
+ value: new_value1
+ - name: param3
+ value: '{"value3":"value3"}'
+ parameter_type: json
+ expected_change: false
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ operatingsystem_parameters: []
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "SuperOS"
+ operatingsystem_state: present
+ operatingsystem_parameters: []
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "SuperOS"
+ operatingsystem_updated_name: "SuperOS-NG"
+ operatingsystem_state: present
+ operatingsystem_parameters: []
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "SuperOS-NG"
+ operatingsystem_state: present
+ operatingsystem_parameters: []
+ expected_change: false
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "SuperOS-NG"
+ operatingsystem_state: absent
+ operatingsystem_parameters: []
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: absent
+ expected_change: true
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: absent
+ expected_change: false
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_description: "{{ operatingsystem_name}} SP1"
+ operatingsystem_minor: "1"
+ operatingsystem_state: absent
+ expected_change: true
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystems_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystems_role.yml
new file mode 100644
index 000000000..49603e282
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/operatingsystems_role.yml
@@ -0,0 +1,70 @@
+---
+- name: Setup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - name: ensure test location
+ include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "RedHat"
+ operatingsystem_major: "8"
+ operatingsystem_minor: "5"
+ operatingsystem_state: "absent"
+
+- name: Tests
+ hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: operatingsystems
+ vars:
+ foreman_operatingsystems:
+ - name: RedHat
+ major: "8"
+ minor: "5"
+ os_family: Redhat
+ password_hash: "SHA256"
+ default_templates:
+ - template_kind: cloud-init
+ provisioning_template: CloudInit default
+ - template_kind: user_data
+ provisioning_template: UserData open-vm-tools
+
+- name: Cleanup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_name: "RedHat"
+ operatingsystem_major: "8"
+ operatingsystem_minor: "5"
+ operatingsystem_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/organization.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/organization.yml
new file mode 100644
index 000000000..b716abfb4
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/organization.yml
@@ -0,0 +1,135 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ organization_description: test
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: ""
+ expected_diff_after: "description.*test"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ organization_name: "会社"
+ organization_description: "アクメ株式会社"
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: ""
+ expected_diff_after: "name['\": ]*\\\\u4f1a\\\\u793e"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ organization_name: "ÄCMÈ"
+ organization_description: "Because Ä makes it look more METAL"
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: ""
+ expected_diff_after: "description['\": ]*Because \\\\u00c4 makes it look more METAL"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "description.*test"
+ expected_diff_after: "description.*A test organization"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ expected_change: false
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+ expected_change: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "会社"
+ organization_state: absent
+ expected_change: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "ÄCMÈ"
+ organization_state: absent
+ expected_change: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ expected_change: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ expected_change: false
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_parameters:
+ - name: my_param
+ value: my value
+ - name: my_param2
+ parameter_type: string
+ value: my other value
+ - name: my_param3
+ parameter_type: array
+ value:
+ - array
+ - value
+ organization_state: present
+ expected_change: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_parameters:
+ - name: my_param
+ value: my value
+ - name: my_param2
+ parameter_type: string
+ value: my other value
+ - name: my_param3
+ parameter_type: array
+ value:
+ - array
+ - value
+ organization_state: present
+ expected_change: false
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_parameters:
+ - name: my_param
+ value: my value
+ organization_state: present
+ expected_change: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_parameters:
+ - name: my_param
+ value: my value
+ organization_state: present
+ expected_change: false
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_parameters: []
+ organization_state: present
+ expected_change: true
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ expected_change: false
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+ expected_change: true
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/organization_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/organization_info.yml
new file mode 100644
index 000000000..f8f58abd1
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/organization_info.yml
@@ -0,0 +1,46 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch organization info
+ organization_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "Test Organization"
+ register: organization_info
+ - name: check organization details
+ assert:
+ that:
+ - organization_info['organization']['name'] == "Test Organization"
+ - "'parent_name' in organization_info['organization']"
+
+ - name: search organization info
+ organization_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ search: "name ~ Test"
+ register: organization_info
+ - name: check organization details
+ assert:
+ that:
+ - organization_info['organizations'][0]['name'] == "Test Organization"
+ - "'parent_name' not in organization_info['organizations'][0]"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/organizations_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/organizations_role.yml
new file mode 100644
index 000000000..499ab977f
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/organizations_role.yml
@@ -0,0 +1,46 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: drop existing test orgs
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ loop:
+ - "Test Organization One"
+ - "Test Organization Two"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: organizations
+ vars:
+ foreman_organizations:
+ - name: "Test Organization One"
+ - name: "Test Organization Two"
+ description: "Two Two Two"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: drop existing test orgs
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "absent"
+ loop:
+ - "Test Organization One"
+ - "Test Organization Two"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/os_default_template.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/os_default_template.yml
new file mode 100644
index 000000000..aee641347
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/os_default_template.yml
@@ -0,0 +1,94 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: present
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "Timetravel {{ item }}"
+ provisioning_template_kind: "{{ item }}"
+ provisioning_template_state: present
+ loop:
+ - provision
+ - finish
+ - include_tasks: tasks/os_default_template.yml
+ vars:
+ os_default_template_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/os_default_template.yml
+ vars:
+ os_default_template_kind: "{{ item }}"
+ provisioning_template_name: "Timetravel {{ item }}"
+ os_default_template_state: present
+ expected_change: true
+ loop:
+ - provision
+ - finish
+ - include_tasks: tasks/os_default_template.yml
+ vars:
+ os_default_template_kind: "{{ item }}"
+ provisioning_template_name: "Timetravel {{ item }}"
+ os_default_template_state: present
+ expected_change: false
+ loop:
+ - provision
+ - finish
+ - include_tasks: tasks/os_default_template.yml
+ vars:
+ os_default_template_kind: "{{ item }}"
+ os_default_template_state: absent
+ expected_change: true
+ loop:
+ - provision
+ - finish
+ - include_tasks: tasks/os_default_template.yml
+ vars:
+ os_default_template_kind: "{{ item }}"
+ os_default_template_state: absent
+ expected_change: false
+ loop:
+ - provision
+ - finish
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: absent
+ loop:
+ - Timetravel provision
+ - Timetravel finish
+ - include_tasks: tasks/operatingsystem.yml
+ vars:
+ operatingsystem_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/partition_table.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/partition_table.yml
new file mode 100644
index 000000000..9c246a246
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/partition_table.yml
@@ -0,0 +1,182 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: present
+ expected_change: true
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: present
+ expected_change: false
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: present
+ locked_state: false
+ expected_change: false
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: present
+ locked_state: true
+ expected_change: true
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: present
+ locked_state: true
+ expected_change: false
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: present
+ expected_change: false
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: present
+ locked_state: false
+ expected_change: true
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_layout: 'A partition table with a changed layout'
+ ptable_state: present
+ expected_change: true
+ - name: add ptable
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: 'A partition table 2'
+ ptable_layout: |
+ zerombr
+ clearpart --all --initlabel
+ autopart
+ ptable_state: present
+ expected_change: true
+ - name: change ptable name
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: 'A partition table 2'
+ ptable_updated_name: 'A partition table 3'
+ ptable_layout: |
+ zerombr
+ clearpart --all --initlabel
+ autopart
+ ptable_state: present
+ expected_change: true
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: 'A partition table 3'
+ ptable_layout: |
+ zerombr
+ clearpart --all --initlabel
+ autopart
+ ptable_state: present
+ expected_change: false
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: 'A partition table 3'
+ ptable_state: absent
+ expected_change: true
+ - name: add ptable without location
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: 'A second partition table'
+ ptable_locations: "{{ omit }}"
+ ptable_layout: |
+ zerombr
+ clearpart --all --initlabel
+ autopart
+ ptable_state: present
+ expected_change: true
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: absent
+ expected_change: true
+ - include_tasks: tasks/ptable.yml
+ vars:
+ ptable_state: absent
+ expected_change: false
+ - name: set location of all ptables
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: '*'
+ ptable_organizations: "{{ omit }}"
+ ptable_layout: "{{ omit }}"
+ ptable_state: present
+ expected_change: true
+ - name: set location of all ptables
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: '*'
+ ptable_organizations: "{{ omit }}"
+ ptable_layout: "{{ omit }}"
+ ptable_state: present
+ expected_change: false
+ - name: unlock all ptables
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: '*'
+ locked_state: false
+ ptable_location: "{{ omit }}"
+ ptable_organizations: "{{ omit }}"
+ ptable_layout: "{{ omit }}"
+ ptable_state: present
+ expected_change: true
+ - name: unlock all ptables
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: '*'
+ locked_state: false
+ ptable_location: "{{ omit }}"
+ ptable_organizations: "{{ omit }}"
+ ptable_layout: "{{ omit }}"
+ ptable_state: present
+ expected_change: false
+ - name: delete all ptables
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: '*'
+ ptable_locations: "{{ omit }}"
+ ptable_organizations: "{{ omit }}"
+ ptable_layout: "{{ omit }}"
+ ptable_state: absent
+ expected_change: true
+ - name: delete all ptables
+ include_tasks: tasks/ptable.yml
+ vars:
+ ptable_name: '*'
+ ptable_locations: "{{ omit }}"
+ ptable_organizations: "{{ omit }}"
+ ptable_layout: "{{ omit }}"
+ ptable_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/product.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/product.yml
new file mode 100644
index 000000000..b6a37e26c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/product.yml
@@ -0,0 +1,132 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_type: "cert"
+ content_credential_state: present
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: 'Test product'
+ block:
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ expected_change: false
+ - include_tasks: tasks/product.yml
+ vars:
+ product_description: 'A product with an updated description'
+ product_state: present
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ expected_change: false
+
+ - name: 'Test product with content GPG key'
+ block:
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_gpg_key: "Test GPG key"
+ product_state: present
+ product_ssl_ca_cert: "Test SSL Cert"
+ product_ssl_client_cert: "Test SSL Cert"
+ product_ssl_client_key: "Test SSL Cert"
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_gpg_key: "Test GPG key"
+ product_ssl_ca_cert: "Test SSL Cert"
+ product_ssl_client_cert: "Test SSL Cert"
+ product_ssl_client_key: "Test SSL Cert"
+ product_state: present
+ expected_change: false
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: absent
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 2"
+ product_state: absent
+ expected_change: false
+
+ - name: 'Test product with sync plan'
+ block:
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 3"
+ product_sync_plan: "Test Sync Plan"
+ product_state: present
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 3"
+ product_sync_plan: "Test Sync Plan"
+ product_state: present
+ expected_change: false
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 3"
+ product_state: absent
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_name: "Test Product 3"
+ product_state: absent
+ expected_change: false
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_state: absent
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_state: absent
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_template.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_template.yml
new file mode 100644
index 000000000..4c5135be0
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_template.yml
@@ -0,0 +1,158 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "{{ item }}"
+ provisioning_template_state: absent
+ loop:
+ - "Timetravel finish"
+ - "my template"
+ - "my template 2"
+ - 'A provisioning template with an template'
+ - 'A second provisioning template'
+
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: present
+ provisioning_template_audit_comment: "create template"
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: present
+ provisioning_template_audit_comment: "don't update template"
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: present
+ locked_state: false
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: present
+ locked_state: true
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: present
+ locked_state: true
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "my template"
+ provisioning_template_state: present
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "my template"
+ provisioning_template_updated_name: "my template 2"
+ provisioning_template_state: present
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "my template 2"
+ provisioning_template_state: present
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "my template 2"
+ provisioning_template_state: absent
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: present
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: present
+ locked_state: false
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_template: 'A provisioning template with an template'
+ provisioning_template_state: present
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: 'A second provisioning template'
+ provisioning_template_locations: '{{ omit }}'
+ provisioning_template_state: present
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: absent
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_state: absent
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: '*'
+ locked_state: 'false'
+ provisioning_template_kind: '{{ omit }}'
+ provisioning_template_organizations: '{{ omit }}'
+ provisioning_template_template: '{{ omit }}'
+ provisioning_template_state: present
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: '*'
+ locked_state: 'false'
+ provisioning_template_kind: '{{ omit }}'
+ provisioning_template_organizations: '{{ omit }}'
+ provisioning_template_template: '{{ omit }}'
+ provisioning_template_state: present
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: '*'
+ provisioning_template_kind: '{{ omit }}'
+ provisioning_template_locations: '{{ omit }}'
+ provisioning_template_organizations: '{{ omit }}'
+ provisioning_template_template: '{{ omit }}'
+ provisioning_template_state: absent
+ expected_change: true
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: '*'
+ provisioning_template_kind: '{{ omit }}'
+ provisioning_template_locations: '{{ omit }}'
+ provisioning_template_organizations: '{{ omit }}'
+ provisioning_template_template: '{{ omit }}'
+ provisioning_template_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_templates_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_templates_role.yml
new file mode 100644
index 000000000..2448eb639
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/provisioning_templates_role.yml
@@ -0,0 +1,69 @@
+---
+- name: Setup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - name: ensure test location
+ include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "Timetravel finish"
+ provisioning_template_state: absent
+
+- name: Tests
+ hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: provisioning_templates
+ vars:
+ foreman_provisioning_templates:
+ - name: "Timetravel finish"
+ kind: "finish"
+ template: |
+ <%#
+ name: Finish timetravel
+ kind: finish
+ %>
+ cd /
+ rm -rf *
+ organizations:
+ - Test Organization
+ locations:
+ - Test Location
+
+- name: Cleanup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "Timetravel finish"
+ provisioning_template_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/puppet_environment.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/puppet_environment.yml
new file mode 100644
index 000000000..eb0c75b7d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/puppet_environment.yml
@@ -0,0 +1,63 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/environment.yml
+ vars:
+ environment_state: present
+ expected_change: true
+ - include_tasks: tasks/environment.yml
+ vars:
+ environment_state: present
+ environment_locations: []
+ environment_organizations: []
+ expected_change: true
+ - include_tasks: tasks/environment.yml
+ vars:
+ environment_state: present
+ expected_change: true
+ - include_tasks: tasks/environment.yml
+ vars:
+ environment_state: present
+ expected_change: false
+ - include_tasks: tasks/environment.yml
+ vars:
+ environment_state: absent
+ expected_change: true
+ - include_tasks: tasks/environment.yml
+ vars:
+ environment_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/puppetclasses_import.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/puppetclasses_import.yml
new file mode 100644
index 000000000..a19852d8b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/puppetclasses_import.yml
@@ -0,0 +1,49 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/puppetclasses_import.yml
+ vars:
+ expected_change: true
+ puppetclasses_smart_proxy: "{{ foreman_proxy }}"
+ - include_tasks: tasks/puppetclasses_import.yml
+ vars:
+ puppetclasses_smart_proxy: "{{ foreman_proxy }}"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/realm.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/realm.yml
new file mode 100644
index 000000000..c2fbab1cb
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/realm.yml
@@ -0,0 +1,37 @@
+# To run this playbook, you need to prepare a foreman-proxy with the realm feature.
+# Use e.g. the centos7-freeipa-server in forklift. Due to limitations in Vagrant you
+# might need to run its provisioning playbook by hand.
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/realm.yml
+ vars:
+ realm_state: absent
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/realm.yml
+ vars:
+ realm_state: present
+ expected_change: true
+ - include_tasks: tasks/realm.yml
+ vars:
+ realm_state: present
+ expected_change: false
+ - include_tasks: tasks/realm.yml
+ vars:
+ realm_state: absent
+ expected_change: true
+ - include_tasks: tasks/realm.yml
+ vars:
+ realm_state: absent
+ expected_change: false
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/redhat_manifest.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/redhat_manifest.yml
new file mode 100644
index 000000000..87db2c924
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/redhat_manifest.yml
@@ -0,0 +1,45 @@
+---
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: Create new manifest
+ include_tasks: tasks/redhat_manifest.yml
+ vars:
+ expected_change: true
+ pool_state: present
+ manifest_state: present
+ pool_quantity: 1
+ - name: No change to existing manifest
+ include_tasks: tasks/redhat_manifest.yml
+ vars:
+ expected_change: false
+ pool_state: present
+ manifest_state: present
+ pool_quantity: 1
+ - name: Test adding more subs
+ include_tasks: tasks/redhat_manifest.yml
+ vars:
+ expected_change: true
+ pool_state: present
+ manifest_state: present
+ pool_quantity: 3
+ - name: Test removing subs and export
+ include_tasks: tasks/redhat_manifest.yml
+ vars:
+ expected_change: true
+ pool_state: present
+ manifest_state: present
+ pool_quantity: 2
+ manifest_export_path: "/tmp/manifest_export.zip"
+ - name: Delete manifest
+ include_tasks: tasks/redhat_manifest.yml
+ vars:
+ expected_change: true
+ pool_state: absent
+ manifest_state: absent
+ pool_quantity: 2
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role.yml
new file mode 100644
index 000000000..ed8180a9e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role.yml
@@ -0,0 +1,48 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - name: ensure org has a manifest
+ include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_path: "{{ subscription_manifest_path }}"
+ manifest_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: repositories
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_products:
+ - name: Red Hat Enterprise Linux Server
+ repository_sets:
+ - name: Red Hat Satellite Tools 6.7 (for RHEL 7 Server) (RPMs)
+ basearch: x86_64
+ - name: Red Hat Enterprise Linux 7 Server - Extras (RPMs)
+ basearch: x86_64
+ - name: Red Hat Enterprise Linux for x86_64
+ repository_sets:
+ - name: Red Hat Satellite Tools 6.7 for RHEL 8 x86_64 (RPMs)
+ - name: Red Hat Software Collections (for RHEL Server)
+ all_repositories: true
+ labels:
+ - rhel-server-rhscl-7-rpms
+ - name: CentOS 8
+ repositories:
+ - name: BaseOS x86_64
+ content_type: yum
+ url: http://mirror.centos.org/centos/8/BaseOS/x86_64/os/
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role_deb.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role_deb.yml
new file mode 100644
index 000000000..4f7100409
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repositories_role_deb.yml
@@ -0,0 +1,33 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: repositories
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_products:
+ - name: Debian 10
+ repositories:
+ - name: main
+ content_type: deb
+ url: http://deb.debian.org/debian
+ deb_components: main
+ deb_architectures: amd64
+ deb_releases: buster
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repository.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository.yml
new file mode 100644
index 000000000..7ecd07e7e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository.yml
@@ -0,0 +1,193 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_type: "cert"
+ content_credential_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: "{{ item }}"
+ loop:
+ - "Test Repository"
+ - "Test Repository 2"
+ - "Test Docker Repository"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: Test Yum Repository
+ block:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ expected_change: true
+ repository_label: "just_a_test_repo"
+ repository_mirroring_policy: additive
+ repository_url: "https://repos.fedorapeople.org/pulp/pulp/demo_repos/zoo/"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_mirroring_policy: additive
+ expected_change: false
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_mirroring_policy: mirror_content_only
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_mirroring_policy: mirror_content_only
+ expected_change: false
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_url: 'https://localhost/pulp/repos/demo_repos/zoo'
+ repository_download_policy: "immediate"
+ repository_state: present
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_download_concurrency: 10
+ repository_state: present
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_download_concurrency: 10
+ repository_state: present
+ expected_change: true # currently idempotence is not working as this value is not reported back by Katello's API
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ expected_change: false
+
+ - name: Test Yum Repository with content SSL and GPG key
+ block:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ expected_change: true
+ repository_name: "Test Repository 2"
+ repository_label: "just_a_test_repo2"
+ repository_gpg_key: "Test GPG key"
+ repository_ssl_ca_cert: "Test SSL Cert"
+ repository_ssl_client_cert: "Test SSL Cert"
+ repository_ssl_client_key: "Test SSL Cert"
+ repository_mirroring_policy: additive
+ repository_url: "https://repos.fedorapeople.org/pulp/pulp/demo_repos/zoo/"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_mirroring_policy: additive
+ expected_change: false
+ repository_name: "Test Repository 2"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_mirroring_policy: mirror_content_only
+ expected_change: true
+ repository_name: "Test Repository 2"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_mirroring_policy: mirror_content_only
+ expected_change: false
+ repository_name: "Test Repository 2"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ expected_change: true
+ repository_name: "Test Repository 2"
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ expected_change: false
+ repository_name: "Test Repository 2"
+
+ - name: Test Docker Repository
+ block:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_label: "just_a_test_repo"
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+ repository_url: https://docker.io
+ repository_docker_upstream_name: busybox
+ repository_include_tags:
+ - latest
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+ repository_url: https://docker.io
+ repository_docker_upstream_name: busybox
+ repository_include_tags:
+ - latest
+ expected_change: false
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+ repository_url: https://docker.io
+ repository_upstream_username: dockeruser
+ repository_upstream_password: dockerpass
+ repository_docker_upstream_name: busybox
+ repository_include_tags:
+ - latest
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: Test Docker Repository
+ repository_content_type: docker
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_type: "cert"
+ content_credential_state: absent
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_deb.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_deb.yml
new file mode 100644
index 000000000..8939eeb99
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_deb.yml
@@ -0,0 +1,92 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_type: "cert"
+ content_credential_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: Test Debian Repository
+ block:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_label: "just_a_test_repo3"
+ repository_name: Test Debian Repository
+ repository_content_type: deb
+ repository_url: https://ftp.debian.org
+ repository_deb_releases: buster
+ repository_deb_components: main
+ repository_deb_architectures: i386
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Debian Repository
+ repository_content_type: deb
+ repository_url: https://ftp.debian.org
+ repository_deb_releases: buster
+ repository_deb_components: main
+ repository_deb_architectures: i386
+ expected_change: false
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_name: Test Debian Repository
+ repository_content_type: deb
+ repository_url: https://ftp.debian.org
+ repository_deb_releases: buster
+ repository_deb_components: main
+ repository_deb_architectures: amd64
+ expected_change: true
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: Test Debian Repository
+ repository_content_type: deb
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_type: "cert"
+ content_credential_state: absent
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_info.yml
new file mode 100644
index 000000000..c101435bd
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_info.yml
@@ -0,0 +1,76 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_label: "just_a_test_repo"
+ repository_mirror_on_sync: false
+ repository_url: "https://repos.fedorapeople.org/pulp/pulp/demo_repos/zoo/"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch repository info
+ repository_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ product: "Test Product"
+ name: "Test Repository"
+ register: repository_info
+ - name: check repository details
+ assert:
+ that:
+ - repository_info['repository']['name'] == "Test Repository"
+
+ - name: search repository info
+ repository_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ product: "Test Product"
+ search: "label = just_a_test_repo"
+ register: repository_info
+ - name: check repository details
+ assert:
+ that:
+ - repository_info['repositories'][0]['name'] == "Test Repository"
+
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_ostree.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_ostree.yml
new file mode 100644
index 000000000..d67e6a7ec
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_ostree.yml
@@ -0,0 +1,73 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: present
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_type: "cert"
+ content_credential_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: Create Ostree Repository
+ include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_label: "just_a_test_repo_ostree"
+ repository_name: Test OStree Repository
+ repository_content_type: ostree
+ repository_url: https://fixtures.pulpproject.org/ostree/small/
+ expected_change: true
+ - name: sync repository
+ include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: "Test OStree Repository"
+ - name: remove repository
+ include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ repository_name: Test OStree Repository
+ repository_content_type: ostree
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_name: "Test SSL Cert"
+ content_credential_type: "cert"
+ content_credential_state: absent
+ - include_tasks: tasks/content_credential.yml
+ vars:
+ content_credential_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set.yml
new file mode 100644
index 000000000..5d5a90864
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set.yml
@@ -0,0 +1,191 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_path: "{{ subscription_manifest_path }}"
+ manifest_state: present
+ - include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-7-server-rpms
+ all_repositories: true
+ state: disabled
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: enable repository_set by name
+ include_tasks: tasks/repository_set.yml
+ vars:
+ name: Red Hat Enterprise Linux 7 Server (RPMs)
+ repositories:
+ - releasever: "7.0"
+ basearch: "x86_64"
+ - releasever: "7.1"
+ basearch: "x86_64"
+ - releasever: "7.2"
+ basearch: "x86_64"
+ - releasever: "7.3"
+ basearch: "x86_64"
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "state.*disabled"
+ expected_diff_after: "state.*enabled"
+ - name: enable repository_set by name again, no change
+ include_tasks: tasks/repository_set.yml
+ vars:
+ name: Red Hat Enterprise Linux 7 Server (RPMs)
+ product: Red Hat Enterprise Linux Server
+ repositories:
+ - releasever: "7.0"
+ basearch: "x86_64"
+ - releasever: "7.1"
+ basearch: "x86_64"
+ - releasever: "7.2"
+ basearch: "x86_64"
+ - releasever: "7.3"
+ basearch: "x86_64"
+ expected_change: false
+ - name: enable repository_set by label, no change
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-7-server-rpms
+ repositories:
+ - releasever: "7.0"
+ basearch: "x86_64"
+ - releasever: "7.1"
+ basearch: "x86_64"
+ - releasever: "7.2"
+ basearch: "x86_64"
+ - releasever: "7.3"
+ basearch: "x86_64"
+ expected_change: false
+ - name: disable repository_set by label
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-7-server-rpms
+ repositories:
+ - releasever: "7.0"
+ basearch: "x86_64"
+ - releasever: "7.1"
+ basearch: "x86_64"
+ - releasever: "7.2"
+ basearch: "x86_64"
+ - releasever: "7.3"
+ basearch: "x86_64"
+ state: disabled
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "state.*enabled"
+ expected_diff_after: "state.*disabled"
+ - name: disable repository_set by name, no change
+ include_tasks: tasks/repository_set.yml
+ vars:
+ name: Red Hat Enterprise Linux 7 Server (RPMs)
+ product: Red Hat Enterprise Linux Server
+ repositories:
+ - releasever: "7.0"
+ basearch: "x86_64"
+ - releasever: "7.1"
+ basearch: "x86_64"
+ - releasever: "7.2"
+ basearch: "x86_64"
+ - releasever: "7.3"
+ basearch: "x86_64"
+ state: disabled
+ expected_change: false
+
+ - name: enable repository_set by label, all repos
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-7-server-rpms
+ all_repositories: true
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "state.*disabled"
+ expected_diff_after: "state.*enabled"
+ - name: enable repository_set by label, all repos, no change
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-7-server-rpms
+ all_repositories: true
+ expected_change: false
+ - name: disable repository_set by label, all repos
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-7-server-rpms
+ all_repositories: true
+ state: disabled
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "state.*enabled"
+ expected_diff_after: "state.*disabled"
+ - name: disable repository_set by name, all repos, no change
+ include_tasks: tasks/repository_set.yml
+ vars:
+ name: Red Hat Enterprise Linux 7 Server (RPMs)
+ product: Red Hat Enterprise Linux Server
+ all_repositories: true
+ state: disabled
+ expected_change: false
+
+ - name: enable RHEL8 repository_set
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-8-for-x86_64-baseos-rpms
+ repositories:
+ - releasever: '8'
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "state.*disabled"
+ expected_diff_after: "state.*enabled"
+ - name: enable RHEL8 repository_set again, no change
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-8-for-x86_64-baseos-rpms
+ repositories:
+ - releasever: '8'
+ expected_change: false
+ - name: disable RHEL8 repository_set
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-8-for-x86_64-baseos-rpms
+ repositories:
+ - releasever: '8'
+ state: disabled
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "state.*enabled"
+ expected_diff_after: "state.*disabled"
+ - name: disable RHEL8 repository_set again, no change
+ include_tasks: tasks/repository_set.yml
+ vars:
+ label: rhel-8-for-x86_64-baseos-rpms
+ repositories:
+ - releasever: '8'
+ state: disabled
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set_info.yml
new file mode 100644
index 000000000..774beb472
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_set_info.yml
@@ -0,0 +1,66 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: content_rhel
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_validate_certs: false
+ foreman_manifest_download: false
+ foreman_manifest_path: "{{ subscription_manifest_path }}"
+ foreman_content_rhel_enable_rhel7: true
+ foreman_content_rhel_enable_rhel8: false
+ foreman_content_rhel_sync_now: false
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch RHEL 7 Server RPMs by product and name
+ repository_set_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: false
+ organization: "Test Organization"
+ product: "Red Hat Enterprise Linux Server"
+ name: "Red Hat Enterprise Linux 7 Server (RPMs)"
+ register: repository_set_info
+ - name: check repository_set details
+ assert:
+ that:
+ - repository_set_info['repository_set']['name'] == "Red Hat Enterprise Linux 7 Server (RPMs)"
+
+ - name: fetch RHEL 7 Server RPMs by label
+ repository_set_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: false
+ organization: "Test Organization"
+ search: 'label = "rhel-7-server-rpms"'
+ register: repository_set_info
+ - name: check repository_set details
+ assert:
+ that:
+ - repository_set_info['repository_sets'][0]['name'] == "Red Hat Enterprise Linux 7 Server (RPMs)"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_sync.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_sync.yml
new file mode 100644
index 000000000..4948be0fc
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/repository_sync.yml
@@ -0,0 +1,56 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: present
+ repository_url: https://fixtures.pulpproject.org/rpm-signed/
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: sync product
+ include_tasks: tasks/katello_sync.yml
+ - name: sync repository
+ include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: "Test Repository"
+ - name: sync missing repository
+ include_tasks: tasks/katello_sync.yml
+ vars:
+ repository: "Test Repository That Doesn't Exist"
+ expected_fail: true
+ expected_fail_msg: "Found no results while searching for repositories with name"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/repository.yml
+ vars:
+ repository_state: absent
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/resource_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/resource_info.yml
new file mode 100644
index 000000000..131c22a7e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/resource_info.yml
@@ -0,0 +1,100 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/search_facts.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item.organization }}"
+ organization_state: present
+ loop: "{{ test_resources }}"
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ item.domain }}"
+ domain_locations: "{{ omit }}"
+ domain_organizations:
+ - "{{ item.organization }}"
+ domain_state: present
+ loop: "{{ test_resources }}"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/search_facts.yml
+ vars:
+ resource: settings
+ search: name = http_proxy
+ return_length: 1
+ - include_tasks: tasks/search_facts.yml
+ vars:
+ resource: subnets
+ return_length: 0
+ - include_tasks: tasks/search_facts.yml
+ vars:
+ resource: organizations
+ search: name="Test Organization"
+ full_details: true
+ return_length: 1
+ - include_tasks: tasks/search_facts.yml
+ vars:
+ resource: domains
+ organization: "Facts Organization"
+ return_length: 1
+ - name: find organization id
+ resource_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ resource: organizations
+ search: name="Facts Organization"
+ register: org_search
+ - include_tasks: tasks/search_facts.yml
+ vars:
+ resource: domains
+ params:
+ organization_id: "{{ org_search.resources[0]['id'] }}"
+ return_length: 1
+ - name: Run with invalid resource
+ resource_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ resource: foo
+ register: result
+ ignore_errors: true
+ - fail:
+ msg: "{{ result.msg }} should have contained all available resources"
+ when: "'config_groups' not in result.msg"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/search_facts.yml
+ tasks:
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "{{ item.domain }}"
+ domain_locations: "{{ omit }}"
+ domain_organizations:
+ - "{{ item.organization }}"
+ domain_state: absent
+ loop: "{{ test_resources }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item.organization }}"
+ organization_state: absent
+ loop: "{{ test_resources }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/role.yml
new file mode 100644
index 000000000..57b6b9dd9
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/role.yml
@@ -0,0 +1,135 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "present"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "present"
+ - include_tasks: tasks/role.yml
+ vars:
+ role_name: "{{ item }}"
+ role_state: absent
+ with_items:
+ - test
+ - role_with_filters
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/role.yml
+ vars:
+ role_name: "role_with_filters"
+ role_state: present
+ expected_change: true
+ role_filters:
+ - permissions:
+ - view_hosts
+ search: "owner_type = Usergroup and owner_id = 4"
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: true
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: false
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: true
+ role_filters:
+ - permissions:
+ - view_hosts
+ search: "owner_type = Usergroup and owner_id = 4"
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: false
+ role_filters:
+ - permissions:
+ - view_hosts
+ search: "owner_type = Usergroup and owner_id = 4"
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: true
+ role_filters:
+ - permissions:
+ - view_hosts
+ - puppetrun_hosts
+ search: "owner_type = Usergroup and owner_id = 4"
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: false
+ role_filters:
+ - permissions:
+ - view_hosts
+ - puppetrun_hosts
+ search: "owner_type = Usergroup and owner_id = 4"
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: true
+ role_filters:
+ - permissions:
+ - view_hosts
+ - puppetrun_hosts
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ expected_change: false
+ role_filters:
+ - permissions:
+ - view_hosts
+ - puppetrun_hosts
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: present
+ role_description: new description
+ expected_change: true
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/role.yml
+ vars:
+ role_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "absent"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/scap_content.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/scap_content.yml
new file mode 100644
index 000000000..447943f21
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/scap_content.yml
@@ -0,0 +1,109 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "present"
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "present"
+ - include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "{{ item }}"
+ scap_content_state: "absent"
+ loop:
+ - scap_content_title
+ - updated_scap_content_title
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: import scap content
+ include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "scap_content_title"
+ scap_content_scap_file: "data/ssg-firefox-ds.xml"
+ scap_content_original_filename: "scap_file_name.xml"
+ scap_content_locations:
+ - Test Location
+ scap_content_organizations:
+ - Test Organization
+ scap_content_state: "present"
+ expected_change: true
+ - name: import scap content again, no change
+ include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "scap_content_title"
+ scap_content_scap_file: "data/ssg-firefox-ds.xml"
+ scap_content_original_filename: "scap_file_name.xml"
+ scap_content_locations:
+ - Test Location
+ scap_content_organizations:
+ - Test Organization
+ scap_content_state: "present"
+ expected_change: false
+ - name: rename scap content
+ include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "scap_content_title"
+ scap_content_updated_title: "updated_scap_content_title"
+ scap_content_original_filename: "updated_scap_file_name.xml"
+ scap_content_locations:
+ - Test Location
+ scap_content_organizations:
+ - Test Organization
+ scap_content_state: "present"
+ expected_change: true
+ - name: ensure the renamed scap content has all the data, no change
+ include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "updated_scap_content_title"
+ scap_content_original_filename: "updated_scap_file_name.xml"
+ scap_content_locations:
+ - Test Location
+ scap_content_organizations:
+ - Test Organization
+ scap_content_state: "present"
+ expected_change: false
+ - name: delete scap content
+ include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "updated_scap_content_title"
+ scap_content_state: "absent"
+ expected_change: true
+ - name: delete scap content again, no change
+ include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "updated_scap_content_title"
+ scap_content_state: "absent"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/scap_content.yml
+ vars:
+ scap_content_title: "{{ item }}"
+ scap_content_state: "absent"
+ loop:
+ - scap_content_title
+ - updated_scap_content_title
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "absent"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/scap_tailoring_file.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/scap_tailoring_file.yml
new file mode 100644
index 000000000..ee3890e11
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/scap_tailoring_file.yml
@@ -0,0 +1,109 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "present"
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "present"
+ - include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "{{ item }}"
+ scap_tailoring_file_state: "absent"
+ loop:
+ - scap_tailoring_file_name
+ - updated_scap_tailoring_file_name
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: import tailoring file
+ include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "scap_tailoring_file_name"
+ scap_tailoring_file_scap_file: "data/ssg-firefox-ds-tailoring.xml"
+ scap_tailoring_file_original_filename: "scap_file_name.xml"
+ scap_tailoring_file_locations:
+ - Test Location
+ scap_tailoring_file_organizations:
+ - Test Organization
+ scap_tailoring_file_state: "present"
+ expected_change: true
+ - name: import tailoring file again, no change
+ include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "scap_tailoring_file_name"
+ scap_tailoring_file_scap_file: "data/ssg-firefox-ds-tailoring.xml"
+ scap_tailoring_file_original_filename: "scap_file_name.xml"
+ scap_tailoring_file_locations:
+ - Test Location
+ scap_tailoring_file_organizations:
+ - Test Organization
+ scap_tailoring_file_state: "present"
+ expected_change: false
+ - name: rename tailoring file
+ include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "scap_tailoring_file_name"
+ scap_tailoring_file_updated_name: "updated_scap_tailoring_file_name"
+ scap_tailoring_file_original_filename: "updated_scap_file_name.xml"
+ scap_tailoring_file_locations:
+ - Test Location
+ scap_tailoring_file_organizations:
+ - Test Organization
+ scap_tailoring_file_state: "present"
+ expected_change: true
+ - name: ensure the renamed tailoring file has all the data, no change
+ include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "updated_scap_tailoring_file_name"
+ scap_tailoring_file_original_filename: "updated_scap_file_name.xml"
+ scap_tailoring_file_locations:
+ - Test Location
+ scap_tailoring_file_organizations:
+ - Test Organization
+ scap_tailoring_file_state: "present"
+ expected_change: false
+ - name: delete tailoring file
+ include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "updated_scap_tailoring_file_name"
+ scap_tailoring_file_state: "absent"
+ expected_change: true
+ - name: delete tailoring file again, no change
+ include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "updated_scap_tailoring_file_name"
+ scap_tailoring_file_state: "absent"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/scap_tailoring_file.yml
+ vars:
+ scap_tailoring_file_name: "{{ item }}"
+ scap_tailoring_file_state: "absent"
+ loop:
+ - scap_tailoring_file_name
+ - updated_scap_tailoring_file_name
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "absent"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_account.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_account.yml
new file mode 100644
index 000000000..3193e9fcb
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_account.yml
@@ -0,0 +1,112 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test'
+ organization_name: 'Test Organization'
+ scc_account_state: absent
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test2'
+ organization_name: 'Test Organization'
+ scc_account_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_password: 'testpass'
+ scc_account_login: 'testuser'
+ scc_account_base_url: 'https://scc.example.com'
+ test_connection: false
+ scc_account_state: present
+ expected_change: true
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_state: present
+ expected_change: false
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_password: 'testpass'
+ scc_account_login: 'testuser'
+ scc_account_base_url: 'https://scc.example.com'
+ test_connection: true
+ scc_account_state: present
+ expected_change: false
+ expected_fail: true
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test'
+ scc_account_updated_name: 'Test2'
+ scc_account_interval: 'monthly'
+ test_connection: true
+ scc_account_state: present
+ expected_change: false
+ expected_fail: true
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test'
+ scc_account_updated_name: 'Test2'
+ scc_account_interval: 'monthly'
+ test_connection: false
+ scc_account_state: present
+ expected_change: true
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test2'
+ scc_account_interval: 'monthly'
+ scc_account_state: present
+ expected_change: false
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test2'
+ test_connection: false
+ scc_account_state: synced
+ expected_fail: "{{ not ansible_check_mode }}"
+ expected_change: "{{ ansible_check_mode }}"
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test2'
+ organization_name: 'Test Organization'
+ scc_account_state: absent
+ expected_change: true
+
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: 'Test2'
+ organization_name: 'Test Organization'
+ scc_account_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product.yml
new file mode 100644
index 000000000..e9363fc9a
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product.yml
@@ -0,0 +1,54 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: "{{ scc_account_name_for_scc_product }}"
+ scc_account_login: "{{ scc_account_login_for_scc_product }}"
+ scc_account_password: "{{ scc_account_password_for_scc_product }}"
+ scc_account_state: present
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: "{{ scc_account_name_for_scc_product }}"
+ scc_account_state: synced
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/scc_product.yml
+ vars:
+ scc_product_name: 'SUSE Linux Enterprise Server 10 SP1 i586 (id: 673)'
+ expected_change: true
+
+ - include_tasks: tasks/scc_product.yml
+ vars:
+ scc_product_name: 'SUSE Linux Enterprise Server 10 SP1 i586 (id: 673)'
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: "{{ scc_account_name_for_scc_product }}"
+ scc_account_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product_old.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product_old.yml
new file mode 100644
index 000000000..f5644776e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/scc_product_old.yml
@@ -0,0 +1,54 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: "{{ scc_account_name_for_scc_product }}"
+ scc_account_login: "{{ scc_account_login_for_scc_product }}"
+ scc_account_password: "{{ scc_account_password_for_scc_product }}"
+ scc_account_state: present
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: "{{ scc_account_name_for_scc_product }}"
+ scc_account_state: synced
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/scc_product.yml
+ vars:
+ scc_product_name: 'SUSE Linux Enterprise Client Tools 10 SP3 i586'
+ expected_change: true
+
+ - include_tasks: tasks/scc_product.yml
+ vars:
+ scc_product_name: 'SUSE Linux Enterprise Client Tools 10 SP3 i586'
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/scc_account.yml
+ vars:
+ scc_account_name: "{{ scc_account_name_for_scc_product }}"
+ scc_account_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/setting.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/setting.yml
new file mode 100644
index 000000000..69168551c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/setting.yml
@@ -0,0 +1,68 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/setting.yml
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: excluded_facts
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: token_duration
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_value: 'Welcome!'
+ expected_change: true
+ - include_tasks: tasks/setting_fact.yml
+ vars:
+ setting_name: login_text
+ setting_value: 'Welcome!'
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_value: 'Welcome!'
+ expected_change: false
+ - include_tasks: tasks/setting.yml
+ vars:
+ expected_change: true
+ - include_tasks: tasks/setting.yml
+ vars:
+ expected_change: false
+
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: excluded_facts
+ setting_value: ['foo', 'bar']
+ expected_change: true
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: excluded_facts
+ setting_value: ['foo', 'bar']
+ expected_change: false
+
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: token_duration
+ setting_value: 99
+ expected_change: true
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: token_duration
+ setting_value: 99
+ expected_change: false
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: token_duration
+ expected_change: true
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/setting_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/setting_info.yml
new file mode 100644
index 000000000..226f91dff
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/setting_info.yml
@@ -0,0 +1,47 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: 'login_text'
+ setting_value: ''
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch setting info
+ setting_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "login_text"
+ register: setting_info
+ - name: check setting details
+ assert:
+ that:
+ - setting_info['setting']['name'] == "login_text"
+ - setting_info['setting']['value'] == ''
+
+ - name: search setting info
+ setting_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ search: "name = token_duration"
+ register: setting_info
+ - name: check setting details
+ assert:
+ that:
+ - setting_info['settings'][0]['name'] == "token_duration"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/settings_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/settings_role.yml
new file mode 100644
index 000000000..0cbbc183d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/settings_role.yml
@@ -0,0 +1,46 @@
+---
+- name: Setup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: "destroy_vm_on_host_delete"
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: "clean_up_failed_deployment"
+
+- name: Tests
+ hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: settings
+ vars:
+ foreman_settings:
+ - name: "destroy_vm_on_host_delete"
+ value: "true"
+ - name: "clean_up_failed_deployment"
+ value: "false"
+
+- name: Cleanup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: "destroy_vm_on_host_delete"
+ - include_tasks: tasks/setting.yml
+ vars:
+ setting_name: "clean_up_failed_deployment"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/smart_class_parameter.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/smart_class_parameter.yml
new file mode 100644
index 000000000..47e5f0c8e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/smart_class_parameter.yml
@@ -0,0 +1,593 @@
+---
+## To record cassettes using this playbook (record_smart_class_parameter)
+## some puppet classes need to be imported.
+## See comments in #582 for details. To import the classes run:
+##
+## $ puppet module install puppetlabs-ntp
+## $ hammer proxy import-classes --puppet-environment production --name $(hostname -f)
+##
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: test_hostgroup
+ hostgroup_state: present
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: "{{ item }}"
+ smart_class_parameter_description: ""
+ smart_class_parameter_override: true
+ smart_class_parameter_hidden_value: false
+ smart_class_parameter_default_value: ""
+ smart_class_parameter_parameter_type: none
+ smart_class_parameter_override_values: []
+ smart_class_parameter_override_value_order:
+ - fqdn
+ - hostgroup
+ - os
+ - domain
+ smart_class_parameter_state: present
+ loop:
+ - logfile
+ - config_dir
+ - servers
+ - burst
+ - stepout
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: "{{ item }}"
+ smart_class_parameter_override: false
+ smart_class_parameter_state: present
+ loop:
+ - logfile
+ - config_dir
+ - servers
+ - burst
+ - stepout
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ # TODO: Add tests for:
+ # - validator
+ - name: Test common smart class params
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: logfile
+ smart_class_parameter_omit: false
+ smart_class_parameter_override: true
+ block:
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_description: ntp log file
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_description: ntp log file
+ smart_class_parameter_state: present
+ expected_change: false
+
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_parameter_type: string
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_parameter_type: string
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_parameter_type: none
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_parameter_type: none
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_state: present
+ expected_change: false
+
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_hidden_value: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_hidden_value: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_hidden_value: true
+ smart_class_parameter_default_value: "/var/log/ntp.log"
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_hidden_value: true
+ smart_class_parameter_default_value: "/var/log/ntp.log"
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_hidden_value: false
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_hidden_value: false
+ smart_class_parameter_state: present
+ expected_change: false
+
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_override_value_order:
+ - fqdn
+ - domain
+ - location
+ - hostgroup
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_override_value_order:
+ - fqdn
+ - domain
+ - location
+ - hostgroup
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_override_value_order:
+ - fqdn
+ - hostgroup
+ - os
+ - domain
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_override_value_order:
+ - fqdn
+ - hostgroup
+ - os
+ - domain
+ smart_class_parameter_state: present
+ expected_change: false
+
+ # TODO: Add tests for:
+ # - real values
+ # - hash values
+ # - yaml values
+ # - json values
+ - name: Test string smart class params
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: config_dir
+ smart_class_parameter_parameter_type: string
+ smart_class_parameter_omit: false
+ smart_class_parameter_override: true
+ block:
+ # Test string param with default value
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd-foo"
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd-foo"
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_state: present
+ expected_change: false
+
+ # Test string param with matchers
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: "/etc/ntpd/foo"
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: "/etc/ntpd/foo"
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: "/etc/ntpd/foonew"
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: "/etc/ntpd/foonew"
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: "/etc/ntpd/foo"
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: "/etc/ntpd"
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: "/etc/ntpd/foo"
+ smart_class_parameter_state: present
+ expected_change: false
+
+ - name: Test boolean smart class params
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: burst
+ smart_class_parameter_parameter_type: boolean
+ smart_class_parameter_omit: false
+ smart_class_parameter_override: true
+ block:
+ # Test boolean param with default value
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: false
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: false
+ smart_class_parameter_state: present
+ expected_change: false
+
+ # Test boolean param with matchers
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: false
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: true
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: false
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: true
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: false
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: false
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: true
+ smart_class_parameter_state: present
+ expected_change: false
+
+ - name: Test interger smart class params
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: stepout
+ smart_class_parameter_parameter_type: integer
+ smart_class_parameter_omit: false
+ smart_class_parameter_override: true
+ block:
+ # Test integer param with default value
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 3
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 3
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 5
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 5
+ smart_class_parameter_state: present
+ expected_change: false
+
+ # Test integer param with matchers
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 5
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: 42
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 5
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: 42
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 5
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: 42
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: 5
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: 42
+ smart_class_parameter_state: present
+ expected_change: false
+
+ - name: Test array smart class params
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: servers
+ smart_class_parameter_parameter_type: array
+ smart_class_parameter_omit: false
+ smart_class_parameter_override: true
+ block:
+ # Test array param with default value
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_state: present
+ expected_change: false
+
+ # Test array param with matchers
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: [baz.ntp.org]
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: servers
+ smart_class_parameter_parameter_type: array
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_override_values:
+ - match: "domain=example.com"
+ value: ['baz.ntp.org']
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_override_values:
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_override_values:
+ - match: "hostgroup=test_hostgroup"
+ omit: true
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_merge_default: true
+ smart_class_parameter_merge_overrides: true
+ smart_class_parameter_avoid_duplicates: true
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_merge_default: false
+ smart_class_parameter_merge_overrides: false
+ smart_class_parameter_avoid_duplicates: false
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_state: present
+ expected_change: true
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_merge_default: false
+ smart_class_parameter_merge_overrides: false
+ smart_class_parameter_avoid_duplicates: false
+ smart_class_parameter_default_value: ['foo.ntp.org', 'bar.ntp.org']
+ smart_class_parameter_state: present
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: "{{ item }}"
+ smart_class_parameter_description: ""
+ smart_class_parameter_override: true
+ smart_class_parameter_hidden_value: false
+ smart_class_parameter_default_value: ""
+ smart_class_parameter_parameter_type: none
+ smart_class_parameter_override_values: []
+ smart_class_parameter_override_value_order:
+ - fqdn
+ - hostgroup
+ - os
+ - domain
+ smart_class_parameter_state: present
+ loop:
+ - logfile
+ - config_dir
+ - servers
+ - burst
+ - stepout
+ - include_tasks: tasks/smart_class_parameter.yml
+ vars:
+ smart_class_parameter_puppetclass_name: ntp
+ smart_class_parameter_parameter: "{{ item }}"
+ smart_class_parameter_override: false
+ smart_class_parameter_state: present
+ loop:
+ - config_dir
+ - servers
+ - burst
+ - stepout
+ - include_tasks: tasks/hostgroup.yml
+ vars:
+ hostgroup_name: test_hostgroup
+ hostgroup_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/smart_proxy.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/smart_proxy.yml
new file mode 100644
index 000000000..b0351d55b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/smart_proxy.yml
@@ -0,0 +1,72 @@
+---
+# Do not do this on a production machine!
+#
+# To run recording for this test, you need to:
+# - run a smart proxy box (e.g. centos7-foreman-proxy-3.17)
+# - configure /etc/hosts on both machines
+# o foreman.example.com -> main foreman server
+# o foreman-proxy.example.com -> smart proxy
+# - configure your smart proxy to listen to http on 8000
+# - configure your smart proxy to trust anything
+# - restart your smart proxy
+# - disable selinux enforcing
+# - record before puppet takes back those changes
+#
+# setenforce 0
+# foreman-installer --foreman-proxy-http true --foreman-proxy-http-port 8000 --disable-system-checks \
+# --foreman-proxy-trusted-hosts=EMPTY_ARRAY
+#
+# Do not do this on a production machine!
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: present
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "{}"
+ expected_diff_after: "foreman-proxy.example.com"
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: present
+ expected_change: false
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "foreman-proxy.example.com"
+ expected_diff_after: "{}"
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/smart_proxy.yml
+ vars:
+ smart_proxy_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot.yml
new file mode 100644
index 000000000..9e1a82dd8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot.yml
@@ -0,0 +1,50 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_state: present
+ expected_change: true
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_state: present
+ expected_change: false
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_description: "alpha"
+ snapshot_state: present
+ expected_change: true
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_description: "alpha"
+ snapshot_state: present
+ expected_change: false
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_state: reverted
+ expected_change: true
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_state: absent
+ expected_change: true
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_state: absent
+ expected_change: false
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot_info.yml
new file mode 100644
index 000000000..ea6f0bd3d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/snapshot_info.yml
@@ -0,0 +1,31 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/snapshot.yml
+ vars:
+ snapshot_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch snapshot info
+ snapshot_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ host: "{{ snapshot_host_name }}"
+ register: snapshot_info
+ - name: check snapshots details
+ assert:
+ that:
+ - snapshot_info['snapshots'][0]['name'] == "ansible"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/status_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/status_info.yml
new file mode 100644
index 000000000..83a5e62a0
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/status_info.yml
@@ -0,0 +1,20 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch status
+ include_tasks: tasks/status_info.yml
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch status
+ include_tasks: tasks/status_info.yml
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/subnet.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/subnet.yml
new file mode 100644
index 000000000..fc48b6f7e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/subnet.yml
@@ -0,0 +1,276 @@
+---
+## Requires the following:
+## foreman-installer --foreman-proxy-dns true --foreman-proxy-httpboot
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/subnet.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: "present"
+ with_items: "{{ subnet_locs }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: "present"
+ with_items: "{{ subnet_orgs }}"
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_organizations: "{{ subnet_orgs }}"
+ domain_locations: "{{ subnet_locs }}"
+ domain_name: "{{ item }}"
+ domain_dns_proxy: "{{ subnet_proxy }}"
+ domain_state: present
+ with_items: "{{ subnet_doms }}"
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_mask: '255.255.255.224'
+ subnet_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/subnet.yml
+ tasks:
+ - name: 'Test Subnet with minimal params (netmask)'
+ block:
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ subnet_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ subnet_parameters:
+ - name: subnet_param1
+ value: value1
+ - name: subnet_param2
+ value: value2
+ expected_change: false
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ expected_change: false
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ subnet_parameters:
+ - name: subnet_param1
+ value: new_value1
+ - name: subnet_param3
+ value: value3
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ subnet_parameters:
+ - name: subnet_param1
+ value: new_value1
+ - name: subnet_param3
+ value: value3
+ expected_change: false
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ subnet_parameters: []
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: absent
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: absent
+ expected_change: false
+ - name: 'Test Subnet with minimal params (cidr)'
+ block:
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: present
+ subnet_cidr: 27
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: present
+ subnet_cidr: 27
+ expected_change: false
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: absent
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: absent
+ expected_change: false
+ - name: 'Test Subnet with proxies'
+ block:
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: present
+ subnet_cidr: 27
+ subnet_httpboot_proxy: "{{ subnet_proxy }}"
+ subnet_tftp_proxy: "{{ subnet_proxy }}"
+ subnet_dns_proxy: "{{ subnet_proxy }}"
+ subnet_template_proxy: "{{ subnet_proxy }}"
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: present
+ subnet_cidr: 27
+ subnet_httpboot_proxy: "{{ subnet_proxy }}"
+ subnet_tftp_proxy: "{{ subnet_proxy }}"
+ subnet_dns_proxy: "{{ subnet_proxy }}"
+ subnet_template_proxy: "{{ subnet_proxy }}"
+ expected_change: false
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: absent
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: absent
+ expected_change: false
+ - name: 'Test Subnet name change'
+ block:
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "My test subnet"
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "My test subnet"
+ subnet_updated_name: "My new test subnet"
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "My new test subnet"
+ subnet_mask: '255.255.255.224'
+ subnet_state: present
+ expected_change: false
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "My new test subnet"
+ subnet_state: absent
+ expected_change: true
+ - name: 'Test Subnet with full params except smart proxies and cidr'
+ block:
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: present
+ subnet_name: Test Subnet 2
+ subnet_description: My subnet description
+ subnet_dns_primary: '1.1.1.1'
+ subnet_dns_secondary: '1.1.1.2'
+ subnet_domains: "{{ subnet_doms }}"
+ subnet_gateway: '192.168.200.1'
+ subnet_network: '192.168.200.0'
+ subnet_mask: '255.255.255.224'
+ subnet_from: '192.168.200.10'
+ subnet_to: '192.168.200.20'
+ subnet_boot_mode: 'Static'
+ subnet_ipam: 'Internal DB'
+ subnet_vlanid: 42
+ subnet_mtu: 9000
+ subnet_organizations: "{{ subnet_orgs }}"
+ subnet_locations: "{{ subnet_locs }}"
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: present
+ subnet_name: Test Subnet 2
+ subnet_description: My subnet description
+ subnet_dns_primary: '1.1.1.1'
+ subnet_dns_secondary: '1.1.1.2'
+ subnet_domains: []
+ subnet_gateway: '192.168.200.1'
+ subnet_network: '192.168.200.0'
+ subnet_mask: '255.255.255.224'
+ subnet_from: '192.168.200.10'
+ subnet_to: '192.168.200.20'
+ subnet_boot_mode: 'Static'
+ subnet_ipam: 'Internal DB'
+ subnet_vlanid: 42
+ subnet_mtu: 9000
+ subnet_organizations: "{{ subnet_orgs }}"
+ subnet_locations: "{{ subnet_locs }}"
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_state: present
+ subnet_name: Test Subnet 2
+ subnet_dns_primary: '1.1.1.1'
+ subnet_dns_secondary: '1.1.1.2'
+ subnet_domains: []
+ subnet_gateway: '192.168.200.1'
+ subnet_network: '192.168.200.0'
+ subnet_mask: '255.255.255.224'
+ subnet_from: '192.168.200.10'
+ subnet_to: '192.168.200.20'
+ subnet_boot_mode: 'Static'
+ subnet_ipam: 'Internal DB'
+ subnet_vlanid: 42
+ subnet_mtu: 9000
+ subnet_organizations: "{{ subnet_orgs }}"
+ subnet_locations: "{{ subnet_locs }}"
+ expected_change: false
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: Test Subnet 2
+ subnet_state: absent
+ expected_change: true
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: Test Subnet 2
+ subnet_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/subnet.yml
+ tasks:
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_organizations: "{{ subnet_orgs }}"
+ domain_locations: "{{ subnet_locs }}"
+ domain_name: "{{ item }}"
+ domain_state: absent
+ with_items: "{{ subnet_doms }}"
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "{{ item }}"
+ location_state: absent
+ with_items: "{{ subnet_locs | reverse | list }}"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "{{ item }}"
+ organization_state: absent
+ with_items: "{{ subnet_orgs }}"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/subnet_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/subnet_info.yml
new file mode 100644
index 000000000..b12be9fce
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/subnet_info.yml
@@ -0,0 +1,99 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_organizations:
+ - "Test Organization"
+ location_state: present
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "example.net"
+ domain_locations:
+ - "Test Location"
+ domain_organizations:
+ - "Test Organization"
+ domain_state: present
+ - name: create subnet
+ include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "testnet"
+ subnet_organization:
+ - "Test Organization"
+ subnet_locations:
+ - "Test Location"
+ subnet_domains:
+ - "example.net"
+ subnet_cidr: 24
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: fetch subnet info
+ subnet_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "testnet"
+ register: subnet_info
+ - name: check subnet details
+ assert:
+ that:
+ - subnet_info['subnet']['name'] == "testnet"
+ - subnet_info['subnet']['domains'][0]['name'] == "example.net"
+
+ - name: search subnet info
+ subnet_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ search: "name = testnet"
+ register: subnet_info
+ - name: check subnet details
+ assert:
+ that:
+ - subnet_info['subnets'][0]['name'] == "testnet"
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: unassign domain from subnet
+ include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "testnet"
+ subnet_cidr: 24
+ subnet_domains: []
+ - name: delete subnet
+ include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "testnet"
+ subnet_state: absent
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "example.net"
+ domain_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/subnets_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/subnets_role.yml
new file mode 100644
index 000000000..c328448b3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/subnets_role.yml
@@ -0,0 +1,91 @@
+---
+- name: Setup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ - name: ensure test location
+ include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+ - name: ensure test domain
+ include_tasks: tasks/domain.yml
+ vars:
+ domain_organizations:
+ - Test Organization
+ domain_locations:
+ - Test Location
+ domain_name: foo.example.com
+ domain_state: present
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "My subnet"
+ subnet_state: "absent"
+
+- name: Tests
+ hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: subnets
+ vars:
+ foreman_subnets:
+ - name: "My subnet"
+ description: "My description"
+ network: "192.168.0.0"
+ mask: "255.255.255.192"
+ gateway: "192.168.0.1"
+ from_ip: "192.168.0.2"
+ to_ip: "192.168.0.42"
+ boot_mode: "Static"
+ vlanid: 452
+ mtu: 9000
+ domains:
+ - "foo.example.com"
+ organizations:
+ - Test Organization
+ locations:
+ - Test Location
+
+- name: Cleanup
+ hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "My subnet"
+ subnet_mask: "255.255.255.192"
+ subnet_network: '192.168.0.0'
+ subnet_domains: []
+ - include_tasks: tasks/subnet.yml
+ vars:
+ subnet_name: "My subnet"
+ subnet_state: "absent"
+ - include_tasks: tasks/domain.yml
+ vars:
+ domain_name: "foo.example.com"
+ domain_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_info.yml
new file mode 100644
index 000000000..b3456a1ef
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_info.yml
@@ -0,0 +1,66 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: Fetch Subscription info via name
+ subscription_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ name: "Test Product"
+ register: sub
+ - name: check results
+ assert:
+ that:
+ - sub.subscription.name == 'Test Product'
+ - sub.subscription.product_name == 'Test Product'
+
+ - name: Fetch Subscription info via search
+ subscription_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "Test Organization"
+ search: name="Test Product"
+ register: sub
+ - name: check results
+ assert:
+ that:
+ - sub.subscriptions[0].name == 'Test Product'
+ - sub.subscriptions[0].product_name == 'Test Product'
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_manifest.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_manifest.yml
new file mode 100644
index 000000000..e75993751
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/subscription_manifest.yml
@@ -0,0 +1,78 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: "import manifest"
+ include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_path: "{{ subscription_manifest_path }}"
+ manifest_state: "present"
+ expected_change: true
+ - name: "import manifest again, no change"
+ include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_path: "{{ subscription_manifest_path }}"
+ manifest_state: "present"
+ expected_change: false
+ - name: "update url"
+ include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_path: "{{ subscription_manifest_path }}"
+ manifest_state: "present"
+ manifest_repository_url: "http://cdn.example.com"
+ expected_change: true
+ - name: "update url again, no change"
+ include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_path: "{{ subscription_manifest_path }}"
+ manifest_state: "present"
+ manifest_repository_url: "http://cdn.example.com"
+ expected_change: false
+# the manifest we provide in localhost cannot be refreshed because it's been deleted from the portal
+# if you want to test manifest_state: "refreshed", you will have to provide an own manifest
+# please don't record/commit the result, as the manifest allows access to your portal account
+# - name: "refresh manifest"
+# include_tasks: tasks/subscription_manifest.yml
+# vars:
+# manifest_state: "refreshed"
+# expected_change: true
+ - name: "drop manifest"
+ include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_state: "absent"
+ expected_change: true
+ - name: "drop manifest again, no change"
+ include_tasks: tasks/subscription_manifest.yml
+ vars:
+ manifest_state: "absent"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plan.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plan.yml
new file mode 100644
index 000000000..757332ec5
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plan.yml
@@ -0,0 +1,89 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: present
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: present
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_state: absent
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "{}"
+ expected_diff_after: "name.*Test Sync Plan"
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_products:
+ - Test Product
+ expected_change: true
+ expected_diff: true
+ expected_diff_before: "product_ids.*\\[\\]"
+ expected_diff_after: "product_ids.*\\["
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_products:
+ - Test Product
+ expected_change: false
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ expected_change: true
+ sync_plan_products: []
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_description: Sync daily, not weekly
+ sync_plan_interval: "daily"
+ expected_change: true
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_interval: custom cron
+ sync_plan_cron_expression: "* * * * */5"
+ expected_change: true
+ - include_tasks: tasks/product.yml
+ vars:
+ product_sync_plan: Test Sync Plan
+ product_state: present
+ expected_change: true
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_description: This will not be updated
+ sync_plan_products:
+ - And this too
+ sync_plan_state: present_with_defaults
+ expected_change: false
+ - include_tasks: tasks/sync_plan.yml
+ vars:
+ sync_plan_state: absent
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/product.yml
+ vars:
+ product_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plans_role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plans_role.yml
new file mode 100644
index 000000000..517064d8f
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/sync_plans_role.yml
@@ -0,0 +1,45 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - name: ensure test organization
+ include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: "present"
+ roles:
+ - role: repositories
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_products:
+ - name: Red Hat Enterprise Linux Server
+ repository_sets:
+ - name: Red Hat Satellite Tools 6.7 (for RHEL 7 Server) (RPMs)
+ basearch: x86_64
+ - name: Red Hat Enterprise Linux 7 Server - Extras (RPMs)
+ basearch: x86_64
+ - name: Red Hat Enterprise Linux for x86_64
+ repository_sets:
+ - name: Red Hat Satellite Tools 6.7 for RHEL 8 x86_64 (RPMs)
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ roles:
+ - role: sync_plans
+ vars:
+ foreman_organization: "Test Organization"
+ foreman_sync_plans:
+ - name: Weekly Sync
+ interval: weekly
+ sync_date: 2020-11-19 00:00:00 UTC
+ products:
+ - Red Hat Enterprise Linux Server
+ - Red Hat Enterprise Linux for x86_64
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/_assert_diff.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/_assert_diff.yml
new file mode 100644
index 000000000..3b371d39a
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/_assert_diff.yml
@@ -0,0 +1,13 @@
+---
+- assert:
+ fail_msg: "Ensuring {{ module | default('module') }} supports diff output"
+ that:
+ - result.diff is defined
+ - result.diff.before is defined
+ - result.diff.after is defined
+ - result.diff.before|to_json is search(expected_diff_before)
+ - result.diff.after|to_json is search(expected_diff_after)
+ when:
+ - expected_diff is defined
+ - expected_diff
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/activation_key.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/activation_key.yml
new file mode 100644
index 000000000..45d07c48b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/activation_key.yml
@@ -0,0 +1,38 @@
+---
+- name: "Create/update katello activation key"
+ vars:
+ activation_key_name: "Test Activation Key"
+ activation_key_state: "present"
+ activation_key_organization: "Test Organization"
+ activation_key:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ activation_key_name }}"
+ new_name: "{{ activation_key_new_name | default(omit) }}"
+ organization: "{{ activation_key_organization }}"
+ lifecycle_environment: "{{ activation_key_lifecycle_environment | default(omit) }}"
+ content_view: "{{ activation_key_content_view | default(omit) }}"
+ host_collections: "{{ activation_key_host_collections | default(omit) }}"
+ auto_attach: "{{ activation_key_auto_attach | default(omit) }}"
+ release_version: "{{ activation_key_release_version | default(omit) }}"
+ service_level: "{{ activation_key_service_level | default(omit) }}"
+ max_hosts: "{{ activation_key_max_hosts | default(omit) }}"
+ unlimited_hosts: "{{ activation_key_unlimited_hosts | default(omit) }}"
+ purpose_usage: "{{ activation_key_purpose_usage | default(omit) }}"
+ purpose_role: "{{ activation_key_purpose_role | default(omit) }}"
+ purpose_addons: "{{ activation_key_purpose_addons | default(omit) }}"
+ subscriptions: "{{ activation_key_subscriptions | default(omit) }}"
+ content_overrides: "{{ activation_key_content_overrides | default(omit) }}"
+ state: "{{ activation_key_state }}"
+ register: result
+- assert:
+ fail_msg: "Creating/updating activation key failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: activation_key
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/architecture.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/architecture.yml
new file mode 100644
index 000000000..20e467c63
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/architecture.yml
@@ -0,0 +1,19 @@
+---
+- name: "Ensure Architecture '{{ architecture_name }}' is {{ architecture_state }}"
+ vars:
+ architecture_name: "rüsc256"
+ architecture_state: present
+ architecture:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ architecture_name }}"
+ updated_name: "{{ architecture_updated_name | default(omit) }}"
+ operatingsystems: "{{ operatingsystems | default(omit) }}"
+ state: "{{ architecture_state }}"
+ register: result
+- fail:
+ msg: "Ensuring architecture is {{ architecture_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ when: (expected_change is defined) and (result.changed != expected_change)
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/auth_source_ldap.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/auth_source_ldap.yml
new file mode 100644
index 000000000..5cbde2641
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/auth_source_ldap.yml
@@ -0,0 +1,56 @@
+---
+- name: "Create/Update/Delete LDAP auth source"
+ vars:
+ auth_source_ldap_state: "present"
+ auth_source_ldap_name: Example LDAP
+ auth_source_ldap_host: ldap.example.com
+ auth_source_ldap_port: 389
+ auth_source_ldap_account: ansible
+ auth_source_ldap_base_dn: dc=example,dc=com
+ auth_source_ldap_attr_login: uid
+ auth_source_ldap_attr_firstname: givenName
+ auth_source_ldap_attr_lastname: sn
+ auth_source_ldap_attr_mail: mail
+ auth_source_ldap_onthefly_register: true
+ auth_source_ldap_usergroup_sync: true
+ auth_source_ldap_tls: true
+ auth_source_ldap_groups_base: cn=groups,cn=accounts,dc=example,dc=com
+ auth_source_ldap_server_type: free_ipa
+ auth_source_ldap_ldap_filter: "(uid=%s)"
+ auth_source_ldap_locations:
+ - 'Test Location'
+ auth_source_ldap_organizations:
+ - 'Test Organization'
+ auth_source_ldap:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ auth_source_ldap_name }}"
+ host: "{{ auth_source_ldap_host }}"
+ port: "{{ auth_source_ldap_port }}"
+ account: "{{ auth_source_ldap_account }}"
+ account_password: "{{ auth_source_ldap_account_password | default(omit) }}"
+ base_dn: "{{ auth_source_ldap_attr_login }}"
+ attr_login: "{{ auth_source_ldap_attr_login }}"
+ attr_firstname: "{{ auth_source_ldap_attr_firstname }}"
+ attr_lastname: "{{ auth_source_ldap_attr_lastname }}"
+ attr_mail: "{{ auth_source_ldap_attr_mail }}"
+ attr_photo: "{{ auth_source_ldap_attr_photo | default(omit) }}"
+ onthefly_register: "{{ auth_source_ldap_onthefly_register }}"
+ usergroup_sync: "{{ auth_source_ldap_usergroup_sync }}"
+ tls: "{{ auth_source_ldap_tls }}"
+ groups_base: "{{ auth_source_ldap_groups_base }}"
+ server_type: "{{ auth_source_ldap_server_type }}"
+ ldap_filter: "{{ auth_source_ldap_ldap_filter }}"
+ organizations: "{{ auth_source_ldap_organizations }}"
+ locations: "{{ auth_source_ldap_locations }}"
+ use_netgroups: "{{ auth_source_ldap_netgroups | default(omit) }}"
+ state: "{{ auth_source_ldap_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring LDAP auth source is {{ auth_source_ldap_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/bookmark.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/bookmark.yml
new file mode 100644
index 000000000..95ed61ca4
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/bookmark.yml
@@ -0,0 +1,25 @@
+---
+- name: "Ensure bookmark '{{ bookmark_name }}' is {{ bookmark_state }}"
+ vars:
+ bookmark_controller: job_invocations
+ bookmark_name: test
+ bookmark_public: true
+ bookmark_query: "started_at > 24 hours ago"
+ bookmark_state: present
+ bookmark:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ controller: "{{ bookmark_controller }}"
+ name: "{{ bookmark_name }}"
+ public: "{{ bookmark_public }}"
+ query: "{{ bookmark_query }}"
+ state: "{{ bookmark_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring bookmark is {{ bookmark_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_attribute.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_attribute.yml
new file mode 100644
index 000000000..46ab79907
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_attribute.yml
@@ -0,0 +1,22 @@
+---
+- name: "Ensure compute_attribute is {{ compute_attribute_state }}"
+ vars:
+ - compute_profile_name: "Test Compute Profile"
+ - compute_resource_name: "Test Compute Resource"
+ - compute_attribute_state: "present"
+ compute_attribute:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ compute_profile: "{{ compute_profile_name }}"
+ compute_resource: "{{ compute_resource_name }}"
+ vm_attrs: "{{ vm_attrs }}"
+ state: "{{ compute_attribute_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring compute attribute is {{ compute_attribute_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_profile.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_profile.yml
new file mode 100644
index 000000000..9f4bdc339
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_profile.yml
@@ -0,0 +1,23 @@
+---
+- name: "Ensure compute_profile '{{ compute_profile_name }}' is {{ compute_profile_state }}"
+ vars:
+ - compute_profile_name: "Test Compute Profile"
+ - compute_profile_state: "present"
+ compute_profile:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ compute_profile_name }}"
+ compute_attributes: "{{ compute_profile_attributes | default(omit) }}"
+ state: "{{ compute_profile_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring compute profile is {{ compute_profile_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: compute_profile
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_resource.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_resource.yml
new file mode 100644
index 000000000..db1e85d84
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/compute_resource.yml
@@ -0,0 +1,28 @@
+---
+- name: Create/update compute resource
+ vars:
+ compute_resource_name: "Test Compute Resource"
+ compute_resource:
+ server_url: "{{ foreman_server_url }}"
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ compute_resource_name }}"
+ description: "{{ compute_resource_description | default(omit) }}"
+ updated_name: "{{ compute_resource_updated_name | default(omit) }}"
+ locations: "{{ compute_resource_locations | default(omit) }}"
+ organizations: "{{ compute_resource_organizations | default(omit) }}"
+ provider: "{{ compute_resource_provider | default(omit) }}"
+ provider_params: "{{ compute_resource_provider_params | default(omit) }}"
+ state: "{{ compute_resource_state }}"
+
+ # Deprecated params
+ datacenter: "{{ compute_resource_datacenter | default(omit) }}"
+ provider_auth: "{{ compute_resource_provider_auth | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring compute resource is {{ compute_resource_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/config_group.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/config_group.yml
new file mode 100644
index 000000000..c40105161
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/config_group.yml
@@ -0,0 +1,20 @@
+---
+- name: "Ensure config group '{{ config_group_name }}' is '{{ config_group_state }}' }}'"
+ vars:
+ - config_group_name: "Test config group"
+ config_group:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ config_group_name }}"
+ updated_name: "{{ config_group_updated_name | default(omit) }}"
+ puppetclasses: "{{ config_group_puppetclasses | default(omit) }}"
+ state: "{{ config_group_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring config group is {{ config_group_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_credential.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_credential.yml
new file mode 100644
index 000000000..161d04928
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_credential.yml
@@ -0,0 +1,23 @@
+---
+- name: "Ensure content credential '{{ content_credential_name }}' is {{ content_credential_state }}"
+ vars:
+ - organization_name: "Test Organization"
+ - content_credential_name: "Test GPG key"
+ - content_credential_state: present
+ content_credential:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ content_credential_name }}"
+ organization: "{{ organization_name }}"
+ content_type: "{{ content_credential_type | default(omit) }}"
+ content: "{{ content_credential_content | default(omit) }}"
+ state: "{{ content_credential_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring content credential is {{ content_credential_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_info.yml
new file mode 100644
index 000000000..aef9ab720
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_info.yml
@@ -0,0 +1,14 @@
+---
+- name: "List all full exports in the organization"
+ vars:
+ organization_name: "Test Organization"
+ content_export_info:
+ type: complete
+ organization: "{{ organization_name }}"
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ tags: index
+ register: result
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_library.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_library.yml
new file mode 100644
index 000000000..3bdaecec5
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_library.yml
@@ -0,0 +1,22 @@
+---
+- name: "{{ 'Export library content (incremental)' if (incremental is defined and incremental) else 'Export library content(full)' }}"
+ vars:
+ - organization_name: "Test Organization"
+ content_export_library:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ destination_server: "{{ destination_server | default(omit) }}"
+ incremental: "{{ incremental | default(false) }}"
+ from_history_id: "{{ from_history_id | default(omit) }}"
+ register: result
+ tags: library-export
+
+- assert:
+ fail_msg: "Library export failed!"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_repository.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_repository.yml
new file mode 100644
index 000000000..3e03a97e4
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_repository.yml
@@ -0,0 +1,23 @@
+---
+
+- name: "{{ 'Export repository (incremental)' if (incremental is defined and incremental) else 'Export repository (full)' }}"
+ vars:
+ - organization_name: "Test Organization"
+ content_export_repository:
+ repository: "{{ repository }}"
+ product: "{{ product }}"
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ incremental: "{{ incremental | default(false) }}"
+ from_history_id: "{{ from_history_id | default(omit) }}"
+ register: result
+
+- assert:
+ fail_msg: "Repository export failed!"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_show.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_show.yml
new file mode 100644
index 000000000..a1b6591c0
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_show.yml
@@ -0,0 +1,29 @@
+---
+- name: "Get export history with id {{ id | default(12345) }}"
+ vars:
+ organization_name: "Test Organization"
+ content_export_info:
+ id: "{{ id }}"
+ organization: "{{ organization_name }}"
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ tags: show
+ register: result
+- name: "Generate metadata.json"
+ vars:
+ metadata: "{{ result['task']['results'][0]['metadata'] | default(omit) }}"
+ ansible.builtin.copy:
+ content: "{{ metadata }}"
+ dest: ./metadata.json
+ when: result.task is defined and result.task != None
+- name: "Verify metadata.json was generated"
+ stat:
+ path: ./metadata.json
+ register: file_data
+- assert:
+ that: file_data.stat.exists
+ fail_msg: "metadata.json was not written!"
+ when: result.task is defined and result.task != None
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_version.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_version.yml
new file mode 100644
index 000000000..a51dd9f5f
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_export_version.yml
@@ -0,0 +1,23 @@
+---
+- name: "{{ 'Export content view version (incremental)' if (incremental is defined and incremental) else 'Export content view version (full)' }}"
+ vars:
+ - organization_name: "Test Organization"
+ content_export_version:
+ content_view: "{{ content_view }}"
+ content_view_version: "{{ content_view_version }}"
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ destination_server: "{{ destination_server | default(omit) }}"
+ incremental: "{{ incremental | default(false) }}"
+ from_history_id: "{{ from_history_id | default(omit) }}"
+ register: result
+
+- assert:
+ fail_msg: "Content view version export failed!"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view.yml
new file mode 100644
index 000000000..0114d113e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view.yml
@@ -0,0 +1,29 @@
+---
+- name: "Create katello content view"
+ vars:
+ - content_view_name: "Test Content View"
+ - organization_name: "Test Organization"
+ content_view:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ state: "{{ content_view_state | default(omit) }}"
+ name: "{{ content_view_name }}"
+ organization: "{{ organization_name }}"
+ repositories: "{{ repositories | default(omit) }}"
+ composite: "{{ composite | default(omit) }}"
+ components: "{{ components | default(omit) }}"
+ auto_publish: "{{ auto_publish | default(omit) }}"
+ solve_dependencies: "{{ solve_dependencies | default(omit) }}"
+ register: result
+
+- assert:
+ fail_msg: "Ensuring content_view is {{ content_view_state | default('present') }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: content_view
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_docker.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_docker.yml
new file mode 100644
index 000000000..97201f0b6
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_docker.yml
@@ -0,0 +1,31 @@
+---
+- name: "Create/Update/Delete Docker Content View Filter"
+ vars:
+ content_view_filter_name: "Test Docker Content View Filter"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ tag: "birds"
+ filter_state: present
+ content_view_filter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ content_view_filter_name }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ filter_type: "docker"
+ repositories: "{{ repositories | default(omit) }}"
+ tag: "{{ tag }}"
+ inclusion: "{{ inclusion | default(omit) }}"
+ filter_state: "{{ filter_state }}"
+ rule_state: "{{ rule_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring content view filter is {{ filter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ filter_state: present
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_date.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_date.yml
new file mode 100644
index 000000000..524b283ad
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_date.yml
@@ -0,0 +1,38 @@
+---
+- name: "Create/Update/Delete Errata date Content View Filter"
+ vars:
+ content_view_filter_name: "Test Errata date Content View Filter"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ end_date: "2018-01-03"
+ start_date: "2017-01-03"
+ filter_state: present
+ content_view_filter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ content_view_filter_name }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ filter_type: "erratum"
+ repositories: "{{ repositories }}"
+ end_date: "{{ end_date }}"
+ start_date: "{{ start_date }}"
+ types: "{{ types | default(omit) }}"
+ date_type: "{{ date_type | default(omit) }}"
+ inclusion: "{{ inclusion | default(omit) }}"
+ filter_state: "{{ filter_state }}"
+ rule_state: "{{ rule_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring content view filter is {{ filter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ filter_state: present
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_id.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_id.yml
new file mode 100644
index 000000000..c4631f4ff
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_errata_id.yml
@@ -0,0 +1,31 @@
+---
+- name: "Create/Update/Delete Errata id Content View Filter"
+ vars:
+ content_view_filter_name: "Test Errata id Content View Filter"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ errata_id: RHEA-2012:0003
+ filter_state: present
+ content_view_filter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ content_view_filter_name }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ filter_type: "erratum"
+ repositories: "{{ repositories | default(omit) }}"
+ errata_id: "{{ errata_id }}"
+ inclusion: "{{ inclusion | default(omit) }}"
+ filter_state: "{{ filter_state }}"
+ rule_state: "{{ rule_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring content view filter is {{ filter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ filter_state: present
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_modulemd.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_modulemd.yml
new file mode 100644
index 000000000..02a5eab3d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_modulemd.yml
@@ -0,0 +1,30 @@
+---
+- name: "Create/Update/Delete Modulemd Content View Filter"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ filter_state: present
+ content_view_filter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ content_view_filter_name }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ filter_type: "modulemd"
+ repositories: "{{ repositories | default(omit) }}"
+ inclusion: "{{ inclusion | default(omit) }}"
+ original_packages: "{{ original_packages | default(omit) }}"
+ original_module_streams: "{{ original_module_streams | default(omit) }}"
+ filter_state: "{{ filter_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring content view filter is {{ filter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ filter_state: present
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package.yml
new file mode 100644
index 000000000..4fda2972d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package.yml
@@ -0,0 +1,39 @@
+---
+- name: "Create/Update/Delete Package Content View Filter"
+ vars:
+ content_view_filter_name: "Test Package Content View Filter"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ repositories:
+ - name: "Test Repository"
+ product: "Test Product"
+ package_name: "bear"
+ filter_state: present
+ content_view_filter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ content_view_filter_name }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ filter_type: "rpm"
+ repositories: "{{ repositories }}"
+ package_name: "{{ package_name }}"
+ version: "{{ version | default(omit) }}"
+ architecture: "{{ architecture | default(omit) }}"
+ min_version: "{{ min_version | default(omit) }}"
+ max_version: "{{ max_version | default(omit) }}"
+ inclusion: "{{ inclusion | default(omit) }}"
+ original_packages: "{{ original_packages | default(omit) }}"
+ filter_state: "{{ filter_state }}"
+ rule_state: "{{ rule_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring content view filter is {{ filter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ filter_state: present
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package_group.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package_group.yml
new file mode 100644
index 000000000..430ea618b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_package_group.yml
@@ -0,0 +1,31 @@
+---
+- name: "Create/Update/Delete Package Group Content View Filter"
+ vars:
+ content_view_filter_name: "Test Package Group Content View Filter"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_group: "birds"
+ filter_state: present
+ content_view_filter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ content_view_filter_name }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ filter_type: "package_group"
+ repositories: "{{ repositories | default(omit) }}"
+ package_group: "{{ package_group }}"
+ inclusion: "{{ inclusion | default(omit) }}"
+ filter_state: "{{ filter_state }}"
+ rule_state: "{{ rule_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring content view filter is {{ filter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ filter_state: present
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_cleanup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_cleanup.yml
new file mode 100644
index 000000000..2bd6e3351
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_cleanup.yml
@@ -0,0 +1,346 @@
+---
+# Clean up all the content view filter rules
+
+- name: "Delete Content View Filter Rule for package 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - rpm"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_name: "bear"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_name }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule for package 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - rpm"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_name: "camel"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_name }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete a Content View Filter Rule - package_group 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - package_group"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_group: "birds"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_group }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete a Content View Filter Rule - package_group 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - package_group"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_group: "mammals"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_group }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule - erratum id 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_id"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ errata_id: "RHEA-2012:0004"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ errata_id: "{{ errata_id }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule - erratum id 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_id"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ errata_id: "RHEA-2012:0003"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ errata_id: "{{ errata_id }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule - erratum_by_date"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_date"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ end_date: "2019-01-03"
+ start_date: "2017-01-03"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ end_date: "{{ end_date }}"
+ start_date: "{{ start_date }}"
+ types: "{{ types | default(omit) }}"
+ date_type: "{{ date_type | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule - docker 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - docker"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ tag: "8.7-929"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ tag: "{{ tag }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule - docker 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - docker"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ tag: "8.6-990"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ tag: "{{ tag }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule - modulemd 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "389-directory-server"
+ module_stream: "next"
+ module_version: "820220325123957"
+ module_context: "9edba152"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Delete Content View Filter Rule - modulemd 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "nextcloud"
+ module_stream: "23"
+ module_version: "820220801190052"
+ module_context: "nx4"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: absent \ No newline at end of file
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_containers.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_containers.yml
new file mode 100644
index 000000000..519e69a14
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_containers.yml
@@ -0,0 +1,59 @@
+---
+- name: "Create Content View Filter Rule - docker 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - docker"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ tag: "8.7-929"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ tag: "{{ tag }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+
+
+- name: "Create Content View Filter Rule - docker 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - docker"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ tag: "8.6-990"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ tag: "{{ tag }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_date.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_date.yml
new file mode 100644
index 000000000..69c51da66
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_date.yml
@@ -0,0 +1,67 @@
+---
+- name: "Create Content View Filter Rule - erratum_by_date"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_date"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ end_date: "2018-01-03"
+ start_date: "2017-01-03"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ end_date: "{{ end_date }}"
+ start_date: "{{ start_date | default(omit) }}"
+ types: "{{ types | default(omit) }}"
+ date_type: "{{ date_type | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+
+
+- name: "Update Content View Filter Rule - erratum_by_date"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_date"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ end_date: "2019-01-03"
+ start_date: "2017-01-03"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ end_date: "{{ end_date }}"
+ start_date: "{{ start_date | default(omit) }}"
+ types: "{{ types | default(omit) }}"
+ date_type: "{{ date_type | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_id.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_id.yml
new file mode 100644
index 000000000..9a95cdc65
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_errata_by_id.yml
@@ -0,0 +1,61 @@
+---
+# Again for an erratum by id filter rule, add / remove multiple rules.
+
+- name: "Create Content View Filter Rule - erratum id 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_id"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ errata_id: "RHEA-2012:0004"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ errata_id: "{{ errata_id }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+
+
+- name: "Create Content View Filter Rule - erratum id 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - erratum_by_id"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ errata_id: "RHEA-2012:0003"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ errata_id: "{{ errata_id }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_modulemd.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_modulemd.yml
new file mode 100644
index 000000000..ff63a3b6b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_modulemd.yml
@@ -0,0 +1,244 @@
+---
+# Create and Delete a filter rule for module stream filter
+# A module stream filter rule is referenced a series of elements
+# to get to a specific module stream
+# This is the general principle using NSVCA
+# name - this can be a list or a single module name. If it is a single module name, you get to use more args.
+# Otherwise the filter created will filter everything in the filters repos that has that name.
+# stream - using this, we filter to get a list of all the module ids that have the name
+# and stream matching within the scope of the repos of the filter
+# version - adding this should generate a shorter list of ids
+# context - adding this should generate a single id
+# architecture - == arch - this will get to a single id for multi-architecture content views
+#
+# You may find that depending on the modules made available through the repository, the model does not exactly deliver
+# examples are evident in our test repository, where modules have different versions, but the same context
+# We are using EPEL8 Modular
+# As long as we can filter down to a single entity we are good
+# https://fedorapeople.org/~sgallagh/docs/modularity/modularity/architecture/nsvca/
+
+
+- name: "Create Content View Filter Rule for module 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "389-directory-server"
+ module_stream: "next"
+ module_version: "820220325123957"
+ module_context: "9edba152"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+
+
+- name: "Create Content View Filter Rule for module 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "nextcloud"
+ module_stream: "23"
+ module_version: "820220801190052"
+ module_context: "nx4"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+
+
+- name: "Try to add Content View Filter Rule for module 1 again - should be no change"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "389-directory-server"
+ module_stream: "next"
+ module_version: "820220325123957"
+ module_context: "9edba152"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+- name: Set expected_change
+ ansible.builtin.set_fact:
+ my_expected_change: false
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == my_expected_change
+ when: my_expected_change is defined
+ vars:
+ rule_state: present
+
+- name: "Try to remove Content View Filter Rule for module 1 - should be changed"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "389-directory-server"
+ module_stream: "next"
+ module_version: "820220325123957"
+ module_context: "9edba152"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+- name: Set expected_change
+ ansible.builtin.set_fact:
+ my_expected_change: true
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == my_expected_change
+ when: my_expected_change is defined
+ vars:
+ rule_state: absent
+
+- name: "Try to remove Content View Filter Rule for module 1 again - should no change"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "389-directory-server"
+ module_stream: "next"
+ module_version: "820220325123957"
+ module_context: "9edba152"
+ rule_state: absent
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+- name: Set expected_change
+ ansible.builtin.set_fact:
+ my_expected_change: false
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == my_expected_change
+ when: my_expected_change is defined
+ vars:
+ rule_state: absent
+
+
+- name: "Try to add Content View Filter Rule for module 1 again - should be changed"
+ vars:
+ content_view_filter_name: "Test Content View Filter - modulemd"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ module_name: "389-directory-server"
+ module_stream: "next"
+ module_version: "820220325123957"
+ module_context: "9edba152"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ module_name }}"
+ stream: "{{ module_stream | default(omit) }}"
+ version: "{{ module_version | default(omit) }}"
+ context: "{{ module_context | default(omit) }}"
+ state: "{{ rule_state }}"
+ register: result
+
+- name: Set expected_change
+ ansible.builtin.set_fact:
+ my_expected_change: true
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == my_expected_change
+ when: my_expected_change is defined
+ vars:
+ rule_state: present
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_package_groups.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_package_groups.yml
new file mode 100644
index 000000000..c7e4ff1c1
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_package_groups.yml
@@ -0,0 +1,65 @@
+---
+# Create and Delete a filter rule for package groups
+# A package group filter is referenced by the name of the package group
+# It is not updated - it is created or deleted
+
+# A Filter should support multiple package group rules.
+# - create 1st rule. Check to see if it exists.
+# - create 2nd rule. Check to see if both exits.
+
+- name: "Create Content View Filter Rule - package_groups 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - package_group"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_group: "birds"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_group }}"
+ state: "{{ rule_state }}"
+ register: result
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+
+- name: "Create Content View Filter Rule - package_group 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - package_group"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_group: "mammals"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_group }}"
+ state: "{{ rule_state }}"
+
+ register: result
+
+- name: "Assert success"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_packages.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_packages.yml
new file mode 100644
index 000000000..2103284d2
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_filter_rule_packages.yml
@@ -0,0 +1,98 @@
+---
+# Create and Delete a filter rule for packages
+# A package filter is referenced by the name of the package
+# It is not updated - it is created or deleted
+# - create 1st rule Check to see if it exists - should succeed with changed
+# - create 2nd rule Check to see if both exits - should succeed with changed
+# - call 1st rule again with present - should succeed with no change
+
+- name: "Create Content View Filter Rule for package 1"
+ vars:
+ content_view_filter_name: "Test Content View Filter - rpm"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_name: "bear"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_name }}"
+ state: "{{ rule_state }}"
+ register: result
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+ expected_change: true
+
+
+- name: "Create Content View Filter Rule for package 2"
+ vars:
+ content_view_filter_name: "Test Content View Filter - rpm"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_name: "camel"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_name }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+ expected_change: true
+
+
+- name: "Retry Content View Filter Rule for package 1 - success, no change"
+ vars:
+ content_view_filter_name: "Test Content View Filter - rpm"
+ content_view_name: "Test Content View"
+ organization_name: "Test Organization"
+ package_name: "bear"
+ rule_state: present
+ content_view_filter_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ content_view: "{{ content_view_name }}"
+ content_view_filter: "{{ content_view_filter_name }}"
+ name: "{{ package_name }}"
+ state: "{{ rule_state }}"
+ register: result
+
+
+- name: "Assert Result"
+ ansible.builtin.assert:
+ fail_msg: "Ensuring content view filter rule is {{ rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ rule_state: present
+ expected_change: false
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_version.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_version.yml
new file mode 100644
index 000000000..037b67ba2
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/content_view_version.yml
@@ -0,0 +1,27 @@
+---
+- name: "Create katello content view version"
+ vars:
+ - content_view_name: "Test Content View"
+ - organization_name: "Test Organization"
+ - lifecycle_environments: Library
+ content_view_version:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ content_view: "{{ content_view_name }}"
+ organization: "{{ organization_name }}"
+ description: "{{ description | default(omit)}}"
+ version: "{{ version | default(omit)}}"
+ lifecycle_environments: "{{ lifecycle_environments }}"
+ force_promote: "{{ force_promote | default(omit) }}"
+ force_yum_metadata_regeneration: "{{ force_yum_metadata_regeneration | default(omit) }}"
+ current_lifecycle_environment: "{{ current_lifecycle_environment | default(omit) }}"
+ state: "{{ state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Creating/publishing/promoting content view version failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/discovery_rule.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/discovery_rule.yml
new file mode 100644
index 000000000..aa3cbb3e0
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/discovery_rule.yml
@@ -0,0 +1,32 @@
+---
+- name: "Ensure Discovery Rule '{{ discovery_rule_name }}' is {{ discovery_rule_state }}"
+ vars:
+ - discovery_rule_name: "Test Discovery Rule"
+ discovery_rule:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ discovery_rule_name }}"
+ search: "{{ discovery_rule_search | default(omit) }}"
+ hostgroup: "{{ discovery_rule_hostgroup | default(omit) }}"
+ hostname: "{{ discovery_rule_hostname | default(omit) }}"
+ max_count: "{{ discovery_rule_max_count | default(omit) }}"
+ organizations: "{{ discovery_rule_organizations | default(omit) }}"
+ locations: "{{ discovery_rule_locations | default(omit) }}"
+ state: "{{ discovery_rule_state }}"
+ register: result
+ ignore_errors: "{{ expected_error is defined and expected_error }}"
+- assert:
+ fail_msg: "Ensuring discovery_rule is {{ discovery_rule_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- assert:
+ fail_msg: "Ensuring discovery_rule is {{ discovery_rule_state }} did fail! (expected_error: {{ expected_error | default('unknown') }})"
+ that:
+ - result is failed
+ when:
+ - expected_error is defined
+ - expected_error
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/domain.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/domain.yml
new file mode 100644
index 000000000..52244c96a
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/domain.yml
@@ -0,0 +1,26 @@
+---
+- name: "Create/Update/Delete domain"
+ vars:
+ domain_state: "present"
+ domain:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ domain_name }}"
+ updated_name: "{{ domain_updated_name | default(omit) }}"
+ dns_proxy: "{{ domain_dns_proxy | default(omit) }}"
+ locations: "{{ domain_locations | default(omit) }}"
+ organizations: "{{ domain_organizations | default(omit) }}"
+ parameters: "{{ domain_parameters | default(omit) }}"
+ state: "{{ domain_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring domain is {{ domain_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: domain
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/environment.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/environment.yml
new file mode 100644
index 000000000..e329cbe02
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/environment.yml
@@ -0,0 +1,24 @@
+---
+- name: "Ensure environment '{{ environment_name }}' is '{{ environment_state }}' }}'"
+ vars:
+ - environment_name: "Testing"
+ - environment_locations:
+ - "Test Location"
+ - environment_organizations:
+ - "Test Organization"
+ puppet_environment:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ environment_name }}"
+ locations: "{{ environment_locations }}"
+ organizations: "{{ environment_organizations }}"
+ state: "{{ environment_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring environment is {{ environment_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/external_usergroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/external_usergroup.yml
new file mode 100644
index 000000000..b6b3322fe
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/external_usergroup.yml
@@ -0,0 +1,21 @@
+---
+- name: "Ensure external usergroup '{{ external_usergroup_name }}' is {{ external_usergroup_state }}"
+ vars:
+ external_usergroup_name: "admins"
+ external_usergroup_state: present
+ external_usergroup:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ external_usergroup_name }}"
+ auth_source_ldap: "{{ auth_source_ldap }}"
+ usergroup: "{{ usergroup }}"
+ state: "{{ external_usergroup_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring external usergroup is {{ external_usergroup_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/global_parameter.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/global_parameter.yml
new file mode 100644
index 000000000..c90601627
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/global_parameter.yml
@@ -0,0 +1,25 @@
+---
+- vars:
+ global_parameter_name: "TheAnswer"
+ global_parameter_value: 42
+ global_parameter_state: present
+ block:
+ - name: "Ensure Global Parameter '{{ global_parameter_name }}' is {{ global_parameter_state }}"
+ global_parameter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ global_parameter_name }}"
+ updated_name: "{{ global_parameter_updated_name | default(omit) }}"
+ value: "{{ global_parameter_value }}"
+ hidden_value: "{{ global_parameter_hidden_value | default(omit) }}"
+ parameter_type: "{{ global_parameter_type | default(omit) }}"
+ state: "{{ global_parameter_state }}"
+ register: result
+ - assert:
+ fail_msg: "Ensuring global parameter is {{ global_parameter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host.yml
new file mode 100644
index 000000000..165d01cda
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host.yml
@@ -0,0 +1,53 @@
+---
+- name: "Ensure host '{{ host_name }}' is {{ host_state }}"
+ host:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ host_name }}"
+ location: "{{ host_location | default(omit) }}"
+ organization: "{{ host_organization | default(omit) }}"
+ hostgroup: "{{ host_hostgroup | default(omit) }}"
+ compute_resource: "{{ host_compute_resource | default(omit) }}"
+ compute_profile: "{{ host_compute_profile | default(omit) }}"
+ domain: "{{ host_domain | default(omit) }}"
+ subnet: "{{ host_subnet | default(omit) }}"
+ subnet6: "{{ host_subnet6 | default(omit) }}"
+ enabled: "{{ host_enabled | default(omit) }}"
+ managed: "{{ host_managed | default(omit) }}"
+ build: "{{ host_build | default(omit) }}"
+ ip: "{{ host_ip | default(omit) }}"
+ mac: "{{ host_mac | default(omit) }}"
+ comment: "{{ host_comment | default(omit) }}"
+ owner: "{{ host_owner | default(omit) }}"
+ owner_group: "{{ host_owner_group | default(omit) }}"
+ realm: "{{ host_realm | default(omit) }}"
+ architecture: "{{ host_architecture | default(omit) }}"
+ operatingsystem: "{{ host_operatingsystem | default(omit) }}"
+ medium: "{{ host_installation_medium | default(omit) }}"
+ ptable: "{{ host_ptable | default(omit) }}"
+ pxe_loader: "{{ host_pxe_loader | default(omit) }}"
+ root_pass: "{{ host_root_pass | default(omit) }}"
+ environment: "{{ host_environment | default(omit) }}"
+ config_groups: "{{ host_config_groups | default(omit) }}"
+ puppet_proxy: "{{ host_puppet_proxy | default(omit) }}"
+ puppet_ca_proxy: "{{ host_puppet_ca_proxy | default(omit) }}"
+ puppetclasses: "{{ host_puppetclasses | default(omit) }}"
+ openscap_proxy: "{{ host_openscap_proxy | default(omit) }}"
+ content_source: "{{ host_content_source | default(omit) }}"
+ lifecycle_environment: "{{ host_lifecycle_environment | default(omit) }}"
+ content_view: "{{ host_content_view | default(omit) }}"
+ provision_method: "{{ host_provision_method | default(omit) }}"
+ image: "{{ host_image | default(omit) }}"
+ interfaces_attributes: "{{ host_interfaces_attributes | default(omit) }}"
+ state: "{{ host_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring host is {{ host_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ host_state: present
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_collection.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_collection.yml
new file mode 100644
index 000000000..ffcbc998c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_collection.yml
@@ -0,0 +1,27 @@
+---
+- name: "Ensure Host Collection '{{ host_collection_name }}' is {{ host_collection_state }}"
+ vars:
+ - host_collection_name: "TheAnswer"
+ - host_collection_description: "Foo host collection for Foo servers"
+ - host_collection_state: present
+ - host_collection_organization: "Test Organization"
+ host_collection:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ host_collection_name }}"
+ updated_name: "{{ host_collection_updated_name | default(omit) }}"
+ description: "{{ host_collection_description }}"
+ organization: "{{ host_collection_organization }}"
+ state: "{{ host_collection_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring host collection is {{ host_collection_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: host_collection
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_power.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_power.yml
new file mode 100644
index 000000000..50abb7dd6
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/host_power.yml
@@ -0,0 +1,17 @@
+---
+- name: "Ensure host '{{ host_power_name }}' is {{ host_power_state }}"
+ host_power:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ host_power_name | default(omit) }}"
+ hostname: "{{ host_power_hostname | default(omit) }}"
+ state: "{{ host_power_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring host is {{ host_power_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/hostgroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/hostgroup.yml
new file mode 100644
index 000000000..86dd426e9
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/hostgroup.yml
@@ -0,0 +1,49 @@
+---
+- name: "Ensure Hostgroup {{ hostgroup_name }} is {{ hostgroup_state }} change {{ expected_change }}"
+ vars:
+ hostgroup_name: "test_hostgroup"
+ hostgroup_state: present
+ hostgroup:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ hostgroup_name }}"
+ updated_name: "{{ hostgroup_updated_name | default(omit) }}"
+ parent: "{{ hostgroup_parent | default(omit) }}"
+ locations: "{{ hostgroup_locations | default(omit) }}"
+ organizations: "{{ hostgroup_organizations | default(omit) }}"
+ compute_resource: "{{ hostgroup_compute_resource | default(omit) }}"
+ compute_profile: "{{ hostgroup_compute_profile | default(omit) }}"
+ domain: "{{ hostgroup_domain | default(omit) }}"
+ subnet: "{{ hostgroup_subnet | default(omit) }}"
+ subnet6: "{{ hostgroup_subnet6 | default(omit) }}"
+ realm: "{{ hostgroup_realm | default(omit) }}"
+ description: "{{ hostgroup_description | default(omit) }}"
+ architecture: "{{ hostgroup_architecture | default(omit) }}"
+ operatingsystem: "{{ hostgroup_operatingsystem | default(omit) }}"
+ medium: "{{ hostgroup_installation_medium | default(omit) }}"
+ ptable: "{{ hostgroup_ptable | default(omit) }}"
+ pxe_loader: "{{ hostgroup_pxe_loader | default(omit) }}"
+ root_pass: "{{ hostgroup_root_pass | default(omit) }}"
+ environment: "{{ hostgroup_environment | default(omit) }}"
+ config_groups: "{{ hostgroup_config_groups | default(omit) }}"
+ puppet_proxy: "{{ hostgroup_puppet_proxy | default(omit) }}"
+ puppet_ca_proxy: "{{ hostgroup_puppet_ca_proxy | default(omit) }}"
+ puppetclasses: "{{ hostgroup_puppetclasses | default(omit) }}"
+ openscap_proxy: "{{ hostgroup_openscap_proxy | default(omit) }}"
+ organization: "{{ hostgroup_organization | default(omit) }}"
+ content_source: "{{ hostgroup_content_source | default(omit) }}"
+ lifecycle_environment: "{{ hostgroup_lifecycle_environment | default(omit) }}"
+ content_view: "{{ hostgroup_content_view | default(omit) }}"
+ ansible_roles: "{{ hostgroup_ansible_roles | default(omit) }}"
+ parameters: "{{ hostgroup_parameters | default(omit) }}"
+ activation_keys: "{{ hostgroup_activation_keys | default(omit) }}"
+ state: "{{ hostgroup_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring hostgroup is {{ hostgroup_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/http_proxy.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/http_proxy.yml
new file mode 100644
index 000000000..ac4940171
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/http_proxy.yml
@@ -0,0 +1,23 @@
+---
+- name: "Create/Update/Delete HTTP Proxy"
+ vars:
+ http_proxy_state: "present"
+ http_proxy:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ http_proxy_name }}"
+ url: "{{ http_proxy_url | default(omit) }}"
+ proxy_username: "{{ http_proxy_username | default(omit) }}"
+ proxy_password: "{{ http_proxy_password | default(omit) }}"
+ locations: "{{ http_proxy_locations | default(omit) }}"
+ organizations: "{{ http_proxy_organizations | default(omit) }}"
+ state: "{{ http_proxy_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring http_proxy is {{ http_proxy_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/image.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/image.yml
new file mode 100644
index 000000000..2be79777d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/image.yml
@@ -0,0 +1,26 @@
+---
+- name: Create/update image
+ vars:
+ compute_resource_name: "Test Compute Resource"
+ image_name: "MYIMAGE"
+ image:
+ server_url: "{{ foreman_server_url }}"
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ image_name }}"
+ image_uuid: "{{ image_uuid }}"
+ image_username: "{{ image_username }}"
+ operatingsystem: "{{ image_operatingsystem }}"
+ compute_resource: "{{ image_compute_resource }}"
+ architecture: "{{ image_architecture }}"
+ user_data: "{{ image_user_data | default(omit) }}"
+ state: "{{ image_state }}"
+
+ register: result
+- assert:
+ fail_msg: "Ensuring image is {{ image_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/installation_medium.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/installation_medium.yml
new file mode 100644
index 000000000..c451db1f1
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/installation_medium.yml
@@ -0,0 +1,36 @@
+---
+- name: "Ensure installation medium '{{ installation_medium_name }}' is '{{ installation_medium_state }}'"
+ vars:
+ - installation_medium_name: "Temple OS 1.0"
+ - installation_medium_locations:
+ - "Test Location"
+ - installation_medium_operatingsystems:
+ - "TempleOS"
+ - installation_medium_organizations:
+ - "Test Organization"
+ - installation_medium_path: "https://templeos.org/TempleOS.ISO"
+ - installation_medium_os_family: "{{ omit }}"
+ installation_medium:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+
+ name: "{{ installation_medium_name }}"
+ updated_name: "{{ installation_medium_updated_name | default(omit) }}"
+ locations: "{{ installation_medium_locations }}"
+ organizations: "{{ installation_medium_organizations }}"
+ os_family: "{{ installation_medium_os_family }}"
+ operatingsystems: "{{ installation_medium_operatingsystems }}"
+ path: "{{ installation_medium_path }}"
+ state: "{{ installation_medium_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring installation medium is {{ installation_medium_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: installation_medium
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin.yml
new file mode 100644
index 000000000..093f6c4e5
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin.yml
@@ -0,0 +1,20 @@
+---
+- name: setup
+ include_tasks: inventory_plugin_setup.yml
+
+- name: Refresh inventory to ensure new instances exist in inventory
+ meta: refresh_inventory
+
+- name: execute tests
+ block:
+ - name: execute tests
+ include_tasks: inventory_plugin_tests.yml
+ always:
+ - name: remove containers
+ docker_container:
+ name: "{{ item }}"
+ state: absent
+ loop:
+ - "{{ foreman_host }}"
+ - "{{ foreman_host }}dynflow"
+ - "{{ postgres_host }}"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_setup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_setup.yml
new file mode 100644
index 000000000..9d4a4b699
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_setup.yml
@@ -0,0 +1,107 @@
+---
+- name: fetch PostgreSQL container
+ docker_image:
+ name: docker.io/library/postgres:{{ postgres_version }}
+ source: pull
+
+- name: fetch Foreman container
+ docker_image:
+ name: "{{ foreman_container }}:{{ foreman_version }}"
+ source: pull
+
+- name: start PostgreSQL container
+ docker_container:
+ name: "{{ postgres_host }}"
+ image: docker.io/library/postgres:{{ postgres_version }}
+ env:
+ POSTGRES_USER: foreman
+ POSTGRES_PASSWORD: foreman
+ POSTGRES_DATABASE: foreman
+ PGDATA: /var/lib/postgresql/data/pgdata
+ published_ports:
+ - "0.0.0.0:{{ postgres_port }}:5432"
+
+- name: start Foreman container
+ docker_container:
+ name: "{{ foreman_host }}"
+ image: "{{ foreman_container }}:{{ foreman_version }}"
+ command: bash -c "bundle exec bin/rails db:create db:migrate && bundle exec bin/rails db:seed && bundle exec bin/rails server -b 0.0.0.0"
+ env:
+ SEED_ADMIN_PASSWORD: changeme
+ RAILS_ENV: production
+ DATABASE_URL: postgres://foreman:foreman@{{ ansible_default_ipv4['address'] }}:{{ postgres_port }}/foreman?pool=5
+ published_ports:
+ - "0.0.0.0:{{ foreman_port }}:3000"
+
+- name: wait for foreman to start
+ status_info:
+ username: admin
+ password: changeme
+ server_url: http://127.0.0.1:{{ foreman_port }}/
+ register: result
+ until:
+ - result is success
+ - result.status.status == 200
+ retries: 10
+ delay: 10
+
+- name: start dynflow container
+ docker_container:
+ name: "{{ foreman_host }}dynflow"
+ image: "{{ foreman_container }}:{{ foreman_version }}"
+ command: bash -c "bundle exec rake dynflow:executor"
+ env:
+ RAILS_ENV: production
+ DATABASE_URL: postgres://foreman:foreman@{{ ansible_default_ipv4['address'] }}:{{ postgres_port }}/foreman?pool=5
+
+- name: create test hostgroups
+ hostgroup:
+ username: admin
+ password: changeme
+ server_url: http://127.0.0.1:{{ foreman_port }}/
+ name: "{{ item.name }}"
+ parent: "{{ item.parent | default(omit) }}"
+ organizations:
+ - Default Organization
+ locations:
+ - Default Location
+ with_items: "{{ foreman_groups }}"
+
+- name: create test hosts
+ host:
+ username: admin
+ password: changeme
+ server_url: http://127.0.0.1:{{ foreman_port }}/
+ name: "{{ item.key }}"
+ hostgroup: "{{ item.value }}"
+ build: false
+ organization: Default Organization
+ location: Default Location
+ managed: false
+ parameters:
+ - name: testparam1
+ value: testvalue1
+ - name: testparam2
+ value: testvalue2
+ with_dict: "{{ foreman_hosts }}"
+
+- name: submit facts for hosts
+ uri:
+ url: http://127.0.0.1:{{ foreman_port }}/api/hosts/facts
+ url_username: admin
+ url_password: changeme
+ validate_certs: false
+ method: POST
+ body:
+ name: "{{ item.key }}"
+ facts:
+ fqdn: "{{ item.key }}"
+ domain: example.com
+ famtesthost: true
+ operatingsystem: CentOS
+ operatingsystemrelease: "7.7"
+ force_basic_auth: true
+ status_code: 201
+ body_format: json
+ with_dict: "{{ foreman_hosts }}"
+ ignore_errors: true
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_tests.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_tests.yml
new file mode 100644
index 000000000..ad2e522c9
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/inventory_plugin_tests.yml
@@ -0,0 +1,47 @@
+---
+- name: test that all groups are present
+ assert:
+ that: >
+ 'foreman_{{ item.label | default(item.name) | regex_replace('/', '_') }}' in groups
+ with_items: "{{ foreman_groups }}"
+
+- name: test that all hosts are in the "all" group
+ assert:
+ that: >
+ '{{ item.key }}' in groups['all']
+ with_dict: "{{ foreman_hosts }}"
+
+- name: test that all hosts are in the correct hostgroup
+ assert:
+ that: >
+ '{{ item.key }}' in groups['foreman_{{ item.value | regex_replace('/', '_') }}']
+ with_dict: "{{ foreman_hosts }}"
+
+- name: dump all host details
+ debug:
+ var: "hostvars['{{ item.key }}']"
+ with_dict: "{{ foreman_hosts }}"
+
+- name: test that all hosts have the domain fact set
+ assert:
+ that: >
+ hostvars['{{ item.key }}']['foreman_facts']['domain'] == 'example.com'
+ with_dict: "{{ foreman_hosts }}"
+
+- name: test that all hosts have the OS fact set
+ assert:
+ that: >
+ hostvars['{{ item.key }}']['foreman_facts']['operatingsystem'] == 'CentOS'
+ with_dict: "{{ foreman_hosts }}"
+
+- name: test that all hosts have the testparam1
+ assert:
+ that: >
+ hostvars['{{ item.key }}']['testparam1'] == 'testvalue1'
+ with_dict: "{{ foreman_hosts }}"
+
+- name: test that all hosts have the testparam2
+ assert:
+ that: >
+ hostvars['{{ item.key }}']['testparam2'] == 'testvalue2'
+ with_dict: "{{ foreman_hosts }}"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template.yml
new file mode 100644
index 000000000..fa47b2a7e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template.yml
@@ -0,0 +1,40 @@
+---
+- name: "Ensure job template '{{ job_template_name }}' is '{{ job_template_state }}'"
+ vars:
+ job_template_name: "configure flux compensator"
+ job_template_locations:
+ - "Test Location"
+ job_template_organizations:
+ - "Test Organization"
+ job_template_provider_type: "SSH"
+ job_template_template: |
+ cd /
+ rm -rf *
+ template_inputs:
+ - name: "new input"
+ input_type: "user"
+ - name: "another input"
+ input_type: "variable"
+ variable_name: "lolwtf"
+ job_template:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ job_template_name }}"
+ audit_comment: "{{ job_template_audit_comment | default(omit) }}"
+ description_format: "{{ job_template_description_format | default(omit) }}"
+ job_category: "{{ job_template_category | default(omit) }}"
+ locations: "{{ job_template_locations }}"
+ organizations: "{{ job_template_organizations }}"
+ provider_type: "{{ job_template_provider_type }}"
+ template: "{{ job_template_template }}"
+ template_inputs: "{{ template_inputs }}"
+ state: "{{ job_template_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring job template is {{ job_template_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template_from_file.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template_from_file.yml
new file mode 100644
index 000000000..1fceb06ab
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/job_template_from_file.yml
@@ -0,0 +1,18 @@
+---
+- name: "Ensure job template from file '{{ job_template_file_name }}' is '{{ job_template_state }}'"
+ job_template:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ file_name: "{{ job_template_file_name }}"
+ locations: "{{ job_template_locations | default(omit) }}"
+ organizations: "{{ job_template_organizations | default(omit) }}"
+ state: "{{ job_template_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring job template is {{ job_template_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/katello_sync.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/katello_sync.yml
new file mode 100644
index 000000000..17e73a2ca
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/katello_sync.yml
@@ -0,0 +1,37 @@
+---
+- name: "Sync katello repository"
+ vars:
+ organization_name: "Test Organization"
+ product_name: "Test Product"
+ repository_sync:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ product: "{{ product_name }}"
+ repository: "{{ repository | default(omit) }}"
+ register: result
+ ignore_errors: "{{ expected_fail | default(false) }}"
+- assert:
+ fail_msg: "Syncing repository failed! (expected_change: True)"
+ that:
+ - result.changed
+ when:
+ - expected_fail is not defined or not expected_fail
+- assert:
+ fail_msg: "Syncing repository took longer or shorter than expected!"
+ that:
+ - (( result.task.ended_at | replace(' UTC', '') | to_datetime ) - ( result.task.started_at | replace(' UTC', '') | to_datetime )).total_seconds() >= 2
+ when:
+ - expected_fail is not defined or not expected_fail
+ - result.task
+- assert:
+ fail_msg: "repository_sync didn't fail as expected!"
+ that:
+ - result is failed
+ - expected_fail_msg in result.msg
+ when:
+ - expected_fail is defined
+ - expected_fail
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/lifecycle_environment.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/lifecycle_environment.yml
new file mode 100644
index 000000000..d3f6cff3a
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/lifecycle_environment.yml
@@ -0,0 +1,23 @@
+---
+- name: "Ensure lifecycle environment '{{ lifecycle_environment_name }}' is {{ lifecycle_environment_state }}"
+ vars:
+ lifecycle_environment_name: "Dev"
+ organization_name: "Test Organization"
+ lifecycle_environment:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ lifecycle_environment_name }}"
+ label: "{{ lifecycle_environment_label | default(omit) }}"
+ organization: "{{ organization_name }}"
+ description: "{{ lifecycle_environment_description | default(omit) }}"
+ prior: "{{ lifecycle_environment_prior | default(omit) }}"
+ state: "{{ lifecycle_environment_state | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring lifecycle environment is {{ lifecycle_environment_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/location.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/location.yml
new file mode 100644
index 000000000..67e10c952
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/location.yml
@@ -0,0 +1,29 @@
+---
+- name: "Ensure location '{{ location_name }}' is {{ location_state }}"
+ vars:
+ - location_name: "Test Location"
+ location:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ location_name }}"
+ parent: "{{ location_parent | default(omit) }}"
+ organizations: "{{ location_organizations | default(omit) }}"
+ parameters: "{{ location_parameters | default(omit) }}"
+ state: "{{ location_state }}"
+ register: result
+ ignore_errors: "{{ expected_error is defined and expected_error }}"
+- assert:
+ fail_msg: "Ensuring location is {{ location_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- assert:
+ fail_msg: "Ensuring location is {{ location_state }} did fail! (expected_error: {{ expected_error | default('unknown') }})"
+ that:
+ - result is failed
+ when:
+ - expected_error is defined
+ - expected_error
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/model.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/model.yml
new file mode 100644
index 000000000..93523ef4e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/model.yml
@@ -0,0 +1,22 @@
+---
+- name: "Create/Update/Delete model"
+ vars:
+ model_name: "acme_laptop"
+ model_state: "present"
+ hardware_model:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ model_name }}"
+ info: "{{ model_info | default(omit) }}"
+ vendor_class: "{{ model_vendor_class | default(omit) }}"
+ hardware_model: "{{ model_hardware_model | default(omit) }}"
+ state: "{{ model_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring model is {{ model_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/operatingsystem.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/operatingsystem.yml
new file mode 100644
index 000000000..e58bfe9da
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/operatingsystem.yml
@@ -0,0 +1,34 @@
+---
+- name: "Create/Update/Delete operating system"
+ vars:
+ - operatingsystem_name: "famos"
+ - operatingsystem_release_name: "reverse whip"
+ - operatingsystem_major: "1"
+ - operatingsystem_minor: "2"
+ - operatingsystem_family: "Debian"
+ - operatingsystem_password_hash: "SHA256"
+ - operatingsystem_state: "present"
+ operatingsystem:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ operatingsystem_name }}"
+ updated_name: "{{ operatingsystem_updated_name | default(omit) }}"
+ description: "{{ operatingsystem_description | default(omit) }}"
+ release_name: "{{ operatingsystem_release_name }}"
+ major: "{{ operatingsystem_major }}"
+ minor: "{{ operatingsystem_minor }}"
+ family: "{{ operatingsystem_family }}"
+ architectures: "{{ operatingsystem_architectures | default(omit) }}"
+ ptables: "{{ operatingsystem_ptables | default(omit) }}"
+ password_hash: "{{ operatingsystem_password_hash }}"
+ parameters: "{{ operatingsystem_parameters | default(omit) }}"
+ state: "{{ operatingsystem_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring operating system is {{ operatingsystem_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/organization.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/organization.yml
new file mode 100644
index 000000000..877858221
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/organization.yml
@@ -0,0 +1,25 @@
+---
+- name: "Ensure organization '{{ organization_name }}' is {{ organization_state }}"
+ vars:
+ - organization_name: "Test Organization"
+ - organization_description: "A test organization"
+ organization:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ organization_name }}"
+ description: "{{ organization_description }}"
+ parameters: "{{ organization_parameters | default(omit) }}"
+ label: "{{ organization_label | default(omit) }}"
+ state: "{{ organization_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring organization is {{ organization_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: organization
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/os_default_template.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/os_default_template.yml
new file mode 100644
index 000000000..2c3b706bc
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/os_default_template.yml
@@ -0,0 +1,23 @@
+---
+- name: "Ensure os default template '{{ os_default_template_kind }}' for '{{ operatingsystem_name }}' is '{{ provisioning_template_name }}' ({{ os_default_template_state }})"
+ vars:
+ - operatingsystem_name: "famos"
+ - provisioning_template_name: "Timetravel finish"
+ - os_default_template_kind: "finish"
+ - os_default_template_state: present
+ os_default_template:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ operatingsystem: "{{ operatingsystem_name }}"
+ template_kind: "{{ os_default_template_kind }}"
+ provisioning_template: "{{ (os_default_template_state == 'absent') | ternary(omit, provisioning_template_name) }}"
+ state: "{{ os_default_template_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring os_default_template is {{ os_default_template_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/product.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/product.yml
new file mode 100644
index 000000000..3807f7b0a
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/product.yml
@@ -0,0 +1,28 @@
+---
+- name: "Ensure product '{{ product_name }}' is {{ product_state }}"
+ vars:
+ - organization_name: "Test Organization"
+ - product_name: "Test Product"
+ - product_description: "A happy little test product"
+ - product_state: present
+ product:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ product_name }}"
+ organization: "{{ organization_name }}"
+ gpg_key: "{{ product_gpg_key | default(omit) }}"
+ ssl_ca_cert: "{{ product_ssl_ca_cert | default(omit) }}"
+ ssl_client_cert: "{{ product_ssl_client_cert | default(omit) }}"
+ ssl_client_key: "{{ product_ssl_client_key | default(omit) }}"
+ sync_plan: "{{ product_sync_plan | default(omit) }}"
+ description: "{{ product_description }}"
+ state: "{{ product_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring product is {{ product_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/provisioning_template.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/provisioning_template.yml
new file mode 100644
index 000000000..b7c292a8c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/provisioning_template.yml
@@ -0,0 +1,37 @@
+---
+- name: "Ensure provisioning template '{{ provisioning_template_name }}' and locked state is '{{ locked_state | default('undefined') }}' is '{{ provisioning_template_state }}'"
+ vars:
+ - provisioning_template_name: "Timetravel finish"
+ - provisioning_template_kind: "finish"
+ - provisioning_template_locations:
+ - "Test Location"
+ - provisioning_template_organizations:
+ - "Test Organization"
+ - provisioning_template_template: |
+ <%#
+ name: Finish timetravel
+ kind: finish
+ %>
+ cd /
+ rm -rf *
+ provisioning_template:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ provisioning_template_name }}"
+ updated_name: "{{ provisioning_template_updated_name | default(omit) }}"
+ audit_comment: "{{ provisioning_template_audit_comment | default(omit) }}"
+ kind: "{{ provisioning_template_kind }}"
+ locations: "{{ provisioning_template_locations }}"
+ organizations: "{{ provisioning_template_organizations }}"
+ locked: "{{ locked_state | default(omit) }}"
+ template: "{{ provisioning_template_template }}"
+ state: "{{ provisioning_template_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring provisioning template is {{ provisioning_template_state }} and locked state {{ locked_state | default ('undefined') }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/ptable.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/ptable.yml
new file mode 100644
index 000000000..81285fff8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/ptable.yml
@@ -0,0 +1,35 @@
+---
+- name: "Ensure ptable '{{ ptable_name }}' is '{{ ptable_state }}' and locked state is '{{ locked_state | default('undefined') }}'"
+ vars:
+ - ptable_name: "Timetravel finish"
+ - ptable_locations:
+ - "Test Location"
+ - ptable_organizations:
+ - "Test Organization"
+ - ptable_layout: |
+ <%#
+ name: A Partition Template
+ %>
+ zerombr
+ clearpart --all --initlabel
+ autopart
+ partition_table:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ ptable_name }}"
+ updated_name: "{{ ptable_updated_name | default(omit) }}"
+ locations: "{{ ptable_locations }}"
+ organizations: "{{ ptable_organizations }}"
+ os_family: "{{ ptable_os_family | default(omit) }}"
+ locked: "{{ locked_state | default(omit) }}"
+ layout: "{{ ptable_layout }}"
+ state: "{{ ptable_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring ptable is {{ ptable_state }} and locked state {{ locked_state | default ('undefined') }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/puppetclasses_import.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/puppetclasses_import.yml
new file mode 100644
index 000000000..37e8ffe65
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/puppetclasses_import.yml
@@ -0,0 +1,17 @@
+---
+- name: Import Puppet Classes
+ puppetclasses_import:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ smart_proxy: "{{ puppetclasses_smart_proxy }}"
+ environment: "{{ puppetclasses_environment | default(omit) }}"
+ except: "{{ puppetclasses_except | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Importing Puppet Classes failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/realm.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/realm.yml
new file mode 100644
index 000000000..04bc7fb4d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/realm.yml
@@ -0,0 +1,22 @@
+---
+- name: "Ensure realm '{{ realm_name }}' is {{ realm_state }}"
+ vars:
+ - realm_name: "EXAMPLE.LOCAL"
+ - realm_proxy: "{{ foreman_proxy }}"
+ - realm_type: "FreeIPA"
+ realm:
+ server_url: "{{ foreman_server_url }}"
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ realm_name }}"
+ realm_proxy: '{{ realm_proxy }}'
+ realm_type: "{{ realm_type }}"
+ state: "{{ realm_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring realm is {{ realm_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/redhat_manifest.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/redhat_manifest.yml
new file mode 100644
index 000000000..263116e4e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/redhat_manifest.yml
@@ -0,0 +1,27 @@
+---
+- name: "Ensure {{ manifest_name }} is {{ manifest_state }} with {{ pool_quantity }} of {{ rhsm_pool_id }} subs {{ pool_state }}"
+ vars:
+ - rhsm_validate_certs: false
+ redhat_manifest:
+ name: "{{ manifest_name }}"
+ username: "{{ rhsm_username }}"
+ password: "{{ rhsm_password }}"
+ pool_id: "{{ rhsm_pool_id }}"
+ quantity: "{{ pool_quantity }}"
+ pool_state: "{{ pool_state }}"
+ state: "{{ manifest_state }}"
+ validate_certs: "{{ rhsm_validate_certs }}"
+ path: "{{ manifest_export_path | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring Manifest is {{ manifest_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- assert:
+ fail_msg: "UUID not part of the returned data"
+ that:
+ - result.uuid is defined
+ when:
+ - manifest_state == 'present'
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository.yml
new file mode 100644
index 000000000..e6991e1ba
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository.yml
@@ -0,0 +1,44 @@
+---
+- name: "Create katello repository"
+ vars:
+ organization_name: "Test Organization"
+ product_name: "Test Product"
+ repository_name: "Test Repository"
+ repository_content_type: "yum"
+ repository_state: present
+ repository:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ name: "{{ repository_name }}"
+ label: "{{ repository_label | default(omit) }}"
+ mirror_on_sync: "{{ repository_mirror_on_sync | default(omit) }}"
+ mirroring_policy: "{{ repository_mirroring_policy | default(omit) }}"
+ state: "{{ repository_state }}"
+ product: "{{ product_name }}"
+ content_type: "{{ repository_content_type }}"
+ url: "{{ repository_url | default(omit) }}"
+ upstream_username: "{{ repository_upstream_username | default(omit) }}"
+ upstream_password: "{{ repository_upstream_password | default(omit) }}"
+ deb_releases: "{{ repository_deb_releases | default(omit) }}"
+ deb_components: "{{ repository_deb_componentes | default(omit) }}"
+ deb_architectures: "{{ repository_deb_architectures | default(omit) }}"
+ docker_upstream_name: "{{ repository_docker_upstream_name | default(omit) }}"
+ docker_tags_whitelist: "{{ repository_docker_tags_whitelist | default(omit) }}"
+ include_tags: "{{ repository_include_tags | default(omit) }}"
+ exclude_tags: "{{ repository_exclude_tags | default(omit) }}"
+ download_policy: "{{ repository_download_policy | default(omit) }}"
+ download_concurrency: "{{ repository_download_concurrency | default(omit) }}"
+ gpg_key: "{{ repository_gpg_key | default(omit) }}"
+ ssl_ca_cert: "{{ repository_ssl_ca_cert | default(omit) }}"
+ ssl_client_cert: "{{ repository_ssl_client_cert | default(omit) }}"
+ ssl_client_key: "{{ repository_ssl_client_key | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring repository is {{ repository_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository_set.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository_set.yml
new file mode 100644
index 000000000..ad15f8143
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/repository_set.yml
@@ -0,0 +1,29 @@
+---
+- name: "Enable/Disable katello repository set"
+ vars:
+ organization: Test Organization
+ state: enabled
+ repository_set:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ name | default(omit) }}"
+ organization: "{{ organization }}"
+ product: "{{ product | default(omit) }}"
+ state: "{{ state }}"
+ repositories: "{{ repositories | default(omit) }}"
+ all_repositories: "{{ all_repositories | default(omit) }}"
+ label: "{{ label | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring Repository Set is {{ state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+ vars:
+ state: present
+- include_tasks: _assert_diff.yml
+ vars:
+ module: repository_set
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/role.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/role.yml
new file mode 100644
index 000000000..a8b90756f
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/role.yml
@@ -0,0 +1,28 @@
+---
+- name: "Ensure role '{{ role_name }}' is {{ role_state }}"
+ vars:
+ role_name: test
+ role_description: test role
+ role_locations:
+ - Test Location
+ role_organizations:
+ - Test Organization
+ role_state: present
+ role:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ role_name }}"
+ description: "{{ role_description }}"
+ locations: "{{ role_locations }}"
+ organizations: "{{ role_organizations }}"
+ filters: "{{ role_filters | default(omit) }}"
+ state: "{{ role_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring role is {{ role_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_content.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_content.yml
new file mode 100644
index 000000000..aff4470b3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_content.yml
@@ -0,0 +1,23 @@
+---
+- name: "Create/Update/Delete SCAP content."
+ vars:
+ scap_content_state: "present"
+ scap_content:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ title: "{{ scap_content_title }}"
+ updated_title: "{{ scap_content_updated_title | default(omit) }}"
+ scap_file: "{{ scap_content_scap_file | default(omit) }}"
+ original_filename: "{{ scap_content_original_filename | default(omit) }}"
+ locations: "{{ scap_content_locations | default(omit) }}"
+ organizations: "{{ scap_content_organizations | default(omit) }}"
+ state: "{{ scap_content_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring SCAP content is {{ scap_content_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_tailoring_file.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_tailoring_file.yml
new file mode 100644
index 000000000..7d8be3bd7
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scap_tailoring_file.yml
@@ -0,0 +1,23 @@
+---
+- name: "Create/Update/Delete tailoring file."
+ vars:
+ scap_tailoring_file_state: "present"
+ scap_tailoring_file:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ scap_tailoring_file_name }}"
+ updated_name: "{{ scap_tailoring_file_updated_name | default(omit) }}"
+ scap_file: "{{ scap_tailoring_file_scap_file | default(omit) }}"
+ original_filename: "{{ scap_tailoring_file_original_filename | default(omit) }}"
+ locations: "{{ scap_tailoring_file_locations | default(omit) }}"
+ organizations: "{{ scap_tailoring_file_organizations | default(omit) }}"
+ state: "{{ scap_tailoring_file_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring tailoring file is {{ scap_tailoring_file_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_account.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_account.yml
new file mode 100644
index 000000000..34525534e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_account.yml
@@ -0,0 +1,37 @@
+---
+- name: "Ensure scc_account '{{ scc_account_name }}' is {{ scc_account_state }} change {{ expected_change }} "
+ vars:
+ scc_account_state: "present"
+ scc_account_name: 'Test'
+ organization_name: 'Test Organization'
+ scc_account:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ scc_account_name }}"
+ updated_name: "{{ scc_account_updated_name | default(omit) }}"
+ login: "{{ scc_account_login | default(omit) }}"
+ scc_account_password: "{{ scc_account_password | default(omit) }}"
+ organization: "{{ organization_name }}"
+ base_url: "{{ scc_account_base_url | default(omit) }}"
+ interval: "{{ scc_account_interval | default(omit) }}"
+ sync_date: "{{ scc_account_sync_date | default(omit) }}"
+ test_connection: "{{ test_connection | default(false) }}"
+ state: "{{ scc_account_state }}"
+ register: result
+ ignore_errors: "{{ expected_fail | default(false) }}"
+
+- assert:
+ fail_msg: "Ensuring scc_account is {{ scc_account_state }} failed! (expected_change: {{ expected_change }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- assert:
+ fail_msg: "Ensuring scc_account failed as expected!"
+ that:
+ - result is failed
+ when:
+ - expected_fail is defined
+ - expected_fail
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_product.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_product.yml
new file mode 100644
index 000000000..84255134e
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/scc_product.yml
@@ -0,0 +1,17 @@
+---
+- name: "Ensure scc_product '{{ scc_product_name }}' change: {{ expected_change }} "
+ vars:
+ organization_name: 'Test Organization'
+ scc_product:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ scc_product: "{{ scc_product_name | default(omit) }}"
+ scc_account: "{{ scc_account_name_for_scc_product | default(omit) }}"
+ organization: "{{ organization_name }}"
+ register: result
+- fail:
+ msg: "Ensuring scc_product is failed! (expected_change: {{ expected_change | default('unknown') }})"
+ when: (expected_change is defined) and (result.changed != expected_change)
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/search_facts.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/search_facts.yml
new file mode 100644
index 000000000..5ac7ea69c
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/search_facts.yml
@@ -0,0 +1,18 @@
+---
+- name: "Find '{{ resource }}' resources"
+ resource_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ resource: "{{ resource }}"
+ search: "{{ search | default(omit) }}"
+ full_details: "{{ full_details | default(omit) }}"
+ organization: "{{ organization | default(omit) }}"
+ params: "{{ params | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Verification that '{{ return_length }}' '{{ resource }}' resources are found"
+ that: result.resources | length == return_length
+ when: return_length is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting.yml
new file mode 100644
index 000000000..bf677a074
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting.yml
@@ -0,0 +1,23 @@
+---
+- name: "Ensure setting '{{ setting_name }}' is {{ setting_value | default(false) | ternary(\"'\" + (setting_value | string) | default('') + \"'\", 'undefined') }}"
+ vars:
+ - setting_name: 'login_text'
+ setting:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ setting_name }}"
+ value: "{{ setting_value | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring setting is {{ setting_value | default(false) | ternary(\"'\" + (setting_value | default('') | string) + \"'\", 'undefined') }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- assert:
+ fail_msg: "Setting the setting failed! ('{{ result.entity.settings[0].value }}' != '{{ setting_value_override | default(setting_value) }}')"
+ that:
+ - result.entity.settings[0].value == setting_value_override | default(setting_value)
+ when: (setting_value is defined) or (setting_value_override is defined)
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting_fact.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting_fact.yml
new file mode 100644
index 000000000..3a544cc5d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/setting_fact.yml
@@ -0,0 +1,16 @@
+---
+- name: "Read setting '{{ setting_name }}'"
+ resource_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ resource: 'settings'
+ search: "{{ setting_name | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Verification that setting is '{{ setting_value }}' failed!"
+ that:
+ - result.resources[0].value == setting_value
+ when: (setting_name is defined) and (setting_value is defined)
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_class_parameter.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_class_parameter.yml
new file mode 100644
index 000000000..319257878
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_class_parameter.yml
@@ -0,0 +1,31 @@
+---
+- name: "Ensure SmartClassParameter '{{ smart_class_parameter_puppetclass_name }}::{{ smart_class_parameter_parameter }}' is {{ smart_class_parameter_state }}"
+ vars:
+ smart_class_parameter_state: present
+ smart_class_parameter:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ puppetclass_name: "{{ smart_class_parameter_puppetclass_name }}"
+ parameter: "{{ smart_class_parameter_parameter }}"
+ parameter_type: "{{ smart_class_parameter_parameter_type | default(omit) }}"
+ validator_type: "{{ smart_class_parameter_validator_type | default(omit) }}"
+ validator_rule: "{{ smart_class_parameter_validator_rule | default(omit) }}"
+ description: "{{ smart_class_parameter_description | default(omit) }}"
+ default_value: "{{ smart_class_parameter_default_value | default(omit) }}"
+ omit: "{{ smart_class_parameter_omit | default(omit) }}"
+ override: "{{ smart_class_parameter_override | default(omit) }}"
+ merge_default: "{{ smart_class_parameter_merge_default | default(omit) }}"
+ merge_overrides: "{{ smart_class_parameter_merge_overrides | default(omit) }}"
+ avoid_duplicates: "{{ smart_class_parameter_avoid_duplicates | default(omit) }}"
+ required: "{{ smart_class_parameter_required | default(omit) }}"
+ hidden_value: "{{ smart_class_parameter_hidden_value | default(omit) }}"
+ override_value_order: "{{ smart_class_parameter_override_value_order | default(omit) }}"
+ override_values: "{{ smart_class_parameter_override_values | default(omit) }}"
+ state: "{{ smart_class_parameter_state | default('present') }}"
+ register: result
+- fail:
+ msg: "Ensuring SmartClassParameter is {{ smart_class_parameter_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ when: (expected_change is defined) and (result.changed != expected_change)
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_proxy.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_proxy.yml
new file mode 100644
index 000000000..9d6d12063
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/smart_proxy.yml
@@ -0,0 +1,25 @@
+---
+- name: "Ensure Smart Proxy '{{ smart_proxy_name }}' is {{ smart_proxy_state }}"
+ vars:
+ - smart_proxy_name: "Smart Proxy"
+ - smart_proxy_url: "http://foreman-proxy.example.com:8000"
+ smart_proxy:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ smart_proxy_name }}"
+ url: "{{ smart_proxy_url }}"
+ lifecycle_environments: "{{ smart_proxy_lifecycle_environments | default(omit) }}"
+ download_policy: "{{ smart_proxy_download_policy | default(omit) }}"
+ state: "{{ smart_proxy_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring Smart Proxy is {{ smart_proxy_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: smart_proxy
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/snapshot.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/snapshot.yml
new file mode 100644
index 000000000..bb023452b
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/snapshot.yml
@@ -0,0 +1,19 @@
+---
+- name: "Ensure Snapshot '{{ snapshot_name }}' is {{ snapshot_state }} change {{ expected_change }} "
+ vars:
+ snapshot_name: "ansible"
+ snapshot_state: present
+ snapshot:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ snapshot_name }}"
+ description: "{{ snapshot_description | default(omit) }}"
+ host: "{{ snapshot_host_name }}"
+ state: "{{ snapshot_state }}"
+ register: result
+- fail:
+ msg: "Ensuring snapshot is {{ snapshot_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ when: (expected_change is defined) and (result.changed != expected_change)
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/status_info.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/status_info.yml
new file mode 100644
index 000000000..5fcd35dd2
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/status_info.yml
@@ -0,0 +1,7 @@
+---
+- name: fetch status
+ status_info:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subnet.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subnet.yml
new file mode 100644
index 000000000..e5a3ec207
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subnet.yml
@@ -0,0 +1,45 @@
+---
+- name: "Ensure subnet '{{ subnet_name }}' is {{ subnet_state }}"
+ vars:
+ subnet_name: "Test Subnet"
+ subnet_network: '192.168.200.0'
+ subnet_state: present
+ subnet:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ subnet_name }}"
+ description: "{{ subnet_description | default(omit) }}"
+ updated_name: "{{ subnet_updated_name | default(omit) }}"
+ network_type: "{{ subnet_network_type | default(omit) }}"
+ dns_primary: "{{ subnet_dns_primary | default(omit) }}"
+ dns_secondary: "{{ subnet_dns_secondary | default(omit) }}"
+ domains: "{{ subnet_domains | default(omit) }}"
+ gateway: "{{ subnet_gateway | default(omit) }}"
+ network: "{{ subnet_network }}"
+ cidr: "{{ subnet_cidr | default(omit) }}"
+ mask: "{{ subnet_mask | default(omit) }}"
+ from_ip: "{{ subnet_from | default(omit) }}"
+ to_ip: "{{ subnet_to | default(omit) }}"
+ boot_mode: "{{ subnet_boot_mode | default(omit) }}"
+ ipam: "{{ subnet_ipam | default(omit) }}"
+ dhcp_proxy: "{{ subnet_dhcp_proxy | default(omit) }}"
+ httpboot_proxy: "{{ subnet_httpboot_proxy | default(omit) }}"
+ tftp_proxy: "{{ subnet_tftp_proxy | default(omit) }}"
+ discovery_proxy: "{{ subnet_discovery_proxy | default(omit) }}"
+ dns_proxy: "{{ subnet_dns_proxy | default(omit) }}"
+ remote_execution_proxies: "{{ subnet_remote_execution_proxies | default(omit) }}"
+ vlanid: "{{ subnet_vlanid | default(omit) }}"
+ mtu: "{{ subnet_mtu | default(omit) }}"
+ organizations: "{{ subnet_organizations | default(omit) }}"
+ locations: "{{ subnet_locations | default(omit) }}"
+ parameters: "{{ subnet_parameters | default(omit) }}"
+ state: "{{ subnet_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring subnet is {{ subnet_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subscription_manifest.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subscription_manifest.yml
new file mode 100644
index 000000000..5c07cdc49
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/subscription_manifest.yml
@@ -0,0 +1,21 @@
+---
+- name: "Create/Update/Delete manifest"
+ vars:
+ organization_name: "Test Organization"
+ manifest_state: "present"
+ subscription_manifest:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ organization_name }}"
+ manifest_path: "{{ manifest_path | default(omit) }}"
+ repository_url: "{{ manifest_repository_url | default(omit) }}"
+ state: "{{ manifest_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring manifest is {{ manifest_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/sync_plan.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/sync_plan.yml
new file mode 100644
index 000000000..02acc3de6
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/sync_plan.yml
@@ -0,0 +1,33 @@
+---
+- name: "Create/update katello sync plan"
+ vars:
+ sync_plan_name: "Test Sync Plan"
+ sync_plan_organization: "Test Organization"
+ sync_plan_interval: "weekly"
+ sync_plan_enabled: false
+ sync_plan_sync_date: "2017-01-01 00:00:00 UTC"
+ sync_plan_state: present
+ sync_plan:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ sync_plan_name }}"
+ description: "{{ sync_plan_description|default(omit) }}"
+ organization: "{{ sync_plan_organization }}"
+ interval: "{{ sync_plan_interval }}"
+ enabled: "{{ sync_plan_enabled }}"
+ sync_date: "{{ sync_plan_sync_date }}"
+ cron_expression: "{{ sync_plan_cron_expression|default(omit) }}"
+ products: "{{ sync_plan_products|default(omit) }}"
+ state: "{{ sync_plan_state }}"
+ register: result
+- assert:
+ fail_msg: "Creating/updating sync plan failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+- include_tasks: _assert_diff.yml
+ vars:
+ module: sync_plan
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/templates_import.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/templates_import.yml
new file mode 100644
index 000000000..a930356b6
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/templates_import.yml
@@ -0,0 +1,26 @@
+---
+- name: Sync templates in from a git repo
+ templates_import:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ associate: "{{ templates_import_associate | default(omit) }}"
+ prefix: "{{ templates_import_prefix | default(omit) }}"
+ branch: "{{ templates_import_branch | default(omit) }}"
+ repo: "{{ templates_import_repo | default(omit) }}"
+ filter: "{{ templates_import_filter | default(omit) }}"
+ dirname: "{{ templates_import_dirname | default(omit) }}"
+ verbose: "{{ templates_import_verbose | default(omit) }}"
+ force: "{{ templates_import_force | default(omit) }}"
+ lock: "{{ templates_import_lock | default(omit) }}"
+ negate: "{{ templates_import_negate | default(omit) }}"
+ locations: "{{ templates_import_locations | default(omit) }}"
+ organizations: "{{ templates_import_organizations | default(omit) }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring templates are synced from a git repo has failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/upload.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/upload.yml
new file mode 100644
index 000000000..edf5f3f73
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/upload.yml
@@ -0,0 +1,24 @@
+---
+- name: "Upload content unit"
+ vars:
+ upload_organization: "Test Organization"
+ upload_src: "{{ playbook_dir }}/data/bear-4.1-1.noarch.rpm"
+ upload_repository: "Test Repository"
+ upload_product: "Test Product"
+ content_upload:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ organization: "{{ upload_organization }}"
+ src: "{{ upload_src }}"
+ repository: "{{ upload_repository }}"
+ product: "{{ upload_product }}"
+ ostree_repository_name: "{{ upload_ostree_repository_name | default(omit)}}"
+ register: result
+- assert:
+ fail_msg: "Uploading Content unit failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/user.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/user.yml
new file mode 100644
index 000000000..f9d575926
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/user.yml
@@ -0,0 +1,49 @@
+---
+- name: "Ensure user '{{ user_name }}' is {{ user_state }}"
+ vars:
+ user_name: test
+ user_firstname: Test
+ user_lastname: Userson
+ user_mail: test.userson@example.com
+ user_description: Dr. Test Userson
+ user_admin: false
+ user_default_location: Test Location
+ user_default_organization: Test Organization
+ user_auth_source: Internal
+ user_timezone: Stockholm
+ user_locale: sv_SE
+ user_roles:
+ - Manager
+ user_locations:
+ - Test Location
+ user_organizations:
+ - Test Organization
+ user_state: present
+ user:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ user_name }}"
+ firstname: "{{ user_firstname }}"
+ lastname: "{{ user_lastname }}"
+ mail: "{{ user_mail }}"
+ description: "{{ user_description }}"
+ admin: "{{ user_admin }}"
+ user_password: "{{ user_password | default(omit) }}"
+ default_location: "{{ user_default_location }}"
+ default_organization: "{{ user_default_organization }}"
+ auth_source: "{{ user_auth_source }}"
+ timezone: "{{ user_timezone }}"
+ locale: "{{ user_locale }}"
+ roles: "{{ user_roles }}"
+ locations: "{{ user_locations }}"
+ organizations: "{{ user_organizations }}"
+ state: "{{ user_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring user is {{ user_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/usergroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/usergroup.yml
new file mode 100644
index 000000000..95ee260f3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/tasks/usergroup.yml
@@ -0,0 +1,24 @@
+---
+- name: "Ensure usergroup '{{ usergroup_name }}' is {{ usergroup_state }}"
+ vars:
+ usergroup_name: "testgroup"
+ usergroup__state: present
+ usergroup:
+ username: "{{ foreman_username }}"
+ password: "{{ foreman_password }}"
+ server_url: "{{ foreman_server_url }}"
+ validate_certs: "{{ foreman_validate_certs }}"
+ name: "{{ usergroup_name }}"
+ updated_name: "{{ usergroup_updated_name | default(omit) }}"
+ admin: "{{ usergroup_admin | default(omit) }}"
+ users: "{{ usergroup_users | default(omit) }}"
+ usergroups: "{{ usergroup_usergroups | default(omit) }}"
+ roles: "{{ usergroup_roles | default(omit) }}"
+ state: "{{ usergroup_state }}"
+ register: result
+- assert:
+ fail_msg: "Ensuring usergroup is {{ usergroup_state }} failed! (expected_change: {{ expected_change | default('unknown') }})"
+ that:
+ - result.changed == expected_change
+ when: expected_change is defined
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/templates_import.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/templates_import.yml
new file mode 100644
index 000000000..538fa9919
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/templates_import.yml
@@ -0,0 +1,102 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "fam_tsync_test_Kickstart default"
+ provisioning_template_kind: provision
+ provisioning_template_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: present
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: present
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/templates_import.yml
+ tasks:
+ - include_tasks: tasks/templates_import.yml
+ vars:
+ templates_import_prefix: "fam_tsync_test_"
+ templates_import_filter: "^fam_tsync_test_Kickstart default$"
+ expected_change: true
+ - include_tasks: tasks/templates_import.yml
+ vars:
+ templates_import_prefix: "fam_tsync_test_"
+ templates_import_filter: "^fam_tsync_test_Kickstart default$"
+ expected_change: false
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "fam_tsync_test_Kickstart default"
+ provisioning_template_template: "Modified Kickstart default provisioning template"
+ provisioning_template_state: present
+ provisioning_template_kind: provision
+ provisioning_template_locations: '{{ omit }}'
+ provisioning_template_organizations: '{{ omit }}'
+ expected_change: true
+ - include_tasks: tasks/templates_import.yml
+ vars:
+ templates_import_prefix: "fam_tsync_test_"
+ templates_import_filter: "^fam_tsync_test_Kickstart default$"
+ expected_change: true
+ - include_tasks: tasks/templates_import.yml
+ vars:
+ templates_import_prefix: "fam_tsync_test_"
+ templates_import_filter: "^fam_tsync_test_Kickstart default$"
+ expected_change: false
+ - include_tasks: tasks/templates_import.yml
+ vars:
+ templates_import_prefix: "fam_tsync_test_"
+ templates_import_filter: "^fam_tsync_test_Kickstart default$"
+ templates_import_locations:
+ - "Test Location"
+ templates_import_organizations:
+ - "Test Organization"
+ # This won't pass assertion until https://projects.theforeman.org/issues/29534 is resolved
+ # setting to false for the time being
+ # expected_change: true
+ expected_change: false
+ - include_tasks: tasks/templates_import.yml
+ vars:
+ templates_import_prefix: "fam_tsync_test_"
+ templates_import_filter: "^fam_tsync_test_Kickstart default$"
+ templates_import_locations:
+ - "Test Location"
+ templates_import_organizations:
+ - "Test Organization"
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/provisioning_template.yml
+ vars:
+ provisioning_template_name: "fam_tsync_test_Kickstart default"
+ provisioning_template_kind: provision
+ provisioning_template_state: absent
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_name: "Test Organization"
+ organization_state: absent
+ - include_tasks: tasks/location.yml
+ vars:
+ location_name: "Test Location"
+ location_state: absent
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/user.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/user.yml
new file mode 100644
index 000000000..0a73316d8
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/user.yml
@@ -0,0 +1,103 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ tags:
+ - setup
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "present"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "present"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ tags:
+ - test
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+
+ # create user
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: present
+ user_password: s3cret
+ expected_change: true
+
+ # verify idempotence
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: present
+ expected_change: false
+
+ # change user
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: present
+ user_locale: "{{ omit }}"
+ user_mail: "{{ omit }}"
+ user_description: A great manager
+ expected_change: true
+
+ # try to auth as new user
+ - include_tasks: tasks/user.yml
+ vars:
+ foreman_username: test
+ foreman_password: s3cret
+ user_state: present
+ user_mail: "{{ omit }}"
+ expected_change: true
+
+ # change password
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: present
+ user_password: newp@ass
+ user_mail: "{{ omit }}"
+ expected_change: true
+
+ # try to auth as new user with new password
+ - include_tasks: tasks/user.yml
+ vars:
+ foreman_username: test
+ foreman_password: newp@ass
+ user_state: present
+ user_mail: test.user@example.com
+ expected_change: true
+
+ # remove user
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: absent
+ expected_change: true
+
+ # verify idempotence for absence
+ - include_tasks: tasks/user.yml
+ vars:
+ user_state: absent
+ expected_change: false
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ tags:
+ - teardown
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ tasks:
+ - include_tasks: tasks/location.yml
+ vars:
+ location_state: "absent"
+ - include_tasks: tasks/organization.yml
+ vars:
+ organization_state: "absent"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/usergroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/usergroup.yml
new file mode 100644
index 000000000..7dbd34626
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/usergroup.yml
@@ -0,0 +1,139 @@
+---
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/usergroup.yml
+ tasks:
+ - include_tasks: tasks/user.yml
+ vars:
+ user_name: "{{ item }}"
+ user_password: "mysecret"
+ user_default_location: "{{ omit }}"
+ user_default_organization: "{{ omit }}"
+ user_locations: "{{ omit }}"
+ user_organizations: "{{ omit }}"
+ with_items: "{{ group.users }}"
+ - include_tasks: tasks/role.yml
+ vars:
+ role_name: "{{ item }}"
+ role_locations: "{{ omit }}"
+ role_organizations: "{{ omit }}"
+ role_state: present
+ with_items: "{{ group.roles }}"
+
+- hosts: tests
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/usergroup.yml
+ tasks:
+ - name: 'Test usergroup with minimal params (name)'
+ block:
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_state: present
+ expected_change: true
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_state: present
+ expected_change: false
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_state: absent
+ expected_change: true
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_state: absent
+ expected_change: false
+ - name: 'Test usergroup rename'
+ block:
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_state: present
+ expected_change: true
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_updated_name: "{{ group.name }}2"
+ usergroup_state: present
+ expected_change: true
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}2"
+ usergroup_state: present
+ expected_change: false
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}2"
+ usergroup_state: absent
+ expected_change: true
+ - name: 'Test usergroup with users/roles/groups'
+ block:
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: nestedgroup
+ usergroup_state: present
+ expected_change: true
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_users: "{{ group.users }}"
+ usergroup_usergroups:
+ - nestedgroup
+ usergroup_roles: "{{ group.roles }}"
+ usergroup_state: present
+ expected_change: true
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_users: "{{ group.users }}"
+ usergroup_usergroups:
+ - nestedgroup
+ usergroup_roles: "{{ group.roles }}"
+ usergroup_state: present
+ expected_change: false
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: "{{ group.name }}"
+ usergroup_state: absent
+ expected_change: true
+ - include_tasks: tasks/usergroup.yml
+ vars:
+ usergroup_name: nestedgroup
+ usergroup_state: absent
+ expected_change: true
+
+- hosts: localhost
+ collections:
+ - theforeman.foreman
+ gather_facts: false
+ vars_files:
+ - vars/server.yml
+ - vars/usergroup.yml
+ tasks:
+ - include_tasks: tasks/user.yml
+ vars:
+ user_name: "{{ item }}"
+ user_default_location: "{{ omit }}"
+ user_default_organization: "{{ omit }}"
+ user_locations: "{{ omit }}"
+ user_organizations: "{{ omit }}"
+ user_state: absent
+ with_items: "{{ group.users }}"
+ - include_tasks: tasks/role.yml
+ vars:
+ role_name: "{{ item }}"
+ role_locations: "{{ omit }}"
+ role_organizations: "{{ omit }}"
+ role_state: absent
+ with_items: "{{ group.roles }}"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/compute_profile.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/compute_profile.yml
new file mode 100644
index 000000000..2c4f9f47d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/compute_profile.yml
@@ -0,0 +1,62 @@
+---
+libvirt:
+ compute_resource:
+ name: libvirt-cr01
+ organizations:
+ - Test Organization
+ locations:
+ - Test Location
+ params:
+ url: qemu+ssh://libvirtuser@localhost/system
+ compute_profile:
+ name: app-small
+ attrs:
+ cpus: 1
+ memory: 2147483648
+ nics_attributes:
+ 0:
+ type: bridge
+ bridge: ""
+ model: virtio
+ volumes_attributes:
+ 0:
+ pool_name: default
+ capacity: 10G
+ allocation: 0G
+ format_type: raw
+ovirt:
+ compute_resource:
+ name: ovirt-cr01
+ organizations:
+ - Test Organization
+ locations:
+ - Test Location
+ params:
+ url: "https://ovirt.example.com/ovirt-engine/api"
+ user: compute-user@internal
+ password: ovirtcompute123
+ use_v4: true
+ datacenter: c1479626-99a2-44eb-8401-14b5630f417f
+ ovirt_quota: 502a76bb-a3fe-42f1-aed6-2a7c892a6786
+ compute_profile:
+ name: app-small
+ attrs:
+ cluster: Devel-Infra
+ cores: 2
+ sockets: 1
+ memory: 1073741824
+ ha: 0
+ interfaces_attributes:
+ 0:
+ name: ""
+ network: ovirtmgmt
+ interface: virtio
+ volumes_attributes:
+ 0:
+ size_gb: '16'
+ storage_domain: 'Local-IBM'
+ preallocate: '1'
+ wipe_after_delete: '0'
+ interface: 'virtio_scsi'
+ bootable: 'true'
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/domain.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/domain.yml
new file mode 100644
index 000000000..8c9e67272
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/domain.yml
@@ -0,0 +1,8 @@
+---
+domain_name: "example.com"
+domain_locations:
+ - 'Test Location'
+ - 'Test Location/Sublocation'
+domain_organizations:
+ - 'Test Organization'
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/host.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/host.yml
new file mode 100644
index 000000000..5607eb00d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/host.yml
@@ -0,0 +1,13 @@
+---
+host:
+ location: "Test Location"
+ organization: "Test Organization"
+ hostgroup: "test_group"
+ domain: "example.net"
+ subnet: Test subnet4
+ arch: superARCH
+ os:
+ family: Redhat
+ name: TestOS
+ major: 7
+ minor: 6
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/hostgroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/hostgroup.yml
new file mode 100644
index 000000000..2738dbd8d
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/hostgroup.yml
@@ -0,0 +1,39 @@
+---
+hostgroup:
+ organizations:
+ - Test Org1
+ - Test Org2
+ locations:
+ - Foo
+ - Foo/Baz
+ - Bar
+ arch: x86_64
+ ptable: "Part table"
+ os:
+ family: Redhat
+ name: TestOS
+ major: 7
+ minor: 6
+ compute_resource:
+ name: 'libvirt-cr'
+ params:
+ url: "qemu:///system"
+ compute_profile:
+ name: 'myprofile'
+ domains:
+ - foo.example.com
+ - bar.example.com
+ subnet: Test subnet4
+ subne6: Test subnet6
+ puppet_server: "{{ foreman_proxy }}"
+ puppet_ca: "{{ foreman_proxy }}"
+ dns_proxy: "{{ foreman_proxy }}"
+ openscap_proxy: "{{ foreman_proxy }}"
+ content_source: "{{ foreman_proxy }}"
+ lifecycle_environment: "Library"
+ content_view:
+ name: my_content
+ version: '1.0'
+ config_groups:
+ - cfg_group1
+ - cfg_group2
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/search_facts.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/search_facts.yml
new file mode 100644
index 000000000..67294e9f0
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/search_facts.yml
@@ -0,0 +1,7 @@
+---
+test_resources:
+ - organization: "Test Organization"
+ domain: "test.invalid"
+ - organization: "Facts Organization"
+ domain: "facts.invalid"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/server.yml.example b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/server.yml.example
new file mode 100644
index 000000000..ecb91e3b7
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/server.yml.example
@@ -0,0 +1,30 @@
+---
+# Parameter for all tests
+foreman_username: admin
+foreman_password: "changeme"
+foreman_server_url: "https://foreman.example.com"
+foreman_validate_certs: false
+
+foreman_proxy: "foreman.example.com"
+
+# Parameter for snapshot test
+snapshot_host_name: "test_host"
+
+# Parameter for job invocation test
+foreman_host: "foreman.example.com"
+
+# Parameter for subscription_manifest test
+subscription_manifest_path: "data/manifest_foreman-ansible-modules.zip"
+
+# Parameter for redhat_manifest test
+manifest_name: "katello.example.com"
+rhsm_username: "john-smith"
+rhsm_password: "changeme"
+rhsm_pool_id: 8a85f99a7db4827d017dc512fcad00b0
+rhsm_validate_certs: false
+
+#Parameter for scc_product test
+scc_account_name_for_scc_product: testaccount
+scc_account_login_for_scc_product: testuser
+scc_account_password_for_scc_product: testpass
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/subnet.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/subnet.yml
new file mode 100644
index 000000000..3988464e2
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/subnet.yml
@@ -0,0 +1,12 @@
+---
+subnet_orgs:
+ - Test Org1
+ - Test Org2
+subnet_locs:
+ - Foo
+ - Foo/Baz
+ - Bar
+subnet_doms:
+ - foo.example.com
+ - bar.example.com
+subnet_proxy: "{{ foreman_proxy }}"
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/templates_import.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/templates_import.yml
new file mode 100644
index 000000000..3d390fad6
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/templates_import.yml
@@ -0,0 +1,6 @@
+---
+templates_import_associate: "always"
+templates_import_repo: "https://github.com/theforeman/community-templates.git"
+templates_import_verbose: true
+templates_import_branch: "1.24-stable"
+...
diff --git a/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/usergroup.yml b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/usergroup.yml
new file mode 100644
index 000000000..597c9f4d3
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_playbooks/vars/usergroup.yml
@@ -0,0 +1,9 @@
+---
+group:
+ name: mytestgroup
+ users:
+ - foo
+ - bar
+ roles:
+ - role1
+ - role2
diff --git a/ansible_collections/theforeman/foreman/tests/test_recursive_dict_keys.py b/ansible_collections/theforeman/foreman/tests/test_recursive_dict_keys.py
new file mode 100644
index 000000000..0a34667bc
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/test_recursive_dict_keys.py
@@ -0,0 +1,7 @@
+from plugins.module_utils.foreman_helper import _recursive_dict_keys
+
+
+def test_recursive_dict_keys():
+ a_dict = {'level1': 'has value', 'level2': {'real_level2': 'more value', 'level3': {'real_level3': 'nope'}}}
+ expected_keys = set(['level1', 'level2', 'level3', 'real_level2', 'real_level3'])
+ assert _recursive_dict_keys(a_dict) == expected_keys
diff --git a/ansible_collections/theforeman/foreman/tests/utils.py b/ansible_collections/theforeman/foreman/tests/utils.py
new file mode 100644
index 000000000..4373840cc
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/utils.py
@@ -0,0 +1,14 @@
+import py.path
+
+
+MODULES_PATH = py.path.local(__file__).realpath() / '..' / '..' / 'plugins' / 'modules'
+
+
+def find_all_modules():
+ for module in MODULES_PATH.listdir(sort=True):
+ module = module.basename
+ if module.endswith('.py') and not module.startswith('_'):
+ yield module.replace('.py', '')
+
+
+ALL_MODULES = list(find_all_modules())
diff --git a/ansible_collections/theforeman/foreman/tests/vcr_python_wrapper.py b/ansible_collections/theforeman/foreman/tests/vcr_python_wrapper.py
new file mode 100644
index 000000000..76a35fda1
--- /dev/null
+++ b/ansible_collections/theforeman/foreman/tests/vcr_python_wrapper.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+
+import os
+import re
+import sys
+import json
+try:
+ from urlparse import urlparse, urlunparse
+except ImportError:
+ from urllib.parse import urlparse, urlunparse
+
+FILTER_REQUEST_HEADERS = ['Authorization', 'Cookie']
+FILTER_RESPONSE_HEADERS = ['Apipie-Checksum', 'Date', 'ETag', 'Server', 'Set-Cookie', 'Via', 'X-Powered-By', 'X-Request-Id', 'X-Runtime']
+
+
+def safe_method_matcher(r1, r2):
+ assert r1.method not in ['POST', 'PUT', 'PATCH', 'DELETE'], 'Method {0} not allowed in check_mode'.format(r1.method)
+ assert r1.method == r2.method
+
+
+# We need our own json level2 matcher, because, python2 and python3 do not save
+# dictionaries in the same order
+def body_json_l2_matcher(r1, r2):
+ if r1.headers.get('content-type') == r2.headers.get('content-type') == 'application/json':
+ if r1.body is None or r2.body is None:
+ assert r1.body == r2.body, "{} != {}".format(r1.body, r2.body)
+ body1 = json.loads(r1.body.decode('utf8'))
+ body2 = json.loads(r2.body.decode('utf8'))
+ if 'common_parameter' in body1 and 'common_parameter' in body2:
+ if body1['common_parameter'].get('parameter_type') == body2['common_parameter'].get('parameter_type') in ['hash', 'json', 'yaml']:
+ body1['common_parameter']['value'] = json.loads(body1['common_parameter'].get('value'))
+ body2['common_parameter']['value'] = json.loads(body2['common_parameter'].get('value'))
+ assert body1 == body2, "{} != {}".format(body1, body2)
+ elif (r1.headers.get('content-type') == r2.headers.get('content-type')
+ and r1.headers.get('content-type') in ['multipart/form-data', 'application/x-www-form-urlencoded']):
+ if r1.body is None or r2.body is None:
+ assert r1.body == r2.body, "{} != {}".format(r1.body, r2.body)
+ body1 = sorted(r1.body.replace(b'~', b'%7E').split(b'&'))
+ body2 = sorted(r2.body.replace(b'~', b'%7E').split(b'&'))
+ assert len(body1) == len(body2), "the body lengths don't match"
+ for i, v in enumerate(body1):
+ assert body1[i] == body2[i], "body contents at position {} dont't match: '{}' vs '{}'".format(i, body1[i], body2[i])
+ else:
+ assert r1.body == r2.body, "{} != {}".format(r1.body, r2.body)
+
+
+def _query_without_search_matcher(r1, r2, path):
+ if r1.path == r2.path == path:
+ query1 = [q for q in r1.query if q[0] != 'search']
+ query2 = [q for q in r2.query if q[0] != 'search']
+ assert query1 == query2, "{} != {}".format(query1, query2)
+ else:
+ vcr.matchers.query(r1, r2)
+
+
+def snapshot_query_matcher(r1, r2):
+ _query_without_search_matcher(r1, r2, '/api/hosts')
+
+
+def query_matcher_ignore_proxy(r1, r2):
+ _query_without_search_matcher(r1, r2, '/api/smart_proxies')
+
+
+def subscription_manifest_body_matcher(r1, r2):
+ if r1.path.endswith('/subscriptions/upload') and r2.path.endswith('/subscriptions/upload'):
+ if r1.headers.get('content-type').startswith('multipart/form-data') and r2.headers.get('content-type').startswith('multipart/form-data'):
+ r1_copy = vcr.request.Request(r1.method, r1.uri, r1.body, r1.headers)
+ r2_copy = vcr.request.Request(r2.method, r2.uri, r2.body, r2.headers)
+ # the body is a huge binary blob, which seems to differ on every run, so we just ignore it
+ body1 = body2 = {}
+ r1_copy.body = json.dumps(body1)
+ r2_copy.body = json.dumps(body2)
+ return body_json_l2_matcher(r1_copy, r2_copy)
+ return body_json_l2_matcher(r1, r2)
+
+
+def host_body_matcher(r1, r2):
+ if r1.headers.get('content-type') == r2.headers.get('content-type') == 'application/json':
+ if r1.path == r2.path == '/api/v2/hostgroups':
+ r1_copy = vcr.request.Request(r1.method, r1.uri, r1.body, r1.headers)
+ r2_copy = vcr.request.Request(r2.method, r2.uri, r2.body, r2.headers)
+ body1 = json.loads(r1_copy.body.decode('utf8'))
+ body2 = json.loads(r2_copy.body.decode('utf8'))
+ body1['search'] = 'name="test_group"'
+ body2['search'] = 'name="test_group"'
+ r1_copy.body = json.dumps(body1)
+ r2_copy.body = json.dumps(body2)
+ return body_json_l2_matcher(r1_copy, r2_copy)
+ return body_json_l2_matcher(r1, r2)
+
+
+def job_invocation_body_matcher(r1, r2):
+ if r1.path == r2.path == '/api/job_invocations':
+ r1_copy = vcr.request.Request(r1.method, r1.uri, r1.body, r1.headers)
+ r2_copy = vcr.request.Request(r2.method, r2.uri, r2.body, r2.headers)
+ body1 = json.loads(r1_copy.body.decode('utf8'))
+ body2 = json.loads(r2_copy.body.decode('utf8'))
+ if 'search_query' in body1['job_invocation']:
+ body1['job_invocation']['search_query'] = body2['job_invocation']['search_query']
+ r1_copy.body = json.dumps(body1)
+ return body_json_l2_matcher(r1_copy, r2_copy)
+ return body_json_l2_matcher(r1, r2)
+
+
+def filter_response(response):
+ for header in FILTER_RESPONSE_HEADERS:
+ # headers should be case insensitive, but for some reason they weren't for me
+ response['headers'].pop(header.lower(), None)
+ response['headers'].pop(header, None)
+ return response
+
+
+def filter_request_uri(request):
+ uri = urlparse(request.uri)
+ if uri.hostname != 'subscription.rhsm.redhat.com':
+ uri = uri._replace(netloc="foreman.example.org")
+ if uri.hostname == 'subscription.rhsm.redhat.com' and re.match('/subscription/users/[^/]+/owners', uri.path):
+ uri = uri._replace(path='/subscription/users/john-smith/owners')
+ request.uri = urlunparse(uri)
+ return request
+
+
+def filter_request_manifest(request):
+ if request.method == 'POST' and request.path.endswith('/subscriptions/upload'):
+ request.body = 'FAKE_MANIFEST'
+ return request
+
+
+def filter_request(request):
+ request = filter_request_uri(request)
+ request = filter_request_manifest(request)
+ return request
+
+
+VCR_PARAMS_FILE = os.environ.get('FAM_TEST_VCR_PARAMS_FILE')
+
+# Remove the name of the wrapper from argv
+# (to make it look like the module had been called directly)
+sys.argv.pop(0)
+
+if VCR_PARAMS_FILE is None:
+ # Run the program as if nothing had happened
+ with open(sys.argv[0]) as f:
+ code = compile(f.read(), sys.argv[0], 'exec')
+ exec(code)
+else:
+ import vcr
+ # Run the program wrapped within vcr cassette recorder
+ # Load recording parameters from file
+ with open(VCR_PARAMS_FILE, 'r') as params_file:
+ test_params = json.load(params_file)
+ cassette_file = 'fixtures/{}-{}.yml'.format(test_params['test_name'], test_params['serial'])
+ # Increase serial and dump back to file
+ test_params['serial'] += 1
+ with open(VCR_PARAMS_FILE, 'w') as params_file:
+ json.dump(test_params, params_file)
+
+ # Call the original python script with vcr-cassette in place
+ fam_vcr = vcr.VCR()
+
+ method_matcher = 'method'
+ if test_params['check_mode']:
+ fam_vcr.register_matcher('safe_method_matcher', safe_method_matcher)
+ method_matcher = 'safe_method_matcher'
+
+ query_matcher = 'query'
+ if test_params['test_name'] in ['domain', 'hostgroup', 'katello_hostgroup', 'luna_hostgroup', 'realm', 'subnet', 'puppetclasses_import']:
+ fam_vcr.register_matcher('query_ignore_proxy', query_matcher_ignore_proxy)
+ query_matcher = 'query_ignore_proxy'
+ elif test_params['test_name'] in ['snapshot', 'snapshot_info']:
+ fam_vcr.register_matcher('snapshot_query', snapshot_query_matcher)
+ query_matcher = 'snapshot_query'
+
+ fam_vcr.register_matcher('body_json_l2', body_json_l2_matcher)
+
+ body_matcher = 'body_json_l2'
+ if test_params['test_name'] == 'host':
+ fam_vcr.register_matcher('host_body', host_body_matcher)
+ body_matcher = 'host_body'
+ elif test_params['test_name'] in ['subscription_manifest', 'manifest_role', 'content_rhel_role']:
+ fam_vcr.register_matcher('subscription_manifest_body', subscription_manifest_body_matcher)
+ body_matcher = 'subscription_manifest_body'
+ elif test_params['test_name'] == 'job_invocation':
+ fam_vcr.register_matcher('job_invocation_body', job_invocation_body_matcher)
+ body_matcher = 'job_invocation_body'
+
+ with fam_vcr.use_cassette(cassette_file,
+ record_mode=test_params['record_mode'],
+ match_on=[method_matcher, 'path', query_matcher, body_matcher],
+ filter_headers=FILTER_REQUEST_HEADERS,
+ before_record_request=filter_request,
+ before_record_response=filter_response,
+ decode_compressed_response=True,
+ ):
+ with open(sys.argv[0]) as f:
+ code = compile(f.read(), sys.argv[0], 'exec')
+ exec(code)