OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2014 The Swarming Authors. All rights reserved. | 2 # Copyright 2014 The Swarming Authors. All rights reserved. |
3 # Use of this source code is governed by the Apache v2.0 license that can be | 3 # Use of this source code is governed by the Apache v2.0 license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 import collections | 6 import collections |
7 import datetime | 7 import datetime |
8 import logging | 8 import logging |
9 import os | 9 import os |
10 import StringIO | 10 import StringIO |
11 import sys | 11 import sys |
12 import tarfile | 12 import tarfile |
13 import tempfile | 13 import tempfile |
| 14 import textwrap |
14 import unittest | 15 import unittest |
15 | 16 |
16 APP_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) | 17 APP_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
17 | 18 |
18 import test_env | 19 import test_env |
19 test_env.setup_test_env() | 20 test_env.setup_test_env() |
20 | 21 |
21 from google.appengine.ext import ndb | 22 from google.appengine.ext import ndb |
22 | 23 |
23 from components import auth | 24 from components import auth |
24 from components import auth_testing | 25 from components import auth_testing |
25 from components.auth import model | 26 from components.auth import model |
26 from test_support import test_case | 27 from test_support import test_case |
27 | 28 |
| 29 # Must be after 'components' import, since they add it to sys.path. |
| 30 from google import protobuf |
| 31 |
| 32 from proto import config_pb2 |
28 import importer | 33 import importer |
29 | 34 |
30 | 35 |
31 def build_tar_gz(content): | 36 def build_tar_gz(content): |
32 """Returns bytes of tar.gz archive build from {filename -> body} dict.""" | 37 """Returns bytes of tar.gz archive build from {filename -> body} dict.""" |
33 out = StringIO.StringIO() | 38 out = StringIO.StringIO() |
34 with tarfile.open(mode='w|gz', fileobj=out) as tar: | 39 with tarfile.open(mode='w|gz', fileobj=out) as tar: |
35 for name, value in content.iteritems(): | 40 for name, value in content.iteritems(): |
36 # tarfile module doesn't support in-memory files (it tries to os.stat | 41 # tarfile module doesn't support in-memory files (it tries to os.stat |
37 # them), so dump to disk first to keep the code simple. | 42 # them), so dump to disk first to keep the code simple. |
(...skipping 24 matching lines...) Expand all Loading... |
62 modified_by=ident('admin'), | 67 modified_by=ident('admin'), |
63 modified_ts=datetime.datetime(1999, 1, 2, 3, 4, 5, 6), | 68 modified_ts=datetime.datetime(1999, 1, 2, 3, 4, 5, 6), |
64 members=[ident(x) for x in members], | 69 members=[ident(x) for x in members], |
65 nested=nested or []) | 70 nested=nested or []) |
66 | 71 |
67 | 72 |
68 def fetch_groups(): | 73 def fetch_groups(): |
69 return {x.key.id(): x.to_dict() for x in model.AuthGroup.query()} | 74 return {x.key.id(): x.to_dict() for x in model.AuthGroup.query()} |
70 | 75 |
71 | 76 |
| 77 def put_config(config_proto, config): |
| 78 importer.GroupImporterConfig( |
| 79 key=importer.config_key(), |
| 80 config_proto=config_proto, |
| 81 config=config).put() |
| 82 |
| 83 |
72 class ImporterTest(test_case.TestCase): | 84 class ImporterTest(test_case.TestCase): |
73 def setUp(self): | 85 def setUp(self): |
74 super(ImporterTest, self).setUp() | 86 super(ImporterTest, self).setUp() |
75 auth_testing.mock_is_admin(self, True) | 87 auth_testing.mock_is_admin(self, True) |
76 auth_testing.mock_get_current_identity(self) | 88 auth_testing.mock_get_current_identity(self) |
77 | 89 |
78 def mock_urlfetch(self, urls): | 90 def mock_urlfetch(self, urls): |
79 def mock_get_access_token(*_args): | 91 def mock_get_access_token(*_args): |
80 return 'token', 0 | 92 return 'token', 0 |
81 self.mock(auth, 'get_access_token', mock_get_access_token) | 93 self.mock(auth, 'get_access_token', mock_get_access_token) |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
216 systems=['ldap'], | 228 systems=['ldap'], |
217 groups=['ldap/group-a', 'ldap/group-b'], | 229 groups=['ldap/group-a', 'ldap/group-b'], |
218 domain='example.com') | 230 domain='example.com') |
219 | 231 |
220 def test_import_external_groups(self): | 232 def test_import_external_groups(self): |
221 self.mock_now(datetime.datetime(2010, 1, 2, 3, 4, 5, 6)) | 233 self.mock_now(datetime.datetime(2010, 1, 2, 3, 4, 5, 6)) |
222 | 234 |
223 service_id = auth.Identity.from_bytes('service:some-service') | 235 service_id = auth.Identity.from_bytes('service:some-service') |
224 self.mock(auth, 'get_service_self_identity', lambda: service_id) | 236 self.mock(auth, 'get_service_self_identity', lambda: service_id) |
225 | 237 |
226 importer.write_config([ | 238 importer.write_config_text(""" |
227 { | 239 tarball { |
228 'domain': 'example.com', | 240 domain: "example.com" |
229 'format': 'tarball', | 241 groups: "ldap/new" |
230 'groups': ['ldap/new'], | 242 oauth_scopes: "scope" |
231 'oauth_scopes': ['scope'], | 243 systems: "ldap" |
232 'systems': ['ldap'], | 244 url: "https://fake_tarball" |
233 'url': 'https://fake_tarball', | 245 } |
234 }, | 246 plainlist { |
235 { | 247 group: "external_1" |
236 'format': 'plainlist', | 248 oauth_scopes: "scope" |
237 'group': 'external_1', | 249 url: "https://fake_external_1" |
238 'oauth_scopes': ['scope'], | 250 } |
239 'url': 'https://fake_external_1', | 251 plainlist { |
240 }, | 252 domain: "example.com" |
241 { | 253 group: "external_2" |
242 'description': 'Some external group', | 254 oauth_scopes: "scope" |
243 'domain': 'example.com', | 255 url: "https://fake_external_2" |
244 'format': 'plainlist', | 256 } |
245 'group': 'external_2', | 257 """) |
246 'oauth_scopes': ['scope'], | |
247 'url': 'https://fake_external_2', | |
248 }, | |
249 ]) | |
250 | 258 |
251 self.mock_urlfetch({ | 259 self.mock_urlfetch({ |
252 'https://fake_tarball': build_tar_gz({ | 260 'https://fake_tarball': build_tar_gz({ |
253 'ldap/new': 'a\nb', | 261 'ldap/new': 'a\nb', |
254 }), | 262 }), |
255 'https://fake_external_1': 'abc@test.com\ndef@test.com\n', | 263 'https://fake_external_1': 'abc@test.com\ndef@test.com\n', |
256 'https://fake_external_2': '123\n456', | 264 'https://fake_external_2': '123\n456', |
257 }) | 265 }) |
258 | 266 |
259 # Should be deleted during import, since not in a imported bundle. | 267 # Should be deleted during import, since not in a imported bundle. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 'description': u'', | 304 'description': u'', |
297 'globs': [], | 305 'globs': [], |
298 'members': [ident('123'), ident('456')], | 306 'members': [ident('123'), ident('456')], |
299 'modified_by': service_id, | 307 'modified_by': service_id, |
300 'modified_ts': datetime.datetime(2010, 1, 2, 3, 4, 5, 6), | 308 'modified_ts': datetime.datetime(2010, 1, 2, 3, 4, 5, 6), |
301 'nested': [], | 309 'nested': [], |
302 }, | 310 }, |
303 } | 311 } |
304 self.assertEqual(expected_groups, fetch_groups()) | 312 self.assertEqual(expected_groups, fetch_groups()) |
305 | 313 |
| 314 def test_read_config_text(self): |
| 315 # Empty. |
| 316 put_config('', '') |
| 317 self.assertEqual('', importer.read_config_text()) |
| 318 # Good. |
| 319 put_config('tarball{}', '') |
| 320 self.assertEqual('tarball{}', importer.read_config_text()) |
| 321 # Legacy. |
| 322 put_config('', '[{"url":"12"}]') |
| 323 self.assertEqual('tarball {\n url: "12"\n}\n', importer.read_config_text()) |
| 324 |
| 325 def test_write_config_text(self): |
| 326 put_config('', 'legacy') |
| 327 importer.write_config_text('tarball{url:"12"\nsystems:"12"}') |
| 328 e = importer.config_key().get() |
| 329 self.assertEqual('legacy', e.config) |
| 330 self.assertEqual('tarball{url:"12"\nsystems:"12"}', e.config_proto) |
| 331 |
| 332 def test_legacy_json_config_to_proto(self): |
| 333 msg = importer.legacy_json_config_to_proto(""" |
| 334 [ |
| 335 { |
| 336 "url": "https://example.com/all_users", |
| 337 "group": "plain-list", |
| 338 "format": "plainlist" |
| 339 }, |
| 340 { |
| 341 "url": "https://example.com/tarball.tar.gz", |
| 342 "domain": "example.com", |
| 343 "oauth_scopes": [ |
| 344 "oauth-scope" |
| 345 ], |
| 346 "systems": [ |
| 347 "ldap" |
| 348 ], |
| 349 "groups": [ |
| 350 "ldap/a", |
| 351 "ldap/b" |
| 352 ] |
| 353 } |
| 354 ] |
| 355 """) |
| 356 expected = textwrap.dedent(""" |
| 357 tarball { |
| 358 url: "https://example.com/tarball.tar.gz" |
| 359 oauth_scopes: "oauth-scope" |
| 360 domain: "example.com" |
| 361 systems: "ldap" |
| 362 groups: "ldap/a" |
| 363 groups: "ldap/b" |
| 364 } |
| 365 plainlist { |
| 366 url: "https://example.com/all_users" |
| 367 group: "plain-list" |
| 368 } |
| 369 """.lstrip('\n')) |
| 370 self.assertEqual(expected, protobuf.text_format.MessageToString(msg)) |
| 371 |
306 | 372 |
307 if __name__ == '__main__': | 373 if __name__ == '__main__': |
308 if '-v' in sys.argv: | 374 if '-v' in sys.argv: |
309 unittest.TestCase.maxDiff = None | 375 unittest.TestCase.maxDiff = None |
310 logging.basicConfig(level=logging.DEBUG) | 376 logging.basicConfig(level=logging.DEBUG) |
311 else: | 377 else: |
312 logging.basicConfig(level=logging.FATAL) | 378 logging.basicConfig(level=logging.FATAL) |
313 unittest.main() | 379 unittest.main() |
OLD | NEW |