def test_get_application_by_name(db, test_application): application = Application.get_by_name(test_application.application_name) assert application is test_application assert application.domain_name == 'foo' application = Application.get_by_name(test_application.application_name + '1s') assert application is None
def test_create_application_cache_invalidation(db, test_team): assert Application.get_by_name('bar') is None assert len(Application.get_multi_by_team(test_team.id)) == 0 assert len(Application.get_all()) == 0 Application.create('bar', test_team.id) assert Application.get_by_name('bar') is not None assert len(Application.get_multi_by_team(test_team.id)) == 1 assert len(Application.get_all()) == 1
def test_unarchive_application(db, test_user, test_team, test_application, test_application_auth): test_application.archive() assert Application.get_by_name(test_application.application_name) is None test_application.unarchive() assert Application.get_by_name( test_application.application_name) is not None test_application.archive() test_team.archive() test_application.unarchive() assert Application.get_by_name(test_application.application_name) is None
def test_delete_application(db, test_user, test_team, test_application, test_application_auth): assert Application.get_by_name( test_application.application_name) is test_application assert Application.get_multi_by_team(test_team.id) == [test_application] assert Application.get_all() == [test_application] Application.delete(test_application.id) assert Application.get_by_name(test_application.application_name) is None assert Application.get_multi_by_team(test_team.id) == [] assert Application.get_all() == [] assert ApplicationAuth.get(test_application_auth.id) is None
def test_archive_application(db, test_user, test_team, test_application, test_application_auth): instance = Application.get_by_name(test_application.application_name) assert instance is test_application assert Application.get_multi_by_team(test_team.id) == [test_application] assert Application.get_all() == [test_application] test_application.archive() assert Application.get_by_name(test_application.application_name) is None assert Application.get_multi_by_team(test_team.id) == [] assert Application.get_all() == [] assert ApplicationAuth.find(Authority.READ, test_user.id, test_application.id) is not None
def put(self, webhook_id): """To update subscription settings of an application Request body schema same to ``POST`` method. :param application_name: The name of application. :param webhook_id: The id of webhook. :param webhoo_type: default 0, set universal with 1 :status 200: thr request is successful. :status 404: The application or webhoook not found. """ webhook = self._get_webhook_or_404(webhook_id) self._check_authority(webhook) data = request.get_json() or {} validate_fields(webhook_schema, data, partial=False) if not webhook.is_normal: webhook.update_url(data['webhook_url']) return api_response() application_name = request.args['application_name'] application = Application.get_by_name(application_name) webhook.batch_unsubscribe(application.id) webhook.update_url(data['webhook_url']) for action_name in data.get('event_list', []): action_type = getattr(action_types, action_name) webhook.subscribe(application.id, action_type) return api_response()
def get(self, application_name, cluster_name, key): """Get the audit logs of specified instance key. :param application_name: The name of application. :param cluster_name: The name of clsuter. :param key: The key of instance. :query date: The date specified to search, default is today. :query start: The offset of pagination. Default is ``0``. :>header Authorization: Huskar Token (See :ref:`token`) :status 403: You don't have required authority. :status 501: The server is in minimal mode. :status 200: The result is in the response. (See :ref:`Audit Log Schema <audit_schema>`) """ check_application(application_name) check_cluster_name(cluster_name, application_name) start = request.args.get('start', type=int, default=0) application = Application.get_by_name(application_name) can_view_sensitive_data = AuditLog.can_view_sensitive_data( g.auth.id, self.instance_type, application.id) items = AuditLog.get_multi_by_instance_index(self.instance_type, application.id, cluster_name, key) items = items[start:start + 20] if not can_view_sensitive_data: items = [item.desensitize() for item in items] return api_response(audit_log_schema.dump(items, many=True).data)
def _create(self, ignore_existed=False): team_name = request.values['team'].strip() application_name = request.values['application'].strip() validate_fields(application_schema, {'name': application_name, 'team_name': team_name}) team = Team.get_by_name(team_name) if team is None: abort(400, 'team "%s" does not exist' % team_name) require_team_admin_or_site_admin(team) application = Application.get_by_name(application_name) if application is not None: if ignore_existed: return api_response() raise ApplicationExistedError( 'application: {} has existed, application is globally ' 'unique'.format(application)) try: application = Application.create(application_name, team.id) except NameOccupiedError: abort(400, 'The application name {0} has been occupied.'.format( application_name)) audit_log.emit( audit_log.types.CREATE_APPLICATION, application=application, team=team) return api_response()
def test_get_team_application_token_with_unknown_application( client, db, test_team, admin_user, admin_token, application_name): application = Application.get_by_name(application_name) assert application is None r = client.post( '/api/team/%s/application/%s/token' % (test_team.team_name, application_name), data={'owner_email': admin_user.username + '@foo.bar'}, headers={'Authorization': admin_token}, ) assert_response_ok(r) application = Application.get_by_name(application_name) assert application is not None user = User.get_by_token(settings.SECRET_KEY, r.json['data']['token']) assert user and user.username == application.application_name
def test_application_transfer_team(db, test_application, faker): orig_team_id = test_application.team_id dest_team = Team.create(faker.name()) test_application.transfer_team(dest_team.id) application = Application.get_by_name(test_application.application_name) assert application.team_id == dest_team.id assert test_application.id not in Application.get_ids_by_team(orig_team_id) assert test_application.id in Application.get_ids_by_team(dest_team.id)
def _optional_instance_indices(application_name, cluster_name, instance_key, action_type): _, action_name = action_types[action_type].split('_', 1) instance_type = INSTANCE_TYPE_MAP[action_name.lower()] application = None with _suppress_exception(application_name=application_name): application = Application.get_by_name(application_name) if application: yield (instance_type, application.id, cluster_name, instance_key)
def destroy_application(name): application = Application.get_by_name(name) if application is not None: Application.delete(application.id) logger.info('Removed application from DBMS: %s', name) for type_name in (SERVICE_SUBDOMAIN, SWITCH_SUBDOMAIN, CONFIG_SUBDOMAIN): path = '/huskar/%s/%s' % (type_name, name) if huskar_client.client.exists(path): huskar_client.client.delete(path, recursive=True) logger.info('Removed application from ZooKeeper: %s', path)
def _optional_indices(application_name): application = None team = None with _suppress_exception(application_name=application_name): application = Application.get_by_name(application_name) with _suppress_exception(application_name=application_name): team = application and application.team if application: yield (TYPE_APPLICATION, application.id) if team: yield (TYPE_TEAM, team.id)
def check_application(application_name): if is_application_blacklisted(application_name): raise ApplicationNotExistedError( 'application: {} is blacklisted'.format(application_name)) if g.auth.is_minimal_mode: return application = Application.get_by_name(application_name) if application is None: raise ApplicationNotExistedError( "application: {} doesn't exist".format(application_name)) return application
def _find_target(self, name): if self.target_type is AuditLog.TYPE_SITE: return 0 if self.target_type is AuditLog.TYPE_TEAM: team = Team.get_by_name(name) if team is not None: return team.id if self.target_type is AuditLog.TYPE_APPLICATION: application = Application.get_by_name(name) if application is not None: return application.id
def test_add_application_without_validation(client, mocker, test_user, admin_token, fake_team): invalid_name = '@_@::+1s' data = {'team': fake_team.team_name, 'application': invalid_name} headers = {'Authorization': admin_token} r = client.post('/api/application', data=data, headers=headers) assert r.status_code == 400 assert r.json['status'] == 'ValidationError' assert json.loads(r.json['message'])['name'][0] assert Application.get_by_name(invalid_name) is None def fake_switch(name, default=True): if name == SWITCH_VALIDATE_SCHEMA: return False return default mocker.patch.object(switch, 'is_switched_on', fake_switch) r = client.post('/api/application', data=data, headers=headers) assert_response_ok(r) assert Application.get_by_name(invalid_name)
def get(self, webhook_id): """Get the webhook subscriptions list of specified application and The ``read`` authority is required. The response looks like:: { "status": "SUCCESS", "message": "", "data": { "webhook_id": 1, "webhook_url": "http://www.example.com", "webhook_type": 0, "event_list": [ "CREATE_CONFIG_CLUSTER", "DELETE_CONFIG_CLUSTER", ... ] } } The content of ``event_list`` is a list of action that already defined in Huskar. :param application_name: The name of application. :status 200: The request is successful. :status 404: The application not found. """ webhook = self._get_webhook_or_404(webhook_id) if not webhook.is_normal: return api_response( data={ 'webhook_id': webhook.id, 'webhook_url': webhook.url, 'webhook_type': webhook.hook_type, 'event_list': [] }) application_name = request.args['application_name'] check_application_auth(application_name, Authority.READ) application = Application.get_by_name(application_name) subscriptions = webhook.get_multi_subscriptions(application.id) data = { 'webhook_id': webhook.id, 'webhook_url': webhook.url, 'webhook_type': webhook.hook_type, 'event_list': [action_types[x.action_type] for x in subscriptions] } return api_response(data=data)
def get(self, application_name): """Gets an application by its name. The response looks like:: { "status": "SUCCESS", "message": "", "data": { "item": { "name": "foo.test", "team_name": "foo", "team_desc": "foo-bar", "is_deprecated": false, "is_blacklisted": false, "route_stage": { "altc1-channel-stable-1": "S" } } } } There is nothing acts HTTP cache in this API like the :ref:`application_list` was done. :param application_name: The name of deleting application. :<header Authorization: Huskar Token (See :ref:`token`) :status 404: The application does not exist yet. :status 200: The application was returned successfully. """ if g.auth.is_minimal_mode: if not application_manifest.check_is_application(application_name): abort(404, 'application does not exist') result = application_schema.dump({ 'name': application_name, 'team_name': Team.DEFAULT_NAME, 'team_desc': Team.DEFAULT_NAME, }) else: application = Application.get_by_name(application_name) if application is None: abort(404, 'application does not exist') result = application_schema.dump({ 'name': application.application_name, 'team_name': application.team.team_name, 'team_desc': application.team.team_desc, }) return api_response({'item': result.data})
def put(self, application_name, infra_type, infra_name): """Configures the infrastructure in specified application. The input schema looks like:: { "url": "sam+redis://redis.foobar/overall" } :param application_name: The application which uses infrastructure. :param infra_type: ``database``, ``redis`` or ``amqp``. :param infra_name: The unique code-reference name of infrastructure. :query scope_type: ``idcs`` or ``clusters``. :query scope_name: The ezone id or cluster name. :query owner_mail: The email of resource owner which will receive the notification of infra config creation. :<header Authorization: Huskar Token (See :ref:`token`) :<header Content-Type: ``application/json`` :status 200: The same as ``GET``. """ with self._update(application_name, request, infra_type, infra_name) as args: application_name, infra_info, scope_type, scope_name, value = args owner_mail = request.args.get('owner_mail', '').strip() is_newcomer = len(infra_info.list_by_infra_name(infra_name)) == 0 infra_info.set_by_name(infra_name, scope_type, scope_name, value) if is_newcomer and owner_mail: owned_application = Application.get_by_name(application_name) owner_user = User.get_by_email(owner_mail) infra_owner_emails = settings.ADMIN_INFRA_OWNER_EMAILS.get( infra_type, []) is_authorized = (owner_user is not None and owned_application.check_auth( Authority.READ, owner_user.id)) deliver_email_safe(EmailTemplate.INFRA_CONFIG_CREATE, owner_mail, { 'application_name': application_name, 'infra_name': infra_name, 'infra_type': infra_type, 'is_authorized': is_authorized, }, cc=infra_owner_emails) infra_config = infra_info.list_by_infra_name(infra_name) return api_response({'infra_config': dump_infra_config(infra_config)})
def post(self): """Create a new webhook. The request accepting a JSON body, the schema likes:: { "webhook_url": "http://www.example.com", "event_list": [ "CREATE_CONFIG_CLUSTER", "DELETE_CONFIG_CLUSTER" ] } The content of ``event_list`` should be a list of action that already defined in Huskar. The ``application_name`` is only required when the ``webhook_type`` is 0, it means the webhook want to subscribe some events of specified application. If the ``webhook_type`` value specified with 1, a universal webhook will be registered which will receive all the events of Huskar site, so the ``event_list`` will be ignored because that is unnecessary. :param webhook_type: default 0, set ``site`` level with 1. :param application_name: The name of application, optional. :form webhook_url: the webhook url. :form event_list: event list want subscribed :status 404: The application not found. :status 200: successful request. """ webhook_type = request.args.get('webhook_type', default=0, type=int) self._check_authority(webhook_type) data = request.get_json() or {} validate_fields(webhook_schema, data, partial=False) if webhook_type == Webhook.TYPE_UNIVERSAL: webhook = Webhook.create(data['webhook_url'], webhook_type) return api_response() application_name = request.args['application_name'] application = Application.get_by_name(application_name) webhook = Webhook.create(data['webhook_url'], webhook_type) for action_name in data.get('event_list', []): action_type = getattr(action_types, action_name) webhook.subscribe(application.id, action_type) return api_response()
def publish(self, application_names, user_name, user_type, action_type, action_data=None, severity=SEVERITY_DANGEROUS): for application_name in application_names: action_name = action_types[action_type] application = Application.get_by_name(application_name) if application is not None: subs = Webhook.search_subscriptions( application_id=application.id, action_type=action_type) event_data = { 'application_name': application_name, 'user_name': user_name, 'user_type': user_type, 'severity': severity, 'action_name': action_name, 'action_data': action_data } for sub in subs: self._add(notify_callback, url=sub.webhook.url, data=event_data)
def _get_application_or_404(self, application_name): application = Application.get_by_name(application_name) if application is None: abort(404, 'application %s does not exist' % application_name) return application
def ensure_application(self): return (Application.get_by_name(self.application_name) or Application.create(self.application_name, self.ensure_team().id))