##// END OF EJS Templates
pull-requests: added commit flow into pr listing tables
pull-requests: added commit flow into pr listing tables

File last commit:

r5088:8f6d1ed6 default
r5170:a77dd674 default
Show More
server_utils.py
221 lines | 6.9 KiB | text/x-python | PythonLexer
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
copyrights: updated for 2023
r5088 # Copyright (C) 2010-2023 RhodeCode GmbH
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 #
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License, version 3
# (only), as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# This program is dual-licensed. If you wish to learn more about the
# RhodeCode Enterprise Edition, including its added features, Support services,
# and proprietary license terms, please see https://rhodecode.com/licenses/
import os
import time
import tempfile
import pytest
python3: remove usage of subprocess32
r4926 import subprocess
testing: added webhook tests and fixed tags adding
r4879 import logging
python3: fix urllib usage
r4914 from urllib.request import urlopen
from urllib.error import URLError
python3: fix import configparser
r4927 import configparser
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS
from rhodecode.tests.utils import is_url_reachable
testing: added webhook tests and fixed tags adding
r4879 log = logging.getLogger(__name__)
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
def get_port(pyramid_config):
config = configparser.ConfigParser()
config.read(pyramid_config)
return config.get('server:main', 'port')
def get_host_url(pyramid_config):
"""Construct the host url using the port in the test configuration."""
core: dropped usage of configobj entirely
r4975 port = get_port(pyramid_config)
return f'127.0.0.1:{port}'
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
def assert_no_running_instance(url):
if is_url_reachable(url):
core: dropped usage of configobj entirely
r4975 print(f"Hint: Usually this means another instance of server "
f"is running in the background at {url}.")
pytest.fail(f"Port is not free at {url}, cannot start server at")
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
class ServerBase(object):
_args = []
log_file_name = 'NOT_DEFINED.log'
tests: fixed all tests for python3 BIG changes
r5087 status_url_tmpl = 'http://{host}:{port}/_admin/ops/ping'
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
def __init__(self, config_file, log_file):
self.config_file = config_file
core: dropped usage of configobj entirely
r4975 config = configparser.ConfigParser()
config.read(config_file)
self._config = {k: v for k, v in config['server:main'].items()}
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
self._args = []
self.log_file = log_file or os.path.join(
tempfile.gettempdir(), self.log_file_name)
self.process = None
self.server_out = None
testing: added webhook tests and fixed tags adding
r4879 log.info("Using the {} configuration:{}".format(
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 self.__class__.__name__, config_file))
if not os.path.isfile(config_file):
core: dropped usage of configobj entirely
r4975 raise RuntimeError(f'Failed to get config at {config_file}')
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
@property
def command(self):
return ' '.join(self._args)
@property
tests: fixed starting of customized gunicorn with a explicit --bind call
r4976 def bind_addr(self):
return '{host}:{port}'.format(**self._config)
@property
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 def http_url(self):
template = 'http://{host}:{port}/'
return template.format(**self._config)
def host_url(self):
tests: fixed starting of customized gunicorn with a explicit --bind call
r4976 host = get_host_url(self.config_file)
return f'http://{host}'
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
def get_rc_log(self):
with open(self.log_file) as f:
return f.read()
tests: fixed all tests for python3 BIG changes
r5087 def assert_message_in_server_logs(self, message):
server_logs = self.get_rc_log()
assert message in server_logs
tests: increase timeouts for better test stability
r2462 def wait_until_ready(self, timeout=30):
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 host = self._config['host']
port = self._config['port']
status_url = self.status_url_tmpl.format(host=host, port=port)
start = time.time()
while time.time() - start < timeout:
try:
urlopen(status_url)
break
except URLError:
time.sleep(0.2)
else:
tests: use pytest fail when vcs_operations cannot start required components
r2461 pytest.fail(
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 "Starting the {} failed or took more than {} "
"seconds. cmd: `{}`".format(
self.__class__.__name__, timeout, self.command))
testing: added webhook tests and fixed tags adding
r4879 log.info('Server of {} ready at url {}'.format(
server-utils: report server ready state
r2466 self.__class__.__name__, status_url))
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 def shutdown(self):
self.process.kill()
self.server_out.flush()
self.server_out.close()
def get_log_file_with_port(self):
log_file = list(self.log_file.partition('.log'))
log_file.insert(1, get_port(self.config_file))
log_file = ''.join(log_file)
return log_file
class RcVCSServer(ServerBase):
"""
Represents a running VCSServer instance.
"""
log_file_name = 'rc-vcsserver.log'
status_url_tmpl = 'http://{host}:{port}/status'
tests: fixed all tests for python3 BIG changes
r5087 def __init__(self, config_file, log_file=None, workers='2'):
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 super(RcVCSServer, self).__init__(config_file, log_file)
tests: fixed starting of customized gunicorn with a explicit --bind call
r4976 self._args = [
tests: fixed all tests for python3 BIG changes
r5087 'gunicorn',
'--bind', self.bind_addr,
'--worker-class', 'gevent',
'--backlog', '16',
'--timeout', '300',
'--workers', workers,
tests: fixed starting of customized gunicorn with a explicit --bind call
r4976 '--paste', self.config_file]
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
def start(self):
env = os.environ.copy()
self.log_file = self.get_log_file_with_port()
self.server_out = open(self.log_file, 'w')
host_url = self.host_url()
assert_no_running_instance(host_url)
tests: fixed starting of customized gunicorn with a explicit --bind call
r4976 print(f'rhodecode-vcsserver starting at: {host_url}')
print(f'rhodecode-vcsserver command: {self.command}')
print(f'rhodecode-vcsserver logfile: {self.log_file}')
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
python3: remove usage of subprocess32
r4926 self.process = subprocess.Popen(
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 self._args, bufsize=0, env=env,
stdout=self.server_out, stderr=self.server_out)
class RcWebServer(ServerBase):
"""
Represents a running RCE web server used as a test fixture.
"""
log_file_name = 'rc-web.log'
status_url_tmpl = 'http://{host}:{port}/_admin/ops/ping'
tests: fixed all tests for python3 BIG changes
r5087 def __init__(self, config_file, log_file=None, workers='1'):
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 super(RcWebServer, self).__init__(config_file, log_file)
self._args = [
tests: fixed all tests for python3 BIG changes
r5087 'gunicorn',
'--bind', self.bind_addr,
'--worker-class', 'gevent',
'--backlog', '16',
'--timeout', '300',
'--workers', workers,
tests: fixed starting of customized gunicorn with a explicit --bind call
r4976 '--paste', self.config_file]
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
def start(self):
env = os.environ.copy()
env['RC_NO_TMP_PATH'] = '1'
self.log_file = self.get_log_file_with_port()
self.server_out = open(self.log_file, 'w')
host_url = self.host_url()
assert_no_running_instance(host_url)
tests: fixed starting of customized gunicorn with a explicit --bind call
r4976 print(f'rhodecode-web starting at: {host_url}')
print(f'rhodecode-web command: {self.command}')
print(f'rhodecode-web logfile: {self.log_file}')
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457
python3: remove usage of subprocess32
r4926 self.process = subprocess.Popen(
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 self._args, bufsize=0, env=env,
stdout=self.server_out, stderr=self.server_out)
def repo_clone_url(self, repo_name, **kwargs):
params = {
'user': TEST_USER_ADMIN_LOGIN,
'passwd': TEST_USER_ADMIN_PASS,
'host': get_host_url(self.config_file),
'cloned_repo': repo_name,
}
params.update(**kwargs)
tests: fixed all tests for python3 BIG changes
r5087 _url = f"http://{params['user']}:{params['passwd']}@{params['host']}/{params['cloned_repo']}"
tests: rewrote code for running vcs_operations. Now it starts it's own...
r2457 return _url