| 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 |