]>
Commit | Line | Data |
---|---|---|
20effc67 TL |
1 | """ |
2 | Run a set of bucket notification tests on rgw. | |
3 | """ | |
4 | from io import BytesIO | |
5 | from configobj import ConfigObj | |
6 | import base64 | |
7 | import contextlib | |
8 | import logging | |
9 | import os | |
10 | import random | |
11 | import string | |
12 | ||
13 | from teuthology import misc as teuthology | |
14 | from teuthology import contextutil | |
15 | from teuthology.orchestra import run | |
16 | ||
17 | log = logging.getLogger(__name__) | |
18 | ||
19 | ||
20 | @contextlib.contextmanager | |
21 | def download(ctx, config): | |
22 | assert isinstance(config, dict) | |
23 | log.info('Downloading bucket-notifications-tests...') | |
24 | testdir = teuthology.get_testdir(ctx) | |
25 | branch = ctx.config.get('suite_branch') | |
26 | repo = ctx.config.get('suite_repo') | |
27 | log.info('Using branch %s from %s for bucket notifications tests', branch, repo) | |
28 | for (client, client_config) in config.items(): | |
29 | ctx.cluster.only(client).run( | |
30 | args=['git', 'clone', '-b', branch, repo, '{tdir}/ceph'.format(tdir=testdir)], | |
31 | ) | |
32 | ||
33 | sha1 = client_config.get('sha1') | |
34 | ||
35 | if sha1 is not None: | |
36 | ctx.cluster.only(client).run( | |
37 | args=[ | |
38 | 'cd', '{tdir}/ceph'.format(tdir=testdir), | |
39 | run.Raw('&&'), | |
40 | 'git', 'reset', '--hard', sha1, | |
41 | ], | |
42 | ) | |
43 | ||
44 | try: | |
45 | yield | |
46 | finally: | |
47 | log.info('Removing bucket-notifications-tests...') | |
48 | testdir = teuthology.get_testdir(ctx) | |
49 | for client in config: | |
50 | ctx.cluster.only(client).run( | |
51 | args=[ | |
52 | 'rm', | |
53 | '-rf', | |
54 | '{tdir}/ceph'.format(tdir=testdir), | |
55 | ], | |
56 | ) | |
57 | ||
58 | def _config_user(bntests_conf, section, user): | |
59 | """ | |
60 | Configure users for this section by stashing away keys, ids, and | |
61 | email addresses. | |
62 | """ | |
63 | bntests_conf[section].setdefault('user_id', user) | |
64 | bntests_conf[section].setdefault('email', '{user}+test@test.test'.format(user=user)) | |
65 | bntests_conf[section].setdefault('display_name', 'Mr. {user}'.format(user=user)) | |
66 | bntests_conf[section].setdefault('access_key', | |
67 | ''.join(random.choice(string.ascii_uppercase) for i in range(20))) | |
68 | bntests_conf[section].setdefault('secret_key', | |
69 | base64.b64encode(os.urandom(40)).decode()) | |
70 | ||
71 | ||
72 | @contextlib.contextmanager | |
73 | def pre_process(ctx, config): | |
74 | """ | |
75 | This function creates a directory which is required to run some AMQP tests. | |
76 | """ | |
77 | assert isinstance(config, dict) | |
78 | log.info('Pre-processing...') | |
79 | ||
80 | for (client, _) in config.items(): | |
81 | (remote,) = ctx.cluster.only(client).remotes.keys() | |
82 | test_dir=teuthology.get_testdir(ctx) | |
83 | ||
84 | ctx.cluster.only(client).run( | |
85 | args=[ | |
86 | 'mkdir', '-p', '/home/ubuntu/.aws/models/s3/2006-03-01/', | |
87 | ], | |
88 | ) | |
89 | ||
90 | ctx.cluster.only(client).run( | |
91 | args=[ | |
92 | 'cd', '/home/ubuntu/.aws/models/s3/2006-03-01/', run.Raw('&&'), 'cp', '{tdir}/ceph/examples/boto3/service-2.sdk-extras.json'.format(tdir=test_dir), 'service-2.sdk-extras.json' | |
93 | ], | |
94 | ) | |
95 | ||
96 | try: | |
97 | yield | |
98 | finally: | |
99 | log.info('Pre-processing completed...') | |
100 | test_dir = teuthology.get_testdir(ctx) | |
101 | for (client, _) in config.items(): | |
102 | (remote,) = ctx.cluster.only(client).remotes.keys() | |
103 | ||
104 | ctx.cluster.only(client).run( | |
105 | args=[ | |
106 | 'rm', '-rf', '/home/ubuntu/.aws/models/s3/2006-03-01/service-2.sdk-extras.json', | |
107 | ], | |
108 | ) | |
109 | ||
110 | ctx.cluster.only(client).run( | |
111 | args=[ | |
112 | 'cd', '/home/ubuntu/', run.Raw('&&'), 'rmdir', '-p', '.aws/models/s3/2006-03-01/', | |
113 | ], | |
114 | ) | |
115 | ||
116 | ||
117 | @contextlib.contextmanager | |
118 | def create_users(ctx, config): | |
119 | """ | |
120 | Create a main and an alternate s3 user. | |
121 | """ | |
122 | assert isinstance(config, dict) | |
123 | log.info('Creating rgw user...') | |
124 | testdir = teuthology.get_testdir(ctx) | |
125 | ||
126 | users = {'s3 main': 'foo'} | |
127 | for client in config['clients']: | |
128 | bntests_conf = config['bntests_conf'][client] | |
129 | for section, user in users.items(): | |
130 | _config_user(bntests_conf, section, '{user}.{client}'.format(user=user, client=client)) | |
131 | log.debug('Creating user {user} on {host}'.format(user=bntests_conf[section]['user_id'], host=client)) | |
132 | cluster_name, daemon_type, client_id = teuthology.split_role(client) | |
133 | client_with_id = daemon_type + '.' + client_id | |
134 | ctx.cluster.only(client).run( | |
135 | args=[ | |
136 | 'adjust-ulimits', | |
137 | 'ceph-coverage', | |
138 | '{tdir}/archive/coverage'.format(tdir=testdir), | |
139 | 'radosgw-admin', | |
140 | '-n', client_with_id, | |
141 | 'user', 'create', | |
142 | '--uid', bntests_conf[section]['user_id'], | |
143 | '--display-name', bntests_conf[section]['display_name'], | |
144 | '--access-key', bntests_conf[section]['access_key'], | |
145 | '--secret', bntests_conf[section]['secret_key'], | |
146 | '--cluster', cluster_name, | |
147 | ], | |
148 | ) | |
149 | ||
150 | try: | |
151 | yield | |
152 | finally: | |
153 | for client in config['clients']: | |
154 | for user in users.values(): | |
155 | uid = '{user}.{client}'.format(user=user, client=client) | |
156 | cluster_name, daemon_type, client_id = teuthology.split_role(client) | |
157 | client_with_id = daemon_type + '.' + client_id | |
158 | ctx.cluster.only(client).run( | |
159 | args=[ | |
160 | 'adjust-ulimits', | |
161 | 'ceph-coverage', | |
162 | '{tdir}/archive/coverage'.format(tdir=testdir), | |
163 | 'radosgw-admin', | |
164 | '-n', client_with_id, | |
165 | 'user', 'rm', | |
166 | '--uid', uid, | |
167 | '--purge-data', | |
168 | '--cluster', cluster_name, | |
169 | ], | |
170 | ) | |
171 | ||
172 | @contextlib.contextmanager | |
173 | def configure(ctx, config): | |
174 | assert isinstance(config, dict) | |
175 | log.info('Configuring bucket-notifications-tests...') | |
176 | testdir = teuthology.get_testdir(ctx) | |
177 | for client, properties in config['clients'].items(): | |
178 | (remote,) = ctx.cluster.only(client).remotes.keys() | |
179 | bntests_conf = config['bntests_conf'][client] | |
180 | ||
181 | conf_fp = BytesIO() | |
182 | bntests_conf.write(conf_fp) | |
183 | remote.write_file( | |
184 | path='{tdir}/ceph/src/test/rgw/bucket_notification/bn-tests.{client}.conf'.format(tdir=testdir, client=client), | |
185 | data=conf_fp.getvalue(), | |
186 | ) | |
187 | ||
188 | remote.run( | |
189 | args=[ | |
190 | 'cd', | |
191 | '{tdir}/ceph/src/test/rgw/bucket_notification'.format(tdir=testdir), | |
192 | run.Raw('&&'), | |
193 | './bootstrap', | |
194 | ], | |
195 | ) | |
196 | ||
197 | try: | |
198 | yield | |
199 | finally: | |
200 | log.info('Removing bn-tests.conf file...') | |
201 | testdir = teuthology.get_testdir(ctx) | |
202 | for client, properties in config['clients'].items(): | |
203 | (remote,) = ctx.cluster.only(client).remotes.keys() | |
204 | remote.run( | |
205 | args=['rm', '-f', | |
206 | '{tdir}/ceph/src/test/rgw/bucket_notification/bn-tests.{client}.conf'.format(tdir=testdir,client=client), | |
207 | ], | |
208 | ) | |
209 | ||
210 | @contextlib.contextmanager | |
211 | def run_tests(ctx, config): | |
212 | """ | |
213 | Run the bucket notifications tests after everything is set up. | |
214 | :param ctx: Context passed to task | |
215 | :param config: specific configuration information | |
216 | """ | |
217 | assert isinstance(config, dict) | |
218 | log.info('Running bucket-notifications-tests...') | |
219 | testdir = teuthology.get_testdir(ctx) | |
220 | for client, client_config in config.items(): | |
221 | (remote,) = ctx.cluster.only(client).remotes.keys() | |
222 | ||
223 | attr = ["!kafka_test", "!amqp_test", "!amqp_ssl_test", "!modification_required", "!manual_test"] | |
224 | ||
225 | if 'extra_attr' in client_config: | |
226 | attr = client_config.get('extra_attr') | |
227 | ||
228 | args = [ | |
229 | 'BNTESTS_CONF={tdir}/ceph/src/test/rgw/bucket_notification/bn-tests.{client}.conf'.format(tdir=testdir, client=client), | |
230 | '{tdir}/ceph/src/test/rgw/bucket_notification/virtualenv/bin/python'.format(tdir=testdir), | |
231 | '-m', 'nose', | |
232 | '-s', | |
233 | '{tdir}/ceph/src/test/rgw/bucket_notification/test_bn.py'.format(tdir=testdir), | |
234 | '-v', | |
235 | '-a', ','.join(attr), | |
236 | ] | |
237 | ||
238 | remote.run( | |
239 | args=args, | |
240 | label="bucket notification tests against different endpoints" | |
241 | ) | |
242 | yield | |
243 | ||
244 | @contextlib.contextmanager | |
245 | def task(ctx,config): | |
246 | """ | |
247 | To run bucket notification tests under Kafka endpoint the prerequisite is to run the kafka server. Also you need to pass the | |
248 | 'extra_attr' to the notification tests. Following is the way how to run kafka and finally bucket notification tests:: | |
249 | ||
250 | tasks: | |
251 | - kafka: | |
252 | client.0: | |
253 | kafka_version: 2.6.0 | |
254 | - notification_tests: | |
255 | client.0: | |
256 | extra_attr: ["kafka_test"] | |
257 | ||
258 | To run bucket notification tests under AMQP endpoint the prerequisite is to run the rabbitmq server. Also you need to pass the | |
259 | 'extra_attr' to the notification tests. Following is the way how to run rabbitmq and finally bucket notification tests:: | |
260 | ||
261 | tasks: | |
262 | - rabbitmq: | |
263 | client.0: | |
264 | - notification_tests: | |
265 | client.0: | |
266 | extra_attr: ["amqp_test"] | |
267 | ||
268 | If you want to run the tests against your changes pushed to your remote repo you can provide 'suite_branch' and 'suite_repo' | |
269 | parameters in your teuthology-suite command. Example command for this is as follows:: | |
270 | ||
271 | teuthology-suite --ceph-repo https://github.com/ceph/ceph-ci.git -s rgw:notifications --ceph your_ceph_branch_name -m smithi --suite-repo https://github.com/your_name/ceph.git --suite-branch your_branch_name | |
272 | ||
273 | """ | |
274 | assert config is None or isinstance(config, list) \ | |
275 | or isinstance(config, dict), \ | |
276 | "task kafka only supports a list or dictionary for configuration" | |
277 | ||
278 | all_clients = ['client.{id}'.format(id=id_) | |
279 | for id_ in teuthology.all_roles_of_type(ctx.cluster, 'client')] | |
280 | if config is None: | |
281 | config = all_clients | |
282 | if isinstance(config, list): | |
283 | config = dict.fromkeys(config) | |
284 | clients=config.keys() | |
285 | ||
286 | log.debug('Notifications config is %s', config) | |
287 | ||
288 | bntests_conf = {} | |
289 | ||
290 | for client in clients: | |
291 | endpoint = ctx.rgw.role_endpoints.get(client) | |
292 | assert endpoint, 'bntests: no rgw endpoint for {}'.format(client) | |
293 | ||
294 | bntests_conf[client] = ConfigObj( | |
295 | indent_type='', | |
296 | infile={ | |
297 | 'DEFAULT': | |
298 | { | |
299 | 'port':endpoint.port, | |
300 | 'host':endpoint.dns_name, | |
301 | }, | |
302 | 's3 main':{} | |
303 | } | |
304 | ) | |
305 | ||
306 | with contextutil.nested( | |
307 | lambda: download(ctx=ctx, config=config), | |
308 | lambda: pre_process(ctx=ctx, config=config), | |
309 | lambda: create_users(ctx=ctx, config=dict( | |
310 | clients=clients, | |
311 | bntests_conf=bntests_conf, | |
312 | )), | |
313 | lambda: configure(ctx=ctx, config=dict( | |
314 | clients=config, | |
315 | bntests_conf=bntests_conf, | |
316 | )), | |
317 | lambda: run_tests(ctx=ctx, config=config), | |
318 | ): | |
319 | pass | |
320 | yield |