##// END OF EJS Templates
server-utils: report server ready state
marcink -
r2466:f1a30267 default
parent child Browse files
Show More
@@ -1,194 +1,197 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21
22 22 import os
23 23 import time
24 24 import tempfile
25 25 import pytest
26 26 import subprocess32
27 27 import configobj
28 28
29 29 from urllib2 import urlopen, URLError
30 30 from pyramid.compat import configparser
31 31
32 32
33 33 from rhodecode.tests import TEST_USER_ADMIN_LOGIN, TEST_USER_ADMIN_PASS
34 34 from rhodecode.tests.utils import is_url_reachable
35 35
36 36
37 37 def get_port(pyramid_config):
38 38 config = configparser.ConfigParser()
39 39 config.read(pyramid_config)
40 40 return config.get('server:main', 'port')
41 41
42 42
43 43 def get_host_url(pyramid_config):
44 44 """Construct the host url using the port in the test configuration."""
45 45 return '127.0.0.1:%s' % get_port(pyramid_config)
46 46
47 47
48 48 def assert_no_running_instance(url):
49 49 if is_url_reachable(url):
50 50 print("Hint: Usually this means another instance of server "
51 51 "is running in the background at %s." % url)
52 52 pytest.fail(
53 53 "Port is not free at %s, cannot start server at" % url)
54 54
55 55
56 56 class ServerBase(object):
57 57 _args = []
58 58 log_file_name = 'NOT_DEFINED.log'
59 59 status_url_tmpl = 'http://{host}:{port}'
60 60
61 61 def __init__(self, config_file, log_file):
62 62 self.config_file = config_file
63 63 config_data = configobj.ConfigObj(config_file)
64 64 self._config = config_data['server:main']
65 65
66 66 self._args = []
67 67 self.log_file = log_file or os.path.join(
68 68 tempfile.gettempdir(), self.log_file_name)
69 69 self.process = None
70 70 self.server_out = None
71 71 print("Using the {} configuration:{}".format(
72 72 self.__class__.__name__, config_file))
73 73
74 74 if not os.path.isfile(config_file):
75 75 raise RuntimeError('Failed to get config at {}'.format(config_file))
76 76
77 77 @property
78 78 def command(self):
79 79 return ' '.join(self._args)
80 80
81 81 @property
82 82 def http_url(self):
83 83 template = 'http://{host}:{port}/'
84 84 return template.format(**self._config)
85 85
86 86 def host_url(self):
87 87 return 'http://' + get_host_url(self.config_file)
88 88
89 89 def get_rc_log(self):
90 90 with open(self.log_file) as f:
91 91 return f.read()
92 92
93 93 def wait_until_ready(self, timeout=30):
94 94 host = self._config['host']
95 95 port = self._config['port']
96 96 status_url = self.status_url_tmpl.format(host=host, port=port)
97 97 start = time.time()
98 98
99 99 while time.time() - start < timeout:
100 100 try:
101 101 urlopen(status_url)
102 102 break
103 103 except URLError:
104 104 time.sleep(0.2)
105 105 else:
106 106 pytest.fail(
107 107 "Starting the {} failed or took more than {} "
108 108 "seconds. cmd: `{}`".format(
109 109 self.__class__.__name__, timeout, self.command))
110 110
111 print('Server of {} ready at url {}'.format(
112 self.__class__.__name__, status_url))
113
111 114 def shutdown(self):
112 115 self.process.kill()
113 116 self.server_out.flush()
114 117 self.server_out.close()
115 118
116 119 def get_log_file_with_port(self):
117 120 log_file = list(self.log_file.partition('.log'))
118 121 log_file.insert(1, get_port(self.config_file))
119 122 log_file = ''.join(log_file)
120 123 return log_file
121 124
122 125
123 126 class RcVCSServer(ServerBase):
124 127 """
125 128 Represents a running VCSServer instance.
126 129 """
127 130
128 131 log_file_name = 'rc-vcsserver.log'
129 132 status_url_tmpl = 'http://{host}:{port}/status'
130 133
131 134 def __init__(self, config_file, log_file=None):
132 135 super(RcVCSServer, self).__init__(config_file, log_file)
133 136 self._args = [
134 137 'gunicorn', '--paste', self.config_file]
135 138
136 139 def start(self):
137 140 env = os.environ.copy()
138 141
139 142 self.log_file = self.get_log_file_with_port()
140 143 self.server_out = open(self.log_file, 'w')
141 144
142 145 host_url = self.host_url()
143 146 assert_no_running_instance(host_url)
144 147
145 148 print('rhodecode-vcsserver starting at: {}'.format(host_url))
146 149 print('rhodecode-vcsserver command: {}'.format(self.command))
147 150 print('rhodecode-vcsserver logfile: {}'.format(self.log_file))
148 151
149 152 self.process = subprocess32.Popen(
150 153 self._args, bufsize=0, env=env,
151 154 stdout=self.server_out, stderr=self.server_out)
152 155
153 156
154 157 class RcWebServer(ServerBase):
155 158 """
156 159 Represents a running RCE web server used as a test fixture.
157 160 """
158 161
159 162 log_file_name = 'rc-web.log'
160 163 status_url_tmpl = 'http://{host}:{port}/_admin/ops/ping'
161 164
162 165 def __init__(self, config_file, log_file=None):
163 166 super(RcWebServer, self).__init__(config_file, log_file)
164 167 self._args = [
165 168 'gunicorn', '--worker-class', 'gevent', '--paste', config_file]
166 169
167 170 def start(self):
168 171 env = os.environ.copy()
169 172 env['RC_NO_TMP_PATH'] = '1'
170 173
171 174 self.log_file = self.get_log_file_with_port()
172 175 self.server_out = open(self.log_file, 'w')
173 176
174 177 host_url = self.host_url()
175 178 assert_no_running_instance(host_url)
176 179
177 180 print('rhodecode-web starting at: {}'.format(host_url))
178 181 print('rhodecode-web command: {}'.format(self.command))
179 182 print('rhodecode-web logfile: {}'.format(self.log_file))
180 183
181 184 self.process = subprocess32.Popen(
182 185 self._args, bufsize=0, env=env,
183 186 stdout=self.server_out, stderr=self.server_out)
184 187
185 188 def repo_clone_url(self, repo_name, **kwargs):
186 189 params = {
187 190 'user': TEST_USER_ADMIN_LOGIN,
188 191 'passwd': TEST_USER_ADMIN_PASS,
189 192 'host': get_host_url(self.config_file),
190 193 'cloned_repo': repo_name,
191 194 }
192 195 params.update(**kwargs)
193 196 _url = 'http://%(user)s:%(passwd)s@%(host)s/%(cloned_repo)s' % params
194 197 return _url
General Comments 0
You need to be logged in to leave comments. Login now