Пример #1
0
 def setUp(self):
     super(ProjectsTestCase, self).setUp()
     self.mock(storage, 'get_self_config_async', mock.Mock())
     storage.get_self_config_async.return_value = future(
         service_config_pb2.ServicesCfg(services=[
             service_config_pb2.Service(
                 id='foo', metadata_url='https://foo.com/metadata'),
             service_config_pb2.Service(id='metadataless'),
         ]))
Пример #2
0
 def service_proto(
     sid='deadbeef',
     metadata_url='https://a.com/metadata',
     jwt_auth=None):
   return service_config_pb2.Service(
       id=sid,
       metadata_url=metadata_url,
       jwt_auth=jwt_auth)
Пример #3
0
  def test_has_service_access(self):
    self.assertFalse(acl.can_read_config_set('services/swarming'))

    service_cfg = service_config_pb2.Service(
        id='swarming', access=['group:swarming-app'])
    services.get_service_async.side_effect = lambda sid: future(service_cfg)
    auth.is_group_member.side_effect = lambda g, *_: g == 'swarming-app'

    self.assertTrue(acl.can_read_config_set('services/swarming'))
Пример #4
0
  def test_has_service_access(self):
    self.assertFalse(can_read_config_set('services/swarming'))

    services.get_services_async.return_value = future([
      service_config_pb2.Service(
          id='swarming', access=['group:swarming-app']),
    ])
    auth.is_group_member.side_effect = lambda g, *_: g == 'swarming-app'

    self.assertTrue(can_read_config_set('services/swarming'))
Пример #5
0
    def test_get_metadata_async(self):
        self.mock(storage, 'get_self_config_async', mock.Mock())
        storage.get_self_config_async.return_value = future(
            service_config_pb2.ServicesCfg(services=[
                service_config_pb2.Service(
                    id='foo', metadata_url='https://foo.com/metadata')
            ]))

        self.mock(net, 'json_request_async', mock.Mock())
        net.json_request_async.return_value = future({
            'version': '1.0',
            'validation': {
                'url':
                'https://a.com/validate',
                'patterns': [
                    {
                        'config_set': 'projects/foo',
                        'path': 'bar.cfg'
                    },
                    {
                        'config_set': 'regex:services/.+',
                        'path': 'regex:.+'
                    },
                ]
            }
        })

        metadata = services.get_metadata_async('foo').get_result()
        self.assertEqual(
            metadata,
            service_config_pb2.ServiceDynamicMetadata(
                validation=service_config_pb2.Validator(
                    url='https://a.com/validate',
                    patterns=[
                        service_config_pb2.ConfigPattern(
                            config_set='projects/foo', path='bar.cfg'),
                        service_config_pb2.ConfigPattern(
                            config_set='regex:services/.+', path='regex:.+'),
                    ])))

        net.json_request_async.assert_called_once_with(
            'https://foo.com/metadata', scopes=net.EMAIL_SCOPE)

        storage.get_self_config_async.assert_called_once_with(
            common.SERVICES_REGISTRY_FILENAME, service_config_pb2.ServicesCfg)
