├── .env.example ├── .github ├── CODEOWNERS ├── PULL_REQUEST_TEMPLATE.md ├── auto_assign.yml ├── dependabot.yml ├── dependency_tests.yaml └── workflows │ ├── auto_assignment.yaml │ ├── auto_branching.yml │ ├── auto_cherry_pick.yml │ ├── auto_cherry_pick_merge.yaml │ ├── auto_cherry_pick_merged.yaml │ ├── dependency_merge.yml │ ├── dispatch_release.yml │ ├── prt_labels.yml │ ├── prt_result.yml │ ├── pull_request.yml │ ├── required_labels.yml │ ├── stale.yml │ ├── update_robottelo_image.yml │ └── weekly.yml ├── .gitignore ├── .pre-commit-config.yaml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.rst ├── conf ├── ansible.yaml.template ├── ansible_hub.yaml.template ├── azure.yaml.template ├── broker.yaml.template ├── bugzilla.yaml.template ├── capsule.yaml.template ├── clone.yaml.template ├── container.yaml.template ├── container_repo.yaml.template ├── content_host.yaml.template ├── docker.yaml.template ├── dynaconf_hooks.py ├── ec2.yaml.template ├── fake_capsules.yaml.template ├── fam.yaml.template ├── flavors.yaml.template ├── gce.yaml.template ├── git.yaml.template ├── http_proxy.yaml.template ├── infoblox.yaml.template ├── ipa.yaml.template ├── jira.yaml.template ├── ldap.yaml.template ├── libvirt.yaml.template ├── manifest.yaml.template ├── migrations.py ├── ohsnap.yaml.template ├── openldap.yaml.template ├── oscap.yaml.template ├── osp.yaml.template ├── performance.yaml.template ├── provisioning.yaml.template ├── remotedb.yaml.template ├── report_portal.yaml.template ├── repos.yaml.template ├── rh_cloud.yaml.template ├── rhbk.yaml.template ├── rhev.yaml.template ├── rhsso.yaml.template ├── robottelo.yaml.template ├── server.yaml.template ├── shared_function.yaml.template ├── subscription.yaml.template ├── supportability.yaml ├── ui.yaml.template ├── upgrade.yaml.template ├── virtwho.yaml.template └── vmware.yaml.template ├── conftest.py ├── docs ├── Makefile ├── code_standards.rst ├── committing.rst ├── conf.py ├── features │ ├── commands.rst │ ├── decorators.rst │ ├── index.rst │ └── ssh.rst ├── index.rst └── reviewing_PRs.rst ├── logging.yaml ├── manage.yml ├── pyproject.toml ├── pytest_fixtures ├── component │ ├── acs.py │ ├── activationkey.py │ ├── ansible.py │ ├── architecture.py │ ├── computeprofile.py │ ├── contentview.py │ ├── discovery.py │ ├── domain.py │ ├── flatpak.py │ ├── global_params.py │ ├── host.py │ ├── hostgroup.py │ ├── http_proxy.py │ ├── katello_certs_check.py │ ├── lce.py │ ├── leapp_client.py │ ├── maintain.py │ ├── os.py │ ├── oscap.py │ ├── partition_table.py │ ├── permissions.py │ ├── provision_azure.py │ ├── provision_capsule_pxe.py │ ├── provision_gce.py │ ├── provision_libvirt.py │ ├── provision_pxe.py │ ├── provision_vmware.py │ ├── provisioning_template.py │ ├── puppet.py │ ├── repository.py │ ├── rh_cloud.py │ ├── satellite_auth.py │ ├── settings.py │ ├── smartproxy.py │ ├── subnet.py │ ├── subscription.py │ ├── taxonomy.py │ ├── templatesync.py │ ├── usage_report.py │ ├── user.py │ ├── user_role.py │ └── virtwho_config.py └── core │ ├── broker.py │ ├── contenthosts.py │ ├── reporting.py │ ├── sat_cap_factory.py │ ├── sys.py │ ├── ui.py │ ├── upgrade.py │ └── xdist.py ├── pytest_plugins ├── auto_vault.py ├── capsule_n-minus.py ├── disable_rp_params.py ├── external_logging.py ├── factory_collection.py ├── fixture_markers.py ├── fspath_plugins.py ├── infra_dependent_markers.py ├── issue_handlers.py ├── jira_comments.py ├── logging_hooks.py ├── manual_skipped.py ├── marker_deselection.py ├── markers.py ├── metadata_markers.py ├── requirements │ ├── req_updater.py │ └── update_requirements.py ├── rerun_rp │ ├── README.adoc │ └── rerun_rp.py ├── sanity_plugin.py ├── select_random_tests.py ├── settings_skip.py ├── upgrade │ └── scenario_workers.py └── video_cleanup.py ├── requirements-optional.txt ├── requirements.txt ├── robottelo.yaml.sample ├── robottelo ├── __init__.py ├── cli │ ├── __init__.py │ ├── acs.py │ ├── activationkey.py │ ├── admin.py │ ├── ansible.py │ ├── architecture.py │ ├── arfreport.py │ ├── auth.py │ ├── base.py │ ├── bootdisk.py │ ├── capsule.py │ ├── computeprofile.py │ ├── computeresource.py │ ├── content_credentials.py │ ├── content_export.py │ ├── content_import.py │ ├── contentview.py │ ├── defaults.py │ ├── discoveredhost.py │ ├── discoveryrule.py │ ├── docker.py │ ├── domain.py │ ├── environment.py │ ├── erratum.py │ ├── fact.py │ ├── file.py │ ├── filter.py │ ├── flatpak_remote.py │ ├── globalparam.py │ ├── gpgkey.py │ ├── hammer.py │ ├── host.py │ ├── host_registration.py │ ├── hostcollection.py │ ├── hostgroup.py │ ├── http_proxy.py │ ├── insights.py │ ├── job_invocation.py │ ├── job_template.py │ ├── ldapauthsource.py │ ├── lifecycleenvironment.py │ ├── location.py │ ├── medium.py │ ├── model.py │ ├── module_stream.py │ ├── operatingsys.py │ ├── org.py │ ├── ostreebranch.py │ ├── package.py │ ├── partitiontable.py │ ├── product.py │ ├── proxy.py │ ├── puppet.py │ ├── realm.py │ ├── recurring_logic.py │ ├── report.py │ ├── report_template.py │ ├── repository.py │ ├── repository_set.py │ ├── rex_feature.py │ ├── role.py │ ├── scap_policy.py │ ├── scap_tailoring_files.py │ ├── scapcontent.py │ ├── scparams.py │ ├── settings.py │ ├── simple_content_access.py │ ├── sm_advanced.py │ ├── sm_advanced_by_tag.py │ ├── sm_backup.py │ ├── sm_health.py │ ├── sm_maintenance_mode.py │ ├── sm_packages.py │ ├── sm_restore.py │ ├── sm_service.py │ ├── sm_update.py │ ├── sm_upgrade.py │ ├── srpm.py │ ├── subnet.py │ ├── subscription.py │ ├── syncplan.py │ ├── task.py │ ├── template.py │ ├── template_input.py │ ├── template_sync.py │ ├── user.py │ ├── usergroup.py │ ├── virt_who_config.py │ └── webhook.py ├── config │ ├── __init__.py │ └── validators.py ├── constants │ ├── __init__.py │ └── repos.py ├── content_info.py ├── exceptions.py ├── host_helpers │ ├── __init__.py │ ├── api_factory.py │ ├── capsule_mixins.py │ ├── cli_factory.py │ ├── contenthost_mixins.py │ ├── repository_mixins.py │ ├── satellite_mixins.py │ └── ui_factory.py ├── hosts.py ├── logging.py ├── ssh.py └── utils │ ├── __init__.py │ ├── datafactory.py │ ├── decorators │ ├── __init__.py │ ├── func_locker.py │ └── func_shared │ │ ├── __init__.py │ │ ├── base.py │ │ ├── file_storage.py │ │ ├── redis_storage.py │ │ └── shared.py │ ├── installer.py │ ├── io │ └── __init__.py │ ├── issue_handlers │ ├── README.md │ ├── __init__.py │ ├── bugzilla.py │ └── jira.py │ ├── ohsnap.py │ ├── report_portal │ ├── README.adoc │ ├── __init__.py │ └── portal.py │ ├── shared_resource.py │ ├── ssh.py │ ├── url.py │ ├── vault.py │ ├── version.py │ └── virtwho.py ├── scripts ├── config_helpers.py ├── customer_scenarios.py ├── fix_uuids.sh ├── fixture_cli.py ├── graph_entities.py ├── hammer_command_tree.py ├── polarion-test-case-upload.sh ├── polarion-test-run-upload.sh ├── populate_jira_cache.py ├── token_editor.py ├── tokenize_customer_scenario.py ├── validate_config.py └── vault_login.py ├── selenium_grid.sh ├── settings.sample.yaml ├── testimony.yaml └── tests ├── __init__.py ├── foreman ├── __init__.py ├── api │ ├── __init__.py │ ├── test_acs.py │ ├── test_activationkey.py │ ├── test_ansible.py │ ├── test_architecture.py │ ├── test_audit.py │ ├── test_bookmarks.py │ ├── test_capsule.py │ ├── test_capsulecontent.py │ ├── test_classparameters.py │ ├── test_computeprofile.py │ ├── test_computeresource_azurerm.py │ ├── test_computeresource_gce.py │ ├── test_computeresource_libvirt.py │ ├── test_computeresource_vmware.py │ ├── test_contentcredentials.py │ ├── test_contentview.py │ ├── test_contentviewfilter.py │ ├── test_contentviewversion.py │ ├── test_convert2rhel.py │ ├── test_discoveredhost.py │ ├── test_discoveryrule.py │ ├── test_docker.py │ ├── test_environment.py │ ├── test_eol_banner.py │ ├── test_errata.py │ ├── test_filter.py │ ├── test_foremantask.py │ ├── test_host.py │ ├── test_hostcollection.py │ ├── test_hostgroup.py │ ├── test_http_proxy.py │ ├── test_ldapauthsource.py │ ├── test_lifecycleenvironment.py │ ├── test_location.py │ ├── test_media.py │ ├── test_multiple_paths.py │ ├── test_notifications.py │ ├── test_operatingsystem.py │ ├── test_organization.py │ ├── test_oscap_tailoringfiles.py │ ├── test_oscappolicy.py │ ├── test_parameters.py │ ├── test_partitiontable.py │ ├── test_permission.py │ ├── test_ping.py │ ├── test_product.py │ ├── test_provisioning.py │ ├── test_provisioning_puppet.py │ ├── test_provisioningtemplate.py │ ├── test_registration.py │ ├── test_remoteexecution.py │ ├── test_reporttemplates.py │ ├── test_repositories.py │ ├── test_repository.py │ ├── test_repository_set.py │ ├── test_rhc.py │ ├── test_rhcloud_inventory.py │ ├── test_rhsm.py │ ├── test_role.py │ ├── test_settings.py │ ├── test_subnet.py │ ├── test_subscription.py │ ├── test_syncplan.py │ ├── test_template_combination.py │ ├── test_templatesync.py │ ├── test_user.py │ ├── test_usergroup.py │ └── test_webhook.py ├── cli │ ├── __init__.py │ ├── test_abrt.py │ ├── test_acs.py │ ├── test_activationkey.py │ ├── test_ansible.py │ ├── test_architecture.py │ ├── test_artifacts.py │ ├── test_auth.py │ ├── test_bootdisk.py │ ├── test_bootstrap_script.py │ ├── test_capsule.py │ ├── test_capsulecontent.py │ ├── test_classparameters.py │ ├── test_computeresource_azurerm.py │ ├── test_computeresource_ec2.py │ ├── test_computeresource_libvirt.py │ ├── test_computeresource_osp.py │ ├── test_computeresource_rhev.py │ ├── test_computeresource_vmware.py │ ├── test_container_management.py │ ├── test_contentaccess.py │ ├── test_contentcredentials.py │ ├── test_contentview.py │ ├── test_contentviewfilter.py │ ├── test_discoveredhost.py │ ├── test_discoveryrule.py │ ├── test_docker.py │ ├── test_domain.py │ ├── test_environment.py │ ├── test_errata.py │ ├── test_fact.py │ ├── test_filter.py │ ├── test_flatpak.py │ ├── test_foremantask.py │ ├── test_globalparam.py │ ├── test_hammer.py │ ├── test_host.py │ ├── test_hostcollection.py │ ├── test_hostgroup.py │ ├── test_http_proxy.py │ ├── test_installer.py │ ├── test_jobtemplate.py │ ├── test_ldapauthsource.py │ ├── test_leapp_client.py │ ├── test_lifecycleenvironment.py │ ├── test_location.py │ ├── test_logging.py │ ├── test_medium.py │ ├── test_model.py │ ├── test_operatingsystem.py │ ├── test_organization.py │ ├── test_oscap.py │ ├── test_oscap_tailoringfiles.py │ ├── test_ostreebranch.py │ ├── test_partitiontable.py │ ├── test_ping.py │ ├── test_product.py │ ├── test_provisioning.py │ ├── test_provisioningtemplate.py │ ├── test_puppetclass.py │ ├── test_realm.py │ ├── test_registration.py │ ├── test_remoteexecution.py │ ├── test_report.py │ ├── test_reporttemplates.py │ ├── test_repositories.py │ ├── test_repository.py │ ├── test_repository_set.py │ ├── test_rhcloud_inventory.py │ ├── test_role.py │ ├── test_satellitesync.py │ ├── test_settings.py │ ├── test_sso.py │ ├── test_subnet.py │ ├── test_subscription.py │ ├── test_syncplan.py │ ├── test_templatesync.py │ ├── test_usage_report.py │ ├── test_user.py │ ├── test_usergroup.py │ ├── test_vm_install_products_package.py │ └── test_webhook.py ├── conftest.py ├── data │ ├── 99-haproxy.conf │ ├── U_RHEL_7_V3R6_STIG_SCAP_1-2_Benchmark.xml │ ├── ant-7.7.7-1.noarch.rpm │ ├── certs.sh │ ├── emanuel.iso │ ├── expired-manifest.zip │ ├── extensions.txt │ ├── generate-ca.sh │ ├── generate-crt.sh │ ├── hammer_commands.json │ ├── haproxy.cfg │ ├── openssl.cnf │ ├── os_template.txt │ ├── partition_script.txt │ ├── puppet_custom_selinux-0.3.1.tar.gz │ ├── puppetlabs-ntp-3.2.1.tar.gz │ ├── report_template.txt │ ├── scap-security-guide-satellite-4.3.4-1.el9sat.noarch.rpm │ ├── scap-security-guide-satellite-4.3.4-1.el9sat.noarch.rpm.txt │ ├── scap-security-guide-satellite-4.3.5-1.el9sat.noarch.rpm │ ├── scap-security-guide-satellite-4.3.5-1.el9sat.noarch.rpm.txt │ ├── snippet.txt │ ├── ssg-rhel7-ds-tailoring.xml │ ├── sshkeys.json │ ├── uri.sh │ ├── usage_report.yml │ ├── valid_cert.crt │ ├── valid_gpg_key.txt │ ├── valid_gpg_key_beta.txt │ ├── which-2.19-6.el6.src.rpm │ ├── which-2.19-6.el6.x86_64.rpm │ └── zoo_custom_gpgkey.txt ├── destructive │ ├── __init__.py │ ├── conftest.py │ ├── test_ansible.py │ ├── test_auth.py │ ├── test_capsule_loadbalancer.py │ ├── test_capsulecontent.py │ ├── test_clone.py │ ├── test_contenthost.py │ ├── test_contentview.py │ ├── test_discoveredhost.py │ ├── test_fm_upgrade.py │ ├── test_foreman_rake.py │ ├── test_foreman_service.py │ ├── test_host.py │ ├── test_infoblox.py │ ├── test_installer.py │ ├── test_katello_certs_check.py │ ├── test_ldap_authentication.py │ ├── test_ldapauthsource.py │ ├── test_leapp_satellite.py │ ├── test_packages.py │ ├── test_ping.py │ ├── test_puppetplugin.py │ ├── test_realm.py │ ├── test_registration.py │ ├── test_remoteexecution.py │ ├── test_rename.py │ └── test_repository.py ├── endtoend │ ├── __init__.py │ ├── test_api_endtoend.py │ └── test_cli_endtoend.py ├── installer │ ├── __init__.py │ ├── test_infoblox.py │ └── test_installer.py ├── longrun │ ├── __init__.py │ ├── test_inc_updates.py │ ├── test_oscap.py │ └── test_remoteexecution.py ├── maintain │ ├── test_advanced.py │ ├── test_backup_restore.py │ ├── test_health.py │ ├── test_maintenance_mode.py │ ├── test_offload_DB.py │ ├── test_packages.py │ ├── test_service.py │ └── test_upgrade.py ├── sanity │ └── test_bvt.py ├── sys │ ├── __init__.py │ ├── test_dynflow.py │ ├── test_fam.py │ ├── test_katello_certs_check.py │ ├── test_pulp3_filesystem.py │ └── test_webpack.py ├── ui │ ├── __init__.py │ ├── conftest.py │ ├── test_acs.py │ ├── test_activationkey.py │ ├── test_ansible.py │ ├── test_architecture.py │ ├── test_audit.py │ ├── test_bookmarks.py │ ├── test_branding.py │ ├── test_capsulecontent.py │ ├── test_computeprofiles.py │ ├── test_computeresource.py │ ├── test_computeresource_azurerm.py │ ├── test_computeresource_ec2.py │ ├── test_computeresource_gce.py │ ├── test_computeresource_libvirt.py │ ├── test_computeresource_vmware.py │ ├── test_config_group.py │ ├── test_containerimagetag.py │ ├── test_contentcredentials.py │ ├── test_contenthost.py │ ├── test_contentview.py │ ├── test_contentview_old.py │ ├── test_dashboard.py │ ├── test_discoveredhost.py │ ├── test_discoveryrule.py │ ├── test_documentation_links.py │ ├── test_domain.py │ ├── test_eol_banner.py │ ├── test_errata.py │ ├── test_fact.py │ ├── test_flatpak.py │ ├── test_hardwaremodel.py │ ├── test_host.py │ ├── test_hostcollection.py │ ├── test_hostgroup.py │ ├── test_http_proxy.py │ ├── test_jobtemplate.py │ ├── test_ldap_authentication.py │ ├── test_leapp_client.py │ ├── test_lifecycleenvironment.py │ ├── test_location.py │ ├── test_media.py │ ├── test_modulestreams.py │ ├── test_operatingsystem.py │ ├── test_organization.py │ ├── test_oscapcontent.py │ ├── test_oscappolicy.py │ ├── test_oscaptailoringfile.py │ ├── test_package.py │ ├── test_partitiontable.py │ ├── test_product.py │ ├── test_provisioningtemplate.py │ ├── test_puppetclass.py │ ├── test_puppetenvironment.py │ ├── test_registration.py │ ├── test_remoteexecution.py │ ├── test_reporttemplates.py │ ├── test_repositories.py │ ├── test_repository.py │ ├── test_rhc.py │ ├── test_rhcloud_insights.py │ ├── test_rhcloud_inventory.py │ ├── test_role.py │ ├── test_search.py │ ├── test_settings.py │ ├── test_smartclassparameter.py │ ├── test_subnet.py │ ├── test_subscription.py │ ├── test_sync.py │ ├── test_syncplan.py │ ├── test_templatesync.py │ ├── test_user.py │ ├── test_usergroup.py │ └── test_webhook.py └── virtwho │ ├── __init__.py │ ├── api │ ├── __init__.py │ ├── test_esx_sca.py │ ├── test_hyperv_sca.py │ ├── test_kubevirt_sca.py │ ├── test_libvirt_sca.py │ └── test_nutanix_sca.py │ ├── cli │ ├── __init__.py │ ├── test_esx_sca.py │ ├── test_hyperv_sca.py │ ├── test_kubevirt_sca.py │ ├── test_libvirt_sca.py │ └── test_nutanix_sca.py │ ├── conftest.py │ └── ui │ ├── __init__.py │ ├── test_esx_sca.py │ ├── test_hyperv_sca.py │ ├── test_kubevirt_sca.py │ ├── test_libvirt_sca.py │ └── test_nutanix_sca.py ├── new_upgrades ├── __init__.py ├── conftest.py ├── test_activation_key.py ├── test_bookmarks.py ├── test_capsule.py ├── test_classparameter.py ├── test_contentview.py ├── test_discovery.py ├── test_errata.py ├── test_hostcontent.py ├── test_hostgroup.py ├── test_performance_tuning.py ├── test_puppet.py ├── test_remoteexecution.py ├── test_repository.py ├── test_role.py └── test_satellitesync.py ├── robottelo ├── __init__.py ├── conftest.py ├── data │ └── test_dsa.key ├── test_cli.py ├── test_cli_method_calls.py ├── test_datafactory.py ├── test_decorators.py ├── test_dependencies.py ├── test_func_locker.py ├── test_func_shared.py ├── test_hammer.py ├── test_helpers.py ├── test_issue_handlers.py ├── test_report.py ├── test_shared_resource.py └── test_ssh.py └── upgrades ├── __init__.py ├── conftest.py ├── test_activation_key.py ├── test_bookmarks.py ├── test_capsule.py ├── test_classparameter.py ├── test_client.py ├── test_contentview.py ├── test_discovery.py ├── test_errata.py ├── test_host.py ├── test_hostcontent.py ├── test_hostgroup.py ├── test_performance_tuning.py ├── test_provisioningtemplate.py ├── test_puppet.py ├── test_remoteexecution.py ├── test_repository.py ├── test_role.py ├── test_satellitesync.py ├── test_subnet.py ├── test_subscription.py ├── test_syncplan.py ├── test_user.py ├── test_usergroup.py └── test_virtwho.py /.env.example: -------------------------------------------------------------------------------- 1 | # Procedure to enable vault interation with robottelo: 2 | # 1. Copy .env.example to .env file to set this as root level directory for Dynaconf Vault integrtion 3 | # 2. Set VAULT_ENABLED_FOR_DYNACONF to true to enable vault integration 4 | # 3. Set right vaules for VAULT_URL_FOR_DYNACONF, VAULT_MOUNT_POINT_FOR_DYNACONF and VAULT_PATH_FOR_DYNACONF 5 | # 4. Run 'make vault-login' to login into vault and to generate and set th token automatically 6 | # 5. To use secret from vault for any settings in conf/*.yaml, use the format: '@format {this._secret_name_in_vault_}' 7 | # 6. bugzilla.yaml Example: 8 | # BUGZILLA: 9 | # URL: https://bugzilla.redhat.com 10 | # API_KEY: '@format {this.vault_bz-api-key}' 11 | # 7. Execute command `vault kv get ` to list all the secrets from vault 12 | VAULT_ENABLED_FOR_DYNACONF=false 13 | VAULT_URL_FOR_DYNACONF=http://localhost:8200 14 | # Specify the secrets engine for kv, default is 1 15 | VAULT_KV_VERSION_FOR_DYNACONF=2 16 | # Specify certs to access secrets on https vault 17 | VAULT_VERIFY_FOR_DYNACONF=false 18 | # Authenticate with token https://www.vaultproject.io/docs/auth/token 19 | # VAULT_TOKEN_FOR_DYNACONF=myroot 20 | # Authenticate with AppRole https://www.vaultproject.io/docs/auth/approle 21 | # VAULT_ROLE_ID_FOR_DYNACONF= 22 | # VAULT_SECRET_ID_FOR_DYNACONF= 23 | # Authenticate with AWS IAM https://www.vaultproject.io/docs/auth/aws 24 | # The IAM Credentials can be retrieved from the standard providers: https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html 25 | # VAULT_AUTH_WITH_IAM_FOR_DYNACONF=False 26 | # VAULT_AUTH_ROLE_FOR_DYNACONF=vault-role 27 | # Authenticate with root token 28 | # VAULT_ROOT_TOKEN_FOR_DYNACONF=root-token 29 | # Path of secrets 30 | VAULT_MOUNT_POINT_FOR_DYNACONF=somemount 31 | VAULT_PATH_FOR_DYNACONF=somepath 32 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Problem Statement 2 | 3 | 4 | ### Solution 5 | 6 | 7 | ### Related Issues 8 | 9 | 10 | 14 | -------------------------------------------------------------------------------- /.github/auto_assign.yml: -------------------------------------------------------------------------------- 1 | addAssignees: author 2 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # This is the configuration file for Dependabot. You can find configuration information below. 2 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 3 | # Note: Dependabot has a configurable max open PR limit of 5 4 | 5 | version: 2 6 | updates: 7 | # Maintain dependencies for Robottelo itself 8 | - package-ecosystem: "pip" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | labels: 13 | - '6.17.z' 14 | - '6.16.z' 15 | - "CherryPick" 16 | - "dependencies" 17 | - "6.15.z" 18 | - "6.14.z" 19 | ignore: 20 | - dependency-name: "cryptography" 21 | update-types: ["version-update:semver-minor"] 22 | 23 | # Maintain dependencies for our GitHub Actions 24 | - package-ecosystem: "github-actions" 25 | directory: "/" 26 | schedule: 27 | interval: "daily" 28 | labels: 29 | - '6.17.z' 30 | - '6.16.z' 31 | - "CherryPick" 32 | - "dependencies" 33 | - "6.15.z" 34 | - "6.14.z" 35 | -------------------------------------------------------------------------------- /.github/dependency_tests.yaml: -------------------------------------------------------------------------------- 1 | broker: "tests/foreman/ -k 'test_host_registration_end_to_end or test_positive_erratum_applicability or test_positive_upload_content'" 2 | deepdiff: "tests/foreman/endtoend/test_api_endtoend.py -k 'test_positive_get_links'" 3 | dynaconf: "tests/foreman/api/test_ldapauthsource.py -k 'test_positive_endtoend'" 4 | manifester: "tests/foreman/cli/test_contentview.py -k 'test_positive_promote_rh_content'" 5 | navmazing: "tests/foreman/ui/test_repository.py -k 'test_positive_create_as_non_admin_user'" 6 | pyotp: "tests/foreman/ui/test_ldap_authentication.py -k 'test_positive_login_user_password_otp'" 7 | pytest-xdist: "tests/foreman/ -n 3 -m 'build_sanity'" 8 | pytest: "tests/foreman/ -m 'build_sanity'" 9 | python-box: "tests/foreman/cli/test_webhook.py -k 'test_positive_end_to_end'" 10 | requests: "tests/foreman/cli/test_repository.py -k 'test_file_repo_contains_only_newer_file'" 11 | wait-for: "tests/foreman/api/test_reporttemplates.py -k 'test_positive_schedule_entitlements_report'" 12 | wrapanapi: "tests/foreman/api/test_computeresource_gce.py::TestGCEHostProvisioningTestCase::test_positive_gce_host_provisioned[sat]" 13 | -------------------------------------------------------------------------------- /.github/workflows/auto_assignment.yaml: -------------------------------------------------------------------------------- 1 | name: 'Auto Assign' 2 | 3 | on: 4 | pull_request_target: 5 | types: 6 | - opened 7 | - ready_for_review 8 | - reopened 9 | - synchronize 10 | 11 | 12 | jobs: 13 | add-assignees: # This needed for to create the gh issue in case of failed auto-cherry-pick 14 | name: Add author to assignee 15 | if: "!contains(github.event.pull_request.labels.*.name, 'Auto_Cherry_Picked')" 16 | runs-on: ubuntu-latest 17 | steps: 18 | - uses: kentaro-m/auto-assign-action@v2.0.0 19 | with: 20 | configuration-path: ".github/auto_assign.yml" 21 | -------------------------------------------------------------------------------- /.github/workflows/dispatch_release.yml: -------------------------------------------------------------------------------- 1 | ### The auto release workflow triggered through dispatch request from CI 2 | name: auto-release 3 | 4 | # Run on workflow dispatch from CI 5 | on: 6 | workflow_dispatch: 7 | inputs: 8 | tag_name: 9 | type: string 10 | description: Name of the tag 11 | 12 | jobs: 13 | auto-tag-and-release: 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Git User setup 20 | run: "git config --local user.email Satellite-QE.satqe.com && git config --local user.name Satellite-QE" 21 | 22 | - name: Tag latest commit 23 | run: "git tag -a ${{ github.event.inputs.tag_name }} -m 'Tagged By SatelliteQE Automation User'" 24 | 25 | - name: Push the tag to the upstream 26 | run: "git push ${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}.git --tags" 27 | 28 | - name: create a new release from the tag 29 | env: 30 | credentials: ${{ secrets.GH_TOKEN }} 31 | run: "curl -L -X POST -H \"Authorization: Bearer ${{ secrets.SATQE_GH_TOKEN }}\" ${GITHUB_API_URL}/repos/${GITHUB_REPOSITORY}/releases -d '{\"tag_name\": \"${{ github.event.inputs.tag_name }}\", \"target_commitish\":\"master\", \"name\":\"${{ github.event.inputs.tag_name }}\", \"draft\":false, \"prerelease\":true, \"generate_release_notes\": true}'" 32 | -------------------------------------------------------------------------------- /.github/workflows/required_labels.yml: -------------------------------------------------------------------------------- 1 | # CI jobs to check specific labels present / absent 2 | name: required_labels 3 | 4 | on: 5 | pull_request: 6 | types: [opened, labeled, unlabeled, synchronize] 7 | 8 | jobs: 9 | cherrypick_label: 10 | name: Enforcing cherrypick labels 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: mheap/github-action-required-labels@v5 14 | with: 15 | mode: exactly 16 | count: 1 17 | labels: "CherryPick, No-CherryPick" 18 | -------------------------------------------------------------------------------- /.github/workflows/stale.yml: -------------------------------------------------------------------------------- 1 | # This workflow warns and then closes issues and PRs that have had no activity for a specified amount of time. 2 | # 3 | # You can adjust the behavior by modifying this file. 4 | # For more information, see: 5 | # https://github.com/actions/stale 6 | name: Warn and Close stale issues and pull requests 7 | 8 | on: 9 | schedule: 10 | - cron: '30 5 * * *' 11 | 12 | jobs: 13 | warn_and_close_stails: 14 | runs-on: ubuntu-latest 15 | permissions: 16 | issues: write 17 | pull-requests: write 18 | steps: 19 | - uses: actions/stale@v9 20 | with: 21 | repo-token: ${{ secrets.GITHUB_TOKEN }} 22 | days-before-issue-stale: 90 23 | days-before-pr-stale: 45 24 | days-before-issue-close: 7 25 | days-before-pr-close: 7 26 | stale-issue-message: 'This issue has not been updated in the past 90 days.' 27 | stale-pr-message: 'This pull request has not been updated in the past 45 days.' 28 | close-issue-message: 'This issue is now being closed after stale warnings.' 29 | close-pr-message: 'This pull request is now being closed after stale warnings.' 30 | only-issue-labels: 'Failed_AutoCherryPick' 31 | remove-stale-when-updated: true 32 | -------------------------------------------------------------------------------- /.github/workflows/update_robottelo_image.yml: -------------------------------------------------------------------------------- 1 | # Update robottelo image on quay. 2 | name: update_robottelo_image 3 | 4 | on: 5 | push: 6 | branches: 7 | - master 8 | - 6.*.z 9 | workflow_dispatch: 10 | 11 | jobs: 12 | robottelo_container: 13 | name: Update Robottelo container image on Quay. 14 | runs-on: ubuntu-latest 15 | 16 | steps: 17 | - name: Checkout 18 | uses: actions/checkout@v4 19 | with: 20 | # do not store the auth token in git config 21 | persist-credentials: false 22 | 23 | - name: Get image tag 24 | id: image_tag 25 | run: | 26 | TAG="${GITHUB_REF##*/}" 27 | TAG=${TAG/master/latest} 28 | echo "IMAGE_TAG=$TAG" >> $GITHUB_OUTPUT 29 | 30 | - name: Build Robottelo image 31 | id: build-image 32 | uses: redhat-actions/buildah-build@v2 33 | with: 34 | image: robottelo 35 | tags: ${{ steps.image_tag.outputs.IMAGE_TAG }} 36 | containerfiles: | 37 | ./Dockerfile 38 | 39 | - name: Push Robottelo image to quay.io 40 | id: push-to-quay 41 | uses: redhat-actions/push-to-registry@v2 42 | with: 43 | image: robottelo 44 | tags: ${{ steps.image_tag.outputs.IMAGE_TAG }} 45 | registry: ${{ secrets.QUAY_SERVER }}/${{ secrets.QUAY_NAMESPACE }} 46 | username: ${{ secrets.QUAY_USERNAME }} 47 | password: ${{ secrets.QUAY_PASSWORD }} 48 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # configuration for pre-commit git hooks 2 | 3 | ci: 4 | autofix_prs: false # disable autofixing PRs 5 | 6 | repos: 7 | - repo: https://github.com/pre-commit/pre-commit-hooks 8 | rev: v5.0.0 9 | hooks: 10 | - id: trailing-whitespace 11 | exclude: tests/foreman/data/ 12 | - id: check-yaml 13 | - id: debug-statements 14 | - repo: https://github.com/astral-sh/ruff-pre-commit 15 | rev: v0.11.11 16 | hooks: 17 | - id: ruff 18 | args: [--fix, --exit-non-zero-on-fix, --target-version=py310] 19 | - id: ruff-format 20 | - repo: local 21 | hooks: 22 | - id: fix-uuids 23 | name: Robottelo Custom Fix UUIDs script 24 | description: This hook runs the scripts/fix_uuids.sh script 25 | language: script 26 | entry: scripts/fix_uuids.sh 27 | verbose: true 28 | types: [text] 29 | require_serial: true 30 | - repo: https://github.com/gitleaks/gitleaks 31 | rev: v8.26.0 32 | hooks: 33 | - id: gitleaks 34 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM quay.io/fedora/python-312:latest 2 | MAINTAINER https://github.com/SatelliteQE 3 | 4 | ENV PYCURL_SSL_LIBRARY=openssl \ 5 | ROBOTTELO_DIR="${HOME}/robottelo" \ 6 | UV_PYTHON="${APP_ROOT}/bin/python3" \ 7 | UV_NO_CACHE=1 8 | 9 | COPY --from=ghcr.io/astral-sh/uv:latest /uv /bin/uv 10 | 11 | USER 1001 12 | COPY --chown=1001:0 / ${ROBOTTELO_DIR} 13 | 14 | WORKDIR "${ROBOTTELO_DIR}" 15 | RUN git config --global --add safe.directory ${ROBOTTELO_DIR} && \ 16 | uv pip install -r requirements.txt 17 | 18 | CMD make test-robottelo 19 | -------------------------------------------------------------------------------- /conf/ansible.yaml.template: -------------------------------------------------------------------------------- 1 | AAP_INTEGRATION: 2 | AAP_FQDN: env-aap-01.example.com 3 | # USERNAME: Login for AAP 4 | USERNAME: 5 | # PASSWORD: Password for AAP 6 | PASSWORD: 7 | # Red Hat Satellite 6 type credentials for dynamic inventory testing 8 | SATELLITE_CREDENTIALS: 9 | # Satellite as a Dynamic Inventory in Ansible Tower 10 | SATELLITE_INVENTORY: 11 | # Job template and host_config_key for ansible-callback with Satellite testing 12 | CALLBACK_JOB_TEMPLATE: 13 | HOST_CONFIG_KEY: 14 | -------------------------------------------------------------------------------- /conf/ansible_hub.yaml.template: -------------------------------------------------------------------------------- 1 | ANSIBLE_HUB: 2 | URL: 3 | TOKEN: 4 | SSO_URL: 5 | -------------------------------------------------------------------------------- /conf/azure.yaml.template: -------------------------------------------------------------------------------- 1 | AZURERM: 2 | # Client ID of the AzureRM account 3 | CLIENT_ID: 4 | # Client Secret of the AzureRM account 5 | CLIENT_SECRET: 6 | # The subscription ID is a GUID that uniquely identifies your subscription to use Azure services. 7 | SUBSCRIPTION_ID: 8 | # The resource group where the resources will be created under above subscription 9 | RESOURCE_GROUP: 10 | # Tenant ID, the ID of the AAD directory in which you created the application 11 | TENANT_ID: 12 | # Azure Region 13 | AZURE_REGION: East US 14 | # SSH Public Key of the user from which login as passwordless in VM 15 | SSH_PUB_KEY: 16 | # Username of admin user(non-root) 17 | USERNAME: 18 | # Password of the admin user 19 | PASSWORD: 20 | # Azure Private subnet details 21 | AZURE_SUBNET: SATQE-vnet-default 10.0.0.0/24 22 | -------------------------------------------------------------------------------- /conf/broker.yaml.template: -------------------------------------------------------------------------------- 1 | BROKER: 2 | # Broker has its own config which you can find by running `broker --version` 3 | HOST_WORKFLOWS: 4 | POWER_CONTROL: vm-power-operation 5 | EXTEND: extend-vm 6 | -------------------------------------------------------------------------------- /conf/bugzilla.yaml.template: -------------------------------------------------------------------------------- 1 | BUGZILLA: 2 | # url default value is set to 'https://bugzilla.redhat.com' even if not provided. 3 | URL: https://bugzilla.redhat.com 4 | # Provide api_key to access Bugzilla REST API 5 | API_KEY: replace-with-bugzilla-api-key 6 | -------------------------------------------------------------------------------- /conf/capsule.yaml.template: -------------------------------------------------------------------------------- 1 | CAPSULE: 2 | # Capsule hostname for N-minus testing 3 | HOSTNAME: 4 | VERSION: 5 | # The full release version (6.9.2) 6 | RELEASE: # populate with capsule version 7 | # The snap version currently testing (if applicable) 8 | # SNAP: 9 | # The source of Capsule packages. Can be one of: 10 | # internal, ga, nightly 11 | SOURCE: "internal" 12 | # The base os rhel version where the capsule installed 13 | # RHEL_VERSION: 14 | # The Ansible Tower workflow used to deploy a capsule 15 | DEPLOY_WORKFLOWS: 16 | PRODUCT: deploy-capsule # workflow to deploy OS with product running on top of it 17 | OS: deploy-rhel # workflow to deploy OS that is ready to run the product 18 | # Dictionary of arguments which should be passed along to the deploy workflow 19 | DEPLOY_ARGUMENTS: 20 | deploy_network_type: '@jinja {{"ipv6" if this.server.is_ipv6 else "ipv4"}}' 21 | -------------------------------------------------------------------------------- /conf/clone.yaml.template: -------------------------------------------------------------------------------- 1 | CLONE: 2 | # satellite restore using clone rpm 3 | CLONE_RPM: false 4 | # mount point of customers backup data 5 | BACKUP_DIR: "/tmp/customer-dbs" 6 | # customers database server 7 | DB_SERVER: 8 | # Restore selinux context across filesystem, applicable for specific database. 9 | RESTORECON: false 10 | # It is used when we perform db upgrade or migration using pulp data 11 | INCLUDE_PULP_DATA: false 12 | # customer name 13 | CUSTOMER_NAME: 14 | # satellite clone upstream branch 15 | SATELLITE_CLONE_UPSTREAM_REPOS: "https://github.com/RedHatSatellite/satellite-clone.git" 16 | # clone_dir for upstream satellite clone 17 | UPSTREAM_CLONE_DIR: "/root/satellite-clone" 18 | # clone_dir for downstream satellite clone 19 | DOWNSTREAM_CLONE_DIR: "/usr/share/satellite-clone" 20 | -------------------------------------------------------------------------------- /conf/container.yaml.template: -------------------------------------------------------------------------------- 1 | --- 2 | CONTAINER: 3 | CLIENTS: 4 | - docker 5 | - podman 6 | REGISTRY_HUB: https://mirror.gcr.io 7 | UPSTREAM_NAME: 'library/busybox' 8 | ALTERNATIVE_UPSTREAM_NAMES: 9 | - hello-world 10 | - alpine 11 | DOCKER: 12 | REPO_UPSTREAM_NAME: 'openshift3/logging-elasticsearch' 13 | PULP: 14 | REGISTRY_HUB: 'https://ghcr.io' 15 | RH: 16 | REGISTRY_HUB: 'https://registry.redhat.io/' 17 | UPSTREAM_NAME: 'openshift3/ose-metrics-hawkular-openshift-agent' 18 | ... 19 | -------------------------------------------------------------------------------- /conf/container_repo.yaml.template: -------------------------------------------------------------------------------- 1 | # Container registry and repo set information to use for container repo syncing. 2 | CONTAINER_REPO: 3 | registries: 4 | redhat: 5 | URL: https://registry.redhat.io 6 | USERNAME: 7 | PASSWORD: 8 | REPOS_TO_SYNC: 9 | - rhscl/mysql-57-rhel7 10 | - rhscl/ruby-24-rhel7 11 | # Boolean to control test collection for long-password based tests 12 | LONG_PASS: True 13 | quay: 14 | URL: https://quay.io 15 | USERNAME: 16 | PASSWORD: 17 | # I N C E P T I O N 18 | REPOS_TO_SYNC: 19 | - satelliteqe/robottelo 20 | -------------------------------------------------------------------------------- /conf/docker.yaml.template: -------------------------------------------------------------------------------- 1 | DOCKER: 2 | # External docker registry URL in the format http[s]://[:] 3 | EXTERNAL_REGISTRY_1: 4 | # Private docker registry URL in the format http[s]://[:] 5 | PRIVATE_REGISTRY_URL: https://registry.hub.docker.com 6 | # Private docker registry name 7 | PRIVATE_REGISTRY_NAME: username/imagename 8 | # Private docker registry username 9 | PRIVATE_REGISTRY_USERNAME: 10 | # Private docker registry password 11 | PRIVATE_REGISTRY_PASSWORD: 12 | # Image Pass Registry 13 | IMAGE_REGISTRY: 14 | # image repository URL 15 | URL: 16 | # Pull a non-namespace image using the image pass registry proxy 17 | NON_NAMESPACE: 18 | # Proxy for the non-namespace image 19 | PROXY: 20 | # Username for the non-namespace image pass registry proxy 21 | USERNAME: 22 | # Password for the non-namespace image pass registry proxy 23 | PASSWORD: 24 | # Pull a namespace image using the image pass registry proxy 25 | NAMESPACE: 26 | # proxy for the namespace image 27 | PROXY: 28 | # Username for the namespace image pass registry proxy 29 | USERNAME: 30 | # Password for the namespace image pass registry proxy 31 | PASSWORD: 32 | -------------------------------------------------------------------------------- /conf/ec2.yaml.template: -------------------------------------------------------------------------------- 1 | EC2: 2 | # AWS EC2 to be added as a compute resource. 3 | # Access key ID of the IAM user 4 | ACCESS_KEY: access_key 5 | # Secret access key of the IAM user 6 | SECRET_KEY: secret_key 7 | # AWS region for the compute resources 8 | REGION: us-west-2 9 | # Compute resource profile image 10 | IMAGE: ami-image 11 | # Compute resource profile availability zone 12 | AVAILABILITY_ZONE: us-west-2a 13 | # Compute resource profile subnet / 14 | SUBNET: 15 | # Compute resource profile security groups list 16 | SECURITY_GROUPS: secgrp 17 | # Compute resource profile security managed ip, available values Private, Public 18 | MANAGED_IP: Private 19 | -------------------------------------------------------------------------------- /conf/fake_capsules.yaml.template: -------------------------------------------------------------------------------- 1 | FAKE_CAPSULES: 2 | # a range of ports configured for capsule port mapping represented by a tuple: 3 | # , (no brackets) 4 | # for RHEL7 - the ports needs to have a correct selinux context set: 5 | # 'semanage port -a -t websm_port_t -p tcp ' 6 | PORT_RANGE: "9091-14999" 7 | -------------------------------------------------------------------------------- /conf/flavors.yaml.template: -------------------------------------------------------------------------------- 1 | FLAVORS: 2 | # 6 CPU, 24 GB RAM, 100 GB disk 3 | DEFAULT: satqe-ssd.standard.std 4 | # 16 CPU, 32 GB RAM, 160 GB disk 5 | LARGE: satqe-ssd.standard.xxxl 6 | # 6 CPU, 24 GB RAM, 500 GB disk 7 | UPGRADE: satqe-ssd.upgrade.std 8 | # 8 CPU, 32 GB RAM, 500 GB disk 9 | CUSTOM_DB: satqe-ssd.customerdb.std 10 | -------------------------------------------------------------------------------- /conf/gce.yaml.template: -------------------------------------------------------------------------------- 1 | GCE: 2 | # Google Provider as Compute Resource 3 | # client json Certificate path which is local path on satellite 4 | CERT_PATH: /usr/share/foreman/path/to/certificate.json 5 | # Zones 6 | ZONE: northamerica-northeast1-a 7 | # client certificate 8 | CERT: "{}" # client json Certificate 9 | -------------------------------------------------------------------------------- /conf/git.yaml.template: -------------------------------------------------------------------------------- 1 | GIT: 2 | USERNAME: admin 3 | PASSWORD: chageme 4 | SSH_PORT: 22 5 | HTTP_PORT: 80 6 | HOSTNAME: localhost 7 | GITHUB_TOKEN: 8 | -------------------------------------------------------------------------------- /conf/http_proxy.yaml.template: -------------------------------------------------------------------------------- 1 | HTTP_PROXY: 2 | UN_AUTH_PROXY_URL: # http://proxy-01.example.com:3423 3 | HTTP_PROXY_IPV6_URL: # http://proxy-01.ipv6.example.com:3423 4 | AUTH_PROXY_URL: # http://proxy-02.example.com:3423 5 | USERNAME: auth-proxy-user 6 | PASSWORD: auth-proxy-password 7 | -------------------------------------------------------------------------------- /conf/infoblox.yaml.template: -------------------------------------------------------------------------------- 1 | INFOBLOX: 2 | HOSTNAME: infoblox.example.com 3 | # username: Login for Infoblox instance 4 | USERNAME: 5 | # password: Password for Infoblox instance 6 | PASSWORD: 7 | #Domain 8 | DOMAIN: 9 | #Network Address 10 | NETWORK: 11 | #Network Prefix 12 | NETWORK_PREFIX: 13 | #Network Netmask 14 | NETMASK: 15 | #Starting range of IP 16 | START_RANGE: 17 | #Ending range of IP 18 | END_RANGE: 19 | -------------------------------------------------------------------------------- /conf/ipa.yaml.template: -------------------------------------------------------------------------------- 1 | # For LDAP freeIPA Authentication. 2 | IPA: 3 | HOSTNAME: # replace with hostname 4 | USERNAME: # replace with username 5 | PASSWORD: # update the password 6 | BASEDN: # replace with basedn 7 | GRPBASEDN: # replace with group basedn 8 | USER: foreman 9 | OTP_USER: otp_user 10 | TIME_BASED_SECRET: # update the time based token secret 11 | DISABLED_IPA_USER: disabled_user 12 | USERS: 13 | USER: satuser_01 14 | ADMIN: satadmin_01 15 | GROUPS: 16 | USERS: satusers 17 | ADMINS: satadmins 18 | KEYTAB_URL: 19 | -------------------------------------------------------------------------------- /conf/jira.yaml.template: -------------------------------------------------------------------------------- 1 | JIRA: 2 | # url default value is set to 'https://issues.redhat.com' even if not provided. 3 | URL: https://issues.redhat.com 4 | # Provide api_key to access Jira REST API 5 | API_KEY: replace-with-jira-api-key 6 | COMMENT_TYPE: group 7 | COMMENT_VISIBILITY: "Red Hat Employee" 8 | ENABLE_COMMENT: false 9 | # Comment only if jira is in one of the following state 10 | ISSUE_STATUS: ["Testing", "Release Pending"] 11 | CACHE_FILE: jira_status_cache.json 12 | CACHE_TTL_DAYS: 7 13 | -------------------------------------------------------------------------------- /conf/ldap.yaml.template: -------------------------------------------------------------------------------- 1 | # For Active Directory LDAP Authentication. 2 | LDAP: 3 | HOSTNAME: # replace with AD ldap server name 4 | 2016: foo.example.com # 5 | 2019: foo19.example.com # 6 | USERNAME: foobar 7 | PASSWORD: secret # update with password 8 | BASEDN: cn=Foo,dc=bar,dc=baz,dc=example,dc=com # update base dn 9 | GRPBASEDN: dc=bar,dc=baz,dc=example,dc=com # update with group base dn 10 | REALM: BAR.BAZ.EXAMPLE.COM # update with realm address 11 | NAMESERVER: # update with the ip of the ad ldap server name 12 | 2016: 192.168.0.2 # 13 | 2019: 192.168.0.3 # 14 | NAMESERVER6: 15 | 2019: 2001::beef:face # 16 | WORKGROUP: # udpate with ldap server's domain name 17 | 2016: FOO # 18 | 2019: FOO19 # 19 | -------------------------------------------------------------------------------- /conf/libvirt.yaml.template: -------------------------------------------------------------------------------- 1 | LIBVIRT: 2 | # External Libvirt Hostname 3 | LIBVIRT_HOSTNAME: # libvirt.example.com 4 | # Path on the Libvirt host, where the virtual images will be stored. 5 | # The default libvirt image dir will be used i.e., "/var/lib/libvirt/images/". 6 | LIBVIRT_IMAGE_DIR: /var/lib/libvirt/images 7 | # For discovery ISO 8 | # Discovery ISO name is required for PXE-less discovery tests. ISO's are 9 | # rebuilt with extra kernel options for unattended pxe-less discovery 10 | # ISO file names should be like below for downstream_el6 and el7 environments: 11 | # foreman-discovery-image-3.0.5-3_unattended_down_el7.iso 12 | # foreman-discovery-image-3.0.5-3_unattended_down_el6.iso 13 | -------------------------------------------------------------------------------- /conf/manifest.yaml.template: -------------------------------------------------------------------------------- 1 | MANIFEST: 2 | MANIFESTER_DIRECTORY: "" 3 | GOLDEN_TICKET: 4 | # Value of SAT_VERSION setting should be in the form "sat-X.Y", e.g. "sat-6.11" 5 | SAT_VERSION: "" 6 | OFFLINE_TOKEN: "" 7 | # Manifests with simple content access enabled should not use a quantity higher than 1 for any subscription 8 | # unless doing so is required for a test. 9 | SUBSCRIPTION_DATA: 10 | # NAME should be an exact match of the subscription name as listed on the Customer Portal 11 | - NAME: "" 12 | QUANTITY: 13 | - NAME: "" 14 | QUANTITY: 15 | SIMPLE_CONTENT_ACCESS: "enabled" 16 | URL: 17 | TOKEN_REQUEST: "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token" 18 | ALLOCATIONS: "https://api.access.redhat.com/management/v1/allocations" 19 | ENTITLEMENT: 20 | SAT_VERSION: "" 21 | OFFLINE_TOKEN: "" 22 | SUBSCRIPTION_DATA: 23 | - NAME: "" 24 | QUANTITY: 25 | - NAME: "" 26 | QUANTITY: 27 | SIMPLE_CONTENT_ACCESS: "disabled" 28 | URL: 29 | TOKEN_REQUEST: "https://sso.redhat.com/auth/realms/redhat-external/protocol/openid-connect/token" 30 | ALLOCATIONS: "https://api.access.redhat.com/management/v1/allocations/" 31 | -------------------------------------------------------------------------------- /conf/ohsnap.yaml.template: -------------------------------------------------------------------------------- 1 | OHSNAP: 2 | HOST: "replace by ohsnap repo host url" 3 | REQUEST_RETRY: 4 | # how long should we keep retrying to get data (seconds) 5 | TIMEOUT: 120 6 | # delay between retries (seconds) 7 | DELAY: 3 8 | -------------------------------------------------------------------------------- /conf/openldap.yaml.template: -------------------------------------------------------------------------------- 1 | # For Open Ldap Authentication 2 | OPEN_LDAP: 3 | HOSTNAME: # replace with env openldap server 4 | USERNAME: cn=ldapadmin,dc=example,dc=com 5 | OPEN_LDAP_USER: foreman 6 | PASSWORD: # replace with actual password 7 | BASE_DN: dc=example,dc=com 8 | GROUP_BASE_DN: ou=foobargroup,ou=users,dc=example,dc=com 9 | -------------------------------------------------------------------------------- /conf/oscap.yaml.template: -------------------------------------------------------------------------------- 1 | OSCAP: 2 | RHEL_MAJOR_VERSION: "@jinja {{this.server.version.rhel_version | int }}" 3 | CONTENT_PATH: '@format /usr/share/xml/scap/ssg/content/ssg-rhel{this.oscap.rhel_major_version}-ds.xml' 4 | # see: robottelo/constants/__init__.py OSCAP_PROFILE 5 | PROFILE: '@format security{this.oscap.rhel_major_version}' 6 | CONTENT_DIR: /usr/share/xml/scap/ssg/content 7 | -------------------------------------------------------------------------------- /conf/osp.yaml.template: -------------------------------------------------------------------------------- 1 | OSP: 2 | # Openstack to be added as a compute resource 3 | HOSTNAME: 4 | OSP16: hostname.example.com 5 | OSP17: hostname.example.com 6 | # Openstack authentication url 7 | AUTH_URL: 8 | OSP16: '@format http://{this.osp.hostname.osp16}:5000' 9 | OSP17: '@format http://{this.osp.hostname.osp17}:5000' 10 | # Openstack api url For eg: https://hostname:port/v3/auth/tokens 11 | API_URL: 12 | OSP16: '@format {this.osp.auth_url.osp16}/v3/auth/tokens' 13 | OSP17: '@format {this.osp.auth_url.osp17}/v3/auth/tokens' 14 | # Login for Openstack 15 | USERNAME: 16 | # Password for Openstack 17 | PASSWORD: 18 | # Name of Security group 19 | SECURITY_GROUP: 20 | # Openstack tenant to be used 21 | TENANT: 22 | # Name of VM to power On/Off & delete 23 | VM_NAME: 24 | # ID of the domain for the project 25 | PROJECT_DOMAIN_ID: 26 | # Openstack network name 27 | NETWORK_NAME: 28 | # Openstack rhel8 image name 29 | RHEL8_IMAGE: 30 | # Openstack template's configuration flavour name 31 | FLAVOR_NAME: 32 | # Openstack ssh-key configuration 33 | SSHKEY: 34 | -------------------------------------------------------------------------------- /conf/performance.yaml.template: -------------------------------------------------------------------------------- 1 | PERFORMANCE: 2 | # Control whether or not to time on hammer commands in robottelo/cli/base.py 3 | # Default set to be 0, i.e. no timing of performance is measured and thus no 4 | # interference to original robottelo tests. 5 | TIME_HAMMER: false 6 | -------------------------------------------------------------------------------- /conf/provisioning.yaml.template: -------------------------------------------------------------------------------- 1 | PROVISIONING: 2 | VLAN_ID: 3 | HOST_ROOT_PASSWORD: 4 | HOST_SSH_KEY_PRIV: 5 | HOST_SSH_KEY_PUB: 6 | PROVISIONING_SAT_WORKFLOW: 7 | PROVISIONING_HOST_WORKFLOW: 8 | -------------------------------------------------------------------------------- /conf/remotedb.yaml.template: -------------------------------------------------------------------------------- 1 | REMOTEDB: 2 | # Unconfigured Satellite hostname 3 | SERVER: 4 | # PostgreSQL DB Server 5 | DB_SERVER: 6 | # Databases 7 | foreman: 8 | username: foreman 9 | db_name: foreman 10 | candlepin: 11 | username: candlepin 12 | db_name: candlepin 13 | pulp: 14 | username: pulp 15 | db_name: pulpcore 16 | # Common databases passwords 17 | db_password: 18 | # SSL connection for Satellite and database server 19 | SSL: ON 20 | # DB port 21 | PORT: 5432 22 | -------------------------------------------------------------------------------- /conf/report_portal.yaml.template: -------------------------------------------------------------------------------- 1 | REPORT_PORTAL: 2 | # URL of the Report portal instance 3 | PORTAL_URL: https://reportportal.example.com 4 | PROJECT: Satellite6 5 | # API key 6 | API_KEY: rp-user-api-token 7 | # To skip the rerun, if the failed tests in last run more than fail_threshold 8 | # if its not set, 20% by default will be considered 9 | FAIL_THRESHOLD: 0 10 | # name of the launch for reporting results to 11 | LAUNCH_NAME: launch-name 12 | -------------------------------------------------------------------------------- /conf/rh_cloud.yaml.template: -------------------------------------------------------------------------------- 1 | RH_CLOUD: 2 | TOKEN: this-isnt-the-token 3 | INSTALL_RHC: false 4 | ORGANIZATION: 5 | ACTIVATION_KEY: ak_name 6 | CRC_ENV: prod 7 | IOP_ADVISOR_ENGINE: 8 | IMAGE_PATH: 9 | REGISTRY: 10 | USERNAME: 11 | TOKEN: 12 | SETUP_SCRIPT: 13 | -------------------------------------------------------------------------------- /conf/rhbk.yaml.template: -------------------------------------------------------------------------------- 1 | # section for RHBK integration 2 | RHBK: 3 | # RHBK Hostname 4 | HOST_NAME: # update with rhbk host name 5 | # RHBK port, 8443 by default 6 | HOST_PORT: # update with rhbk host name 7 | # RHBK Host Url 8 | HOST_URL: # update with rhbk environment url 9 | # RHBK Host Admin of Realm 10 | RHBK_USER: sat_admin 11 | # RHBK Host Admin Password 12 | RHBK_PASSWORD: # update with password 13 | # RHBK Host Realm 14 | REALM: satqe 15 | TOTP_SECRET: # update with the totp secret token 16 | -------------------------------------------------------------------------------- /conf/rhev.yaml.template: -------------------------------------------------------------------------------- 1 | RHEV: 2 | # RHEV to be added as a compute resource. 3 | # RHEV API URL, e.g. https://ovirt.example.com/ovirt-engine/api 4 | HOSTNAME: 5 | # Login for RHEVM, e.g. admin@internal 6 | USERNAME: 7 | # Password for RHEVM 8 | PASSWORD: 9 | # RHEVM datacenter, e.g. Default 10 | DATACENTER: 11 | # Name of VM that should be used 12 | VM_NAME: 13 | # RHEVM cluster, e.g. Default 14 | CLUSTER: 15 | # VM storage domain name 16 | STORAGE_DOMAIN: 17 | # RHEV Compute resource image data 18 | # Operating system of the image 19 | IMAGE_OS: 20 | # Architecture of the image 21 | IMAGE_ARCH: 22 | # Login to the image 23 | IMAGE_USERNAME: root 24 | # Password of that user 25 | IMAGE_PASSWORD: 26 | # Image name on the external provider 27 | IMAGE_NAME: 28 | # Image UUID 29 | IMAGE_UUID: 30 | # Interface used for some tests; not required to work with provisioning, not required to be in VLAN 31 | INTERFACE: 32 | # VLAN network prefix: network_name = 33 | NETWORK_PREFIX: 34 | # RHV CA cert for adding RHV as compute resource 35 | CA_CERT: | 36 | ---BEGIN CERT--- 37 | line1 38 | line2 39 | ---END CERT 40 | -------------------------------------------------------------------------------- /conf/rhsso.yaml.template: -------------------------------------------------------------------------------- 1 | # section for RH-SSO integration 2 | RHSSO: 3 | # RH-SSO Hostname 4 | HOST_NAME: # update with rhsso host name 5 | # RH-SSO Host Url 6 | HOST_URL: # update with rhsso environment url 7 | # RH-SSO Host Admin of Realm 8 | RHSSO_USER: sat_admin 9 | # RH-SSO Host Admin Password 10 | RHSSO_PASSWORD: # update with password 11 | # RH-SSO Host Realm 12 | REALM: satqe 13 | TOTP_SECRET: # update with the totp secret token 14 | -------------------------------------------------------------------------------- /conf/robottelo.yaml.template: -------------------------------------------------------------------------------- 1 | ROBOTTELO: 2 | LOCALE: en_US.UTF-8 3 | # Update upstream=false for downstream run 4 | UPSTREAM: false 5 | # Logging verbosity, one of debug, info, warning, error, critical 6 | VERBOSITY: debug 7 | # Directory for temporary files 8 | TMP_DIR: /var/tmp 9 | 10 | # - The URL of container hosting repos on SatLab 11 | # Example url - http://: 12 | # Use https://github.com/SatelliteQE/fedorapeople-repos to deploy and configure the repos hosting container 13 | REPOS_HOSTING_URL: replace-with-repo-hosting-url 14 | # Run one datapoint or multiple datapoints for tests 15 | RUN_ONE_DATAPOINT: false 16 | # Satellite version supported by this branch 17 | # UNDR version is used for some URL composition 18 | SATELLITE_VERSION: "6.18" 19 | # Update non-ga versions with each release 20 | SAT_NON_GA_VERSIONS: 21 | - '6.16' 22 | - '6.17' 23 | # The Base OS RHEL Version(x.y) where the satellite would be installed 24 | RHEL_VERSION: "8.10" 25 | # The source of RHEL packages. Can be one of: 26 | # internal, ga (CDN) 27 | RHEL_SOURCE: "ga" 28 | # Dynaconf and Dynaconf hooks related options 29 | SETTINGS: 30 | GET_FRESH: true 31 | IGNORE_VALIDATION_ERRORS: false 32 | # Stage docs url 33 | STAGE_DOCS_URL: https://docs.redhat.com 34 | SHARED_RESOURCE_WAIT: 2 35 | -------------------------------------------------------------------------------- /conf/shared_function.yaml.template: -------------------------------------------------------------------------------- 1 | SHARED_FUNCTION: 2 | # The default storage handler to use, available handlers: file, redis 3 | # by default storage=file 4 | STORAGE: file 5 | # Namespace scope by default used the md5 of kattelo certificate of the server 6 | SCOPE: 7 | # enabled, by default enabled=false, the shared decorator will 8 | # immediately run the function and the function result data are not saved 9 | # to enable the shared functionality set enabled=true 10 | ENABLED: false 11 | # The lock timeout, to be able to use the shared data, each caller have to lock 12 | # the access to storage to have consistent values, by default 2 hours, to be 13 | # able to handle long running functions, the value is in second 14 | LOCK_TIMEOUT: 7200 15 | # How much time the shared data is considered valid, the value is in second 16 | # by default 24 hours 17 | SHARE_TIMEOUT: 86400 18 | # If redis is used as storage, by default redis_host=localhost 19 | REDIS_HOST: localhost 20 | # The port redis is accessible at that redis_host, by default 6379 21 | REDIS_PORT: 6379 22 | # The redis db index, by default 0 23 | REDIS_DB: 0 24 | # The redis password index, by default None 25 | REDIS_PASSWORD: 26 | # How much time we retry if a function call fail, by default call_retries=2 27 | CALL_RETRIES: 2 28 | -------------------------------------------------------------------------------- /conf/subscription.yaml.template: -------------------------------------------------------------------------------- 1 | SUBSCRIPTION: 2 | # subscription username 3 | RHN_USERNAME: 4 | # subscription password 5 | RHN_PASSWORD: 6 | # subscription pool id 7 | RHN_POOLID: 8 | # lifecycle API url 9 | LIFECYCLE_API_URL: 10 | -------------------------------------------------------------------------------- /conf/supportability.yaml: -------------------------------------------------------------------------------- 1 | supportability: 2 | content_hosts: 3 | default_os_name: "RedHat" 4 | rhel: 5 | versions: [7,'7_fips', 8, '8_fips', 9, '9_fips', 10,] 6 | -------------------------------------------------------------------------------- /conf/ui.yaml.template: -------------------------------------------------------------------------------- 1 | UI: 2 | SCREENSHOTS_PATH: '@format {env[ROBOTTELO_DIR]}/screenshots/' 3 | # Webdriver logging options 4 | LOG_DRIVER_COMMANDS: 5 | - newSession 6 | - windowMaximize 7 | - get 8 | - findElement 9 | - sendKeysToElement 10 | - clickElement 11 | - mouseMoveTo 12 | 13 | # browser tells robottelo which browser to use when testing UI. Valid values: 14 | # * selenium 15 | # * remote: to access the remote browser, the webdriver and command_executor 16 | # are required. 17 | BROWSER: remote 18 | # Webdriver to use. Valid values are chrome, firefox 19 | WEBDRIVER: chrome 20 | # Binary location for selected wedriver 21 | WEBDRIVER_BINARY: /usr/bin/chromedriver 22 | RECORD_VIDEO: false 23 | GRID_URL: http://127.0.0.1:4444 24 | 25 | # Web_Kaifuku Settings (checkout https://github.com/RonnyPfannschmidt/webdriver_kaifuku) 26 | WEBKAIFUKU: 27 | webdriver: '@jinja {{ this.ui.browser if this.ui.browser in ["remote"] else this.ui.webdriver}}' 28 | webdriver_options: 29 | command_executor: '@jinja {{ this.ui.grid_url }}' 30 | desired_capabilities: 31 | browserName: chrome 32 | se:recordVideo: '@jinja {{ this.ui.record_video }}' 33 | se:screenResolution: 1920x1080 34 | se:maxduration: 5400 35 | se:idleTimeout: 5000 36 | chromeOptions: 37 | args: 38 | - disable-web-security 39 | - ignore-certificate-errors 40 | prefs: 41 | download.prompt_for_download: false 42 | 43 | -------------------------------------------------------------------------------- /conf/upgrade.yaml.template: -------------------------------------------------------------------------------- 1 | UPGRADE: 2 | # Base version of the Satellite, Capsule. 3 | FROM_VERSION: '6.16' 4 | # Target version of the Satellite, Capsule. 5 | TO_VERSION: '6.17' 6 | # Satellite, Capsule hosts RHEL operating system version. 7 | OS: rhel9 8 | # The job template Broker should use to upgrade a Satellite 9 | SATELLITE_UPGRADE_JOB_TEMPLATE: satellite-upgrade 10 | # Capsule's activation key will only be available when we spawn the VM using upgrade template. 11 | CAPSULE_AK: 12 | RHEL8: rhel8_capsule_ak 13 | RHEL9: rhel9_capsule_ak 14 | -------------------------------------------------------------------------------- /conf/vmware.yaml.template: -------------------------------------------------------------------------------- 1 | VMWARE: 2 | # VMware to be added as a compute resource 3 | # VCENTER: vmware vcenter URL 4 | VCENTER7: 5 | HOSTNAME: 6 | HYPERVISOR: 7 | # mac_address: Mac address of the vm_name 8 | MAC_ADDRESS: 9 | VCENTER8: 10 | HOSTNAME: 11 | HYPERVISOR: 12 | # mac_address: Mac address of the vm_name 13 | MAC_ADDRESS: 14 | # USERNAME: Login for vmware 15 | USERNAME: 16 | # PASSWORD: Password for vmware 17 | PASSWORD: 18 | # DATACENTER: vmware datacenter 19 | DATACENTER: 20 | # CLUSTER: vmware cluster 21 | CLUSTER: 22 | # DATASTORE: vmware datastore 23 | DATASTORE: 24 | # datastore_cluster: storage datastore cluster 25 | DATASTORE_CLUSTER: 26 | # VM_NAME: Name of VM to power On/Off & delete 27 | VM_NAME: 28 | # VMware Compute resource image data 29 | # IMAGE_OS: Operating system of the image 30 | IMAGE_OS: 31 | # IMAGE_ARCH: Architecture of the image 32 | IMAGE_ARCH: 33 | # IMAGE_USERNAME: Login to the image 34 | IMAGE_USERNAME: 35 | # IMAGE_PASSWORD: Password to the image 36 | IMAGE_PASSWORD: 37 | # IMAGE_NAME: Image name on the external provider 38 | IMAGE_NAME: 39 | -------------------------------------------------------------------------------- /docs/features/decorators.rst: -------------------------------------------------------------------------------- 1 | Decorators 2 | ========== 3 | 4 | This section explains Robottelo decorators. 5 | 6 | .. contents:: 7 | 8 | Modules 9 | ------- 10 | 11 | Robottelo decorators are located under 12 | :doc:`decorator package `. Most of them are used to 13 | control if a test must be skipped or executed accordingly with specific 14 | configurations. 15 | 16 | 17 | cacheable 18 | --------- 19 | 20 | ``cacheable`` makes an optional object cache available. This is used when creating factory objects for CLI tests. For example:: 21 | 22 | from robottelo.utils.decorators import cacheable 23 | 24 | @cacheable 25 | def make_role(options=None): 26 | """create a role using ``hammer role create``""" 27 | -------------------------------------------------------------------------------- /docs/features/index.rst: -------------------------------------------------------------------------------- 1 | Features 2 | ======== 3 | 4 | This is Robottelo Features documentation. It contains a high level explanation 5 | about its capabilities. 6 | 7 | .. toctree:: 8 | :maxdepth: 1 9 | 10 | commands 11 | decorators 12 | ssh 13 | -------------------------------------------------------------------------------- /docs/features/ssh.rst: -------------------------------------------------------------------------------- 1 | SSH (Secure SHell) 2 | ================== 3 | 4 | This section explains Robottelo's ssh module. 5 | 6 | .. contents:: 7 | 8 | Introduction 9 | ------------ 10 | 11 | Robottelo uses ssh extensively to access remote servers. 12 | Functions from ``robottello.utils.ssh`` make ssh access easier and are 13 | explained on next sections. 14 | 15 | Main Functions 16 | -------------- 17 | 18 | ``command`` is the main function of ssh module. 19 | Its full signature is:: 20 | 21 | def command(cmd, hostname=None, output_format=None, username=None, 22 | password=None, key_filename=None, timeout=10): 23 | """Executes SSH command(s) on remote hostname.""" 24 | 25 | Most of parameters can be read from ``conf/server.yaml`` file. 26 | So in a properly configured project commands can be easily executed on host. 27 | The function returns a result object containing the attributes: stdout, stderr, and status. 28 | The following code was executed to generate the example of first section of 29 | this document:: 30 | 31 | >>> from robottelo.utils import ssh 32 | >>> print(ssh.command('cat /etc/redhat-release')) 33 | Red Hat Enterprise Linux Server release 7.2 (Maipo) 34 | 35 | Helper Functions 36 | ---------------- 37 | 38 | The module provide some helper functions which use ``command`` internally 39 | for common ssh operations: 40 | 41 | - **add_authorized_key**: Add public key to remote authorized keys; 42 | - **is_ssh_pub_key**: Validate public key. 43 | -------------------------------------------------------------------------------- /docs/reviewing_PRs.rst: -------------------------------------------------------------------------------- 1 | 2 | 3 | Reviewing PRs 4 | ============= 5 | 6 | Ensure commits are squashed. 7 | 8 | Thoroughly review each change for errors or departures from the **Robottelo** 9 | :doc:`code standards `. 10 | 11 | If you note something that should be changed, or want clarification, add a 12 | comment to the line of code or the PR as a whole. 13 | 14 | If tests were added, ensure the PR includes the results or simply a message 15 | stating *"All tests passed."* or *"Unable to run tests at this time due to 16 | _____."* 17 | 18 | **Don't merge** unless there have been two ACKs. 19 | 20 | **Don't merge** unless the PR passes the Travis CI build. 21 | 22 | Once all the above criteria have been met, and the author has completed all 23 | changes, then you may merge. 24 | 25 | 26 | ToDo 27 | ---- 28 | Elaborate on the process. 29 | -------------------------------------------------------------------------------- /logging.yaml: -------------------------------------------------------------------------------- 1 | # Not processed by dynaconf, used directly by robottelo.logging for logzero config 2 | robottelo: 3 | level: WARNING 4 | fileLevel: DEBUG 5 | collection: 6 | level: INFO 7 | fileLevel: INFO 8 | config: 9 | level: ERROR 10 | fileLevel: INFO 11 | nailgun: 12 | level: ERROR 13 | fileLevel: DEBUG 14 | airgun: 15 | level: ERROR 16 | fileLevel: DEBUG 17 | widgetastic_null: 18 | level: ERROR 19 | fileLevel: DEBUG 20 | navmazing_null: 21 | level: ERROR 22 | fileLevel: DEBUG 23 | robozilla: 24 | level: ERROR 25 | fileLevel: DEBUG 26 | broker: 27 | level: WARNING 28 | fileLevel: DEBUG 29 | manifester: 30 | level: INFO 31 | fileLevel: DEBUG 32 | other: 33 | fileLevel: INFO 34 | -------------------------------------------------------------------------------- /manage.yml: -------------------------------------------------------------------------------- 1 | project_name: Robottelo 2 | help_text: This is the {project_name} interactive shell 3 | 4 | # interactive shell 5 | shell: 6 | ipython_auto_reload: true 7 | auto_import: 8 | display: true 9 | objects: 10 | robottelo.config.settings: 11 | as: settings 12 | init: configure 13 | nailgun.entities: 14 | as: entities 15 | nailgun: 16 | as: 17 | - ng 18 | - nailgun 19 | robottelo: 20 | as: 21 | - rt 22 | - robottelo 23 | submodules: true 24 | banner: 25 | enabled: true 26 | message: Welcome to {project_name} Interactive shell 27 | readline_enabled: false 28 | 29 | # commands 30 | 31 | groups: 32 | - ui: 33 | short_help: Commands to interactively browse UI 34 | help_text: | 35 | Commands to interactively browse UI. 36 | 37 | inline_commands: [] 38 | -------------------------------------------------------------------------------- /pytest_fixtures/component/acs.py: -------------------------------------------------------------------------------- 1 | # Alternate Content Sources fixtures 2 | import pytest 3 | 4 | from robottelo.constants.repos import CUSTOM_FILE_REPO, CUSTOM_RPM_REPO 5 | 6 | 7 | @pytest.fixture(scope='module') 8 | def module_yum_repo(module_target_sat, module_org): 9 | product = module_target_sat.api.Product(organization=module_org).create() 10 | repo = module_target_sat.api.Repository( 11 | product=product, content_type='yum', url=CUSTOM_RPM_REPO 12 | ).create() 13 | repo.sync() 14 | return repo 15 | 16 | 17 | @pytest.fixture(scope='module') 18 | def module_file_repo(module_target_sat, module_org): 19 | product = module_target_sat.api.Product(organization=module_org).create() 20 | repo = module_target_sat.api.Repository( 21 | product=product, content_type='file', url=CUSTOM_FILE_REPO 22 | ).create() 23 | repo.sync() 24 | return repo 25 | -------------------------------------------------------------------------------- /pytest_fixtures/component/ansible.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from robottelo.cli.ansible import Ansible 4 | 5 | 6 | @pytest.fixture(scope="session") 7 | def import_ansible_roles(default_smart_proxy): 8 | """Import ansible roles to default_smart_proxy for tests""" 9 | Ansible.roles_import({'proxy-id': default_smart_proxy.id}) 10 | Ansible.variables_import({'proxy-id': default_smart_proxy.id}) 11 | -------------------------------------------------------------------------------- /pytest_fixtures/component/architecture.py: -------------------------------------------------------------------------------- 1 | # Architecture Fixtures 2 | import pytest 3 | 4 | from robottelo.constants import DEFAULT_ARCHITECTURE 5 | 6 | 7 | @pytest.fixture(scope='session') 8 | def default_architecture(session_target_sat): 9 | return ( 10 | session_target_sat.api.Architecture() 11 | .search(query={'search': f'name="{DEFAULT_ARCHITECTURE}"'})[0] 12 | .read() 13 | ) 14 | 15 | 16 | @pytest.fixture(scope='session') 17 | def session_puppet_default_architecture(session_puppet_enabled_sat): 18 | return ( 19 | session_puppet_enabled_sat.api.Architecture() 20 | .search(query={'search': f'name="{DEFAULT_ARCHITECTURE}"'})[0] 21 | .read() 22 | ) 23 | 24 | 25 | @pytest.fixture(scope='module') 26 | def module_architecture(module_target_sat): 27 | return module_target_sat.api.Architecture().create() 28 | -------------------------------------------------------------------------------- /pytest_fixtures/component/computeprofile.py: -------------------------------------------------------------------------------- 1 | # Compute Profile Fixtures 2 | import pytest 3 | 4 | 5 | @pytest.fixture(scope='module') 6 | def module_compute_profile(module_target_sat): 7 | return module_target_sat.api.ComputeProfile().create() 8 | -------------------------------------------------------------------------------- /pytest_fixtures/component/discovery.py: -------------------------------------------------------------------------------- 1 | from fauxfactory import gen_string 2 | import pytest 3 | 4 | 5 | @pytest.fixture(scope='module') 6 | def module_discovery_hostgroup(module_org, module_location, module_target_sat): 7 | host = module_target_sat.api.Host(organization=module_org, location=module_location).create() 8 | return module_target_sat.api.HostGroup( 9 | organization=[module_org], 10 | location=[module_location], 11 | medium=host.medium, 12 | root_pass=gen_string('alpha'), 13 | operatingsystem=host.operatingsystem, 14 | ptable=host.ptable, 15 | domain=host.domain, 16 | architecture=host.architecture, 17 | ).create() 18 | 19 | 20 | @pytest.fixture(scope='module') 21 | def discovery_org(module_org, module_target_sat): 22 | discovery_org = module_target_sat.update_setting('discovery_organization', module_org.name) 23 | yield module_org 24 | module_target_sat.update_setting('discovery_organization', discovery_org) 25 | 26 | 27 | @pytest.fixture(scope='module') 28 | def discovery_location(module_location, module_target_sat): 29 | discovery_loc = module_target_sat.update_setting('discovery_location', module_location.name) 30 | yield module_location 31 | module_target_sat.update_setting('discovery_location', discovery_loc) 32 | -------------------------------------------------------------------------------- /pytest_fixtures/component/domain.py: -------------------------------------------------------------------------------- 1 | # Domain Fixtures 2 | import pytest 3 | 4 | 5 | @pytest.fixture(scope='session') 6 | def default_domain(session_target_sat, default_smart_proxy): 7 | domain_name = session_target_sat.hostname.partition('.')[-1] 8 | dom = session_target_sat.api.Domain().search(query={'search': f'name={domain_name}'})[0] 9 | if 'dns' in session_target_sat.get_features(): 10 | dom.dns = default_smart_proxy 11 | dom.update(['dns']) 12 | return session_target_sat.api.Domain(id=dom.id).read() 13 | 14 | 15 | @pytest.fixture(scope='module') 16 | def module_domain(module_target_sat, module_org, module_location): 17 | return module_target_sat.api.Domain( 18 | location=[module_location], organization=[module_org] 19 | ).create() 20 | -------------------------------------------------------------------------------- /pytest_fixtures/component/flatpak.py: -------------------------------------------------------------------------------- 1 | # Flatpak-related fixtures 2 | from box import Box 3 | import pytest 4 | 5 | from robottelo.config import settings 6 | from robottelo.constants import FLATPAK_REMOTES 7 | from robottelo.utils.datafactory import gen_string 8 | 9 | 10 | @pytest.fixture 11 | def function_flatpak_remote(request, target_sat, function_org): 12 | """Create flatpak remote, scan it and return both entities""" 13 | remote = FLATPAK_REMOTES[getattr(request, 'param', 'Fedora')] 14 | create_opts = { 15 | 'organization-id': function_org.id, 16 | 'url': remote['url'], 17 | 'name': gen_string('alpha'), 18 | } 19 | if remote['authenticated']: 20 | create_opts['username'] = settings.container_repo.registries.redhat.username 21 | create_opts['token'] = settings.container_repo.registries.redhat.password 22 | fr = target_sat.cli.FlatpakRemote().create(create_opts) 23 | 24 | target_sat.cli.FlatpakRemote().scan({'id': fr['id']}) 25 | scanned_repos = target_sat.cli.FlatpakRemote().repository_list({'flatpak-remote-id': fr['id']}) 26 | assert len(scanned_repos), 'No repositories scanned' 27 | 28 | return Box(remote=fr, repos=scanned_repos) 29 | -------------------------------------------------------------------------------- /pytest_fixtures/component/global_params.py: -------------------------------------------------------------------------------- 1 | # Settings Fixtures 2 | import pytest 3 | 4 | 5 | @pytest.fixture 6 | def multi_global_param_update(request, target_sat): 7 | """ 8 | This fixture is used to alter multiple global parameters in one batch. 9 | """ 10 | key_vals = request.param 11 | param_objects = [] 12 | for key_val in key_vals: 13 | param, new_value = tuple(key_val.split('=')) if '=' in key_val else (key_val, None) 14 | existing_params = target_sat.api.CommonParameter().search(query={'search': f'name={param}'}) 15 | if len(existing_params) > 0: 16 | assert len(existing_params) == 1, 'Unexpected number of parameters returned' 17 | param_object = existing_params[0] 18 | cleanup = False 19 | default_param_value = param_object.value 20 | else: 21 | param_object = target_sat.api.CommonParameter(name=param, value=new_value).create() 22 | cleanup = True 23 | default_param_value = new_value 24 | param_objects.append( 25 | {'object': param_object, 'default': default_param_value, 'cleanup': cleanup} 26 | ) 27 | yield [item['object'] for item in param_objects] 28 | for item in param_objects: 29 | if item['cleanup']: 30 | item['object'].delete() 31 | else: 32 | item['object'].value = item['default'] 33 | item['object'].update({'value'}) 34 | -------------------------------------------------------------------------------- /pytest_fixtures/component/hostgroup.py: -------------------------------------------------------------------------------- 1 | # Hostgroup Fixtures 2 | import pytest 3 | from requests.exceptions import HTTPError 4 | 5 | from robottelo.logging import logger 6 | 7 | 8 | @pytest.fixture(scope='module') 9 | def module_hostgroup(module_target_sat): 10 | return module_target_sat.api.HostGroup().create() 11 | 12 | 13 | @pytest.fixture(scope='class') 14 | def class_hostgroup(class_target_sat, class_org, class_location): 15 | """Create a hostgroup linked to specific org and location created at the class scope""" 16 | hostgroup = class_target_sat.api.HostGroup( 17 | organization=[class_org], location=[class_location] 18 | ).create() 19 | yield hostgroup 20 | try: 21 | hostgroup.delete() 22 | except HTTPError: 23 | logger.exception('Exception while deleting class scope hostgroup entity in teardown') 24 | -------------------------------------------------------------------------------- /pytest_fixtures/component/lce.py: -------------------------------------------------------------------------------- 1 | # Lifecycle Environment Fixtures 2 | import pytest 3 | 4 | from robottelo.constants import ENVIRONMENT 5 | 6 | 7 | @pytest.fixture(scope='session') 8 | def default_lce(session_target_sat): 9 | return session_target_sat.api.LifecycleEnvironment().search( 10 | query={'search': f'name="{ENVIRONMENT}"'} 11 | )[0] 12 | 13 | 14 | @pytest.fixture(scope='module') 15 | def module_lce(module_org, module_target_sat): 16 | return module_target_sat.api.LifecycleEnvironment(organization=module_org).create() 17 | 18 | 19 | @pytest.fixture 20 | def function_lce(function_org, target_sat): 21 | return target_sat.api.LifecycleEnvironment(organization=function_org).create() 22 | 23 | 24 | @pytest.fixture(scope='module') 25 | def module_lce_library(module_org, module_target_sat): 26 | """Returns the Library lifecycle environment from chosen organization""" 27 | return ( 28 | module_target_sat.api.LifecycleEnvironment() 29 | .search(query={'search': f'name={ENVIRONMENT} and organization_id={module_org.id}'})[0] 30 | .read() 31 | ) 32 | 33 | 34 | @pytest.fixture 35 | def function_lce_library(function_org, target_sat): 36 | """Returns the Library lifecycle environment from chosen organization""" 37 | return ( 38 | target_sat.api.LifecycleEnvironment() 39 | .search(query={'search': f'name={ENVIRONMENT} and organization_id={function_org.id}'})[0] 40 | .read() 41 | ) 42 | -------------------------------------------------------------------------------- /pytest_fixtures/component/os.py: -------------------------------------------------------------------------------- 1 | # Operating System Fixtures 2 | import pytest 3 | 4 | from robottelo.config import settings 5 | 6 | 7 | @pytest.fixture(scope='session') 8 | def default_os( 9 | default_architecture, 10 | default_partitiontable, 11 | default_pxetemplate, 12 | session_target_sat, 13 | ): 14 | """Returns an Operating System entity read from searching for supportability.content_host.default_os_name""" 15 | search_string = f'name="{settings.supportability.content_hosts.default_os_name}"' 16 | 17 | try: 18 | os = ( 19 | session_target_sat.api.OperatingSystem() 20 | .search(query={'search': search_string})[0] 21 | .read() 22 | ) 23 | except IndexError as e: 24 | raise RuntimeError(f"Could not find operating system for '{search_string}'") from e 25 | 26 | os.architecture.append(default_architecture) 27 | os.ptable.append(default_partitiontable) 28 | os.provisioning_template.append(default_pxetemplate) 29 | os.update(['architecture', 'ptable', 'provisioning_template']) 30 | 31 | return session_target_sat.api.OperatingSystem(id=os.id).read() 32 | 33 | 34 | @pytest.fixture(scope='module') 35 | def module_os(module_target_sat): 36 | return module_target_sat.api.OperatingSystem().create() 37 | 38 | 39 | @pytest.fixture(scope='module') 40 | def os_path(default_os): 41 | # Check what OS was found to use correct media 42 | if default_os.major == "6": 43 | os_distr_url = settings.repos.rhel6_os 44 | elif default_os.major == "7": 45 | os_distr_url = settings.repos.rhel7_os 46 | elif default_os.major == "8": 47 | os_distr_url = settings.repos.rhel8_os.baseos 48 | elif default_os.major == "9": 49 | os_distr_url = settings.repos.rhel9_os.baseos 50 | else: 51 | pytest.fail('Proposed RHEL version is not supported') 52 | return os_distr_url 53 | -------------------------------------------------------------------------------- /pytest_fixtures/component/partition_table.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from robottelo.constants import DEFAULT_PTABLE 4 | 5 | 6 | @pytest.fixture(scope='session') 7 | def default_partition_table(session_target_sat): 8 | # Get the Partition table ID 9 | return session_target_sat.api.PartitionTable().search( 10 | query={'search': f'name="{DEFAULT_PTABLE}"'} 11 | )[0] 12 | -------------------------------------------------------------------------------- /pytest_fixtures/component/provision_libvirt.py: -------------------------------------------------------------------------------- 1 | # Compute resource - Libvirt entities 2 | import pytest 3 | 4 | 5 | @pytest.fixture(scope='module') 6 | def module_cr_libvirt(module_target_sat, module_org, module_location): 7 | return module_target_sat.api.LibvirtComputeResource( 8 | organization=[module_org], location=[module_location] 9 | ).create() 10 | 11 | 12 | @pytest.fixture(scope='module') 13 | def module_libvirt_image(module_target_sat, module_cr_libvirt): 14 | return module_target_sat.api.Image(compute_resource=module_cr_libvirt).create() 15 | 16 | 17 | @pytest.fixture(scope='module') 18 | def module_libvirt_provisioning_sat(module_provisioning_sat): 19 | # Configure Libvirt CR for provisioning 20 | module_provisioning_sat.sat.configure_libvirt_cr() 21 | return module_provisioning_sat 22 | -------------------------------------------------------------------------------- /pytest_fixtures/component/smartproxy.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from robottelo.config import settings 4 | 5 | 6 | @pytest.fixture(scope='session') 7 | def default_smart_proxy(session_target_sat): 8 | smart_proxy = ( 9 | session_target_sat.api.SmartProxy() 10 | .search(query={'search': f'name={session_target_sat.hostname}'})[0] 11 | .read() 12 | ) 13 | return session_target_sat.api.SmartProxy(id=smart_proxy.id).read() 14 | 15 | 16 | @pytest.fixture(scope='module') 17 | def module_fake_proxy(request, module_target_sat): 18 | """Create a Proxy and register the cleanup function""" 19 | port_pool_range = settings.fake_capsules.port_range 20 | if module_target_sat.execute(f'semanage port -l | grep {port_pool_range}').status != 0: 21 | module_target_sat.execute(f'semanage port -a -t websm_port_t -p tcp {port_pool_range}') 22 | proxy = module_target_sat.cli_factory.make_proxy() 23 | 24 | @request.addfinalizer 25 | def _cleanup(): 26 | module_target_sat.cli.Proxy.delete({'id': proxy['id']}) 27 | 28 | return proxy 29 | -------------------------------------------------------------------------------- /pytest_fixtures/component/subnet.py: -------------------------------------------------------------------------------- 1 | # Subnet Fixtures 2 | import pytest 3 | 4 | 5 | @pytest.fixture(scope='module') 6 | def module_default_subnet(module_target_sat, module_org, module_location): 7 | return module_target_sat.api.Subnet( 8 | location=[module_location], organization=[module_org] 9 | ).create() 10 | -------------------------------------------------------------------------------- /pytest_fixtures/component/subscription.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from robottelo.constants import DEFAULT_SUBSCRIPTION_NAME 4 | 5 | 6 | @pytest.fixture(scope='module') 7 | def default_subscription(module_target_sat, module_sca_manifest_org): 8 | subscription = module_target_sat.api.Subscription( 9 | organization=module_sca_manifest_org.id 10 | ).search(query={'search': f'name="{DEFAULT_SUBSCRIPTION_NAME}"'}) 11 | assert len(subscription) 12 | return subscription[0] 13 | 14 | 15 | @pytest.fixture(scope='module') 16 | def module_subscribe_satellite(module_target_sat): 17 | """Subscribe Satellite to CDN""" 18 | module_target_sat.register_to_cdn() 19 | # Enable extras repo if os_version is RHEL7 20 | if module_target_sat.os_version.major < 8: 21 | module_target_sat.enable_repo( 22 | f'rhel-{module_target_sat.os_version.major}-server-extras-rpms', force=True 23 | ) 24 | yield 25 | module_target_sat.unregister() 26 | 27 | 28 | @pytest.fixture(scope='class') 29 | def class_subscribe_satellite(class_target_sat): 30 | """Subscribe Satellite to CDN""" 31 | class_target_sat.register_to_cdn() 32 | # Enable extras repo if os_version is RHEL7 33 | if class_target_sat.os_version.major < 8: 34 | class_target_sat.enable_repo( 35 | f'rhel-{class_target_sat.os_version.major}-server-extras-rpms', force=True 36 | ) 37 | yield class_target_sat 38 | class_target_sat.unregister() 39 | 40 | 41 | @pytest.fixture 42 | def subscribe_satellite(target_sat): 43 | """Subscribe Satellite to CDN""" 44 | target_sat.register_to_cdn() 45 | # Enable extras repo if os_version is RHEL7 46 | if target_sat.os_version.major < 8: 47 | target_sat.enable_repo(f'rhel-{target_sat.os_version.major}-server-extras-rpms', force=True) 48 | yield 49 | target_sat.unregister() 50 | -------------------------------------------------------------------------------- /pytest_fixtures/component/usage_report.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | from fauxfactory import gen_string 4 | import pytest 5 | import yaml 6 | 7 | from robottelo.constants import DataFile 8 | 9 | 10 | def process_keys(keys): 11 | # get unique highest level items from report keys 12 | return set([key.split('|')[0] for key in keys]) 13 | 14 | 15 | @pytest.fixture(scope='module') 16 | def module_generate_report(module_target_sat): 17 | filename = f'usage_report-{datetime.timestamp(datetime.now())}-{gen_string("alphanumeric")}.yml' 18 | result = module_target_sat.execute(f'satellite-maintain report generate --output {filename}') 19 | assert result.status == 0, 'failed to generate report' 20 | return module_target_sat.load_remote_yaml_file(filename) 21 | 22 | 23 | @pytest.fixture(scope='module') 24 | def module_report_keys(module_generate_report): 25 | return process_keys(module_generate_report.keys()) 26 | 27 | 28 | @pytest.fixture(scope='module') 29 | def module_expected_keys(): 30 | return process_keys(yaml.safe_load(DataFile.USAGE_REPORT_ITEMS.read_text()).keys()) 31 | -------------------------------------------------------------------------------- /pytest_fixtures/component/user.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.fixture 5 | def user_not_exists(request, target_sat): 6 | """Remove a user if it exists. Return whether changes have been applied.""" 7 | if users := target_sat.api.User().search(query={'search': f'login={request.param}'}): 8 | users[0].delete() 9 | return bool(users) 10 | -------------------------------------------------------------------------------- /pytest_fixtures/component/user_role.py: -------------------------------------------------------------------------------- 1 | from fauxfactory import gen_alphanumeric, gen_string 2 | import pytest 3 | 4 | 5 | @pytest.fixture(scope='class') 6 | def class_user_password(): 7 | """Generate a random password for a user, and capture it so a test has access to it""" 8 | return gen_alphanumeric() 9 | 10 | 11 | @pytest.fixture 12 | def function_role(target_sat): 13 | return target_sat.api.Role().create() 14 | 15 | 16 | @pytest.fixture(scope='module') 17 | def module_user(module_target_sat, module_org, module_location): 18 | return module_target_sat.api.User( 19 | organization=[module_org], location=[module_location] 20 | ).create() 21 | 22 | 23 | @pytest.fixture(scope='module') 24 | def default_viewer_role(module_target_sat, module_org, default_location): 25 | """Custom user with viewer role for tests validating visibility of entities or fields created 26 | by some other user. Created only when accessed, unlike `module_user`. 27 | """ 28 | viewer_role = module_target_sat.api.Role().search(query={'search': 'name="Viewer"'})[0] 29 | custom_password = gen_string('alphanumeric') 30 | custom_user = module_target_sat.api.User( 31 | admin=False, 32 | default_organization=module_org, 33 | location=[default_location], 34 | organization=[module_org], 35 | role=[viewer_role], 36 | password=custom_password, 37 | ).create() 38 | custom_user.password = custom_password 39 | return custom_user 40 | -------------------------------------------------------------------------------- /pytest_fixtures/core/reporting.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | from _pytest.junitxml import xml_key 4 | import pytest 5 | from xdist import get_xdist_worker_id 6 | 7 | from robottelo.config import setting_is_set, settings 8 | 9 | FMT_XUNIT_TIME = '%Y-%m-%dT%H:%M:%S' 10 | 11 | 12 | def pytest_report_header(config): 13 | """Called when pytest session starts""" 14 | messages = [] 15 | 16 | shared_function_enabled = 'OFF' 17 | scope = '' 18 | storage = 'file' 19 | if setting_is_set('shared_function'): 20 | if settings.shared_function.enabled: 21 | shared_function_enabled = 'ON' 22 | scope = settings.shared_function.scope 23 | if not scope: 24 | scope = '' 25 | storage = settings.shared_function.storage 26 | messages.append( 27 | f'shared_function enabled - {shared_function_enabled} - scope: {scope} - storage: {storage}' 28 | ) 29 | return messages 30 | 31 | 32 | def pytest_sessionstart(session): 33 | """Workaround for https://github.com/pytest-dev/pytest/issues/7767 34 | 35 | remove if resolved and set autouse=True for record_testsuite_timestamp_xml fixture 36 | """ 37 | if get_xdist_worker_id(session) == 'master' and session.config.pluginmanager.hasplugin( 38 | 'junitxml' 39 | ): 40 | xml = session.config._store.get(xml_key, None) 41 | if xml: 42 | xml.add_global_property( 43 | 'start_time', datetime.datetime.now(datetime.UTC).strftime(FMT_XUNIT_TIME) 44 | ) 45 | 46 | 47 | @pytest.fixture(autouse=False, scope='session') 48 | def record_testsuite_timestamp_xml(record_testsuite_property): 49 | now = datetime.datetime.now(datetime.UTC) 50 | record_testsuite_property('start_time', now.strftime(FMT_XUNIT_TIME)) 51 | -------------------------------------------------------------------------------- /pytest_fixtures/core/upgrade.py: -------------------------------------------------------------------------------- 1 | from broker import Broker 2 | import pytest 3 | 4 | from robottelo.hosts import Capsule 5 | from robottelo.logging import logger 6 | 7 | 8 | @pytest.fixture 9 | def dependent_scenario_name(request): 10 | """ 11 | This fixture is used to collect the dependent test case name. 12 | """ 13 | return [ 14 | mark.kwargs['depend_on'].__name__ 15 | for mark in request.node.own_markers 16 | if 'depend_on' in mark.kwargs 17 | ][0] 18 | 19 | 20 | @pytest.fixture(scope="session") 21 | def pre_configured_capsule(worker_id, session_target_sat): 22 | """ 23 | This fixture returns the Capsule object matching the pre-configured capsule 24 | 25 | This fixture assumes that the Capsule is already integrated with Satellite and 26 | the Capsule host is present in the broker inventory. 27 | """ 28 | inventory = {h.hostname for h in Broker().from_inventory()} 29 | capsules = {h.name for h in session_target_sat.api.Capsule().search()} 30 | logger.debug( 31 | f'Hosts in the inventory: {inventory}. Capsules attached to Satellite: {capsules}.' 32 | ) 33 | # do an intersection of both sets to just select those hosts that we have in the capsules 34 | # from that intersection take the Capsule that is not Satellite and return it 35 | intersect = inventory.intersection(capsules) 36 | intersect.discard(session_target_sat.hostname) 37 | logger.debug(f'Capsules found: {intersect}') 38 | assert len(intersect) == 1, "More than one Capsule found in the inventory" 39 | target_capsule = intersect.pop() 40 | host = Capsule.get_host_by_hostname(target_capsule) 41 | logger.info(f'xdist worker {worker_id} was assigned pre-configured Capsule {target_capsule}') 42 | return host 43 | -------------------------------------------------------------------------------- /pytest_plugins/auto_vault.py: -------------------------------------------------------------------------------- 1 | """Plugin enables pytest to notify and update the requirements""" 2 | 3 | from robottelo.utils.vault import Vault 4 | 5 | 6 | def pytest_addoption(parser): 7 | """Options to allow user to update the requirements""" 8 | with Vault() as vclient: 9 | vclient.login() 10 | -------------------------------------------------------------------------------- /pytest_plugins/disable_rp_params.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | 4 | @pytest.hookimpl(trylast=True) 5 | def pytest_configure(config): 6 | """Override Report Portal (RP) service objects attribute 7 | to prevent it from posting the parameter values of the tests. 8 | This is to make RP to correctly match and handle the test re-runs. 9 | 10 | We can remove this once we implement a compatible parametrization 11 | """ 12 | if hasattr(config, 'py_test_service'): 13 | config.py_test_service.rp_supports_parameters = False 14 | -------------------------------------------------------------------------------- /pytest_plugins/external_logging.py: -------------------------------------------------------------------------------- 1 | from robottelo.config import settings 2 | 3 | 4 | def pytest_addoption(parser): 5 | """Adds option for enabling external logging""" 6 | help_text = ''' 7 | Flag for enabling promtail on the spawned hosts. 8 | This is used for sending of the logs to the external Loki instance 9 | 10 | Usage: --external_logging 11 | ''' 12 | parser.addoption("--external-logging", action="store_true", default=False, help=help_text) 13 | 14 | 15 | def pytest_cmdline_main(config): 16 | if not config.getoption('external_logging', False): 17 | return 18 | settings.set('server.deploy_arguments.promtail_enable', True) 19 | settings.set('capsule.deploy_arguments.promtail_enable', True) 20 | ch = settings.content_host 21 | for os in [i for i in ch if isinstance(ch[i], dict) and ch[i].get('vm')]: 22 | ch[os]['vm']['promtail_enable'] = True 23 | # update the container env too, if available 24 | promtail_var = {'PROMTAIL_ENABLE': "True"} 25 | for os in [i for i in ch if isinstance(ch[i], dict) and ch[i].get('container')]: 26 | settings.set(f'content_host.{os}.container.environment', promtail_var) 27 | -------------------------------------------------------------------------------- /pytest_plugins/factory_collection.py: -------------------------------------------------------------------------------- 1 | from inspect import getmembers, isfunction 2 | 3 | 4 | def pytest_configure(config): 5 | """Register markers related to testimony tokens""" 6 | marker = 'factory_instance: Test uses a fresh satellite or Capsule instance deployed by broker' 7 | config.addinivalue_line("markers", marker) 8 | 9 | 10 | def pytest_collection_modifyitems(session, items, config): 11 | from pytest_fixtures.core import sat_cap_factory 12 | 13 | factory_fixture_names = [m[0] for m in getmembers(sat_cap_factory, isfunction)] 14 | for item in items: 15 | itemfixtures = [ 16 | itm for itm in item.fixturenames if itm not in ('satellite_factory', 'capsule_factory') 17 | ] 18 | has_factoryfixture = set(itemfixtures).intersection(set(factory_fixture_names)) 19 | if has_factoryfixture: 20 | item.add_marker('factory_instance') 21 | -------------------------------------------------------------------------------- /pytest_plugins/fspath_plugins.py: -------------------------------------------------------------------------------- 1 | # File System related Collection Modification/Addition to test cases 2 | import re 3 | 4 | 5 | def pytest_collection_modifyitems(session, items, config): 6 | endpoint_regex = re.compile( 7 | # To match the endpoint in the fspath 8 | r'^.*/(?P\S*)/test_.*.py$', 9 | re.IGNORECASE, 10 | ) 11 | for item in items: 12 | if item.nodeid.startswith('tests/robottelo/') or item.nodeid.startswith('tests/upgrades/'): 13 | continue 14 | 15 | if endpoints := endpoint_regex.findall(item.location[0]): 16 | item.user_properties.append(('endpoint', endpoints[0])) 17 | -------------------------------------------------------------------------------- /pytest_plugins/infra_dependent_markers.py: -------------------------------------------------------------------------------- 1 | # Custom infra dependent markers for selection and deselection of tests 2 | 3 | 4 | def pytest_configure(config): 5 | """Register custom markers to avoid warnings.""" 6 | markers = [ 7 | "on_premises_provisioning: Tests that runs on on_premises Providers", 8 | "ipv6_provisioning: Tests for IPv6 provisioning" 9 | "libvirt_discovery: Tests depends on Libvirt Provider for discovery", 10 | "external_auth: External Authentication tests", 11 | "vlan_networking: Tests depends on static predefined vlan networking etc", 12 | ] 13 | for marker in markers: 14 | config.addinivalue_line("markers", marker) 15 | -------------------------------------------------------------------------------- /pytest_plugins/settings_skip.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from robottelo.config import setting_is_set, settings 4 | 5 | 6 | def pytest_configure(config): 7 | """Register markers related to testimony tokens""" 8 | config.addinivalue_line( 9 | 'markers', 10 | 'skip_if_not_set: List settings sections that must be set for the test to run. ' 11 | 'If settings are missing, the test is skipped in setup.', 12 | ) 13 | 14 | 15 | def pytest_runtest_setup(item): 16 | """Skip in setup if settings mark isn't met 17 | 18 | settings validate method is used, so required fields are checked 19 | 20 | This will be getting updated before too long when dynaconf consolidation happens 21 | """ 22 | skip_marker = item.get_closest_marker('skip_if_not_set', None) 23 | if skip_marker and skip_marker.args: 24 | options_set = {arg.upper() for arg in skip_marker.args} 25 | settings_set = {key for key in settings if not key.endswith('_FOR_DYNACONF')} 26 | if not options_set.issubset(settings_set): 27 | invalid = options_set.difference(settings_set) 28 | raise ValueError( 29 | f'Feature(s): {invalid} not found. Available ones are: {settings_set}.' 30 | ) 31 | 32 | missing = [] 33 | for option in options_set: 34 | # Example: `settings.clients` 35 | if not setting_is_set(option): 36 | # List of all sections that are not fully configured 37 | missing.append(option) 38 | if missing: 39 | pytest.skip(f'Missing configuration for: {missing}.') 40 | -------------------------------------------------------------------------------- /requirements-optional.txt: -------------------------------------------------------------------------------- 1 | # For running tests and checking code quality using these modules. 2 | pytest-cov==6.1.1 3 | redis==6.2.0 4 | pre-commit==4.2.0 5 | ruff==0.11.12 6 | 7 | # For generating documentation. 8 | sphinx==8.2.3 9 | sphinx-autoapi==3.6.0 10 | 11 | # For 'manage' interactive shell 12 | manage==0.1.15 13 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # Version updates managed by dependabot 2 | 3 | apypie==0.7.1 4 | betelgeuse==1.11.0 5 | broker[docker,podman,hussh]==0.6.11 6 | cryptography==43.0.3 7 | deepdiff==8.5.0 8 | dynaconf[vault]==3.2.11 9 | fauxfactory==3.1.2 10 | jinja2==3.1.6 11 | manifester==0.2.10 12 | navmazing==1.3.0 13 | productmd==1.45 14 | pyotp==2.9.0 15 | python-box==7.3.2 16 | pytest==8.3.5 17 | pytest-order==1.3.0 18 | pytest-services==2.2.1 19 | pytest-mock==3.14.1 20 | pytest-reportportal==5.5.0 21 | pytest-xdist==3.6.1 22 | pytest-fixturecollection==0.1.2 23 | pytest-ibutsu==2.3.1 24 | PyYAML==6.0.2 25 | requests==2.32.3 26 | tenacity==9.1.2 27 | testimony==2.4.0 28 | wait-for==1.2.0 29 | wrapanapi==3.7.1 30 | 31 | # Get airgun, nailgun and upgrade from master 32 | airgun @ git+https://github.com/SatelliteQE/airgun.git@master#egg=airgun 33 | nailgun @ git+https://github.com/SatelliteQE/nailgun.git@master#egg=nailgun 34 | --editable . 35 | -------------------------------------------------------------------------------- /robottelo.yaml.sample: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | # Container registry and repo set information to use for container repo syncing. 4 | container_repo: 5 | multi_registry_test_configs: 6 | - label: registry1 7 | registry_url: https://registry2.example.com 8 | registry_username: # Username 9 | registry_password: #Token or password 10 | repos_to_sync: [repo1, repo1/x1, repo2/x4] # These really can be anything, just keep them small 11 | - label: registry2 12 | registry_url: https://registry3.example.com 13 | registry_username: #Username 14 | registry_password: #Password or token 15 | repos_to_sync: [repo2, repo3/x1, repo2/x4] # These really can be anything, just keep them small 16 | 17 | 18 | # RH Registry Token based auth 19 | long_pass_test_registry: 20 | label: rhregistry_tokenauth1 21 | registry_url: https://registry.redhat.io 22 | registry_username: # Username 23 | registry_password: #Token or password needs to be > 255 24 | repos_to_sync: [rhel7, rhel8/net-snmp, rhel7/etcd] # These really can be anything, just keep them small 25 | -------------------------------------------------------------------------------- /robottelo/__init__.py: -------------------------------------------------------------------------------- 1 | """This module contains helper code used by :mod:`tests.foreman` module. 2 | 3 | This module is subservient to :mod:`tests.foreman`, and exists solely for the 4 | sake of helping that module get its work done. For example, 5 | :mod:`tests.foreman.cli` relies upon :mod:`robottelo.cli`. More generally: 6 | code in :mod:`tests` calls code in :mod:`robottelo`, but not the other way 7 | around. 8 | 9 | """ 10 | -------------------------------------------------------------------------------- /robottelo/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/robottelo/cli/__init__.py -------------------------------------------------------------------------------- /robottelo/cli/admin.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer admin [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND Subcommand 7 | [ARG] ... Subcommand arguments 8 | 9 | Subcommands: 10 | logging Logging verbosity level setup 11 | 12 | Options: 13 | -h, --help Print help 14 | """ 15 | 16 | from robottelo.cli.base import Base 17 | 18 | 19 | class Admin(Base): 20 | """Administrative server-side tasks""" 21 | 22 | command_base = 'admin' 23 | 24 | @classmethod 25 | def logging(cls, options=None): 26 | """Logging verbosity level setup""" 27 | cls.command_sub = 'logging' 28 | return cls.execute(cls._construct_command(options), output_format='csv') 29 | -------------------------------------------------------------------------------- /robottelo/cli/architecture.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer architecture [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | add_operatingsystem Associate a resource 14 | create Create an architecture. 15 | delete Delete an architecture. 16 | info Show an architecture. 17 | list List all architectures. 18 | remove_operatingsystem Disassociate a resource 19 | update Update an architecture. 20 | """ 21 | 22 | from robottelo.cli.base import Base 23 | 24 | 25 | class Architecture(Base): 26 | """ 27 | Manipulates Foreman's architecture. 28 | """ 29 | 30 | command_base = 'architecture' 31 | -------------------------------------------------------------------------------- /robottelo/cli/bootdisk.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer bootdisk [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND Subcommand 9 | [ARG] ... Subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | generic Download generic image 14 | host Download host image 15 | subnet Download subnet generic image 16 | """ 17 | 18 | from robottelo.cli.base import Base 19 | 20 | 21 | class Bootdisk(Base): 22 | """Manipulates Bootdisk.""" 23 | 24 | command_base = 'bootdisk' 25 | 26 | @classmethod 27 | def generic(cls, options=None): 28 | """Download generic image""" 29 | cls.command_sub = 'generic' 30 | return cls.execute(cls._construct_command(options), output_format='json') 31 | 32 | @classmethod 33 | def host(cls, options=None): 34 | """Download host image""" 35 | cls.command_sub = 'host' 36 | return cls.execute(cls._construct_command(options), output_format='json') 37 | 38 | @classmethod 39 | def subnet(cls, options=None): 40 | """Download subnet generic image""" 41 | cls.command_sub = 'subnet' 42 | return cls.execute(cls._construct_command(options), output_format='json') 43 | -------------------------------------------------------------------------------- /robottelo/cli/computeprofile.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer compute-profile [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND Subcommand 7 | [ARG] ... Subcommand arguments 8 | 9 | Subcommands: 10 | create Create a compute profile 11 | delete Delete a compute profile 12 | info Show a compute profile 13 | list List of compute profiles 14 | update Update a compute profile 15 | values Create update and delete Compute profile values 16 | 17 | Options: 18 | -h, --help Print help 19 | Update a compute resource. 20 | """ 21 | 22 | from robottelo.cli.base import Base 23 | 24 | 25 | class ComputeProfile(Base): 26 | """ 27 | Manipulates Foreman's compute-profile. 28 | """ 29 | 30 | command_base = 'compute-profile' 31 | 32 | @classmethod 33 | def values_create(cls, options=None): 34 | """Create Compute profile values""" 35 | cls.command_sub = 'values create' 36 | return cls.execute(cls._construct_command(options), output_format='csv') 37 | -------------------------------------------------------------------------------- /robottelo/cli/content_credentials.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer content-credential [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a content credential 14 | delete Destroy a content credential 15 | info Show a content credential 16 | list List content credentials 17 | update Update a content credential 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class ContentCredential(Base): 24 | """ 25 | Manipulates Foreman's content credentials. 26 | """ 27 | 28 | command_base = 'content-credential' 29 | command_requires_org = True 30 | 31 | @classmethod 32 | def info(cls, options=None): 33 | """ 34 | Gets information for a content credential 35 | """ 36 | 37 | cls.command_sub = 'info' 38 | 39 | return cls.execute(cls._construct_command(options), output_format='json') 40 | -------------------------------------------------------------------------------- /robottelo/cli/content_import.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer content-import [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | library Imports a content archive to an organization's library 14 | lifecycle environment 15 | list View content view import histories 16 | version Imports a content archive to a content view version 17 | 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class ContentImport(Base): 24 | """ 25 | Import content to satellite 26 | """ 27 | 28 | command_base = 'content-import' 29 | command_requires_org = True 30 | 31 | @classmethod 32 | def list(cls, options=None): 33 | """ 34 | List previous imports 35 | """ 36 | cls.command_sub = 'list' 37 | return cls.execute(cls._construct_command(options), output_format='json') 38 | 39 | @classmethod 40 | def library(cls, options, timeout=None): 41 | """ 42 | Make library import 43 | """ 44 | cls.command_sub = 'library' 45 | return cls.execute(cls._construct_command(options), output_format='json', timeout=timeout) 46 | 47 | @classmethod 48 | def version(cls, options, timeout=None): 49 | """ 50 | Make CV version export 51 | """ 52 | cls.command_sub = 'version' 53 | return cls.execute(cls._construct_command(options), output_format='json', timeout=timeout) 54 | 55 | @classmethod 56 | def repository(cls, options, timeout=None): 57 | """ 58 | Make a repository import 59 | """ 60 | cls.command_sub = 'repository' 61 | return cls.execute(cls._construct_command(options), output_format='json', timeout=timeout) 62 | -------------------------------------------------------------------------------- /robottelo/cli/defaults.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer defaults [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | add Add a default parameter to config 14 | delete Delete a default param 15 | list List all the default parameters 16 | providers List all the providers 17 | """ 18 | 19 | from robottelo.cli.base import Base 20 | 21 | 22 | class Defaults(Base): 23 | """Manipulates Defaults entity""" 24 | 25 | command_base = 'defaults' 26 | 27 | @classmethod 28 | def add(cls, options=None): 29 | """Add parameter to config 30 | Usage:: 31 | 32 | hammer defaults add [OPTIONS] 33 | 34 | Options:: 35 | 36 | --param-name OPTION_NAME The name of the default option 37 | (e.g. organization_id). 38 | --param-value OPTION_VALUE The value for the default option 39 | --provider OPTION_PROVIDER The name of the provider providing 40 | the value. For list available 41 | providers see `hammer defaults 42 | providers`. 43 | """ 44 | cls.command_sub = 'add' 45 | return cls.execute(cls._construct_command(options)) 46 | 47 | @classmethod 48 | def delete(cls, options=None): 49 | """Delete parameter from config 50 | Usage:: 51 | 52 | hammer defaults delete [OPTIONS] 53 | 54 | Options:: 55 | 56 | --param-name OPTION_NAME The name of the default option 57 | """ 58 | cls.command_sub = 'delete' 59 | return cls.execute(cls._construct_command(options)) 60 | -------------------------------------------------------------------------------- /robottelo/cli/discoveryrule.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer discovery-rule [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a discovery rule 14 | delete Delete a rule 15 | info Show a discovery rule 16 | list List all discovery rules 17 | update Update a rule 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class DiscoveryRule(Base): 24 | """Manipulates Discovery Rules""" 25 | 26 | command_base = 'discovery-rule' 27 | -------------------------------------------------------------------------------- /robottelo/cli/domain.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer domain [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a domain. 14 | delete Delete a domain. 15 | delete_parameter Delete parameter for a domain. 16 | info Show a domain. 17 | list List of domains 18 | set_parameter Create or update parameter for a domain. 19 | update Update a domain. 20 | """ 21 | 22 | from robottelo.cli.base import Base 23 | 24 | 25 | class Domain(Base): 26 | """ 27 | Manipulates Foreman's domains. 28 | """ 29 | 30 | command_base = 'domain' 31 | -------------------------------------------------------------------------------- /robottelo/cli/environment.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer environment [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create an environment 14 | delete Delete an environment 15 | info Show an environment 16 | list List all environments 17 | sc-params List all smart class parameters 18 | update Update an environment 19 | """ 20 | 21 | from robottelo.cli.base import Base 22 | 23 | 24 | class Environment(Base): 25 | """Manipulates Foreman's environments.""" 26 | 27 | command_base = 'puppet-environment' 28 | 29 | @classmethod 30 | def sc_params(cls, options=None): 31 | """List all smart class parameters.""" 32 | cls.command_sub = 'sc-params' 33 | return cls.execute(cls._construct_command(options), output_format='json') 34 | -------------------------------------------------------------------------------- /robottelo/cli/erratum.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer erratum [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | info Show an erratum 14 | list List errata 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class Erratum(Base): 21 | """Manipulates Foreman's erratum.""" 22 | 23 | command_base = 'erratum' 24 | -------------------------------------------------------------------------------- /robottelo/cli/fact.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer fact [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | list List all fact values. 14 | """ 15 | 16 | from robottelo.cli.base import Base 17 | 18 | 19 | class Fact(Base): 20 | """ 21 | Searches Foreman's facts. 22 | """ 23 | 24 | command_base = 'fact' 25 | -------------------------------------------------------------------------------- /robottelo/cli/file.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer file [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | info Show a file 14 | list List files 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class File(Base): 21 | """ 22 | Manipulates files command. 23 | """ 24 | 25 | command_base = 'file' 26 | -------------------------------------------------------------------------------- /robottelo/cli/filter.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | hammer filter [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters:: 6 | 7 | SUBCOMMAND subcommand 8 | [ARG] ... subcommand arguments 9 | 10 | Subcommands:: 11 | 12 | available-permissions List all permissions 13 | available-resources List available resource types. 14 | create Create a filter 15 | delete Delete a filter 16 | info Show a filter 17 | list List all filters 18 | update Update a filter 19 | """ 20 | 21 | from robottelo.cli.base import Base 22 | 23 | 24 | class Filter(Base): 25 | """Manipulates Katello's filter command.""" 26 | 27 | command_base = 'filter' 28 | 29 | @classmethod 30 | def available_permissions(cls, options=None): 31 | cls.command_sub = 'available-permissions' 32 | return cls.execute(cls._construct_command(options), output_format='csv') 33 | -------------------------------------------------------------------------------- /robottelo/cli/globalparam.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer global-parameter [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | delete Delete a common_parameter 14 | list List all common parameters. 15 | set Set a global parameter. 16 | """ 17 | 18 | from robottelo.cli.base import Base 19 | 20 | 21 | class GlobalParameter(Base): 22 | """ 23 | Manipulates Foreman's global parameters. 24 | """ 25 | 26 | command_base = 'global-parameter' 27 | 28 | @classmethod 29 | def set(cls, options=None): 30 | """Set global parameter""" 31 | cls.command_sub = 'set' 32 | return cls.execute(cls._construct_command(options)) 33 | -------------------------------------------------------------------------------- /robottelo/cli/gpgkey.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer gpg [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a GPG Key 14 | delete Destroy a GPG Key 15 | info Show a GPG key 16 | list List GPG Keys 17 | update Update a GPG Key 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class GPGKey(Base): 24 | """ 25 | Manipulates Foreman's GPG Keys. 26 | """ 27 | 28 | command_base = 'gpg' 29 | command_requires_org = True 30 | 31 | @classmethod 32 | def info(cls, options=None): 33 | """ 34 | Gets information for GPG Key 35 | """ 36 | 37 | cls.command_sub = 'info' 38 | 39 | return cls.execute(cls._construct_command(options), output_format='json') 40 | -------------------------------------------------------------------------------- /robottelo/cli/host_registration.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer host-registration [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND Subcommand 7 | [ARG] ... Subcommand arguments 8 | 9 | Subcommands: 10 | generate-command Generate global registration command 11 | 12 | Options: 13 | -h, --help Print help 14 | 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class HostRegistration(Base): 21 | """Manipulates hammer host-registration command""" 22 | 23 | command_base = 'host-registration' 24 | 25 | @classmethod 26 | def generate_command(cls, options): 27 | """Generate global registration command""" 28 | cls.command_sub = 'generate-command' 29 | return cls.execute(cls._construct_command(options)) 30 | -------------------------------------------------------------------------------- /robottelo/cli/http_proxy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | http-proxy [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND Subcommand 7 | [ARG] ... Subcommand arguments 8 | 9 | Subcommands: 10 | create Create an HTTP Proxy 11 | delete Delete an HTTP Proxy 12 | info Show an HTTP Proxy 13 | list List of HTTP Proxies 14 | update Update an HTTP Proxy 15 | 16 | Options: 17 | -h, --help Print help 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class HttpProxy(Base): 24 | """Manipulates http-proxy command.""" 25 | 26 | command_base = 'http-proxy' 27 | -------------------------------------------------------------------------------- /robottelo/cli/insights.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer insights [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND Subcommand 7 | [ARG] ... Subcommand arguments 8 | 9 | Subcommands: 10 | cloud-connector Manage cloud connector setup 11 | inventory Manage inventory related operations 12 | 13 | Options: 14 | -h, --help Print help 15 | 16 | """ 17 | 18 | from robottelo.cli.base import Base 19 | 20 | 21 | class Insights(Base): 22 | """ 23 | Exports content from satellite 24 | """ 25 | 26 | command_base = 'insights' 27 | command_requires_org = True 28 | 29 | @classmethod 30 | def inventory_sync(cls, options): 31 | """ 32 | Start inventory status sync 33 | """ 34 | cls.command_sub = 'inventory sync' 35 | return cls.execute(cls._construct_command(options)) 36 | 37 | @classmethod 38 | def inventory_generate_report(cls, options): 39 | """ 40 | Start new report generation 41 | """ 42 | cls.command_sub = 'inventory generate-report' 43 | return cls.execute(cls._construct_command(options)) 44 | 45 | @classmethod 46 | def inventory_download_report(cls, options): 47 | """ 48 | Download the last generated report 49 | """ 50 | cls.command_sub = 'inventory download-report' 51 | return cls.execute(cls._construct_command(options)) 52 | 53 | @classmethod 54 | def cloud_connector_enable(cls, options=None): 55 | """ 56 | Enable cloud connector 57 | """ 58 | cls.command_sub = 'cloud-connector enable' 59 | return cls.execute(cls._construct_command(options)) 60 | -------------------------------------------------------------------------------- /robottelo/cli/job_invocation.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer job-invocation [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND Subcommand 7 | [ARG] ... Subcommand arguments 8 | 9 | Subcommands: 10 | cancel Cancel the job 11 | create Create a job invocation 12 | info Show job invocation 13 | list List job invocations 14 | output View the output for a host 15 | rerun Rerun the job 16 | 17 | """ 18 | 19 | from robottelo.cli.base import Base 20 | 21 | 22 | class JobInvocation(Base): 23 | """ 24 | Run remote jobs. 25 | """ 26 | 27 | command_base = 'job-invocation' 28 | 29 | @classmethod 30 | def get_output(cls, options): 31 | """Get output of the job invocation""" 32 | cls.command_sub = 'output' 33 | return cls.execute(cls._construct_command(options)) 34 | 35 | @classmethod 36 | def create(cls, options, timeout=None): 37 | """Create a job""" 38 | cls.command_sub = 'create' 39 | return cls.execute(cls._construct_command(options), output_format='csv', timeout=timeout) 40 | -------------------------------------------------------------------------------- /robottelo/cli/job_template.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer job-template [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | 7 | SUBCOMMAND subcommand 8 | [ARG] ... subcommand arguments 9 | 10 | Subcommands: 11 | 12 | create Create a job template 13 | delete Delete a job template 14 | dump View job template content 15 | info Show job template details 16 | list List job templates 17 | update Update a job template 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class JobTemplate(Base): 24 | """ 25 | Manipulate job templates. 26 | """ 27 | 28 | command_base = 'job-template' 29 | -------------------------------------------------------------------------------- /robottelo/cli/ldapauthsource.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer auth-source ldap [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | create Create an LDAP authentication source 13 | delete Delete an LDAP authentication source 14 | info Show an LDAP authentication source 15 | list List all LDAP authentication sources 16 | update Update an LDAP authentication source 17 | """ 18 | 19 | from robottelo.cli.base import Base 20 | 21 | 22 | class LDAPAuthSource(Base): 23 | """Manipulates LDAP auth source""" 24 | 25 | command_base = 'auth-source ldap' 26 | 27 | 28 | class ExternalAuthSource(Base): 29 | """Manipulates External auth source 30 | 31 | Usage: 32 | hammer auth-source external [OPTIONS] SUBCOMMAND [ARG] ... 33 | 34 | Subcommands: 35 | info Show an external user group for user group 36 | list List all external user groups for user group 37 | update Update external user group 38 | """ 39 | 40 | command_base = 'auth-source external' 41 | -------------------------------------------------------------------------------- /robottelo/cli/lifecycleenvironment.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer lifecycle-environment [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | list List environments in an organization 14 | update Update an environment 15 | create Create an environment 16 | delete Destroy an environment 17 | info Show an environment 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class LifecycleEnvironment(Base): 24 | """ 25 | Manipulates Katello engine's lifecycle-environment command. 26 | """ 27 | 28 | command_base = 'lifecycle-environment' 29 | command_requires_org = True 30 | 31 | @classmethod 32 | def list(cls, options=None, per_page=False): 33 | return super().list(options, per_page=per_page) 34 | 35 | @classmethod 36 | def paths(cls, options=None): 37 | cls.command_sub = 'paths' 38 | return cls.execute(cls._construct_command(options)) 39 | -------------------------------------------------------------------------------- /robottelo/cli/medium.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer medium [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | add_operatingsystem Associate a resource 14 | create Create a medium. 15 | delete Delete a medium. 16 | info Show a medium. 17 | list List all media. 18 | remove_operatingsystem Disassociate a resource 19 | update Update a medium. 20 | """ 21 | 22 | from robottelo.cli.base import Base 23 | 24 | 25 | class Medium(Base): 26 | """ 27 | Manipulates Foreman's installation media. 28 | """ 29 | 30 | command_base = 'medium' 31 | -------------------------------------------------------------------------------- /robottelo/cli/model.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer model [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a model. 14 | delete Delete a model. 15 | info Show a model. 16 | list List all models. 17 | update Update a model. 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class Model(Base): 24 | """ 25 | Manipulates Foreman's hardware model. 26 | """ 27 | 28 | command_base = 'model' 29 | -------------------------------------------------------------------------------- /robottelo/cli/module_stream.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer module-stream [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | info Show a module-stream 14 | list List module-streams 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class ModuleStream(Base): 21 | """ 22 | Manipulates module-stream command. 23 | """ 24 | 25 | command_base = 'module-stream' 26 | -------------------------------------------------------------------------------- /robottelo/cli/ostreebranch.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer ostree-branch [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | info Show an ostree branch 14 | list List ostree_branches 15 | 16 | """ 17 | 18 | from robottelo.cli.base import Base 19 | 20 | 21 | class OstreeBranch(Base): 22 | """Manipulates Ostree branches.""" 23 | 24 | command_base = 'ostree-branch' 25 | -------------------------------------------------------------------------------- /robottelo/cli/package.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer package [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | info Show a package 14 | list List packages 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class Package(Base): 21 | """ 22 | Manipulates packages command. 23 | """ 24 | 25 | command_base = 'package' 26 | -------------------------------------------------------------------------------- /robottelo/cli/partitiontable.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer partition-table [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | add_operatingsystem Associate a resource 14 | create Create a ptable. 15 | delete Delete a ptable. 16 | dump View partition table content. 17 | info Show a ptable. 18 | list List all ptables. 19 | remove_operatingsystem Disassociate a resource 20 | update Update a ptable. 21 | """ 22 | 23 | from robottelo.cli.base import Base 24 | 25 | 26 | class PartitionTable(Base): 27 | """ 28 | Manipulates Foreman's partition tables. 29 | """ 30 | 31 | command_base = 'partition-table' 32 | -------------------------------------------------------------------------------- /robottelo/cli/proxy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer proxy [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a smart proxy. 14 | delete Delete a smart_proxy. 15 | import_classes Import puppet classes from puppet proxy. 16 | info Show a smart proxy. 17 | list List all smart_proxies. 18 | refresh-features Refresh smart proxy features 19 | update Update a smart proxy. 20 | """ 21 | 22 | from robottelo.cli.base import Base 23 | 24 | 25 | class CapsuleTunnelError(Exception): 26 | """Raised when tunnel creation fails.""" 27 | 28 | 29 | class Proxy(Base): 30 | """Manipulates Foreman's smart proxies.""" 31 | 32 | command_base = 'proxy' 33 | 34 | @classmethod 35 | def import_classes(cls, options=None): 36 | """Import puppet classes from puppet proxy.""" 37 | cls.command_sub = 'import-classes' 38 | return cls.execute(cls._construct_command(options)) 39 | 40 | @classmethod 41 | def refresh_features(cls, options=None): 42 | """Refreshes smart proxy features""" 43 | cls.command_sub = 'refresh-features' 44 | return cls.execute(cls._construct_command(options)) 45 | -------------------------------------------------------------------------------- /robottelo/cli/puppet.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer puppet-class [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | info Show a puppetclass 14 | list List all puppetclasses. 15 | sc-params List all smart class parameters 16 | """ 17 | 18 | from robottelo.cli.base import Base 19 | 20 | 21 | class Puppet(Base): 22 | """ 23 | Search Foreman's puppet modules. 24 | """ 25 | 26 | command_base = 'puppet-class' 27 | 28 | @classmethod 29 | def sc_params(cls, options=None): 30 | """ 31 | Usage: 32 | hammer puppet-class sc-params [OPTIONS] 33 | 34 | Options: 35 | --order ORDER sort results 36 | --page PAGE paginate results 37 | --per-page PER_PAGE number of entries per request 38 | --puppet-class PUPPET_CLASS_NAME Puppet class name 39 | --puppet-class-id PUPPET_CLASS_ID ID of Puppet class 40 | --search SEARCH filter results 41 | """ 42 | cls.command_sub = 'sc-params' 43 | return cls.execute(cls._construct_command(options), output_format='csv') 44 | -------------------------------------------------------------------------------- /robottelo/cli/realm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer realm [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND subcommand 7 | [ARG] ... subcommand arguments 8 | 9 | Subcommands: 10 | create Create a realm 11 | delete Delete a realm 12 | info Show a realm 13 | list List of realms 14 | update Update a realm 15 | 16 | Options: 17 | -h, --help print help 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class Realm(Base): 24 | """Manipulates Realm subcommand""" 25 | 26 | command_base = 'realm' 27 | -------------------------------------------------------------------------------- /robottelo/cli/recurring_logic.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer recurring-logic [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND subcommand 7 | [ARG] ... subcommand arguments 8 | 9 | Subcommands: 10 | cancel Cancel recurring logic 11 | info Show recurring logic details 12 | list List recurring logics 13 | """ 14 | 15 | from robottelo.cli.base import Base 16 | 17 | 18 | class RecurringLogic(Base): 19 | """ 20 | Manipulate recurring logics 21 | """ 22 | 23 | command_base = 'recurring-logic' 24 | -------------------------------------------------------------------------------- /robottelo/cli/report.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer config-report [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | delete Delete report. 14 | info Show info for report. 15 | list List reports. 16 | 17 | """ 18 | 19 | from robottelo.cli.base import Base 20 | 21 | 22 | class ConfigReport(Base): 23 | """ 24 | Manipulates Foreman's config reports. 25 | """ 26 | 27 | command_base = 'config-report' 28 | -------------------------------------------------------------------------------- /robottelo/cli/rex_feature.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer remote-execution-feature [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND Subcommand 9 | [ARG] ... Subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | info Show remote execution feature 14 | list List remote execution features 15 | update Update a job template 16 | 17 | """ 18 | 19 | from robottelo.cli.base import Base 20 | 21 | 22 | class RemoteExecutionFeature(Base): 23 | """ 24 | Handles Remote Execution Feature commands 25 | """ 26 | 27 | command_base = 'remote-execution-feature' 28 | -------------------------------------------------------------------------------- /robottelo/cli/role.py: -------------------------------------------------------------------------------- 1 | """Usage:: 2 | 3 | hammer role [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters:: 6 | 7 | SUBCOMMAND subcommand 8 | [ARG] ... subcommand arguments 9 | 10 | Subcommands:: 11 | 12 | clone Clone a role 13 | create Create an role. 14 | delete Delete an role. 15 | filters List all filters. 16 | info Show a role 17 | list List all roles. 18 | update Update an role. 19 | """ 20 | 21 | from robottelo.cli.base import Base 22 | 23 | 24 | class Role(Base): 25 | """Manipulates Katello engine's role command.""" 26 | 27 | command_base = 'role' 28 | 29 | @classmethod 30 | def filters(cls, options=None): 31 | """List all filters""" 32 | cls.command_sub = 'filters' 33 | return cls.execute(cls._construct_command(options), output_format='json') 34 | 35 | @classmethod 36 | def clone(cls, options): 37 | """Clone a role""" 38 | cls.command_sub = 'clone' 39 | result = cls.execute(cls._construct_command(options), output_format='csv') 40 | # Fetch new role 41 | if len(result) > 0 and 'id' in result[0]: 42 | new_role = cls.info({'id': result[0]['id']}) 43 | if len(new_role) > 0: 44 | result = new_role 45 | return result 46 | -------------------------------------------------------------------------------- /robottelo/cli/scap_policy.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | policy [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a Policy 14 | delete Delete a Policy 15 | info Show a Policy 16 | list List Policies 17 | update Update a Policy 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class Scappolicy(Base): 24 | """Manipulates Satellite's oscap policy.""" 25 | 26 | command_base = 'policy' 27 | -------------------------------------------------------------------------------- /robottelo/cli/scap_tailoring_files.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | tailoring-file [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a Tailoring file 14 | delete Deletes a Tailoring file 15 | download Show a Tailoring file as XML 16 | info Show a Tailoring file 17 | list List Tailoring files 18 | update Update a Tailoring file 19 | """ 20 | 21 | from robottelo.cli.base import Base 22 | 23 | 24 | class TailoringFiles(Base): 25 | """Manipulates Satellite's tailoring-file.""" 26 | 27 | command_base = 'tailoring-file' 28 | 29 | @classmethod 30 | def download_tailoring_file(cls, options): 31 | """Downloads the tailoring file from satellite""" 32 | cls.command_sub = 'download' 33 | return cls.execute(cls._construct_command(options), output_format='table') 34 | -------------------------------------------------------------------------------- /robottelo/cli/scapcontent.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | scap-content [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create SCAP content 14 | delete Deletes an SCAP content 15 | info Show an SCAP content 16 | list List SCAP contents 17 | update Update an SCAP content 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class Scapcontent(Base): 24 | """Manipulates Satellite's scap-content.""" 25 | 26 | command_base = 'scap-content' 27 | 28 | @classmethod 29 | def bulk_upload(cls, options=None): 30 | """Delete assignment sync plan and product.""" 31 | cls.command_sub = 'bulk-upload' 32 | return cls.execute(cls._construct_command(options)) 33 | -------------------------------------------------------------------------------- /robottelo/cli/settings.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer settings [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | list List all settings 14 | set Update a setting 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class Settings(Base): 21 | """Manipulates Foreman's settings.""" 22 | 23 | command_base = 'settings' 24 | 25 | @classmethod 26 | def set(cls, options=None): 27 | """Update a setting""" 28 | cls.command_sub = 'set' 29 | 30 | return cls.execute(cls._construct_command(options)) 31 | -------------------------------------------------------------------------------- /robottelo/cli/simple_content_access.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer simple-content-access [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | disable Disable simple content access for a manifest 14 | enable Enable simple content access for a manifest 15 | status Check if the specified organization has 16 | Simple Content Access enabled 17 | 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | 22 | 23 | class SimpleContentAccess(Base): 24 | """ 25 | Manipulates Katello engine's simple-content-access command. 26 | """ 27 | 28 | command_base = 'simple-content-access' 29 | 30 | @classmethod 31 | def disable(cls, options=None, timeout=None): 32 | """Disable simple content access for a manifest""" 33 | cls.command_sub = 'disable' 34 | return cls.execute(cls._construct_command(options), ignore_stderr=True, timeout=timeout) 35 | 36 | @classmethod 37 | def enable(cls, options=None, timeout=None): 38 | """Enable simple content access for a manifest""" 39 | cls.command_sub = 'enable' 40 | return cls.execute(cls._construct_command(options), ignore_stderr=True, timeout=timeout) 41 | 42 | @classmethod 43 | def status(cls, options=None, timeout=None): 44 | """Check if the specified organization has Simple Content Access enabled""" 45 | cls.command_sub = 'status' 46 | return cls.execute(cls._construct_command(options), ignore_stderr=True, timeout=timeout) 47 | -------------------------------------------------------------------------------- /robottelo/cli/sm_advanced_by_tag.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | satellite-maintain advanced procedure by-tag [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND subcommand 7 | [ARG] ... subcommand arguments 8 | 9 | Subcommands: 10 | backup Run procedures tagged #backup 11 | maintenance-mode-off Run procedures tagged #maintenance_mode_off 12 | maintenance-mode-on Run procedures tagged #maintenance_mode_on 13 | post-migrations Run procedures tagged #post_migrations 14 | pre-migrations Run procedures tagged #pre_migrations 15 | restore Run procedures tagged #restore 16 | 17 | Options: 18 | -h, --help print help 19 | """ 20 | 21 | from robottelo.cli.base import Base 22 | 23 | 24 | class AdvancedByTag(Base): 25 | """Manipulates Satellite-maintain's advanced procedure by-tag command""" 26 | 27 | command_base = 'advanced procedure by-tag' 28 | 29 | @classmethod 30 | def post_migrations(cls, options=None): 31 | """Build satellite-maintain advanced procedure by-tag post-migrations""" 32 | cls.command_sub = 'post-migrations' 33 | options = options or {} 34 | return cls.sm_execute(cls._construct_command(options)) 35 | 36 | @classmethod 37 | def pre_migrations(cls, options=None): 38 | """Build satellite-maintain advanced procedure by-tag pre-migrations""" 39 | cls.command_sub = 'pre-migrations' 40 | options = options or {} 41 | return cls.sm_execute(cls._construct_command(options)) 42 | 43 | @classmethod 44 | def restore(cls, options=None): 45 | """Build satellite-maintain advanced procedure by-tag restore""" 46 | cls.command_sub = 'restore' 47 | options = options or {} 48 | return cls.sm_execute(cls._construct_command(options)) 49 | -------------------------------------------------------------------------------- /robottelo/cli/sm_backup.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | satellite-maintain backup [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND subcommand 7 | [ARG] ... subcommand arguments 8 | 9 | Subcommands: 10 | online Keep services online during backup 11 | offline Shut down services to preserve consistent backup 12 | 13 | Options: 14 | -h, --help print help 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class Backup(Base): 21 | """Manipulates Satellite-maintain's backup command""" 22 | 23 | command_base = 'backup' 24 | 25 | @classmethod 26 | def run_backup(cls, backup_dir='/tmp/', backup_type='online', options=None, timeout=None): 27 | """Build satellite-maintain backup online/offline""" 28 | cls.command_sub = backup_type 29 | cls.command_end = backup_dir 30 | options = options or {} 31 | return cls.sm_execute(cls._construct_command(options), timeout=timeout) 32 | -------------------------------------------------------------------------------- /robottelo/cli/sm_health.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | satellite-maintain health [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND subcommand 7 | [ARG] ... subcommand arguments 8 | 9 | Subcommands: 10 | list List the checks based on criteria 11 | list-tags List the tags to use for filtering checks 12 | check Run the health checks against the system 13 | 14 | Options: 15 | -h, --help print help 16 | """ 17 | 18 | from robottelo.cli.base import Base 19 | 20 | 21 | class Health(Base): 22 | """Manipulates Satellite-maintain's health command""" 23 | 24 | command_base = 'health' 25 | 26 | @classmethod 27 | def check(cls, options=None, env_var=None): 28 | """Build satellite-maintain health check""" 29 | cls.command_sub = 'check' 30 | options = options or {} 31 | return cls.sm_execute(cls._construct_command(options), env_var=env_var) 32 | 33 | @classmethod 34 | def list(cls, options=None, env_var=None): 35 | """Build satellite-maintain health list""" 36 | cls.command_sub = 'list' 37 | options = options or {} 38 | return cls.sm_execute(cls._construct_command(options), env_var=env_var) 39 | 40 | @classmethod 41 | def list_tags(cls, options=None, env_var=None): 42 | """Build satellite-maintain health list-tags""" 43 | cls.command_sub = 'list-tags' 44 | options = options or {} 45 | return cls.sm_execute(cls._construct_command(options), env_var=env_var) 46 | -------------------------------------------------------------------------------- /robottelo/cli/sm_maintenance_mode.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | satellite-maintain maintenance-mode [OPTIONS] SUBCOMMAND [ARG] ... 4 | Parameters: 5 | SUBCOMMAND subcommand 6 | [ARG] ... subcommand arguments 7 | Subcommands: 8 | start Start maintenance-mode 9 | stop Stop maintenance-mode 10 | status Get maintenance-mode status 11 | is-enabled Get maintenance-mode status code 12 | Options: 13 | -h, --help print help 14 | """ 15 | 16 | from robottelo.cli.base import Base 17 | 18 | 19 | class MaintenanceMode(Base): 20 | """Manipulates Satellite-maintain's maintenance-mode command""" 21 | 22 | command_base = 'maintenance-mode' 23 | 24 | @classmethod 25 | def start(cls, options=None): 26 | """satellite-maintain maintenance-mode start [OPTIONS]""" 27 | cls.command_sub = 'start' 28 | options = options or {} 29 | return cls.sm_execute(cls._construct_command(options)) 30 | 31 | @classmethod 32 | def stop(cls, options=None): 33 | """satellite-maintain maintenance-mode stop [OPTIONS]""" 34 | cls.command_sub = 'stop' 35 | options = options or {} 36 | return cls.sm_execute(cls._construct_command(options)) 37 | 38 | @classmethod 39 | def status(cls, options=None): 40 | """satellite-maintain maintenance-mode status [OPTIONS]""" 41 | cls.command_sub = 'status' 42 | options = options or {} 43 | return cls.sm_execute(cls._construct_command(options)) 44 | 45 | @classmethod 46 | def is_enabled(cls, options=None): 47 | """satellite-maintain maintenance-mode is-enabled [OPTIONS]""" 48 | cls.command_sub = 'is-enabled' 49 | options = options or {} 50 | return cls.sm_execute(cls._construct_command(options)) 51 | -------------------------------------------------------------------------------- /robottelo/cli/sm_restore.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | satellite-maintain restore [OPTIONS] BACKUP_DIR 4 | 5 | Parameters: 6 | BACKUP_DIR Path to backup directory to restore 7 | 8 | Options: 9 | -y, --assumeyes Automatically answer yes for all questions 10 | -w, --whitelist whitelist Comma-separated list of labels of steps to be skipped 11 | -f, --force Force steps that would be skipped as they were already run 12 | -i, --incremental Restore an incremental backup 13 | -h, --help print help 14 | """ 15 | 16 | from robottelo.cli.base import Base 17 | 18 | 19 | class Restore(Base): 20 | """Manipulates Satellite-maintain's restore command""" 21 | 22 | command_base = 'restore' 23 | 24 | @classmethod 25 | def run(cls, backup_dir='/tmp/', timeout='30m', options=None): 26 | """Build satellite-maintain restore""" 27 | # cls.command_sub = 'No subcommand for restore' 28 | cls.command_end = backup_dir 29 | options = options or {} 30 | return cls.sm_execute(cls._construct_command(options), timeout=timeout) 31 | -------------------------------------------------------------------------------- /robottelo/cli/sm_update.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | satellite-maintain update [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND subcommand 7 | [ARG] ... subcommand arguments 8 | 9 | Subcommands: 10 | check Run pre-update checks before updating 11 | run Run an update 12 | 13 | Options: 14 | -h, --help print help 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class Update(Base): 21 | """Manipulates Satellite-maintain's update command""" 22 | 23 | command_base = 'update' 24 | 25 | @classmethod 26 | def check(cls, options=None, env_var=None): 27 | """Build satellite-maintain update check""" 28 | cls.command_sub = 'check' 29 | options = options or {} 30 | return cls.sm_execute(cls._construct_command(options), env_var=env_var) 31 | 32 | @classmethod 33 | def run(cls, options=None, env_var=None): 34 | """Build satellite-maintain update run""" 35 | cls.command_sub = 'run' 36 | options = options or {} 37 | return cls.sm_execute(cls._construct_command(options), env_var=env_var) 38 | -------------------------------------------------------------------------------- /robottelo/cli/sm_upgrade.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | satellite-maintain upgrade [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND subcommand 7 | [ARG] ... subcommand arguments 8 | 9 | Subcommands: 10 | check Run pre-upgrade checks before upgrading to specified version 11 | run Run full upgrade to a specified version 12 | 13 | Options: 14 | -h, --help print help 15 | """ 16 | 17 | from robottelo.cli.base import Base 18 | 19 | 20 | class Upgrade(Base): 21 | """Manipulates Satellite-maintain's health command""" 22 | 23 | command_base = 'upgrade' 24 | 25 | @classmethod 26 | def check(cls, options=None, env_var=None): 27 | """Build satellite-maintain upgrade check""" 28 | cls.command_sub = 'check' 29 | options = options or {} 30 | return cls.sm_execute(cls._construct_command(options), env_var=env_var) 31 | 32 | @classmethod 33 | def run(cls, options=None, env_var=None): 34 | """Build satellite-maintain upgrade run""" 35 | cls.command_sub = 'run' 36 | options = options or {} 37 | return cls.sm_execute(cls._construct_command(options), env_var=env_var) 38 | -------------------------------------------------------------------------------- /robottelo/cli/srpm.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer srpm [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters: 6 | SUBCOMMAND Subcommand 7 | [ARG] ... Subcommand arguments 8 | 9 | Subcommands: 10 | info Show a SRPM Details 11 | list List srpms 12 | """ 13 | 14 | from robottelo.cli.base import Base 15 | 16 | 17 | class Srpm(Base): 18 | """ 19 | Manipulates Katello engine's srpm command. 20 | """ 21 | 22 | command_base = 'srpm' 23 | 24 | @classmethod 25 | def info(cls, options=None): 26 | """Show a SRPM Info""" 27 | cls.command_sub = 'info' 28 | 29 | return cls.execute(cls._construct_command(options), output_format='csv') 30 | 31 | @classmethod 32 | def list(cls, options=None): 33 | """List SRPMs""" 34 | cls.command_sub = 'list' 35 | 36 | return cls.execute(cls._construct_command(options), output_format='csv') 37 | -------------------------------------------------------------------------------- /robottelo/cli/subnet.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer subnet [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a subnet 14 | delete Delete a subnet 15 | info Show a subnet. 16 | list List of subnets 17 | update Update a subnet 18 | 19 | """ 20 | 21 | from robottelo.cli.base import Base 22 | 23 | 24 | class Subnet(Base): 25 | """ 26 | Manipulates Foreman's subnets. 27 | """ 28 | 29 | command_base = 'subnet' 30 | -------------------------------------------------------------------------------- /robottelo/cli/syncplan.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage:: 3 | 4 | hammer sync-plan [OPTIONS] SUBCOMMAND [ARG] ... 5 | 6 | Parameters:: 7 | 8 | SUBCOMMAND subcommand 9 | [ARG] ... subcommand arguments 10 | 11 | Subcommands:: 12 | 13 | create Create a sync plan 14 | delete Destroy a sync plan 15 | info Show a sync plan 16 | list List sync plans 17 | update 18 | """ 19 | 20 | from robottelo.cli.base import Base 21 | from robottelo.exceptions import CLIError 22 | 23 | 24 | class SyncPlan(Base): 25 | """Manipulates Katello engine's sync-plan command.""" 26 | 27 | command_base = 'sync-plan' 28 | 29 | @classmethod 30 | def create(cls, options=None, timeout=None): 31 | """Create a SyncPlan""" 32 | cls.command_sub = 'create' 33 | 34 | if options.get('interval') == 'custom cron' and options.get('cron-expression') is None: 35 | raise CLIError('Missing "cron-expression" option for "custom cron" interval.') 36 | 37 | return super().create(options, timeout) 38 | -------------------------------------------------------------------------------- /robottelo/cli/virt_who_config.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer virt-who-config [OPTIONS] SUBCOMMAND [ARG] ... 4 | 5 | Parameters:: 6 | 7 | SUBCOMMAND subcommand 8 | [ARG] ... subcommand arguments 9 | 10 | Subcommands:: 11 | 12 | create Create a virt-who configuration 13 | delete Delete a virt-who configuration 14 | deploy Download and execute script for the specified 15 | virt-who configuration 16 | fetch Renders a deploy script for the specified 17 | virt-who configuration 18 | info Show a virt-who configuration 19 | list List of virt-who configurations 20 | update Update a virt-who configuration 21 | """ 22 | 23 | from robottelo.cli.base import Base 24 | 25 | 26 | class VirtWhoConfig(Base): 27 | """Manipulates virt-who configuration.""" 28 | 29 | command_base = 'virt-who-config' 30 | 31 | @classmethod 32 | def fetch(cls, options=None, output_format=None): 33 | """Renders a deploy script for the specified virt-who configuration""" 34 | cls.command_sub = 'fetch' 35 | return cls.execute(cls._construct_command(options), output_format=output_format) 36 | 37 | @classmethod 38 | def deploy(cls, options=None): 39 | """runs hammer virt-who-config deploy --id which runs the script on 40 | the satellite server 41 | 42 | :param options: `id` required 43 | :return: Results of the command 44 | """ 45 | cls.command_sub = 'deploy' 46 | return cls.execute(cls._construct_command(options)) 47 | -------------------------------------------------------------------------------- /robottelo/cli/webhook.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: 3 | hammer webhook [OPTIONS] SUBCOMMAND [ARG] ... 4 | Parameters: 5 | SUBCOMMAND Subcommand 6 | [ARG] ... Subcommand arguments 7 | Subcommands: 8 | create Create a Webhook 9 | delete Delete a Webhook 10 | info Show Webhook details 11 | list List Webhooks 12 | update Update a Webhook 13 | Options: 14 | -h, --help Print help 15 | """ 16 | 17 | from robottelo.cli.base import Base, CLIError 18 | from robottelo.constants import WEBHOOK_EVENTS, WEBHOOK_METHODS 19 | 20 | 21 | class Webhook(Base): 22 | command_base = 'webhook' 23 | 24 | @classmethod 25 | def create(cls, options=None, timeout=None): 26 | """Create a webhook""" 27 | cls.command_sub = 'create' 28 | 29 | if options is None: 30 | options = dict() 31 | 32 | if options.get('event', None) not in WEBHOOK_EVENTS: 33 | raise CLIError( 34 | 'The option "event" must be one of predefined events.' 35 | 'See "hammer webhook create --help" for list of allowed events' 36 | ) 37 | 38 | if options.get('http-method', None) not in WEBHOOK_METHODS: 39 | raise CLIError( 40 | 'The option "method" must be one supported HTTP methods. ' 41 | 'See See "hammer webhook create --help" for the list of supported methods' 42 | ) 43 | 44 | return super().create(options, timeout) 45 | -------------------------------------------------------------------------------- /robottelo/constants/repos.py: -------------------------------------------------------------------------------- 1 | """Only External Repos url specific constants module""" 2 | 3 | PULP_FIXTURE_ROOT = 'https://fixtures.pulpproject.org/' 4 | PULP_SUBPATHS_COMBINED = { 5 | 'yum': ['rpm-zstd-metadata/', 'rpm-modular/'], 6 | 'file': ['file-large/', 'file-many/'], 7 | } 8 | CUSTOM_3RD_PARTY_REPO = 'http://repo.calcforge.org/fedora/21/x86_64/' 9 | CUSTOM_FILE_REPO = 'https://fixtures.pulpproject.org/file/' 10 | CUSTOM_KICKSTART_REPO = 'http://ftp.cvut.cz/centos/8/BaseOS/x86_64/kickstart/' 11 | CUSTOM_RPM_REPO = 'https://fixtures.pulpproject.org/rpm-signed/' 12 | CUSTOM_RPM_SHA = 'https://fixtures.pulpproject.org/rpm-with-sha/' 13 | CUSTOM_RPM_SHA_512 = 'https://fixtures.pulpproject.org/rpm-with-sha-512/' 14 | FAKE_5_YUM_REPO = 'https://rplevka.fedorapeople.org/fakerepo01/' 15 | FAKE_YUM_MISSING_REPO = 'https://fixtures.pulpproject.org/missing-repo/' 16 | FAKE_YUM_SRPM_REPO = 'https://fixtures.pulpproject.org/srpm-signed/' 17 | FAKE_YUM_SRPM_DUPLICATE_REPO = 'https://fixtures.pulpproject.org/srpm-duplicate/' 18 | FAKE_YUM_MD5_REPO = 'https://fixtures.pulpproject.org/rpm-with-md5/' 19 | # Fedora's OSTree repo changed to a single repo at 20 | # https://kojipkgs.fedoraproject.org/compose/ostree/repo/ 21 | # With branches for each version. Some tests (test_positive_update_url) still need 2 repos URLs, 22 | # We will use the archived versions for now, but probably need to revisit this. 23 | FEDORA_OSTREE_REPO = 'https://kojipkgs.fedoraproject.org/compose/ostree/repo/' 24 | OSTREE_REPO = 'https://fixtures.pulpproject.org/ostree/small/' 25 | FAKE_0_YUM_REPO_STRING_BASED_VERSIONS = ( 26 | 'https://fixtures.pulpproject.org/rpm-string-version-updateinfo/' 27 | ) 28 | FAKE_ZST_REPO = 'https://fixtures.pulpproject.org/rpm-zstd-metadata' 29 | ANSIBLE_GALAXY = 'https://galaxy.ansible.com/' 30 | ANSIBLE_HUB = 'https://cloud.redhat.com/api/automation-hub/' 31 | -------------------------------------------------------------------------------- /robottelo/host_helpers/__init__.py: -------------------------------------------------------------------------------- 1 | from robottelo.host_helpers.capsule_mixins import CapsuleInfo, EnablePluginsCapsule 2 | from robottelo.host_helpers.contenthost_mixins import ( 3 | HostInfo, 4 | SystemFacts, 5 | VersionedContent, 6 | ) 7 | from robottelo.host_helpers.satellite_mixins import ( 8 | ContentInfo, 9 | EnablePluginsSatellite, 10 | Factories, 11 | ProvisioningSetup, 12 | SystemInfo, 13 | ) 14 | 15 | 16 | class ContentHostMixins(HostInfo, SystemFacts, VersionedContent): 17 | pass 18 | 19 | 20 | class CapsuleMixins(CapsuleInfo, EnablePluginsCapsule): 21 | pass 22 | 23 | 24 | class SatelliteMixins( 25 | ContentInfo, Factories, SystemInfo, EnablePluginsSatellite, ProvisioningSetup 26 | ): 27 | pass 28 | -------------------------------------------------------------------------------- /robottelo/utils/decorators/__init__.py: -------------------------------------------------------------------------------- 1 | """Implements various decorators""" 2 | 3 | from functools import wraps 4 | 5 | OBJECT_CACHE = {} 6 | 7 | 8 | def cacheable(func): 9 | """Decorator that makes an optional object cache available""" 10 | 11 | @wraps(func) 12 | def cacheable_function(options=None, cached=False): 13 | """ 14 | This is the function being returned. 15 | Requires input function's name start with 'make_' 16 | """ 17 | object_key = func.__name__.replace('make_', '') 18 | if cached is True and object_key in OBJECT_CACHE: 19 | return OBJECT_CACHE[object_key] 20 | new_object = func(options) 21 | if cached is True: 22 | OBJECT_CACHE[object_key] = new_object 23 | return new_object 24 | 25 | return cacheable_function 26 | -------------------------------------------------------------------------------- /robottelo/utils/decorators/func_shared/__init__.py: -------------------------------------------------------------------------------- 1 | from robottelo.utils.decorators.func_shared.shared import shared # noqa 2 | from robottelo.utils.decorators.func_shared.shared import SharedFunctionError # noqa 3 | from robottelo.utils.decorators.func_shared.shared import SharedFunctionException # noqa 4 | -------------------------------------------------------------------------------- /robottelo/utils/decorators/func_shared/base.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | class BaseStorageHandler: 5 | @staticmethod 6 | def encode(data): 7 | return json.dumps(data) 8 | 9 | @staticmethod 10 | def decode(data): 11 | return json.loads(data) 12 | 13 | def lock(self, lock_key): 14 | """Return the storage locker context manager""" 15 | raise NotImplementedError 16 | 17 | def when_lock_acquired(self, data): 18 | """called when the lock is acquired to do some added action""" 19 | raise NotImplementedError 20 | 21 | def get(self, key): 22 | """Return the key value""" 23 | raise NotImplementedError 24 | 25 | def set(self, key, value): 26 | """Write the value of key to storage""" 27 | raise NotImplementedError 28 | -------------------------------------------------------------------------------- /robottelo/utils/decorators/func_shared/redis_storage.py: -------------------------------------------------------------------------------- 1 | try: 2 | import redis 3 | except ImportError: 4 | redis = None 5 | 6 | from robottelo.utils.decorators.func_shared.base import BaseStorageHandler 7 | 8 | REDIS_HOST = 'localhost' 9 | REDIS_PORT = 6379 10 | REDIS_DB = 0 11 | REDIS_PASSWORD = None 12 | LOCK_TIMEOUT = 7200 13 | 14 | 15 | class RedisStorageHandler(BaseStorageHandler): 16 | """Redis Key value storage handler""" 17 | 18 | def __init__( 19 | self, 20 | host=REDIS_HOST, 21 | port=REDIS_PORT, 22 | db=REDIS_DB, 23 | password=REDIS_PASSWORD, 24 | lock_timeout=LOCK_TIMEOUT, 25 | ): 26 | self._lock_timeout = lock_timeout 27 | self._client = redis.StrictRedis(host=host, port=port, db=db, password=password) 28 | 29 | @property 30 | def client(self): 31 | return self._client 32 | 33 | def lock(self, key, timeout=None): 34 | """Return the storage locker context manager""" 35 | if timeout is None: 36 | timeout = self._lock_timeout 37 | 38 | lock_key = f'{key}.lock' 39 | # If acquired the lock will be acquired until release 40 | return self.client.lock(lock_key, timeout=None, blocking_timeout=timeout) 41 | 42 | def when_lock_acquired(self, lock_object): 43 | # do nothing 44 | pass 45 | 46 | def get(self, key): 47 | """Return the key value 48 | 49 | :type key: str 50 | """ 51 | value = self.client.get(key) 52 | if value is not None: 53 | value = self.decode(value) 54 | return value 55 | 56 | def set(self, key, value): 57 | """Write the value of key 58 | 59 | :type key: str 60 | :type value: object 61 | """ 62 | value = self.encode(value) 63 | self.client.set(key, value) 64 | -------------------------------------------------------------------------------- /robottelo/utils/report_portal/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/robottelo/utils/report_portal/__init__.py -------------------------------------------------------------------------------- /robottelo/utils/ssh.py: -------------------------------------------------------------------------------- 1 | """Utility module to handle the shared ssh connection.""" 2 | 3 | from robottelo.cli import hammer 4 | 5 | 6 | def get_client( 7 | hostname=None, 8 | username=None, 9 | password=None, 10 | port=22, 11 | ): 12 | """Returns a host object that provides an ssh connection 13 | 14 | Processes ssh credentials in the order: password, key_filename, ssh_key 15 | Config validation enforces one of the three must be set in settings.server 16 | """ 17 | from robottelo.config import settings 18 | from robottelo.hosts import ContentHost 19 | 20 | return ContentHost( 21 | hostname=hostname or settings.server.hostname, 22 | username=username or settings.server.ssh_username, 23 | password=password or settings.server.ssh_password, 24 | port=port or settings.server.ssh_client.port, 25 | ) 26 | 27 | 28 | def command( 29 | cmd, 30 | hostname=None, 31 | output_format=None, 32 | username=None, 33 | password=None, 34 | timeout=None, 35 | port=22, 36 | ): 37 | """Executes SSH command(s) on remote hostname. 38 | 39 | kwargs are passed through to get_connection 40 | 41 | :param str cmd: The command to run 42 | :param str output_format: json, csv or None 43 | :param int timeout: Time to wait for the ssh command to finish. 44 | :param connection_timeout: Time to wait for establishing the connection. 45 | """ 46 | client = get_client( 47 | hostname=hostname, 48 | username=username, 49 | password=password, 50 | port=port, 51 | ) 52 | result = client.execute(cmd, timeout=timeout) 53 | 54 | if output_format and result.status == 0: 55 | if output_format == 'csv': 56 | result.stdout = hammer.parse_csv(result.stdout) if result.stdout else {} 57 | if output_format == 'json': 58 | result.stdout = hammer.parse_json(result.stdout) if result.stdout else None 59 | return result 60 | -------------------------------------------------------------------------------- /robottelo/utils/url.py: -------------------------------------------------------------------------------- 1 | from urllib.parse import urlparse 2 | 3 | 4 | def is_url(url): 5 | try: 6 | result = urlparse(url) 7 | return all([result.scheme, result.netloc]) 8 | except (ValueError, AttributeError): 9 | return False 10 | -------------------------------------------------------------------------------- /robottelo/utils/version.py: -------------------------------------------------------------------------------- 1 | # Utility methods and classes related to Satellite/foreman version handling 2 | import json 3 | 4 | from packaging.version import Version 5 | 6 | 7 | def search_version_key(key, value): # pragma: no cover 8 | """recursively look for 'version' key and transform it in a Version instance""" 9 | if key == 'version' and isinstance(value, str): 10 | return Version(value) 11 | if isinstance(value, dict): 12 | return {k: search_version_key(k, v) for k, v in value.items()} 13 | if isinstance(value, list): 14 | return [search_version_key(key, item) for item in value] 15 | return value 16 | 17 | 18 | class VersionEncoder(json.JSONEncoder): # pragma: no cover 19 | """Transform Version instances to str""" 20 | 21 | def default(self, z): 22 | if isinstance(z, Version): 23 | return str(z) 24 | return super().default(z) 25 | -------------------------------------------------------------------------------- /scripts/graph_entities.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | """Graph relationships between entities. 3 | 4 | For each entity in module ``nailgun.entities``, determine which entities it 5 | depends on. Print this dependency information to stdout in DOT format. To run 6 | this script and generate an image all in one go, use the ``graph-entities`` 7 | command provided by the make file in the parent directory. 8 | 9 | """ 10 | 11 | import inspect 12 | 13 | from nailgun import entities, entity_mixins 14 | 15 | 16 | def graph(): 17 | """Graph the relationships between the entity classes.""" 18 | # Compile a dict of `entity_mixins.Entity` subclasses. 19 | entities_ = {} 20 | for name, klass in inspect.getmembers(entities, inspect.isclass): 21 | if issubclass(klass, entity_mixins.Entity): 22 | entities_[name] = klass 23 | # Generate DOT-formatted output. 24 | print('digraph dependencies {') 25 | for entity_name, entity in entities_.items(): 26 | # Graph out which entities this entity depends on. 27 | for field_name, field in entity.get_fields().items(): 28 | if isinstance(field, (entity_mixins.OneToOneField | entity_mixins.OneToManyField)): 29 | print( 30 | '{} -> {} [label="{}"{}]'.format( 31 | entity_name, 32 | field.entity, 33 | field_name, 34 | ' color=red' if field.required else '', 35 | ) 36 | ) 37 | # Make entities that cannot be created less visible. 38 | if not issubclass(entity, entity_mixins.EntityCreateMixin): 39 | print(f'{entity_name} [style=dotted]') 40 | print('}') 41 | 42 | 43 | if __name__ == '__main__': 44 | graph() 45 | -------------------------------------------------------------------------------- /scripts/hammer_command_tree.py: -------------------------------------------------------------------------------- 1 | """Generate hammer command tree in json format by inspecting every command's 2 | help. 3 | 4 | """ 5 | 6 | import json 7 | 8 | from robottelo import ssh 9 | from robottelo.cli import hammer 10 | from robottelo.config import settings 11 | 12 | 13 | def generate_command_tree(command): 14 | """Recursively walk trhough the hammer commands and subcommands and fetch 15 | their help. Return a dictionary with the contents. 16 | """ 17 | output = ssh.command(f'{command} --help', hostname=settings.server.hostnames[0]).stdout 18 | contents = hammer.parse_help(output) 19 | if len(contents['subcommands']) > 0: 20 | for subcommand in contents['subcommands']: 21 | subcommand.update(generate_command_tree('{} {}'.format(command, subcommand['name']))) 22 | return contents 23 | 24 | 25 | # Generate the json file in the working directory 26 | with open('hammer_commands.json', 'w') as f: 27 | f.write(json.dumps(generate_command_tree('hammer'), indent=2, sort_keys=True)) 28 | -------------------------------------------------------------------------------- /scripts/token_editor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | """Token editor 3 | 4 | Reads Python test modules under test/foreman and edit docstring tokens' prefix 5 | from ``OLD_TOKEN_PREFIX`` to ``NEW_TOKEN_PREFIX``. 6 | """ 7 | 8 | import glob 9 | import os 10 | import re 11 | 12 | ROOT_PATH = os.path.realpath( 13 | os.path.join(os.path.dirname(os.path.abspath(__file__)), os.path.pardir) 14 | ) 15 | TESTIMONY_TOKENS_RE = re.compile(r'TESTIMONY_TOKENS="([\w, ]+)"') 16 | OLD_TOKEN_PREFIX = '@' 17 | NEW_TOKEN_PREFIX = ':' 18 | 19 | with open('Makefile') as handler: 20 | match = TESTIMONY_TOKENS_RE.search(handler.read()) 21 | 22 | if not match: 23 | raise ValueError('Not able to fetch TESTIMONY_TOKENS from Makefile') 24 | 25 | valid_tokens = [token.strip() for token in match.group(1).split(',')] 26 | TOKEN_RE = re.compile( 27 | r'{}({}):'.format(OLD_TOKEN_PREFIX, '|'.join(valid_tokens)), flags=re.IGNORECASE 28 | ) 29 | 30 | test_modules = glob.glob(os.path.join(ROOT_PATH, 'tests', 'foreman', '*', 'test_*.py')) 31 | for test_module in test_modules: 32 | with open(test_module) as handler: 33 | content = handler.read() 34 | content = TOKEN_RE.sub(rf'{NEW_TOKEN_PREFIX}\1:', content) 35 | with open(test_module, 'w') as handler: 36 | handler.write(content) 37 | -------------------------------------------------------------------------------- /scripts/tokenize_customer_scenario.py: -------------------------------------------------------------------------------- 1 | # /// script 2 | # requires-python = ">=3.11" 3 | # dependencies = [ 4 | # "codemod", 5 | # ] 6 | # /// 7 | """ 8 | This script adds ':customerscenario: true' to all tests by uuid 9 | 10 | On command line should be like: 11 | 12 | $ codemod -i -d tests/foreman/cli/ --extension py \ 13 | ':id: 65ba89f0-9bee-43d9-814b-9f5a194558f8' \ 14 | ':id: 65ba89f0-9bee-43d9-814b-9f5a194558f8\n\n :customerscenario: true' # noqa 15 | 16 | But in this script we are doing programatically and interactivelly in Python 17 | 18 | On robottelo root dir run: 19 | $ python scripts/tokenize_customer_scenario.py 20 | """ 21 | 22 | import codemod 23 | from codemod import Query, regex_suggestor, run_interactive 24 | from codemod.helpers import path_filter 25 | 26 | codemod.base.yes_to_all = True 27 | 28 | # this script can be changed to accept this list as param 29 | # or to use robozilla to parse for those ids in BZ api 30 | uids = [ 31 | # '65ba89f0-9bee-43d9-814b-9f5a194558f8', 32 | ] 33 | 34 | query_options = {'root_directory': 'tests/foreman'} 35 | query_options['path_filter'] = path_filter(['py'], None) 36 | 37 | for uid in uids: 38 | match = f':id: {uid}' 39 | subst = f':id: {uid}\n\n :customerscenario: true' 40 | case_i = True 41 | query_options['suggestor'] = regex_suggestor(match, subst, ignore_case=True) 42 | run_interactive(query=Query(**query_options)) 43 | -------------------------------------------------------------------------------- /scripts/validate_config.py: -------------------------------------------------------------------------------- 1 | # /// script 2 | # requires-python = ">=3.11" 3 | # dependencies = [ 4 | # "dynaconf", 5 | # ] 6 | # /// 7 | """Usage: python scripts/validate_config.py""" 8 | 9 | from dynaconf.validator import ValidationError 10 | 11 | from robottelo.config import get_settings 12 | 13 | try: 14 | from robottelo.config import settings 15 | except Exception as err: 16 | print(f"Encountered the following exception, continuing for the sake of validation\n {err}") 17 | 18 | settings = get_settings() 19 | 20 | 21 | def binary_validation(validators): 22 | settings.validators.clear() 23 | settings.validators.extend(validators) 24 | try: 25 | settings.validators.validate() 26 | except (ValidationError, AttributeError) as err: 27 | if len(validators) == 1: 28 | if isinstance(err, AttributeError): 29 | print(f"validator={validators[0].names}:\n {err}") 30 | else: 31 | print(err) 32 | else: 33 | left, right = ( 34 | validators[: len(validators) // 2], 35 | validators[len(validators) // 2 :], # noqa: E203 36 | ) 37 | binary_validation(left) 38 | binary_validation(right) 39 | 40 | 41 | binary_validation(settings.validators[:]) 42 | -------------------------------------------------------------------------------- /scripts/vault_login.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # This Enables and Disables individuals OIDC token to access secrets from vault 3 | import sys 4 | 5 | from robottelo.utils.vault import Vault 6 | 7 | if __name__ == '__main__': 8 | with Vault() as vclient: 9 | if sys.argv[-1] == '--login': 10 | vclient.login() 11 | elif sys.argv[-1] == '--status': 12 | vclient.status() 13 | else: 14 | vclient.logout() 15 | -------------------------------------------------------------------------------- /selenium_grid.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | HUB_IMAGE=${HUB_IMAGE:-"selenium/hub:4.3.0"} 4 | NODE_IMAGE=${NODE_IMAGE:-"selenium/node-chrome:4.3.0"} 5 | 6 | function get_first_ip_from_iface_name { 7 | ip -N a show dev "$1" | awk '/inet /{ print $2 }' | sed 's/\(.*\)\/.*/\1/' | head -n1 8 | } 9 | 10 | function selenium_grid_start_hub { 11 | echo "Creating grid network:" 12 | podman network create selenium-grid 13 | echo "Running selenium hub:" 14 | podman run --name selenium-hub \ 15 | --restart unless-stopped \ 16 | -d \ 17 | --net=selenium-grid \ 18 | -p 4442-4445:4442-4445 \ 19 | "$HUB_IMAGE" 20 | } 21 | 22 | function selenium_grid_start_node { 23 | echo "Running selenium node:" 24 | SUFFIX=`tr -dc A-Za-z0-9 < /dev/urandom | head -c 5` 25 | LISTEN_IP=`get_first_ip_from_iface_name "${LISTEN_DEVICE:-tun0}"` 26 | podman run -d --name "selenium-node-chrome-$SUFFIX" \ 27 | -e SE_EVENT_BUS_HOST="$LISTEN_IP" \ 28 | -e SE_EVENT_BUS_PUBLISH_PORT=4442 \ 29 | -e SE_EVENT_BUS_SUBSCRIBE_PORT=4443 \ 30 | --net=selenium-grid --shm-size=2g \ 31 | "$NODE_IMAGE" 32 | } 33 | 34 | function selenium_grid_cleanup { 35 | echo "Cleaning up the grid:" 36 | podman network rm -f selenium-grid 37 | } 38 | -------------------------------------------------------------------------------- /settings.sample.yaml: -------------------------------------------------------------------------------- 1 | # copy this file as `settings.local.yaml` and override any config provided under `conf/*.yaml` 2 | # or preferably use environment variables instead of this file 3 | # example: 4 | # `export SATQE_SERVER__HOSTNAME=myserver.redhat.com` 5 | --- 6 | 7 | # merge settings from this file with the files that were preloaded from the conf/ directory 8 | # see: https://www.dynaconf.com/merging/ 9 | dynaconf_merge: true 10 | 11 | server: 12 | admin_password: "" 13 | admin_username: "" 14 | hostname: "" 15 | port: null 16 | scheme: https 17 | ssh_key: "" 18 | ssh_password: null 19 | ssh_username: "" 20 | 21 | ssh_client: {} 22 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | This module contains tests both for Foreman and Robottelo itself. 3 | 4 | Tests for Robottelo are in the ``robottelo`` module. Those tests are 5 | inward-facing: they help ensure that this codebase is functioning correctly. 6 | 7 | Tests for Foreman are in the ``foreman`` module. Those tests are 8 | outward-facing: they help ensure that a Foreman deployment is functioning 9 | correctly. 10 | """ 11 | -------------------------------------------------------------------------------- /tests/foreman/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/__init__.py -------------------------------------------------------------------------------- /tests/foreman/api/__init__.py: -------------------------------------------------------------------------------- 1 | """In-depth API tests. 2 | 3 | :mod:`tests.foreman.api.test_multiple_paths` contains tests that are very 4 | generic and apply to a large number of API paths. The other modules contain 5 | tests that are more specific to individual API paths. 6 | 7 | """ 8 | -------------------------------------------------------------------------------- /tests/foreman/api/test_foremantask.py: -------------------------------------------------------------------------------- 1 | """Tests for the ``foreman_tasks/api/v2/tasks`` path. 2 | 3 | :Requirement: Foremantask 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: TasksPlugin 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | from requests.exceptions import HTTPError 17 | 18 | 19 | def test_negative_fetch_non_existent_task(target_sat): 20 | """Fetch a non-existent task. 21 | 22 | :id: a2a81ca2-63c4-47f5-9314-5852f5e2617f 23 | 24 | :expectedresults: An HTTP 4XX or 5XX message is returned. 25 | 26 | :CaseImportance: Critical 27 | """ 28 | with pytest.raises(HTTPError): 29 | target_sat.api.ForemanTask(id='abc123').read() 30 | 31 | 32 | @pytest.mark.upgrade 33 | @pytest.mark.e2e 34 | def test_positive_get_summary(target_sat): 35 | """Get a summary of foreman tasks. 36 | 37 | :id: bdcab413-a25d-4fe1-9db4-b50b5c31ebce 38 | 39 | :expectedresults: A list of dicts is returned. 40 | 41 | :CaseImportance: Critical 42 | """ 43 | summary = target_sat.api.ForemanTask().summary() 44 | assert isinstance(summary, list) 45 | for item in summary: 46 | assert isinstance(item, dict) 47 | -------------------------------------------------------------------------------- /tests/foreman/api/test_ping.py: -------------------------------------------------------------------------------- 1 | """Test Class for api ping 2 | 3 | :Requirement: Ping 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: API 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: Critical 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.e2e 19 | @pytest.mark.build_sanity 20 | @pytest.mark.upgrade 21 | def test_positive_ping(target_sat): 22 | """Check if all services are running 23 | 24 | :id: b8ecc7ba-8007-4067-bf99-21a82c833de7 25 | 26 | :expectedresults: Overall and individual services status should be 'ok'. 27 | """ 28 | response = target_sat.api.Ping().search_json() 29 | assert response['status'] == 'ok' # overall status 30 | 31 | # Check that all services are OK. ['services'] is in this format: 32 | # 33 | # {'services': { 34 | # 'candlepin': {'duration_ms': '40', 'status': 'ok'}, 35 | # 'candlepin_auth': {'duration_ms': '41', 'status': 'ok'}, 36 | # … 37 | # }, 'status': 'ok'} 38 | services = response['services'] 39 | assert all([service['status'] == 'ok' for service in services.values()]), ( 40 | 'Not all services seem to be up and running!' 41 | ) 42 | -------------------------------------------------------------------------------- /tests/foreman/api/test_rhsm.py: -------------------------------------------------------------------------------- 1 | """Tests for the ``rhsm`` paths. 2 | 3 | No API doc exists for the subscription manager path(s). However, bugzilla bug 4 | 1112802 provides some relevant information. 5 | 6 | 7 | :Requirement: Rhsm 8 | 9 | :CaseAutomation: Automated 10 | 11 | :CaseComponent: SubscriptionManagement 12 | 13 | :team: Phoenix-subscriptions 14 | 15 | :CaseImportance: High 16 | 17 | """ 18 | 19 | import http 20 | 21 | from nailgun import client 22 | import pytest 23 | 24 | from robottelo.config import get_credentials, get_url 25 | 26 | 27 | @pytest.mark.pit_server 28 | def test_positive_path(): 29 | """Check whether the path exists. 30 | 31 | :id: a8706cb7-549b-4426-9bd9-4beecc33c797 32 | 33 | :expectedresults: Issuing an HTTP GET produces an HTTP 200 response 34 | with an ``application/json`` content-type, and the response is a 35 | list. 36 | 37 | :BZ: 1112802 38 | 39 | :customerscenario: true 40 | 41 | :CaseImportance: Critical 42 | """ 43 | path = f'{get_url()}/rhsm' 44 | response = client.get(path, auth=get_credentials(), verify=False) 45 | assert response.status_code == http.client.OK 46 | assert 'application/json' in response.headers['content-type'] 47 | assert isinstance(response.json(), list) 48 | -------------------------------------------------------------------------------- /tests/foreman/api/test_template_combination.py: -------------------------------------------------------------------------------- 1 | """Tests for template combination 2 | 3 | :Requirement: TemplateCombination 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: ProvisioningTemplates 8 | 9 | :Team: Rocket 10 | 11 | """ 12 | 13 | import pytest 14 | from requests.exceptions import HTTPError 15 | 16 | 17 | @pytest.mark.upgrade 18 | def test_positive_end_to_end_template_combination(request, module_target_sat, module_hostgroup): 19 | """Assert API template combination get/delete method works. 20 | 21 | :id: 3a5cb370-c5f6-11e6-bb2f-68f72889dc7g 22 | 23 | :Setup: save a template combination 24 | 25 | :expectedresults: TemplateCombination can be created, retrieved and deleted through API 26 | 27 | :CaseImportance: Critical 28 | 29 | :BZ: 1369737 30 | """ 31 | template = module_target_sat.api.ProvisioningTemplate( 32 | snippet=False, 33 | template_combinations=[ 34 | { 35 | 'hostgroup_id': module_hostgroup.id, 36 | } 37 | ], 38 | ) 39 | template = template.create() 40 | template_combination_dct = template.template_combinations[0] 41 | template_combination = module_target_sat.api.TemplateCombination( 42 | id=template_combination_dct['id'], 43 | provisioning_template=template, 44 | hostgroup=module_hostgroup, 45 | ) 46 | # GET 47 | combination = template_combination.read() 48 | assert template.id == combination.provisioning_template.id 49 | assert module_hostgroup.id == combination.hostgroup.id 50 | 51 | # DELETE 52 | assert len(template.read().template_combinations) == 1 53 | combination.delete() 54 | with pytest.raises(HTTPError): 55 | combination.read() 56 | assert len(template.read().template_combinations) == 0 57 | template.delete() 58 | module_hostgroup.delete() 59 | -------------------------------------------------------------------------------- /tests/foreman/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/cli/__init__.py -------------------------------------------------------------------------------- /tests/foreman/cli/test_capsule.py: -------------------------------------------------------------------------------- 1 | """Test class for the capsule CLI. 2 | 3 | :Requirement: ForemanProxy 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: ForemanProxy 8 | 9 | :Team: Platform 10 | 11 | :CaseImportance: Critical 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | pytestmark = [pytest.mark.run_in_one_thread] 18 | 19 | 20 | @pytest.mark.skip_if_not_set('fake_capsules') 21 | def test_positive_import_puppet_classes(session_puppet_enabled_sat, puppet_proxy_port_range): 22 | """Import puppet classes from proxy 23 | 24 | :id: 42e3a9c0-62e1-4049-9667-f3c0cdfe0b04 25 | 26 | :expectedresults: Puppet classes are imported from proxy 27 | """ 28 | with session_puppet_enabled_sat as puppet_sat: 29 | port = puppet_sat.available_capsule_port 30 | with puppet_sat.default_url_on_new_port(9090, port) as url: 31 | proxy = puppet_sat.cli_factory.make_proxy({'url': url}) 32 | puppet_sat.cli.Proxy.import_classes({'id': proxy['id']}) 33 | puppet_sat.cli.Proxy.delete({'id': proxy['id']}) 34 | 35 | 36 | @pytest.mark.stubbed 37 | def test_positive_capsule_content(): 38 | """Registered and provisioned hosts can consume content from capsule 39 | 40 | :id: 7e5493de-b27b-4adc-ba18-4dc2e94e7305 41 | 42 | :Setup: Capsule with some content synced 43 | 44 | :steps: 45 | 46 | 1. Register a host to the capsule 47 | 2. Sync content from capsule to the host 48 | 3. Unregister host from the capsule 49 | 4. Provision host via capsule 50 | 5. Provisioned host syncs content from capsule 51 | 52 | :expectedresults: Hosts can be successfully registered to the capsule, 53 | consume content and unregister afterwards. Hosts can be successfully 54 | provisioned via capsule and consume content as well. 55 | 56 | :CaseAutomation: NotAutomated 57 | """ 58 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_foremantask.py: -------------------------------------------------------------------------------- 1 | """Tests for the ``foreman_tasks/api/v2/tasks`` path. 2 | 3 | :Requirement: Foremantask 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: TasksPlugin 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.stubbed 19 | def test_positive_tasks_backup(): 20 | """Check no tasks are backup by default when cleaning up tasks from the database and 21 | no /var/lib/foreman/tasks-backup created for backup tasks. 22 | 23 | :id: 3575492c-7802-4b00-aefc-d53141ad7446 24 | 25 | :BZ: 1615015 26 | 27 | :customerscenario: true 28 | 29 | :steps: 30 | 1. To run tasks cleanup every 5mins, 31 | `satellite-installer --foreman-plugin-tasks-cron-line '5 * * * *'` 32 | 2. satellite-installer --foreman-plugin-tasks-backup true (which is default:false) 33 | 3. Verify TASK_BACKUP=true in /etc/cron.d/foreman-tasks (which is default:false) 34 | 4. Create any product or sync any repo to have a valid task. 35 | 5. Include this line "TASK_SEARCH='label = Actions::Katello::Product::Create'" 36 | to /etc/cron.d/foreman-tasks 37 | 6. Watch /var/log/foreman/cron.log for task cleanup of above labelled tasks. 38 | 7. Verify /var/lib/foreman/tasks-backup created and has details of cleaned up tasks. 39 | 40 | :expectedresults: No tasks are backup by default when cleaning up tasks from the database, 41 | and no /var/lib/foreman/tasks-backup created for backup tasks. 42 | 43 | :CaseImportance: High 44 | 45 | :CaseAutomation: NotAutomated 46 | """ 47 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_globalparam.py: -------------------------------------------------------------------------------- 1 | """Test class for Global parameters CLI 2 | 3 | :Requirement: Globalparam 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Parameters 8 | 9 | :Team: Rocket 10 | 11 | :CaseImportance: Critical 12 | 13 | """ 14 | 15 | from functools import partial 16 | 17 | from fauxfactory import gen_string 18 | import pytest 19 | 20 | 21 | @pytest.mark.upgrade 22 | def test_positive_list_delete_by_name(module_target_sat): 23 | """Test Global Param List 24 | 25 | :id: 8dd6c4e8-4ec9-4bee-8a04-f5788960973a 26 | 27 | :expectedresults: Global Param is set, listed, and deleted by name 28 | """ 29 | alphastring = partial(gen_string, 'alpha', 10) 30 | 31 | name = f'opt-{alphastring()}' 32 | value = f'val-{alphastring()} {alphastring()}' 33 | 34 | # Create 35 | module_target_sat.cli.GlobalParameter().set({'name': name, 'value': value}) 36 | 37 | # List by name 38 | result = module_target_sat.cli.GlobalParameter().list({'search': name}) 39 | assert len(result) == 1 40 | assert result[0]['value'] == value 41 | 42 | # Delete 43 | module_target_sat.cli.GlobalParameter().delete({'name': name}) 44 | assert len(module_target_sat.cli.GlobalParameter().list({'search': name})) == 0 45 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_installer.py: -------------------------------------------------------------------------------- 1 | """Tests For Disconnected Satellite Installation 2 | 3 | :Requirement: Installation (disconnected satellite installation) 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Installation 8 | 9 | :Team: Platform 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | pytestmark = [pytest.mark.stubbed] 18 | 19 | 20 | # Notes for installer testing: 21 | # Perhaps there is a convenient log analyzer library out there 22 | # that can parse logs? It would be better (and possibly less 23 | # error-prone) than simply grepping for ERROR/FATAL 24 | 25 | 26 | def test_positive_server_installer_from_iso(): 27 | """Can install product from ISO 28 | 29 | :id: 38c08646-9f71-48d9-a9c2-66bd94c3e5bb 30 | 31 | :expectedresults: Install from ISO is successful. 32 | 33 | :CaseAutomation: NotAutomated 34 | """ 35 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_ping.py: -------------------------------------------------------------------------------- 1 | """Test Class for hammer ping 2 | 3 | :Requirement: Ping 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Hammer 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: Critical 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.pit_server 19 | @pytest.mark.upgrade 20 | @pytest.mark.parametrize('switch_user', [False, True], ids=['root', 'non-root']) 21 | def test_positive_ping(target_sat, switch_user): 22 | """hammer ping return code 23 | 24 | :id: dfa3ab4f-a64f-4a96-8c7f-d940df22b8bf 25 | 26 | :steps: 27 | 1. Execute hammer ping 28 | 2. Check its return code, should be 0 if all services are ok else 29 | != 0 30 | 31 | :expectedresults: hammer ping returns a right return code 32 | 33 | :parametrized: yes 34 | 35 | :BZ: 2122176, 2115775 36 | 37 | :customerscenario: true 38 | """ 39 | result = target_sat.execute(f"su - {'postgres' if switch_user else 'root'} -c 'hammer ping'") 40 | assert result.stderr == '' 41 | 42 | # Filter lines containing status 43 | statuses = [line for line in result.stdout.splitlines() if 'status:' in line.lower()] 44 | 45 | # Get count of total status lines and lines containing OK 46 | status_count = len(statuses) 47 | ok_count = len([status for status in statuses if status.split(':')[1].strip().lower() == 'ok']) 48 | 49 | if status_count == ok_count: 50 | assert result.status == 0, 'Return code should be 0 if all services are ok' 51 | else: 52 | assert result.status != 0, 'Return code should not be 0 if any service is not ok' 53 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_provisioning.py: -------------------------------------------------------------------------------- 1 | """Provisioning tests 2 | 3 | :Requirement: Provisioning 4 | 5 | :CaseAutomation: NotAutomated 6 | 7 | :CaseComponent: Provisioning 8 | 9 | :Team: Rocket 10 | 11 | :CaseImportance: Critical 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.stubbed 19 | @pytest.mark.on_premises_provisioning 20 | def test_rhel_pxe_provisioning_on_libvirt(): 21 | """Provision RHEL system via PXE on libvirt and make sure it behaves 22 | 23 | :id: a272a594-f758-40ef-95ec-813245e44b63 24 | 25 | :steps: 26 | 1. Provision RHEL system via PXE on libvirt 27 | 2. Check that resulting host is registered to Satellite 28 | 3. Check host can install package from Satellite 29 | 30 | :expectedresults: 31 | 1. Host installs 32 | 2. Host is registered to Satellite and subscription status is 'Success' 33 | 3. Host can install package from Satellite 34 | """ 35 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_puppetclass.py: -------------------------------------------------------------------------------- 1 | """Test class for Puppet Classes CLI 2 | 3 | :Requirement: Puppetclass 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Puppet 8 | 9 | :Team: Rocket 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | from robottelo.config import settings 18 | 19 | 20 | @pytest.mark.upgrade 21 | @pytest.mark.skipif((not settings.robottelo.REPOS_HOSTING_URL), reason="Missing repos_hosting_url") 22 | def test_positive_list_smart_class_parameters( 23 | module_import_puppet_module, session_puppet_enabled_sat 24 | ): 25 | """List smart class parameters associated with the puppet class. 26 | 27 | :id: 56b370c2-8fc6-49be-9676-242178cc709a 28 | 29 | :expectedresults: Smart class parameters listed for the class. 30 | """ 31 | class_sc_parameters = session_puppet_enabled_sat.cli.Puppet.sc_params( 32 | {'puppet-class': module_import_puppet_module['puppet_class']} 33 | ) 34 | assert len(class_sc_parameters) == 200 35 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_sso.py: -------------------------------------------------------------------------------- 1 | """Test class for SSO (CLI) 2 | 3 | :Requirement: Sso 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Authentication 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | pytestmark = [pytest.mark.stubbed, pytest.mark.upgrade] 18 | 19 | # Notes for SSO testing: 20 | # Of interest... In some testcases I've placed a few comments prefaced with 21 | # "devnote:" These are -- obviously -- notes from developers that might 22 | # help reiterate something important or a reminder of way(s) to test 23 | # something. 24 | 25 | # There may well be more cases that I have missed for this feature, and 26 | # possibly other LDAP types. These (in particular, the LDAP variations) 27 | # can be easily added later. 28 | 29 | 30 | def test_positive_login_kerberos_user(): 31 | """kerberos user can login to CLI 32 | 33 | :id: 59a1b463-67b3-4f18-b851-afaa3c65ccb6 34 | 35 | :setup: kerberos configured against foreman. 36 | 37 | :expectedresults: Log in to hammer cli successfully 38 | 39 | :CaseAutomation: NotAutomated 40 | """ 41 | 42 | 43 | def test_positive_login_ipa_user(): 44 | """IPA user can login to CLI 45 | 46 | :id: cbd0df84-6a4d-4c82-bf30-cecd51f40c03 47 | 48 | :setup: IPA configured against foreman. 49 | 50 | :expectedresults: Log in to hammer cli successfully 51 | 52 | :CaseAutomation: NotAutomated 53 | """ 54 | 55 | 56 | def test_positive_login_openldap_user(): 57 | """OpenLDAP user can login to CLI 58 | 59 | :id: de31d5eb-4e0d-495e-bf31-bc49f9d50d68 60 | 61 | :setup: OpenLDAP configured against foreman. 62 | 63 | :expectedresults: Log in to hammer cli successfully 64 | 65 | :CaseAutomation: NotAutomated 66 | """ 67 | -------------------------------------------------------------------------------- /tests/foreman/cli/test_usage_report.py: -------------------------------------------------------------------------------- 1 | """Tests related to the satellite usage report 2 | 3 | :Requirement: Hammer 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Hammer 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: Critical 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | def test_positive_usage_report_items(module_target_sat, module_report_keys, module_expected_keys): 19 | """check all expected entries are present in usage report 20 | 21 | :id: fe03c15f-4cd3-4282-988f-28112e60a909 22 | 23 | :expectedresults: All expected top-level entries are present 24 | 25 | """ 26 | if module_report_keys != module_expected_keys: 27 | added_items = module_report_keys - module_expected_keys 28 | removed_items = module_expected_keys - module_report_keys 29 | pytest.fail( 30 | f'Report field mismatch: added items: {added_items}, removed items: {removed_items}' 31 | ) 32 | -------------------------------------------------------------------------------- /tests/foreman/data/99-haproxy.conf: -------------------------------------------------------------------------------- 1 | $AddUnixListenSocket /var/lib/haproxy/dev/log 2 | 3 | # Send HAProxy messages to a dedicated logfile 4 | :programname, startswith, "haproxy" { 5 | /var/log/haproxy.log 6 | stop 7 | } 8 | # Used in Satellite Capsule Loadbalancer 9 | -------------------------------------------------------------------------------- /tests/foreman/data/ant-7.7.7-1.noarch.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/ant-7.7.7-1.noarch.rpm -------------------------------------------------------------------------------- /tests/foreman/data/emanuel.iso: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/emanuel.iso -------------------------------------------------------------------------------- /tests/foreman/data/expired-manifest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/expired-manifest.zip -------------------------------------------------------------------------------- /tests/foreman/data/extensions.txt: -------------------------------------------------------------------------------- 1 | [extensions] 2 | keyUsage = keyEncipherment 3 | subjectAltName = @alt_names 4 | 5 | [client_extensions] 6 | keyUsage = keyEncipherment 7 | extendedKeyUsage = clientAuth 8 | 9 | [wildcard_extensions] 10 | keyUsage = keyEncipherment 11 | subjectAltName = @wildcard_alt_names 12 | 13 | [shortname_extensions] 14 | keyUsage = keyEncipherment 15 | subjectAltName = @shortname_alt_names 16 | 17 | [alt_names] 18 | DNS.1 = foreman.example.com 19 | 20 | [wildcard_alt_names] 21 | DNS.1 = *.example.com 22 | 23 | [shortname_alt_names] 24 | DNS.1 = foreman 25 | -------------------------------------------------------------------------------- /tests/foreman/data/generate-ca.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | touch certindex.txt 4 | mkdir -p certs/ 5 | mkdir -p private/ 6 | 7 | export CERT_HOST="" 8 | sed -i 's//'$HOSTNAME'/g' ./openssl.cnf 9 | 10 | openssl req -new -x509 -extensions v3_ca -nodes -keyout private/cakey.crt \ 11 | -out cacert.crt -days 3650 -config ./openssl.cnf 12 | -------------------------------------------------------------------------------- /tests/foreman/data/generate-crt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | export CERT_HOST=$1 4 | if [[ -z $CERT_HOST ]] ; then 5 | echo "Usage: $0 CERT_HOST" 6 | exit 1 7 | fi 8 | 9 | mkdir $CERT_HOST 10 | cat < /tmp/diskpart.cfg 17 | zerombr yes 18 | clearpart --all --initlabel 19 | part swap --size "$vir_mem" 20 | part /boot --fstype ext3 --size 100 --asprimary 21 | part / --fstype ext3 --size 1024 --grow 22 | EOF 23 | -------------------------------------------------------------------------------- /tests/foreman/data/puppet_custom_selinux-0.3.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/puppet_custom_selinux-0.3.1.tar.gz -------------------------------------------------------------------------------- /tests/foreman/data/puppetlabs-ntp-3.2.1.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/puppetlabs-ntp-3.2.1.tar.gz -------------------------------------------------------------------------------- /tests/foreman/data/report_template.txt: -------------------------------------------------------------------------------- 1 | # this custom template only generate report with all hosts 2 | <%# 3 | name: Custom template 4 | snippet: false 5 | model: ReportTemplate 6 | -%> 7 | <%- load_hosts().each_record do |host| -%> 8 | <%- report_row({ 9 | 'Name': host.name, 10 | 'Operating System': host.operatingsystem, 11 | }) -%> 12 | <%- end -%> 13 | <%= report_render -%> 14 | -------------------------------------------------------------------------------- /tests/foreman/data/scap-security-guide-satellite-4.3.4-1.el9sat.noarch.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/scap-security-guide-satellite-4.3.4-1.el9sat.noarch.rpm -------------------------------------------------------------------------------- /tests/foreman/data/scap-security-guide-satellite-4.3.4-1.el9sat.noarch.rpm.txt: -------------------------------------------------------------------------------- 1 | This is an artificially built SCAP content for testing purposes. It is intentionally an rpm with big version so it can be used for a long time. This content contains one policy "ANSSI-BP-028 (enhanced)" and within it one test "Set Password Minimum Length in login.defs" applicable to RHEL9. 2 | -------------------------------------------------------------------------------- /tests/foreman/data/scap-security-guide-satellite-4.3.5-1.el9sat.noarch.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/scap-security-guide-satellite-4.3.5-1.el9sat.noarch.rpm -------------------------------------------------------------------------------- /tests/foreman/data/scap-security-guide-satellite-4.3.5-1.el9sat.noarch.rpm.txt: -------------------------------------------------------------------------------- 1 | This is an artificially built SCAP content for testing purposes. It is intentionally an rpm with big version (even bigger than the other scap content rpm) so it can be used for a long time (and updates the other rpm). This content contains one policy "ANSSI-BP-028 (enhanced)" and within it one test "Set Password Minimum Length in FISH" applicable to RHEL9. The only purpose of this file is to check the difference between the uploaded SCAP contents by checking for presence of "FISH". 2 | -------------------------------------------------------------------------------- /tests/foreman/data/snippet.txt: -------------------------------------------------------------------------------- 1 | kind: snippet 2 | name: puppet.conf 3 | %> 4 | [main] 5 | <% if @host.operatingsystem.name == "Red Hat" -%> 6 | vardir = /var/puppet 7 | logdir = \$vardir/log 8 | <% else -%> 9 | vardir = /var/lib/puppet 10 | logdir = /var/log/puppet 11 | <% end -%> 12 | rundir = /var/run/puppet 13 | ssldir = \$vardir/ssl 14 | -------------------------------------------------------------------------------- /tests/foreman/data/sshkeys.json: -------------------------------------------------------------------------------- 1 | { 2 | "ssh_keys": { 3 | "invalid_ssh_key": "ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA5mX2JV6T6CVCRmTlC9vrpgEQp259XQYBKIkhWeHtJXGe8bV6RWxR07deny/coS3OZ0TcM8nXb3J3mykaF1xAK+9nXljcIJy76Us9bjXS25UVXQ18DMOQ0mKR3u29jYjw0TCGBUZxjpOTiUudCoAI7i3XHanQz0vyQaKOhDa1fDb3Qc4hKujJYf76J/XPYpb5DHYcWxELgCFo5MWRnYex2L92gm1xcx1CAPVN5JbpIxhkHuXIJx0JBhJAHUvYopByK0ZNFqMkgylVwvuY2gmo085cO6I5GL23NnaKjLKJo7LLPQpJZ1BscMIyrwQTm2CAvJMok6vh88WsB/TI7XXXXX== ares@bart", 4 | "dsa":"ssh-dss AAAAB3NzaC1kc3MAAACBAJn1wEw42PMfGk8BvMsrO3iE8oD6f+NfPhbi74gkW7nlrZcdWRhD+VkyDXwuCkDSxX6lFCJUnVzlheLf+kvAWBopeallZAj/jf7wYjrKElQooO9fMbXMN1fWWnLqL60gE1jybDVoIpILQ/cL7dDzncVH7BkG7iSfcAA59xeXb1O7AAAAFQCuUtss2zhtGxWmtHFncJYhjAbTbwAAAIBULfrBSOjcrHxfi3vzL5nfL/Pkf701xACLs86DE5EUc2Ry6sHb6GhnSP1JE6W+WVmNNteISLyASt1E3m+F9tczc8KG3T5FKA53qBU86FH3/tR+Tu4UAzDhdIJT+4rkbqpT6kR+gNLIZInvN1WGfDDZooGwAaDljBL6Sh4eqtY60AAAAIANHkgBsyVZmPMuVB+RftXZeypUMqKnj3MXIW0+CWB5g8qFxqVKxvKSO3WqP9CzYv3fsOv9LfSLV5AnPWbFJndkKg5M3mbP52eEkrNyasX0d1Z+uBvqh76CwD8eiHnT/yvrj9IFrMqENQKAi7/vBoaUlq2CCydOCA4Sh0UQnh1CNQ==", 5 | "ecdsa":"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHHS2KmNyIYa27Qaa7EHp+2l99ucGStx4P77e03ZvE3yVRJEFikPoP3MJtYYfIe8k1/46MTIZO9CPTX4CYUHEN8=", 6 | "ed":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBrJJAjl+ZGCQ7Y6L97a9UcM/CXCKDP/JD/ndUtNHBW1" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/foreman/data/uri.sh: -------------------------------------------------------------------------------- 1 | echo "Hello!" >/var/tmp/hello.txt 2 | -------------------------------------------------------------------------------- /tests/foreman/data/which-2.19-6.el6.src.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/which-2.19-6.el6.src.rpm -------------------------------------------------------------------------------- /tests/foreman/data/which-2.19-6.el6.x86_64.rpm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/data/which-2.19-6.el6.x86_64.rpm -------------------------------------------------------------------------------- /tests/foreman/data/zoo_custom_gpgkey.txt: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG v1.4.11 (GNU/Linux) 3 | 4 | mQENBE8NW6EBCAC/ht3UujFwxol44zilXcwI8v15gf6X4u3A5Oo2FCEweQfbZw8q 5 | lPGjzRNHcNVO4NIZ+G1fHyWAgcs/xa4fTju4LOJU2OWfbkvGA7tlIIREkEQ9IgMI 6 | i0LJzsHyqhWhJ0S5POCLFyH27R0Vh2wPMwZawoomRVDsghIE8TAJVKIHICVObvGE 7 | VqBGSY1OHvGfZ0ZsnQv3hDmxnyywJkJ96HGVqStS2sW0YkQ77dRY0u6eSI55vwBQ 8 | iV9dCSMs43LpoBL9pFj0ESM76G0GSGF5G9PH2b//y8ehepdS30otiqgjag5Zw76b 9 | qFMHFyq1o5hXJpIPiZaagU1X+wMixPOlqE5LABEBAAG0MER1bW15IFBhY2thZ2Vz 10 | IEdlbmVyYXRvciA8YWRtaW5Aem9vLmV4YW1wbGUuY29tPokBOAQTAQIAIgUCTw1b 11 | oQIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AACgkQ74XM4/ePsZVeCgf+L+HW 12 | f0K7/uzu3Q7G+aOu7qwu0iUK64SEAgtoMdjpjkq+YYxPS60zP7QS3pAzL4N31kT/ 13 | kHQ+OJAg5Z0oegXu9mdhIenks2DaEzN6P2jAhWoRa/az5F9AaJ01WSsspsBpcAyt 14 | 3NB2iGNtzs4v6saUz5mTp1bgmsXolzClHlTSUnjjCfuk7HgzJcCpRxb49tQ5Lo3b 15 | 9k0XPvhhgSdiTFM+CfPl3qgHPENZqyoDOnhvKbMHZg8NCf1NLf8edlk5nWDjHti8 16 | VfkuCSgRzR15SgyEUU1MCQBPEYKy8U6LoOwX8Rl3+lCf9D7rReP74wSEdr9p9cFi 17 | SCFpN6IUJ9pN0tDU3rkBDQRPDVuhAQgAmZB+DKbraTgeW1UOYS/HWzGOR21NR3nq 18 | sxeG249W3OlsZbk/8BJP/DqFAhVbdxvISFkSKURoVXxUwoKx36KZHXIOgCt3vsj5 19 | u2mxF2ajrHBwzM8jrrNy8xdd4DplOP2D0DbuswDi5pqmd/Cd0EdC88ZIPt3Ox/GH 20 | 4uCJOzkCRFcFRZhOT+YC+A3YaVg4UoR3AMup8K81Nm2y8q1pUy/gZvkWMONy5iDX 21 | lyU6enBNv+vmhumyYJT8+rPRW/ztsaBzkvpuXkQTJdWDQbigeK1hBNV5PCjyQydj 22 | P+sKrMxKjyyZ0rcGP1hcCqZuBHZlW0O2WJFKsZv+fY8UJfU08FeAqQARAQABiQEf 23 | BBgBAgAJBQJPDVuhAhsMAAoJEO+FzOP3j7GVhlsH/0emlW/Nk0bSUG4jfAeJAB7H 24 | KRYbr5P/YbbFLEOb4yi2DlPxUac0JoXCMLha9G9LBmQ4IL4qPHdycSlEs4cGBX6W 25 | xn1ti6rJ3LWm5Hb7iUBfIeuKW31thTJK7SAruiBk7g1/I55HlFW0LEfgfVUQf6hJ 26 | 9Rnw6YVXyQAod1x/QmLWw5aQcoksHL/4eRpU74EjuKQdZMLuaherKtY6OTtEDTdm 27 | bEdEINVqR5hYEHgDEPPrPb5MDbQsrMEAwdWPqC2/9cgacO33/VuvXDu74X+TwE/c 28 | OGRCb385XPNS9KApQ4iRTZ6ccOnSJumZbeTTd9DBFwa+T1/xD96yabnaOdJqf6Y= 29 | =RrIG 30 | -----END PGP PUBLIC KEY BLOCK----- 31 | -------------------------------------------------------------------------------- /tests/foreman/destructive/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/destructive/__init__.py -------------------------------------------------------------------------------- /tests/foreman/destructive/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from robottelo.constants import DEFAULT_ORG 4 | 5 | 6 | @pytest.fixture 7 | def default_org(target_sat): 8 | return target_sat.api.Organization().search(query={'search': f'name="{DEFAULT_ORG}"'})[0] 9 | 10 | 11 | @pytest.fixture 12 | def session(module_target_sat, test_name, ui_user, request): 13 | """Session fixture which automatically initializes (but does not start!) 14 | airgun UI session and correctly passes current test name to it. Uses shared 15 | module user credentials to log in. 16 | 17 | Usage:: 18 | 19 | def test_foo(session): 20 | with session: 21 | # your ui test steps here 22 | session.architecture.create({'name': 'bar'}) 23 | """ 24 | with module_target_sat.ui_session(test_name, ui_user.login, ui_user.password) as session: 25 | yield session 26 | -------------------------------------------------------------------------------- /tests/foreman/destructive/test_foreman_rake.py: -------------------------------------------------------------------------------- 1 | """Test class foreman_rake 2 | 3 | :Requirement: TasksPlugin 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseImportance: Medium 8 | 9 | :CaseComponent: TasksPlugin 10 | 11 | :Team: Endeavour 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | pytestmark = pytest.mark.destructive 18 | 19 | 20 | def test_positive_katello_reimport(target_sat): 21 | """Close loop bug for running katello:reimport. Making sure 22 | that katello:reimport works and doesn't throw an error. 23 | 24 | :id: b4119265-1bf0-4b0b-8b96-43f68af39708 25 | 26 | :steps: Have satellite up and run 'foreman-rake katello:reimport' 27 | 28 | :expectedresults: Successfully reimport without errors 29 | 30 | :bz: 1771555 31 | 32 | :customerscenario: true 33 | """ 34 | 35 | result = target_sat.execute('foreman-rake katello:reimport') 36 | assert 'NoMethodError:' not in result.stdout 37 | assert 'rake aborted!' not in result.stdout 38 | -------------------------------------------------------------------------------- /tests/foreman/destructive/test_foreman_service.py: -------------------------------------------------------------------------------- 1 | """Test class Foreman Service Integration with Apache 2 | 3 | :Requirement: Other 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseImportance: Medium 8 | 9 | """ 10 | 11 | import pytest 12 | 13 | from robottelo.constants import DEFAULT_ORG 14 | 15 | pytestmark = pytest.mark.destructive 16 | 17 | 18 | @pytest.mark.upgrade 19 | def test_positive_foreman_service_auto_restart(foreman_service_teardown): 20 | """Foreman Service should get auto-restarted in case it is halted or stopped for some reason 21 | 22 | :CaseComponent: Infrastructure 23 | 24 | :Team: Platform 25 | 26 | :id: 766560b8-30bb-11eb-8dae-d46d6dd3b5b2 27 | 28 | :steps: 29 | 1. Stop the Foreman Service 30 | 2. Make any API call to Satellite 31 | 32 | :expectedresults: Foreman Service should get restarted automatically 33 | """ 34 | sat = foreman_service_teardown 35 | sat.execute('systemctl stop foreman') 36 | result = sat.execute('satellite-maintain service status --only=foreman') 37 | assert result.status == 1 38 | assert 'not running (foreman)' in result.stdout 39 | assert sat.api.Organization().search(query={'search': f'name="{DEFAULT_ORG}"'})[0] 40 | sat.execute('satellite-maintain service status --only=foreman') 41 | -------------------------------------------------------------------------------- /tests/foreman/destructive/test_leapp_satellite.py: -------------------------------------------------------------------------------- 1 | """Tests for leapp upgrade of Satellite 2 | 3 | :CaseAutomation: Automated 4 | 5 | :CaseComponent: Upgrades 6 | 7 | :Team: Platform 8 | 9 | :CaseImportance: High 10 | 11 | """ 12 | 13 | from broker import Broker 14 | import pytest 15 | 16 | from robottelo.hosts import get_sat_rhel_version, get_sat_version 17 | 18 | 19 | @pytest.mark.e2e 20 | @pytest.mark.pit_server 21 | @pytest.mark.skipif( 22 | get_sat_version().minor != 16 or get_sat_rhel_version().major != 8, 23 | reason='Run only on Satellite 6.16 el8', 24 | ) 25 | def test_positive_leapp(target_sat): 26 | """Upgrade satellite's RHEL version using leapp 27 | 28 | :id: 761d4503-0b8c-494d-add5-b870fe1b90b9 29 | 30 | :steps: 31 | 1. Get satellite on source rhel version 32 | 2. Run job template that upgrades satellite to target rhel version 33 | 3. Check results 34 | 35 | :expectedresult: 36 | 1. Rhel version of the satellite has been updated 37 | """ 38 | # Getting original RHEL version so we can increment it later in the test 39 | orig_rhel_ver = target_sat.os_version.major 40 | Broker().execute( 41 | job_template="satellite-leapp-upgrade", 42 | target_vm=target_sat.name, 43 | ) 44 | # Recreate the session object within a Satellite object after upgrading 45 | target_sat.connect() 46 | # Clean cached properties after the upgrade 47 | target_sat.clean_cached_properties() 48 | # Get RHEL version after upgrading 49 | res_rhel_version = target_sat.os_version.major 50 | # Check if RHEL was upgraded 51 | assert res_rhel_version == orig_rhel_ver + 1, 'RHEL was not upgraded' 52 | # Check satellite's health 53 | sat_health = target_sat.execute('satellite-maintain health check') 54 | assert sat_health.status == 0, 'Satellite health check failed' 55 | -------------------------------------------------------------------------------- /tests/foreman/destructive/test_ping.py: -------------------------------------------------------------------------------- 1 | """Test Class for hammer ping 2 | 3 | :Requirement: Ping 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Hammer 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: Critical 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | pytestmark = pytest.mark.destructive 18 | 19 | 20 | @pytest.fixture(scope='module') 21 | def tomcat_service_teardown(request, module_target_sat): 22 | assert module_target_sat.cli.Service.stop(options={'only': 'tomcat.service'}).status == 0 23 | 24 | @request.addfinalizer 25 | def _finalize(): 26 | assert module_target_sat.cli.Service.start(options={'only': 'tomcat.service'}).status == 0 27 | 28 | return module_target_sat 29 | 30 | 31 | def test_negative_cli_ping_fail_status(tomcat_service_teardown): 32 | """Negative test to verify non-zero status code of CLI ping fail 33 | 34 | :id: 8f8675aa-df52-11eb-9353-b0a460e02491 35 | 36 | :customerscenario: true 37 | 38 | :BZ: 1941240 39 | 40 | :expectedresults: Hammer ping fails and returns non-zero(1) status code. 41 | """ 42 | result = tomcat_service_teardown.execute("hammer ping") 43 | assert result.status == 1 44 | 45 | 46 | def test_negative_api_ping_fail_status(tomcat_service_teardown): 47 | """Negative test to verify FAIL status when API ping fail 48 | 49 | :id: 6bd2c552-29d7-4f49-81dd-f8d5ff0e7c39 50 | 51 | :customerscenario: true 52 | 53 | :BZ: 1835122 54 | 55 | :CaseComponent: API 56 | 57 | :expectedresults: API ping fails and shows FAIL status. 58 | """ 59 | response = tomcat_service_teardown.api.Ping().search_json() 60 | assert response['status'] == 'FAIL' 61 | -------------------------------------------------------------------------------- /tests/foreman/endtoend/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/endtoend/__init__.py -------------------------------------------------------------------------------- /tests/foreman/installer/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/installer/__init__.py -------------------------------------------------------------------------------- /tests/foreman/installer/test_infoblox.py: -------------------------------------------------------------------------------- 1 | """Tests for Infoblox Plugin 2 | 3 | :Requirement: Infoblox, Installer 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: DHCPDNS 8 | 9 | :Team: Rocket 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.stubbed 19 | @pytest.mark.upgrade 20 | def test_dhcp_ip_range(): 21 | """Check host get IP from Infoblox IP range while provisioning a host 22 | 23 | :id: ba957e82-79bb-11e6-94c5-68f72889dc7f 24 | 25 | :steps: Provision a host with infoblox as dhcp provider 26 | 27 | :expectedresults: Check host ip is on infoblox range configured by 28 | option --foreman-proxy-plugin-dhcp-infoblox-use-ranges=true 29 | 30 | :CaseAutomation: NotAutomated 31 | """ 32 | 33 | 34 | @pytest.mark.stubbed 35 | @pytest.mark.upgrade 36 | def test_dns_records(): 37 | """Check DNS records are updated via infoblox DNS plugin 38 | 39 | :id: 007ad06e-79bc-11e6-885f-68f72889dc7f 40 | 41 | :steps: 42 | 43 | 1. Provision a host with infoblox as dns provider 44 | 2. Update a DNS record on infoblox 45 | 46 | :expectedresults: Check host dns is updated accordingly to infoblox 47 | 48 | :CaseAutomation: NotAutomated 49 | """ 50 | -------------------------------------------------------------------------------- /tests/foreman/longrun/__init__.py: -------------------------------------------------------------------------------- 1 | """These tests may take a long time to run.""" 2 | -------------------------------------------------------------------------------- /tests/foreman/longrun/test_remoteexecution.py: -------------------------------------------------------------------------------- 1 | """Test module for Remote Execution 2 | 3 | :Requirement: Remoteexecution 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: RemoteExecution 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.rhel_ver_list([9]) 19 | def test_positive_run_long_job(module_org, rex_contenthost, module_target_sat): 20 | """Run a long running job 21 | 22 | :id: 76934868-89e6-4eb6-905e-d0d5ededc077 23 | 24 | :expectedresults: Verify the long job was successfully ran and not terminated too soon 25 | 26 | :bz: 2270295 27 | 28 | :parametrized: yes 29 | """ 30 | client = rex_contenthost 31 | invocation_command = module_target_sat.cli_factory.job_invocation( 32 | { 33 | 'job-template': 'Run Command - Script Default', 34 | 'inputs': 'command=sleep 700', 35 | 'search-query': f"name ~ {client.hostname}", 36 | }, 37 | timeout='800s', 38 | ) 39 | result = module_target_sat.cli.JobInvocation.info({'id': invocation_command['id']}) 40 | try: 41 | assert result['success'] == '1' 42 | except AssertionError as err: 43 | raise AssertionError( 44 | 'host output: {}'.format( 45 | ' '.join( 46 | module_target_sat.cli.JobInvocation.get_output( 47 | {'id': invocation_command['id'], 'host': client.hostname} 48 | ) 49 | ) 50 | ) 51 | ) from err 52 | -------------------------------------------------------------------------------- /tests/foreman/maintain/test_offload_DB.py: -------------------------------------------------------------------------------- 1 | """Test class for Offload DB functionality 2 | 3 | :Requirement: Offload DBs from Satellite Server 4 | 5 | :CaseAutomation: ManualOnly 6 | 7 | :CaseComponent: SatelliteMaintain 8 | 9 | :Team: Platform 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | from robottelo.config import settings 18 | 19 | 20 | @pytest.mark.stubbed 21 | @pytest.mark.skipif((not settings.remotedb.server), reason='Intended only for RemoteDB setup') 22 | def test_offload_internal_db_to_external_db_host(): 23 | """Offload internal databases content to an external database host 24 | 25 | :id: d07235c8-4584-469a-a87d-ace4dadb0a1f 26 | 27 | :steps: Run satellite-installer with foreman, candlepin and pulpcore options 28 | referring to external DB host 29 | 30 | :expectedresults: Installed successful, all services running 31 | 32 | :CaseComponent: Installation 33 | """ 34 | -------------------------------------------------------------------------------- /tests/foreman/sys/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/sys/__init__.py -------------------------------------------------------------------------------- /tests/foreman/sys/test_dynflow.py: -------------------------------------------------------------------------------- 1 | """Test class for Dynflow 2 | 3 | :CaseAutomation: Automated 4 | 5 | :CaseComponent: TasksPlugin 6 | 7 | :Team: Endeavour 8 | 9 | :Requirement: TasksPlugin 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.e2e 19 | def test_positive_setup_dynflow(target_sat): 20 | """Set dynflow parameters, restart it and check it adheres to them 21 | 22 | :id: a5aaab5e-bc18-453e-a284-64aef752ec88 23 | 24 | :expectedresults: Correct dynflow processes are running, respecting settings 25 | """ 26 | commands = [ 27 | 'cd /etc/foreman/dynflow/', 28 | 'cp worker-hosts-queue-1.yml test.yml', 29 | 'sed -i s/5/6/ test.yml', 30 | "systemctl restart 'dynflow-sidekiq@test'", 31 | "while ! systemctl status 'dynflow-sidekiq@test' -l | " # no comma here 32 | "grep -q ' of 6 busy' ; do sleep 0.5 ; done", 33 | ] 34 | # if thread count is not respected or the process is not running, this should timeout 35 | assert target_sat.execute(' && '.join(commands)).status == 0 36 | target_sat.execute("systemctl stop 'dynflow-sidekiq@test'; rm /etc/foreman/dynflow/test.yml") 37 | -------------------------------------------------------------------------------- /tests/foreman/sys/test_webpack.py: -------------------------------------------------------------------------------- 1 | """Test class for Webpack 2 | 3 | :CaseAutomation: Automated 4 | 5 | :CaseComponent: Installation 6 | 7 | :Requirement: Installation 8 | 9 | :Team: Endeavour 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | 16 | def test_positive_webpack5(target_sat): 17 | """Check whether Webpack 5 was used at packaging time 18 | 19 | :id: b7f3fbb2-ef4b-4634-877f-b8ea10373e04 20 | 21 | :Verifies: SAT-5741 22 | 23 | :expectedresults: There is a file "public/webpack/foreman_tasks/foreman_tasks_remoteEntry.js" when Webpack 5 has been used. It used to be "public/webpack/foreman-tasks-.js" before. 24 | """ 25 | assert ( 26 | target_sat.execute( 27 | "find /usr/share/gems | grep public/webpack/foreman_tasks/foreman_tasks_remoteEntry.js" 28 | ).status 29 | == 0 30 | ) 31 | -------------------------------------------------------------------------------- /tests/foreman/ui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/ui/__init__.py -------------------------------------------------------------------------------- /tests/foreman/ui/conftest.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/ui/conftest.py -------------------------------------------------------------------------------- /tests/foreman/ui/test_branding.py: -------------------------------------------------------------------------------- 1 | """Tests for branding 2 | 3 | :Requirement: Branding 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Branding 8 | 9 | :Team: Platform 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.e2e 19 | def test_verify_satellite_login_screen_info(target_sat): 20 | """Verify Satellite version on the login screen 21 | 22 | :id: f48110ad-29b4-49b1-972a-a70075a05732 23 | 24 | :steps: Get the info from the login screen 25 | 26 | :expectedresults: 27 | 1. Correct Satellite version 28 | 2. If 'Beta' is present, should fail until a GA snap is received 29 | 30 | :BZ: 1315849, 1367495, 1372436, 1502098, 1540710, 1582476, 1724738, 31 | 1959135, 2076979, 1687250, 1686540, 1742872, 1805642, 2105949 32 | """ 33 | with target_sat.ui_session(login=False) as session: 34 | version = session.login.read_sat_version() 35 | assert f'Version {target_sat.version}' == version['login_text'] 36 | assert 'Beta' not in version['login_text'], '"Beta" should not be there' 37 | -------------------------------------------------------------------------------- /tests/foreman/ui/test_config_group.py: -------------------------------------------------------------------------------- 1 | """Test class for Config Groups UI 2 | 3 | :Requirement: Config Group 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Puppet 8 | 9 | :Team: Rocket 10 | 11 | :CaseImportance: Low 12 | 13 | """ 14 | 15 | from fauxfactory import gen_string 16 | import pytest 17 | 18 | 19 | @pytest.fixture(scope='module') 20 | def module_puppet_class(session_puppet_enabled_sat): 21 | return session_puppet_enabled_sat.api.PuppetClass().create() 22 | 23 | 24 | @pytest.mark.e2e 25 | @pytest.mark.upgrade 26 | def test_positive_end_to_end(session_puppet_enabled_sat, module_puppet_class): 27 | """Perform end to end testing for config group component 28 | 29 | :id: 3ac47175-1239-4481-9ae2-e31980fb6607 30 | 31 | :expectedresults: All expected CRUD actions finished successfully 32 | 33 | :CaseImportance: High 34 | """ 35 | name = gen_string('alpha') 36 | new_name = gen_string('alpha') 37 | with session_puppet_enabled_sat.ui_session() as session: 38 | # Create new config group 39 | session.configgroup.create({'name': name, 'classes.assigned': [module_puppet_class.name]}) 40 | assert session.configgroup.search(name)[0]['Name'] == name 41 | values = session.configgroup.read(name) 42 | assert values['name'] == name 43 | assert len(values['classes']['assigned']) == 1 44 | assert values['classes']['assigned'][0] == module_puppet_class.name 45 | # Update config group with new name 46 | session.configgroup.update(name, {'name': new_name}) 47 | assert session.configgroup.search(new_name)[0]['Name'] == new_name 48 | assert not session.configgroup.search(name) 49 | # Delete config group 50 | session.configgroup.delete(new_name) 51 | assert not session.configgroup.search(new_name) 52 | -------------------------------------------------------------------------------- /tests/foreman/ui/test_flatpak.py: -------------------------------------------------------------------------------- 1 | """Flatpak related tests being run through UI. 2 | 3 | :Requirement: Repository 4 | 5 | :CaseAutomation: Automated 6 | 7 | :CaseComponent: Repositories 8 | 9 | :team: Phoenix-content 10 | 11 | :CaseImportance: High 12 | 13 | """ 14 | 15 | 16 | def test_flatpak_remotes(target_sat, function_org, function_flatpak_remote): 17 | """Ensure Flatpak Remotes are displayed correctly. 18 | 19 | :id: c757094c-e817-4a1b-a8b3-d2ce3f9d6b0e 20 | 21 | :setup: 22 | 1. Create a flatpak remote in an Organization and scan it. 23 | 24 | :steps: 25 | 1. Select the Organization owning the remote. 26 | 2. Navigate to Flatpak Remotes page and read the table. 27 | 28 | :expectedresults: 29 | 1. The remote is displayed correctly. 30 | 31 | """ 32 | with target_sat.ui_session() as session: 33 | session.organization.select(function_org.name) 34 | remotes = session.flatpak_remotes.read_table() 35 | assert len(remotes) == 1 36 | remote = remotes[0] 37 | assert remote['Name'] == function_flatpak_remote.remote.name 38 | assert remote['URL'] == function_flatpak_remote.remote.flatpak_index_url 39 | -------------------------------------------------------------------------------- /tests/foreman/virtwho/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/virtwho/__init__.py -------------------------------------------------------------------------------- /tests/foreman/virtwho/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/virtwho/api/__init__.py -------------------------------------------------------------------------------- /tests/foreman/virtwho/cli/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/virtwho/cli/__init__.py -------------------------------------------------------------------------------- /tests/foreman/virtwho/ui/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/foreman/virtwho/ui/__init__.py -------------------------------------------------------------------------------- /tests/new_upgrades/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/new_upgrades/__init__.py -------------------------------------------------------------------------------- /tests/robottelo/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SatelliteQE/robottelo/5f98fa0f0a67403ea2914b552d6c03acad7a8f19/tests/robottelo/__init__.py -------------------------------------------------------------------------------- /tests/robottelo/conftest.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import glob 3 | import os 4 | from pathlib import Path 5 | from tempfile import NamedTemporaryFile 6 | 7 | from fauxfactory import gen_string 8 | import pytest 9 | 10 | 11 | @pytest.fixture(scope='session', autouse=True) 12 | def align_to_satellite(): 13 | """Override align_to_satellite used in functional tests""" 14 | pass 15 | 16 | 17 | @pytest.fixture 18 | def dummy_test(request): 19 | """This should be indirectly parametrized to provide dynamic dummy_tests to exec_test""" 20 | return request.param 21 | 22 | 23 | @pytest.fixture 24 | def exec_test(request, dummy_test): 25 | """Create a temporary file with the string provided by dummy_test, and run it with pytest.main 26 | 27 | pytest arguments can be indirectly parametrized, and are handled as a string 28 | 29 | Writes and returns a junit-xml file 30 | 31 | """ 32 | param_args = getattr(request, 'param', None) 33 | pytest_args = ['--capture=sys', '-q'] 34 | if param_args: 35 | pytest_args.append(param_args) 36 | test_dir = str(Path(__file__).parent) 37 | report_file = f'report_{gen_string("alphanumeric")}.xml' 38 | pytest_args.append(f'--junit-xml={report_file}') 39 | with NamedTemporaryFile(dir=test_dir, mode='w', prefix='test_', suffix='.py') as f: 40 | f.seek(0) 41 | f.write(dummy_test['body']) 42 | f.flush() 43 | pytest_args.append(f'{f.name}::{dummy_test["name"]}') 44 | pytest.main(pytest_args) 45 | yield report_file 46 | for logfile in glob.glob('robottelo*.log'): 47 | os.remove(logfile) 48 | with contextlib.suppress(OSError): 49 | # the file might not exist if the test fails prematurely 50 | os.remove(report_file) 51 | -------------------------------------------------------------------------------- /tests/robottelo/data/test_dsa.key: -------------------------------------------------------------------------------- 1 | -----BEGIN DSA PRIVATE KEY----- 2 | MIIBuwIBAAKBgQDngaYDZ30c6/7cJgEEbtl8FgKdwhba1Z7oOrOn4MI/6C42G1bY 3 | wMuqZf4dBCglsdq39SHrcjbE8Vq54gPSOh3g4+uV9Rcg5IOoPLbwp2jQfF6f1FIb 4 | sx7hrDCIqUcQccPSxetPBKmXI9RN8rZLaFuQeTnI65BKM98Ruwvq6SI2LwIVAPDP 5 | hSeawaJI27mKqOfe5PPBSmyHAoGBAJMXxXmPD9sGaQ419DIpmZecJKBUAy9uXD8x 6 | gbgeDpwfDaFJP8owByCKREocPFfi86LjCuQkyUKOfjYMN6iHIf1oEZjB8uJAatUr 7 | FzI0ArXtUqOhwTLwTyFuUojE5own2WYsOAGByvgfyWjsGhvckYNhI4ODpNdPlxQ8 8 | ZamaPGPsAoGARmR7CCPjodxASvRbIyzaVpZoJ/Z6x7dAumV+ysrV1BVYd0lYukmn 9 | jO1kKBWApqpH1ve9XDQYN8zgxM4b16L21kpoWQnZtXrY3GZ4/it9kUgyB7+NwacI 10 | BlXa8cMDL7Q/69o0d54U0X/NeX5QxuYR6OMJlrkQB7oiW/P/1mwjQgECFGI9QPSc 11 | h9pT9XHqn+1rZ4bK+QGA 12 | -----END DSA PRIVATE KEY----- 13 | -------------------------------------------------------------------------------- /tests/robottelo/test_decorators.py: -------------------------------------------------------------------------------- 1 | """Unit tests for :mod:`robottelo.utils.decorators`.""" 2 | 3 | from unittest import mock 4 | 5 | import pytest 6 | 7 | from robottelo.utils import decorators 8 | 9 | 10 | class TestCacheable: 11 | """Tests for :func:`robottelo.utils.decorators.cacheable`.""" 12 | 13 | @pytest.fixture 14 | def make_foo(self): 15 | mocked_object_cache_patcher = mock.patch.dict('robottelo.utils.decorators.OBJECT_CACHE') 16 | mocked_object_cache_patcher.start() 17 | 18 | # decorators.cacheable uses the function name as the key, removing make_ 19 | def make_foo(options): 20 | return {'id': 42} 21 | 22 | yield decorators.cacheable(make_foo) 23 | 24 | mocked_object_cache_patcher.stop() 25 | 26 | def test_create_and_not_add_to_cache(self, make_foo): 27 | """Create a new object and not add it to the cache. 28 | First test in the class, as the other tests add to the cache 29 | """ 30 | make_foo(cached=False) 31 | assert 'foo' not in decorators.OBJECT_CACHE 32 | assert decorators.OBJECT_CACHE == {} 33 | 34 | def test_build_cache(self, make_foo): 35 | """Create a new object and add it to the cache.""" 36 | obj = make_foo(cached=True) 37 | assert decorators.OBJECT_CACHE == {'foo': {'id': 42}} 38 | assert id(decorators.OBJECT_CACHE['foo']) == id(obj) 39 | 40 | def test_return_from_cache(self, make_foo): 41 | """Return an already cached object.""" 42 | cache_obj = {'id': 42} 43 | decorators.OBJECT_CACHE['foo'] = cache_obj 44 | obj = make_foo(cached=True) 45 | assert id(cache_obj) == id(obj) 46 | -------------------------------------------------------------------------------- /tests/upgrades/__init__.py: -------------------------------------------------------------------------------- 1 | """Placeholder for the package""" 2 | --------------------------------------------------------------------------------