From a33f706287cb1dcf46d78cac817bb20cc9f9df37 Mon Sep 17 00:00:00 2001 From: Jitendra Yejare Date: Thu, 21 Jan 2021 17:09:46 +0530 Subject: [PATCH] DynaConf CI native changes required in Robottelo * Dynaconf Native Airgun and Nailgun configuration * Initial Robottelo and Server DynaConf YAMLs - The robottelo copy of Gitlab SateQE Jenkins * Commented non-default settings instead of placeholder * New repos missed in robottelo from jenkins-configs * Tools and RHEL8_OS repo dependent tests updated for new dynaconf YAMLs * Removed Robottelo and Server sections from robottelo.properties.sample * Separate repos.yaml and swapped the places of robottelo and server settings in YAML * Logging updated for dynaconf. robottelo and server settings base config removed --- .github/workflows/merge_to_master.yml | 1 + .github/workflows/pull_request.yml | 1 + conf/repos.yaml.template | 31 +++++ conf/robottelo.yaml.template | 62 +++++++++ conf/server.yaml.template | 27 ++++ pytest_fixtures/xdist.py | 4 +- robottelo.properties.sample | 139 ------------------- robottelo/cli/factory.py | 8 +- robottelo/config/__init__.py | 5 + robottelo/config/base.py | 187 -------------------------- robottelo/config/facade.py | 157 +++++++++++++++++++++ robottelo/hosts.py | 4 +- robottelo/vm.py | 4 +- tests/foreman/longrun/test_oscap.py | 6 +- tests/foreman/ui/test_contenthost.py | 4 +- 15 files changed, 299 insertions(+), 341 deletions(-) create mode 100644 conf/repos.yaml.template create mode 100644 conf/robottelo.yaml.template create mode 100644 conf/server.yaml.template diff --git a/.github/workflows/merge_to_master.yml b/.github/workflows/merge_to_master.yml index 468bfea11ec..59ffebc0185 100644 --- a/.github/workflows/merge_to_master.yml +++ b/.github/workflows/merge_to_master.yml @@ -38,6 +38,7 @@ jobs: pip uninstall -y pycurl pip install --compile --no-cache-dir pycurl pip install -U -r requirements.txt -r requirements-optional.txt + for conffile in conf/*.yaml.template; do mv -- "$conffile" "${conffile%.yaml.template}.yaml"; done cp robottelo.properties.sample robottelo.properties cp broker_settings.yaml.example broker_settings.yaml cp virtwho.properties.sample virtwho.properties diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 7863475c87e..d917b01d6a2 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -36,6 +36,7 @@ jobs: pip uninstall -y pycurl pip install --compile --no-cache-dir pycurl pip install -U -r requirements.txt -r requirements-optional.txt + for conffile in conf/*.yaml.template; do mv -- "$conffile" "${conffile%.yaml.template}.yaml"; done cp robottelo.properties.sample robottelo.properties cp broker_settings.yaml.example broker_settings.yaml cp virtwho.properties.sample virtwho.properties diff --git a/conf/repos.yaml.template b/conf/repos.yaml.template new file mode 100644 index 00000000000..e345b33c8ed --- /dev/null +++ b/conf/repos.yaml.template @@ -0,0 +1,31 @@ +REPOS: + # Provide link to rhel6/7/8 repo here, as puppet rpm would require packages from + # RHEL 6/7/8 repo and syncing the entire repo on the fly would take longer for + # tests to run Specify the *.repo link to an internal repo for tests to execute properly + RHEL6_REPO: replace-with-rhel8-repo-http-link + RHEL7_REPO: replace-with-rhel8-repo-http-link + RHEL8_REPO: replace-with-rhel8-repo-http-link + # Provide link to rhel6/7/8 repositories URL as we need all OS packages in order + # to have real installation media for provisioning procedure + # RHEL6_OS: replace-with-rhel6-os-http-link + # RHEL7_OS: replace-with-rhel7-os-http-link + # RHEL8_OS: + # BASEOS: replace-with-rhel8-os-baseos-http-link + # APPSTREAM: replace-with-rhel8-os-appstream-http-link + # If capsule and satellite tools repositories available related packages will + # be pulled from there instead of using the CDN channel. These information is + # more suited to be used for downstream, downstream-iso and zstream builds. + # CAPSULE_REPO: replace-with-capsule-http-link + # SATTOOLS_REPO: + # RHEL6: replace-with-rhel6-http-link + # RHEL7: replace-with-rhel7-http-link + # RHEL8: replace-with-rhel8-http-link + # Downstream Satellite-maintain repo + # SATMAINTENANCE_REPO: replace_with_sat_maintain_repo + # Software Collection Repo + # RHSCL_REPO: replace_with_rhscl_repo + # Ansible 2.8 Repo + # ANSIBLE_REPO: replace_with_ansible_repo + # Added swid_tools_repo for installing swid-tools and dnf-plugin-swidtags packages + # which are essentially required for generating swid tags in RHEL8 content host. + # SWID_TOOLS_REPO: replace_with_swid_tools_repo diff --git a/conf/robottelo.yaml.template b/conf/robottelo.yaml.template new file mode 100644 index 00000000000..2d8f50fa363 --- /dev/null +++ b/conf/robottelo.yaml.template @@ -0,0 +1,62 @@ +ROBOTTELO: + # The directory where screenshots will be saved. + # Note:- Content under /tmp may be deleted after a reboot. + SCREENSHOTS_PATH: /tmp/robottelo/screenshots/ + LOCALE: en_US.UTF-8 + # Update upstream=false for downstream run + UPSTREAM: false + # Logging verbosity, one of debug, info, warning, error, critical + VERBOSITY: debug + # Directory for temporary files + TMP_DIR: /var/tmp + # Web Server to provide various test artifacts + # ARTIFACTS_SERVER: replace-with-artifacts-server + # Webdriver logging options + # A list of commands to be logged + LOG_DRIVER_COMMANDS: + - newSession + - windowMaximize + - get + - findElement + - sendKeysToElement + - clickElement + - mouseMoveTo + # - The URL of container hosting repos on SatLab + # Example url - http://: + # Use https://github.com/SatelliteQE/fedorapeople-repos to deploy and configure the repos hosting container + # REPOS_HOSTING_URL: replace-with-repo-hosting-url + # browser tells robottelo which browser to use when testing UI. Valid values + # are: + # * selenium + # * docker: to use a browser inside a docker container. In order to use this + # feature make sure that the docker daemon is running locally and has its + # unix socket published at unix://var/run/docker.sock. Also make sure that + # the docker image selenium/standalone-firefox is available. + # * remote: to access the remote browser, the webdriver and command_executor + # are required. + BROWSER: selenium + # Webdriver to use. Valid values are chrome, firefox, ie, edge, phantomjs + WEBDRIVER: chrome + # Run browser for UI tests with semicolon delimeted options such as headless. Currently supported for only chrome. + # BROWSEROPTIONS: replace-with-browser-options + # The base DesiredCapabilities dict will be get by the browser + # specified by webdriver config. If you override browserName then that + # browser will be used instead. + # WEBDRIVER_DESIRED_CAPABILITIES: + # PLATFORM: + # MAXDURATION: + # IDLETIMEOUT: + # START-MAXIMISED: + # SCREENRESOLUTION: + # TAGS: + # Binary location for selected wedriver (not needed if using saucelabs) + # WEBDRIVER_BINARY: /usr/bin/firefox + # webdriver_binary=/usr/bin/chromedriver + # webdriver_binary=C:\\Program Files (x86)\\Microsoft Web Driver\\MicrosoftWebDriver.exe + WEBDRIVER_BINARY: /usr/bin/chromedriver + # Zalenium command_executor + # COMMAND_EXECUTOR: http://127.0.0.1:4444/wd/hub + # CDN sync + CDN: true + # Run one datapoint or multiple datapoints for tests + RUN_ONE_DATAPOINT: false diff --git a/conf/server.yaml.template b/conf/server.yaml.template new file mode 100644 index 00000000000..ab0c0c72c19 --- /dev/null +++ b/conf/server.yaml.template @@ -0,0 +1,27 @@ +SERVER: + # Server hostname + # HOSTNAME: replace-with-satellite-hostname + # HTTP scheme when building the server URL + # Suggested values for "scheme" are "http" and "https". + SCHEME: https + # Server port + PORT: 443 + # SSH username + SSH_USERNAME: root + # Use either of SSH_PASSWORD or SSH_KEY or SSH_KEY_STRING below + # SSH password if not using a SSH key to connect + # SSH_PASSWORD: replace-with-ssh-passwd + # Path to private ssh key to be used when connecting via SSH. + # SSH_KEY: + # private ssh key as a string to be used when connecting via SSH. + # SSH_KEY_STRING: + # Admin username when accessing API and UI + ADMIN_USERNAME: admin + # Admin password when accessing API and UI + ADMIN_PASSWORD: changeme + +SSH_CLIENT: + # Time to wait for the ssh command to finish, in seconds + COMMAND_TIMEOUT: 300 + # Time to wait for establishing the ssh connection, in seconds + CONNECTION_TIMEOUT: 10 diff --git a/pytest_fixtures/xdist.py b/pytest_fixtures/xdist.py index 93fe07158df..389c6ee4822 100644 --- a/pytest_fixtures/xdist.py +++ b/pytest_fixtures/xdist.py @@ -9,5 +9,5 @@ def align_xdist_satellites(worker_id): """Set a different Satellite per worker when available in robottelo's config""" settings.configure() settings.server.hostname = settings.server.get_hostname(worker_id) - settings._configure_entities() - settings._configure_airgun() + settings.configure_nailgun() + settings.configure_airgun() diff --git a/robottelo.properties.sample b/robottelo.properties.sample index d95edf18bf6..473ecefa5df 100644 --- a/robottelo.properties.sample +++ b/robottelo.properties.sample @@ -1,143 +1,4 @@ # Make a copy of this file named robottelo.properties -[server] -# Server hostname -hostname= -# Additional satellite hostnames for xdist workers -# gw0= -# gw1= -# gw2= - -# Path to private ssh key to be used when connecting via SSH. -ssh_key= - -# HTTP scheme when building the server URL -# Suggested values for "scheme" are "http" and "https". -# scheme=https - -# Server port -# port=443 - -# SSH username -# ssh_username=root - -# SSH password if not using a SSH key to connect -# ssh_password= - -# Admin username when accessing API and UI -# admin_username=admin - -# Admin password when accessing API and UI -# admin_password=changeme - -# section for ssh client settings -# [ssh_client] -# Time to wait for the ssh command to finish, in seconds -# command_timeout=300 -# Time to wait for establishing the ssh connection, in seconds -# connection_timeout=10 - -# Override robottelo configuration -[robottelo] -# The directory where screenshots will be saved. -# Note:- Content under /tmp may be deleted after a reboot. -# screenshots_path=/tmp/robottelo/screenshots/ -# locale=en_US.UTF-8 -# Update upstream=false for downstream run -# upstream=true -# Logging verbosity, one of debug, info, warning, error, critical -# verbosity=debug -# Directory for temporary files -# tmp_dir=/var/tmp -# Web Server to provide various test artifacts -# artifacts_server=server.example.com -# Webdriver logging options -# A list of commands to be logged -# log_driver_commands=newSession,windowMaximize,get,findElement,sendKeysToElement,clickElement,mouseMoveTo -# - The URL of container hosting repos on SatLab -# Example url - http://: -# Use https://github.com/SatelliteQE/fedorapeople-repos to deploy and configure the repos hosting container -# repos_hosting_url= - -# browser tells robottelo which browser to use when testing UI. Valid values -# are: -# * selenium -# * docker: to use a browser inside a docker container. In order to use this -# feature make sure that the docker daemon is running locally and has its -# unix socket published at unix://var/run/docker.sock. Also make sure that -# the docker image selenium/standalone-firefox is available. -# * saucelabs: makes robottelo run tests on SauceLabs. The saucelabs_user and -# saucelabs_key are required and the browser used is the same specified on -# webdriver. Supported values for webdriver are firefox, chrome and ie, the -# other valid webdriver values are going to be translated to firefox. -# * remote: to access the remote browser, the webdriver and command_executor -# are required. -# browser=selenium - -# Webdriver to use. Valid values are chrome, firefox, ie, edge, phantomjs -# webdriver=chrome - -# Run browser for UI tests with semicolon delimeted options such as headless. Currently supported for only chrome. -# browseroptions= - -# Binary location for selected wedriver (not needed if using saucelabs) -# webdriver_binary=/usr/bin/firefox -# webdriver_binary=/usr/bin/chromedriver -# webdriver_binary=C:\\Program Files (x86)\\Microsoft Web Driver\\MicrosoftWebDriver.exe - -# webdriver_desired_capabilities accepts extra configuration to be passed to -# saucelabs in order to configure the test options. You can use the platform -# configurator (see link below) to get the information about the environment -# you want to test. -# https://wiki.saucelabs.com/display/DOCS/Platform+Configurator/ -# Or you can visit -# https://wiki.saucelabs.com/display/DOCS/Test+Configuration+Options for a -# complete set of options. -# PS.: the base DesiredCapabilities dict will be get by the browser -# specified by webdriver config. If you override browserName then that -# browser will be used instead. -# examples: -# (note: version=) -# webdriver_desired_capabilities=platform=OS X 10.9,version=45.0,build=myBuildName,parentTunnel=otherUser,seleniumVersion=2.48.0 -# webdriver_desired_capabilities=platform=macOS 10.12,version=45.0,build=myBuildName,seleniumVersion=2.48.0,screenResolution=1600x1200 -# webdriver_desired_capabilities=platform=Windows 10,version=14.14393,build=myBuildName,seleniumVersion=2.48.0,screenResolution=1600x1200 -# webdriver_desired_capabilities=platform=Linux,browserName=chrome,unhandledPromptBehavior=dismiss,unexpectedAlertBehaviour=ignore,acceptInsecureCerts=True -# command_executor=http://127.0.0.1:4444/wd/hub - -# saucelabs_user= -# saucelabs_key= - -# cdn=true -# Run one datapoint or multiple datapoints for tests -# run_one_datapoint=false - -# Provide link to rhel6/7 repo here, as puppet rpm would require packages from -# RHEL 6/7 repo and syncing the entire repo on the fly would take longer for -# tests to run Specify the *.repo link to an internal repo for tests to execute -# properly -# rhel6_repo=http://example.com/yum/repo_files/rhel6-updates.repo -# rhel7_repo=http://example.com/yum/repo_files/rhel7-updates.repo -# rhel8_repo=http://example.com/yum/repo_files/rhel8-updates.repo - -# Provide link to rhel6/7 repositories URL as we need all OS packages in order -# to have real installation media for provisioning procedure -# rhel6_os=http://example.com/yum/rhel6-os/ -# rhel7_os=http://example.com/yum/rhel7-os/ - -# RHEL 8 repos -# rhel8_os=baseos=http://example.com/rhel-8/BaseOS/x86_64/os/,appstream=http://example.com/rhel-8/AppStream/x86_64/os/ - - -# If capsule and satellite tools repositories available related packages will -# be pulled from there instead of using the CDN channel. These information is -# more suited to be used for downstream, downstream-iso and zstream builds. -# capsule_repo=http://capsule/repo -# sattools_repo= -# rhel6=http://sattools/repo/el6, -# rhel7=http://sattools/repo/el7, - -# Added swid_tools_repo for installing swid-tools and dnf-plugin-swidtags packages -# which are essentially required for generating swid tags in RHEL8 content host. -# swid_tools_repo=https://example.com/swid-rhel-8.repo # Broker-specific settings # [broker] diff --git a/robottelo/cli/factory.py b/robottelo/cli/factory.py index 1c2a81e7264..b481bd5b44f 100644 --- a/robottelo/cli/factory.py +++ b/robottelo/cli/factory.py @@ -1971,9 +1971,9 @@ def setup_org_for_a_rh_repo(options=None, force_manifest_upload=False, force_use """ custom_repo_url = None if options.get('repository') == REPOS['rhst6']['name']: - custom_repo_url = settings.sattools_repo['rhel6'] + custom_repo_url = settings.sattools_repo.rhel6 elif options.get('repository') == REPOS['rhst7']['name']: - custom_repo_url = settings.sattools_repo['rhel7'] + custom_repo_url = settings.sattools_repo.rhel7 elif options.get('repository') == REPOS['rhel6']['name']: custom_repo_url = settings.rhel6_os elif options.get('repository') == REPOS['rhel7']['name']: @@ -2658,8 +2658,8 @@ def virt_who_hypervisor_config( 'repository-set': REPOSET['rhst7'], 'repository': REPOS['rhst7']['name'], 'repository-id': REPOS['rhst7']['id'], - 'url': settings.sattools_repo['rhel7'], - 'cdn': bool(settings.cdn or not settings.sattools_repo['rhel7']), + 'url': settings.sattools_repo.rhel7, + 'cdn': bool(settings.cdn or not settings.sattools_repo.rhel7), } ] repos.extend(extra_repos) diff --git a/robottelo/config/__init__.py b/robottelo/config/__init__.py index 7c5f8269a4a..755d1c746fa 100644 --- a/robottelo/config/__init__.py +++ b/robottelo/config/__init__.py @@ -9,6 +9,7 @@ from robottelo.config.facade import SettingsFacade from robottelo.config.facade import SettingsNodeWrapper + logger = logging.getLogger('robottelo.config') legacy_settings = LegacySettings() @@ -46,3 +47,7 @@ settings_proxy.set_configs(dynaconf_settings, legacy_settings) settings = SettingsNodeWrapper(settings_proxy) +settings.configure_nailgun() +settings.configure_airgun() +settings.configure_logging() +settings.configure_third_party_logging() diff --git a/robottelo/config/base.py b/robottelo/config/base.py index 4c2b7191cc4..9db8081f2eb 100644 --- a/robottelo/config/base.py +++ b/robottelo/config/base.py @@ -8,11 +8,7 @@ from urllib.parse import urljoin from urllib.parse import urlunsplit -import airgun.settings import yaml -from nailgun import entities -from nailgun import entity_mixins -from nailgun.config import ServerConfig from robottelo.config import casts from robottelo.constants import AZURERM_VALID_REGIONS @@ -1449,8 +1445,6 @@ def configure(self, settings_path=None): raise ImproperlyConfigured(f'Not able to find settings file at {settings_path}') self.reader = INIReader(settings_path) - self._read_robottelo_settings() - self._validation_errors.extend(self._validate_robottelo_settings()) attrs = map(lambda attr_name: (attr_name, getattr(self, attr_name)), dir(self)) feature_settings = filter(lambda tpl: isinstance(tpl[1], FeatureSettings), attrs) @@ -1464,98 +1458,8 @@ def configure(self, settings_path=None): 'Failed to validate the configuration, check the message(s):\n' '{}'.format('\n'.join(self._validation_errors)) ) - - self._configure_logging() - self._configure_third_party_logging() - self._configure_entities() - self._configure_airgun() self._configured = True - def _read_robottelo_settings(self): - """Read Robottelo's general settings.""" - self.log_driver_commands = self.reader.get( - 'robottelo', - 'log_driver_commands', - [ - 'newSession', - 'windowMaximize', - 'get', - 'findElement', - 'sendKeysToElement', - 'clickElement', - 'mouseMoveTo', - ], - list, - ) - self.browser = self.reader.get('robottelo', 'browser', 'selenium') - self.cdn = self.reader.get('robottelo', 'cdn', True, bool) - self.locale = self.reader.get('robottelo', 'locale', 'en_US.UTF-8') - self.rhel6_repo = self.reader.get('robottelo', 'rhel6_repo', None) - self.rhel7_repo = self.reader.get('robottelo', 'rhel7_repo', None) - self.rhel8_repo = self.reader.get('robottelo', 'rhel8_repo', None) - self.rhel6_os = self.reader.get('robottelo', 'rhel6_os', None) - self.rhel7_os = self.reader.get('robottelo', 'rhel7_os', None) - self.rhel8_os = self.reader.get('robottelo', 'rhel8_os', None, dict) - self.capsule_repo = self.reader.get('robottelo', 'capsule_repo', None) - self.rhscl_repo = self.reader.get('robottelo', 'rhscl_repo', None) - self.ansible_repo = self.reader.get('robottelo', 'ansible_repo', None) - self.sattools_repo = self.reader.get('robottelo', 'sattools_repo', None, dict) - self.satmaintenance_repo = self.reader.get('robottelo', 'satmaintenance_repo', None) - self.swid_tools_repo = self.reader.get('robottelo', 'swid_tools_repo', None) - self.screenshots_path = self.reader.get( - 'robottelo', 'screenshots_path', '/tmp/robottelo/screenshots' - ) - self.tmp_dir = self.reader.get('robottelo', 'tmp_dir', '/var/tmp') - self.artifacts_server = self.reader.get('robottelo', 'artifacts_server', None) - self.run_one_datapoint = self.reader.get('robottelo', 'run_one_datapoint', False, bool) - self.upstream = self.reader.get('robottelo', 'upstream', True, bool) - self.verbosity = self.reader.get( - 'robottelo', - 'verbosity', - INIReader.cast_logging_level('debug'), - INIReader.cast_logging_level, - ) - self.webdriver = self.reader.get('robottelo', 'webdriver', 'chrome') - self.saucelabs_user = self.reader.get('robottelo', 'saucelabs_user', None) - self.saucelabs_key = self.reader.get('robottelo', 'saucelabs_key', None) - self.webdriver_binary = self.reader.get('robottelo', 'webdriver_binary', None) - self.browseroptions = self.reader.get('robottelo', 'browseroptions', None) - self.webdriver_desired_capabilities = self.reader.get( - 'robottelo', - 'webdriver_desired_capabilities', - None, - cast=INIReader.cast_webdriver_desired_capabilities, - ) - self.command_executor = self.reader.get( - 'robottelo', 'command_executor', 'http://127.0.0.1:4444/wd/hub' - ) - self.window_manager_command = self.reader.get('robottelo', 'window_manager_command', None) - self.repos_hosting_url = self.reader.get('robottelo', 'repos_hosting_url', None) - - def _validate_robottelo_settings(self): - """Validate Robottelo's general settings.""" - validation_errors = [] - browsers = ('selenium', 'docker', 'saucelabs', 'remote') - webdrivers = ('chrome', 'edge', 'firefox', 'ie', 'phantomjs') - if self.browser not in browsers: - validation_errors.append( - '[robottelo] browser should be one of {}.'.format(', '.join(browsers)) - ) - if self.webdriver not in webdrivers: - validation_errors.append( - '[robottelo] webdriver should be one of {}.'.format(', '.join(webdrivers)) - ) - if self.browser == 'saucelabs': - if self.saucelabs_user is None: - validation_errors.append( - '[robottelo] saucelabs_user must be provided when browser is saucelabs.' - ) - if self.saucelabs_key is None: - validation_errors.append( - '[robottelo] saucelabs_key must be provided when browser is saucelabs.' - ) - return validation_errors - @property def configured(self): """Returns True if the settings have already been configured.""" @@ -1570,97 +1474,6 @@ def all_features(self): ] return self._all_features - def _configure_entities(self): - """Configure NailGun's entity classes. - - Do the following: - - * Set ``entity_mixins.CREATE_MISSING`` to ``True``. This causes method - ``EntityCreateMixin.create_raw`` to generate values for empty and - required fields. - * Set ``nailgun.entity_mixins.DEFAULT_SERVER_CONFIG`` to whatever is - returned by :meth:`robottelo.helpers.get_nailgun_config`. See - ``robottelo.entity_mixins.Entity`` for more information on the effects - of this. - * Set a default value for ``nailgun.entities.GPGKey.content``. - """ - entity_mixins.CREATE_MISSING = True - entity_mixins.DEFAULT_SERVER_CONFIG = ServerConfig( - self.server.get_url(), self.server.get_credentials(), verify=False - ) - - gpgkey_init = entities.GPGKey.__init__ - - def patched_gpgkey_init(self, server_config=None, **kwargs): - """Set a default value on the ``content`` field.""" - gpgkey_init(self, server_config, **kwargs) - self._fields['content'].default = os.path.join( - get_project_root(), 'tests', 'foreman', 'data', 'valid_gpg_key.txt' - ) - - entities.GPGKey.__init__ = patched_gpgkey_init - - def _configure_airgun(self): - """Pass required settings to AirGun""" - airgun.settings.configure( - { - 'airgun': { - 'verbosity': logging.getLevelName(self.verbosity), - 'tmp_dir': self.tmp_dir, - }, - 'satellite': { - 'hostname': self.server.hostname, - 'password': self.server.admin_password, - 'username': self.server.admin_username, - }, - 'selenium': { - 'browser': self.browser, - 'saucelabs_key': self.saucelabs_key, - 'saucelabs_user': self.saucelabs_user, - 'screenshots_path': self.screenshots_path, - 'webdriver': self.webdriver, - 'webdriver_binary': self.webdriver_binary, - 'command_executor': self.command_executor, - 'browseroptions': self.browseroptions, - }, - 'webdriver_desired_capabilities': (self.webdriver_desired_capabilities or {}), - } - ) - - def _configure_logging(self): - """Configure logging for the entire framework. - - If a config named ``logging.conf`` exists in Robottelo's root - directory, the logger is configured using the options in that file. - Otherwise, a custom logging output format is set, and default values - are used for all other logging options. - """ - # All output should be made by the logging module, including warnings - logging.captureWarnings(True) - - # Set the logging level based on the Robottelo's verbosity - for name in ('nailgun', 'robottelo'): - logging.getLogger(name).setLevel(self.verbosity) - - # Allow overriding logging config based on the presence of logging.conf - # file on Robottelo's project root - logging_conf_path = os.path.join(get_project_root(), 'logging.conf') - if os.path.isfile(logging_conf_path): - logging.config.fileConfig(logging_conf_path) - else: - logging.basicConfig(format='%(levelname)s %(module)s:%(lineno)d: %(message)s') - - def _configure_third_party_logging(self): - """Increase the level of third party packages logging.""" - loggers = ( - 'easyprocess', - 'paramiko', - 'requests.packages.urllib3.connectionpool', - 'selenium.webdriver.remote.remote_connection', - ) - for logger in loggers: - logging.getLogger(logger).setLevel(logging.WARNING) - class HttpProxySettings(FeatureSettings): """Http Proxy settings definitions.""" diff --git a/robottelo/config/facade.py b/robottelo/config/facade.py index 3975a546d1b..7377dd56f8d 100644 --- a/robottelo/config/facade.py +++ b/robottelo/config/facade.py @@ -4,8 +4,13 @@ from urllib.parse import urljoin from urllib.parse import urlunsplit +import airgun.settings +from nailgun import entities +from nailgun import entity_mixins +from nailgun.config import ServerConfig from wrapt import CallableObjectProxy +from robottelo.config import casts from robottelo.config.base import get_project_root from robottelo.config.base import INIReader from robottelo.config.base import SETTINGS_FILE_NAME @@ -119,6 +124,94 @@ def __repr__(self): self.__wrapped__, ) + def configure_nailgun(self): + """Configure NailGun's entity classes. + + Do the following: + + * Set ``entity_mixins.CREATE_MISSING`` to ``True``. This causes method + ``EntityCreateMixin.create_raw`` to generate values for empty and + required fields. + * Set ``nailgun.entity_mixins.DEFAULT_SERVER_CONFIG`` to whatever is + returned by :meth:`robottelo.helpers.get_nailgun_config`. See + ``robottelo.entity_mixins.Entity`` for more information on the effects + of this. + * Set a default value for ``nailgun.entities.GPGKey.content``. + """ + entity_mixins.CREATE_MISSING = True + entity_mixins.DEFAULT_SERVER_CONFIG = ServerConfig( + self.server.get_url(), self.server.get_credentials(), verify=False + ) + + gpgkey_init = entities.GPGKey.__init__ + + def patched_gpgkey_init(self, server_config=None, **kwargs): + """Set a default value on the ``content`` field.""" + gpgkey_init(self, server_config, **kwargs) + self._fields['content'].default = os.path.join( + get_project_root(), 'tests', 'foreman', 'data', 'valid_gpg_key.txt' + ) + + entities.GPGKey.__init__ = patched_gpgkey_init + + def configure_airgun(self): + """Pass required settings to AirGun""" + airgun.settings.configure( + { + 'airgun': { + 'verbosity': logging.getLevelName(self.verbosity), + 'tmp_dir': self.tmp_dir, + }, + 'satellite': { + 'hostname': self.server.hostname, + 'password': self.server.admin_password, + 'username': self.server.admin_username, + }, + 'selenium': { + 'browser': self.browser, + 'screenshots_path': self.screenshots_path, + 'webdriver': self.webdriver, + 'webdriver_binary': self.webdriver_binary, + 'command_executor': self.command_executor, + }, + 'webdriver_desired_capabilities': (self.webdriver_desired_capabilities or {}), + } + ) + + def configure_logging(self): + """Configure logging for the entire framework. + + If a config named ``logging.conf`` exists in Robottelo's root + directory, the logger is configured using the options in that file. + Otherwise, a custom logging output format is set, and default values + are used for all other logging options. + """ + # All output should be made by the logging module, including warnings + logging.captureWarnings(True) + + # Set the logging level based on the Robottelo's verbosity + for name in ('nailgun', 'robottelo'): + logging.getLogger(name).setLevel(self.verbosity) + + # Allow overriding logging config based on the presence of logging.conf + # file on Robottelo's project root + logging_conf_path = os.path.join(get_project_root(), 'logging.conf') + if os.path.isfile(logging_conf_path): + logging.config.fileConfig(logging_conf_path) + else: + logging.basicConfig(format='%(levelname)s %(module)s:%(lineno)d: %(message)s') + + def configure_third_party_logging(self): + """Increase the level of third party packages logging.""" + loggers = ( + 'easyprocess', + 'paramiko', + 'requests.packages.urllib3.connectionpool', + 'selenium.webdriver.remote.remote_connection', + ) + for logger in loggers: + logging.getLogger(logger).setLevel(logging.WARNING) + class SettingsFacade: _cache = {} @@ -254,9 +347,23 @@ def __ssh_client_connection_timeout(self): timeout = 10 return timeout + def _robottelo_verbosity(self): + """Casts logging level for robottelo framework, + for more info refer robottelo.config.casts module + """ + cast_logging_level = casts.LoggingLevel() + try: + verbosity = self._get_from_configs('robottelo.verbosity') + verbosity = cast_logging_level(verbosity) + except AttributeError: + verbosity = cast_logging_level('debug') + return verbosity + def _dispatch_computed_value(self, key): if key == "configure": value = self._cached_function(lambda: None) + elif key == "verbosity": + value = self._robottelo_verbosity() elif key == "server.get_credentials": value = self._cached_function(self.__server_get_credentials) elif key == "server.get_url": @@ -284,6 +391,46 @@ def _dispatch_computed_value(self, key): self._add_to_cache(key, value) return value + # TO DO: Should be removed when LegacySettings are removed + def _dispatch_robottelo_value(self, key): + """Returns robottelo setting with dynaconf object in stead of dynaconf.robottelo object + + e.g `self.verbosity` instead of `self.robottelo.verbosity` + """ + robottelo_keys = [setting.lower() for setting in self._configs[0].robottelo.keys()] + top_key = key.split('.')[0] + if top_key in robottelo_keys: + try: + # From DynaConf + value = self.get(f'robottelo.{key}') + except KeyError: + # From Legacy Setting + value = self.get(key) + else: + raise KeyError() + self._add_to_cache(key, value) + return value + + # TO DO: Should be removed when LegacySettings are removed + def _dispatch_repos_value(self, key): + """Returns repos setting with dynaconf object in stead of dynaconf.repos object + + e.g `self.capsule_repo` instead of `self.repos.capsule_repo` + """ + repos_keys = [setting.lower() for setting in self._configs[0].repos.keys()] + top_key = key.split('.')[0] + if top_key in repos_keys: + try: + # From DynaConf + value = self.get(f'repos.{key}') + except KeyError: + # From Legacy Setting + value = self.get(key) + else: + raise KeyError() + self._add_to_cache(key, value) + return value + def _get_from_configs(self, key): for config_provider in self._configs: try: @@ -312,6 +459,16 @@ def get(self, full_path): except KeyError: pass + try: + return self._dispatch_robottelo_value(full_path) + except KeyError: + pass + + try: + return self._dispatch_repos_value(full_path) + except KeyError: + pass + value = self._get_from_configs(full_path) return value diff --git a/robottelo/hosts.py b/robottelo/hosts.py index f9162001442..1e8cc5c9319 100644 --- a/robottelo/hosts.py +++ b/robottelo/hosts.py @@ -78,9 +78,9 @@ def enable_repo(self, repo, force=False): """ downstream_repo = None if repo == REPOS['rhst6']['id']: - downstream_repo = settings.sattools_repo['rhel6'] + downstream_repo = settings.sattools_repo.rhel6 elif repo == REPOS['rhst7']['id']: - downstream_repo = settings.sattools_repo['rhel7'] + downstream_repo = settings.sattools_repo.rhel7 elif repo in (REPOS['rhsc6']['id'], REPOS['rhsc7']['id']): downstream_repo = settings.capsule_repo if force or settings.cdn or not downstream_repo: diff --git a/robottelo/vm.py b/robottelo/vm.py index 22bfc2dfe1c..c77ff4124f2 100644 --- a/robottelo/vm.py +++ b/robottelo/vm.py @@ -378,9 +378,9 @@ def enable_repo(self, repo, force=False): """ downstream_repo = None if repo == REPOS['rhst6']['id']: - downstream_repo = settings.sattools_repo['rhel6'] + downstream_repo = settings.sattools_repo.rhel6 elif repo == REPOS['rhst7']['id']: - downstream_repo = settings.sattools_repo['rhel7'] + downstream_repo = settings.sattools_repo.rhel7 elif repo in (REPOS['rhsc6']['id'], REPOS['rhsc7']['id']): downstream_repo = settings.capsule_repo if force or settings.cdn or not downstream_repo: diff --git a/tests/foreman/longrun/test_oscap.py b/tests/foreman/longrun/test_oscap.py index 04c8d075f9e..cfc29755683 100644 --- a/tests/foreman/longrun/test_oscap.py +++ b/tests/foreman/longrun/test_oscap.py @@ -113,9 +113,9 @@ def configure_puppet_test(cls): ak_name_7 = gen_string('alpha') ak_name_6 = gen_string('alpha') repo_values = [ - {'repo': settings.sattools_repo['rhel8'], 'akname': ak_name_8}, - {'repo': settings.sattools_repo['rhel7'], 'akname': ak_name_7}, - {'repo': settings.sattools_repo['rhel6'], 'akname': ak_name_6}, + {'repo': settings.sattools_repo.rhel8, 'akname': ak_name_8}, + {'repo': settings.sattools_repo.rhel7, 'akname': ak_name_7}, + {'repo': settings.sattools_repo.rhel6, 'akname': ak_name_6}, ] # Create new organization and environment. org = entities.Organization(name=gen_string('alpha')).create() diff --git a/tests/foreman/ui/test_contenthost.py b/tests/foreman/ui/test_contenthost.py index 5d5a951d22b..0c20cb58747 100644 --- a/tests/foreman/ui/test_contenthost.py +++ b/tests/foreman/ui/test_contenthost.py @@ -98,8 +98,8 @@ def repos_collection_for_module_streams(module_org): repos_collection = RepositoryCollection( distro=DISTRO_RHEL8, repositories=[ - YumRepository(url=settings.rhel8_os['baseos']), - YumRepository(url=settings.rhel8_os['appstream']), + YumRepository(url=settings.rhel8_os.baseos), + YumRepository(url=settings.rhel8_os.appstream), YumRepository(url=settings.sattools_repo[DISTRO_RHEL8]), YumRepository(url=CUSTOM_MODULE_STREAM_REPO_2), ],