Пример #6
0
    def test_validation_by_service_async(self):
        cfg = '# a config'
        cfg_b64 = base64.b64encode(cfg)

        self.services = [
            service_config_pb2.Service(id='a'),
            service_config_pb2.Service(id='b'),
            service_config_pb2.Service(id='c'),
        ]

        @ndb.tasklet
        def get_metadata_async(service_id):
            if service_id == 'a':
                raise ndb.Return(
                    service_config_pb2.ServiceDynamicMetadata(
                        validation=service_config_pb2.Validator(
                            patterns=[
                                service_config_pb2.ConfigPattern(
                                    config_set='services/foo',
                                    path='bar.cfg',
                                )
                            ],
                            url='https://bar.verifier',
                        )))
            if service_id == 'b':
                raise ndb.Return(
                    service_config_pb2.ServiceDynamicMetadata(
                        validation=service_config_pb2.Validator(
                            patterns=[
                                service_config_pb2.ConfigPattern(
                                    config_set=r'regex:projects/[^/]+',
                                    path=r'regex:.+\.cfg',
                                )
                            ],
                            url='https://bar2.verifier',
                        )))
            if service_id == 'c':
                raise ndb.Return(
                    service_config_pb2.ServiceDynamicMetadata(
                        validation=service_config_pb2.Validator(
                            patterns=[
                                service_config_pb2.ConfigPattern(
                                    config_set=r'regex:.+',
                                    path=r'regex:.+',
                                )
                            ],
                            url='https://ultimate.verifier',
                        )))
            return None

        self.mock(services, 'get_metadata_async', mock.Mock())
        services.get_metadata_async.side_effect = get_metadata_async

        @ndb.tasklet
        def json_request_async(url, **kwargs):
            raise ndb.Return({
                'messages': [{
                    'text': 'OK from %s' % url,
                    # default severity
                }],
            })

        self.mock(net, 'json_request_async',
                  mock.Mock(side_effect=json_request_async))

        ############################################################################

        result = validation.validate_config('services/foo', 'bar.cfg', cfg)
        self.assertEqual(result.messages, [
            validation_context.Message(text='OK from https://bar.verifier',
                                       severity=logging.INFO),
            validation_context.Message(
                text='OK from https://ultimate.verifier',
                severity=logging.INFO)
        ])
        net.json_request_async.assert_any_call(
            'https://bar.verifier',
            method='POST',
            payload={
                'config_set': 'services/foo',
                'path': 'bar.cfg',
                'content': cfg_b64,
            },
            scopes=net.EMAIL_SCOPE,
        )
        net.json_request_async.assert_any_call(
            'https://ultimate.verifier',
            method='POST',
            payload={
                'config_set': 'services/foo',
                'path': 'bar.cfg',
                'content': cfg_b64,
            },
            scopes=net.EMAIL_SCOPE,
        )

        ############################################################################

        result = validation.validate_config('projects/foo', 'bar.cfg', cfg)
        self.assertEqual(result.messages, [
            validation_context.Message(text='OK from https://bar2.verifier',
                                       severity=logging.INFO),
            validation_context.Message(
                text='OK from https://ultimate.verifier',
                severity=logging.INFO)
        ])
        net.json_request_async.assert_any_call(
            'https://bar2.verifier',
            method='POST',
            payload={
                'config_set': 'projects/foo',
                'path': 'bar.cfg',
                'content': cfg_b64,
            },
            scopes=net.EMAIL_SCOPE,
        )
        net.json_request_async.assert_any_call(
            'https://ultimate.verifier',
            method='POST',
            payload={
                'config_set': 'projects/foo',
                'path': 'bar.cfg',
                'content': cfg_b64,
            },
            scopes=net.EMAIL_SCOPE,
        )

        ############################################################################
        # Error found

        net.json_request_async.side_effect = None
        net.json_request_async.return_value = ndb.Future()
        net.json_request_async.return_value.set_result(
            {'messages': [{
                'text': 'error',
                'severity': 'ERROR'
            }]})

        result = validation.validate_config('projects/baz/refs/x', 'qux.cfg',
                                            cfg)
        self.assertEqual(
            result.messages,
            [validation_context.Message(text='error', severity=logging.ERROR)])

        ############################################################################
        # Less-expected responses

        res = {'messages': [{'severity': 'invalid severity'}, {}, []]}
        net.json_request_async.return_value = ndb.Future()
        net.json_request_async.return_value.set_result(res)

        result = validation.validate_config('projects/baz/refs/x', 'qux.cfg',
                                            cfg)
        self.assertEqual(
            result.messages,
            [
                validation_context.Message(
                    severity=logging.CRITICAL,
                    text=(
                        'Error during external validation: invalid response: '
                        'unexpected message severity: invalid severity\n'
                        'url: https://ultimate.verifier\n'
                        'config_set: projects/baz/refs/x\n'
                        'path: qux.cfg\n'
                        'response: %r' % res),
                ),
                validation_context.Message(severity=logging.INFO, text=''),
                validation_context.Message(
                    severity=logging.CRITICAL,
                    text=(
                        'Error during external validation: invalid response: '
                        'message is not a dict: []\n'
                        'url: https://ultimate.verifier\n'
                        'config_set: projects/baz/refs/x\n'
                        'path: qux.cfg\n'
                        'response: %r' % res),
                ),
            ],
        )