def test_ensure_user_exists_failure_client_error(client, user, mock_backend_client, mock_backend_authenticated_client, settings): with mock.patch('api_server.paas_backends.get_backend_client') as mocked: mocked.return_value = mock_backend_client mock_backend_client.login_or_register.return_value = ( mock_backend_authenticated_client, True) mock_backend_authenticated_client.login_or_register.side_effect = ClientError paas_backends.get_backend_authenticated_client( user.username, settings.DEFAULT_PAAS_BACKEND)
def test_ensure_user_exists_failure_no_credentials(client, user, mock_backend_client, settings): with mock.patch('api_server.paas_backends.get_backend_client') as mocked: mocked.return_value = mock_backend_client with pytest.raises(paas_backends.BackendsUserError): paas_backends.get_backend_authenticated_client( user.username, 'doesnotexist')
def test_ensure_user_exists_failure_client_error( client, user, mock_backend_client, mock_backend_authenticated_client, settings): with mock.patch('api_server.paas_backends.get_backend_client') as mocked: mocked.return_value = mock_backend_client mock_backend_client.login_or_register.return_value = ( mock_backend_authenticated_client, True) mock_backend_authenticated_client.login_or_register.side_effect = ClientError paas_backends.get_backend_authenticated_client( user.username, settings.DEFAULT_PAAS_BACKEND)
def ensure_user_exists(self, username, backend): """Ensure the user with :code:`username` exists, both locally and on the specified backend. If the user does not exist locally, returns False. If the user does not exist on the backend, create it, but return True. :param str username: the username to ensure :param str backend: the PaaS backend to ensure on :raises api_server.clients.exceptions.ClientError: :raises api_server.paas_backends.BackendsError: """ get_backend_authenticated_client(username, backend)
def ensure_user_exists(self, username, backend): """Ensure the user with :code:`username` exists, both locally and on the specified backend. If the user does not exist locally, returns False. If the user does not exist on the backend, create it, but return True. :param str username: the username to ensure :param str backend: the PaaS backend to ensure on :raises api_server.clients.exceptions.ClientError: :raises api_server.paas_backends.BackendsError: """ get_backend_authenticated_client(username, backend)
def get(self, request, app_id): """Get the logs for this application Returns a JSON list of log entries (dict). Each entry has the following structure:{ 'process': 'run.1', 'message': 'sample message', 'app': 'sample-python', 'timestamp': '2016-04-16T14:26:03UTC', } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) lines = request.GET.get('lines', None) if lines is not None: lines = int(lines) logs = auth_client.get_application_logs(app_id, lines) return self.respond_multiple(logs)
def post(self, request, app_id): """Set the environmental variables The body of the request must be a JSON with the format { "VAR1": "value", "VAR2": "value2", ... } To unset a variable, set its value to ``null``. :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ env_vars = json.loads(request.body) backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) for v in env_vars.itervalues(): if v is not None and not _value_regexp.match(v): raise ErrorResponse( message= 'Variable values must be one of {}. Invalid character(s) in {}' .format(_valid_chars, v), status=400) auth_client.set_application_env_variables(app_id, env_vars) return self.respond()
def post(self, request, app_id): """Set the environmental variables The body of the request must be a JSON with the format { "VAR1": "value", "VAR2": "value2", ... } To unset a variable, set its value to ``null``. :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ env_vars = json.loads(request.body) backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) for v in env_vars.itervalues(): if v is not None and not _value_regexp.match(v): raise ErrorResponse(message='Variable values must be one of {}. Invalid character(s) in {}'.format(_valid_chars, v), status=400) auth_client.set_application_env_variables(app_id, env_vars) return self.respond()
def set_config(addon_id): """The addon has been provisioned. Now set the config""" logger = logging.getLogger(__name__) try: addon = Addon.objects.get(pk=addon_id) except Addon.DoesNotExist: logger.exception('Addon with ID {} does not exist.'.format(addon_id)) raise manager = StateMachineManager() if addon.state is not AddonState.provisioned: logger.warning('Addon ID {addon_id}: State {state} is invalid for set_config task.'.format( addon_id=addon_id, state=addon.state, )) return addon_id if not addon.app or not addon.user or addon.config is None: logger.error('''Addon ID {addon_id}: One of the following is invalid for set_config task: app: {app} user: {user} config: {config} '''.format( app=addon.app, user=addon.user, config=addon.config, )) with manager.transition(addon_id, AddonEvent.config_variables_set_failure): pass return addon_id try: backend_client = get_backend_authenticated_client( addon.user.username, addon.app.backend) except BackendsError: logger.exception('Addon ID {addon_id}: Could not get backend client for {backend}.'.format( addon_id=addon_id, backend=addon.app.backend, )) with manager.transition(addon_id, AddonEvent.config_variables_set_failure): pass return addon_id try: backend_client.set_application_env_variables( addon.app.app_id, addon.config) except ClientError: # TODO retriable logger.exception('Addon ID {addon_id}: Could not set config.'.format( addon_id=addon_id, )) with manager.transition(addon_id, AddonEvent.config_variables_set_failure): pass return addon_id with manager.transition(addon_id, AddonEvent.config_variables_set_success): pass return addon_id
def test_ensure_user_exists_success(mock_backend_client, mock_backend_authenticated_client, settings, user): with mock.patch('api_server.paas_backends.get_backend_client') as mocked: mocked.return_value = mock_backend_client mock_backend_client.login_or_register.return_value = ( mock_backend_authenticated_client, True) result = paas_backends.get_backend_authenticated_client( user.username, settings.DEFAULT_PAAS_BACKEND) assert result == mock_backend_authenticated_client
def test_ensure_user_exists_success(mock_backend_client, mock_backend_authenticated_client, settings, user): with mock.patch('api_server.paas_backends.get_backend_client') as mocked: mocked.return_value = mock_backend_client mock_backend_client.login_or_register.return_value = ( mock_backend_authenticated_client, True) result = paas_backends.get_backend_authenticated_client( user.username, settings.DEFAULT_PAAS_BACKEND) assert result == mock_backend_authenticated_client
def get(self, request, app_id): """Get the domains associated with this app :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) domains = auth_client.get_application_domains(app_id) return self.respond_multiple(domains)
def get(self, request, app_id): """Get the domains associated with this app :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) domains = auth_client.get_application_domains(app_id) return self.respond_multiple(domains)
def get(self, request, app_id): """Get the environmental variables :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) env_vars = auth_client.get_application_env_variables(app_id) return self.respond(env_vars)
def delete(self, request, app_id): """Delete an application :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) auth_client.delete_application(app_id) app = App.objects.get(app_id=app_id) app.delete() return self.respond()
def get(self, request, app_id): """Get the environmental variables :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) env_vars = auth_client.get_application_env_variables(app_id) return self.respond(env_vars)
def delete(self, request, app_id, domain): """Remove a domain from the app :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :param str domain: the domain name :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) auth_client.remove_application_domain(app_id, domain) return self.respond()
def get(self, request, app_id): """Get the list of usernames who are collaborators on this app. This does NOT include the app owner. :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) users = auth_client.get_application_collaborators(app_id) return self.respond_multiple(users)
def delete(self, request, app_id, username): """Remove a collaborator from the app :param django.http.HttpRequest request: the request :param str app_id: the app ID :param str username: the username of the collaborator :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) auth_client.remove_application_collaborator(app_id, username) return self.respond()
def delete(self, request, app_id, username): """Remove a collaborator from the app :param django.http.HttpRequest request: the request :param str app_id: the app ID :param str username: the username of the collaborator :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) auth_client.remove_application_collaborator(app_id, username) return self.respond()
def get(self, request, app_id): """Get the list of usernames who are collaborators on this app. This does NOT include the app owner. :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) users = auth_client.get_application_collaborators(app_id) return self.respond_multiple(users)
def delete(self, request, backend, key_name): """Remove a key from the user @type request: django.http.HttpRequest :param django.http.HttpRequest request: the request object :param str backend: the PaaS backend to add this key to :param str key_name: the name of the key :rtype: django.http.HttpResponse """ auth_client = get_backend_authenticated_client( request.user.username, backend) auth_client.remove_key(key_name) return self.respond()
def delete(self, request, backend, key_name): """Remove a key from the user @type request: django.http.HttpRequest :param django.http.HttpRequest request: the request object :param str backend: the PaaS backend to add this key to :param str key_name: the name of the key :rtype: django.http.HttpResponse """ auth_client = get_backend_authenticated_client(request.user.username, backend) auth_client.remove_key(key_name) return self.respond()
def post(self, request, app_id): """Run a one-off command. The request body must be a JSON with the following fields: { "command": "echo 1 2 3" } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ command = json.loads(request.body)['command'] backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) return self.respond(auth_client.run_command(app_id, command))
def post(self, request, app_id): """Run a one-off command. The request body must be a JSON with the following fields: { "command": "echo 1 2 3" } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ command = json.loads(request.body)['command'] backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) return self.respond(auth_client.run_command(app_id, command))
def post(self, request, app_id): """Add a domain to this app The body of the request must be a JSON with the format { "domain": "example.com", } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ domain = json.loads(request.body)['domain'] backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) auth_client.add_application_domain(app_id, domain) return self.respond()
def post(self, request, app_id): """Add a domain to this app The body of the request must be a JSON with the format { "domain": "example.com", } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ domain = json.loads(request.body)['domain'] backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) auth_client.add_application_domain(app_id, domain) return self.respond()
def get(self, request): """Return the list of applications associated with this user. Return format (JSON): { 'backend1': ['app1', ...], 'backend2': ['app1', ...], ... } :param django.http.HttpRequest request: the request object :rtype: django.http.HttpResponse """ result = {} for backend in request.user.profile.get_paas_backends(): auth_client = get_backend_authenticated_client( request.user.username, backend) result[backend] = auth_client.get_all_applications() return self.respond(result)
def post(self, request, app_id): """Update information about this app. The request body must be a JSON with any subset of the following fields: { "owner": "userid" } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ data = json.loads(request.body) backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) if 'owner' in data: self.ensure_user_exists(data['owner'], backend) auth_client.set_application_owner(app_id, data['owner']) return self.respond()
def post(self, request): """Create a new application. The body of the request should be a JSON with the following format: { 'id': 'app_id_here', 'backend': 'backend', } If the 'backend' field is not provided, then the default is used. :param django.http.HttpRequest request: the request object :rtype: django.http.HttpResponse """ data = json.loads(request.body) app_id = data['id'] backend = data.get('backend', settings.DEFAULT_PAAS_BACKEND) # is the user authorized to use this backend? auth_client = get_backend_authenticated_client( request.user.username, backend) # is there already an app with this ID? try: app = App.objects.create(app_id=app_id, backend=backend) except IntegrityError: raise ErrorResponse('App {} already exists. Please pick a new name.'.format(app_id), status=400) try: auth_client.create_application(app_id) except Exception: # on any kind of errors, must delete the app object, # as we essentially took a lock on the name when we # created the object app.delete() # reraise the exception raise return self.respond()
def get(self, request, app_id): """Get information about this app. Returns a JSON with the following fields: { "owner": "userid", "remote": "ssh://[email protected]/app.git" } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) owner = auth_client.get_application_owner(app_id) return self.respond({ 'owner': owner, 'remote': git_remote(get_backend_api_url(backend), app_id) })
def post(self, request): """Add a key to the list of keys for this user. The body of the request must be a JSON with the format { "key_name": "macbookpro", "key": "ssh-rsa ...", "backend": "backend" } "backend" is optional and default to the default backend. :param django.http.HttpRequest request: the request object :rtype: django.http.HttpResponse """ key_info = json.loads(request.body) backend = key_info.get('backend', settings.DEFAULT_PAAS_BACKEND) auth_client = get_backend_authenticated_client( request.user.username, backend) auth_client.add_key(key_info['key_name'], key_info['key']) return self.respond()
def post(self, request, app_id): """Add a collaborator to this app. The body of the request must be a JSON with the format { "username": "******", } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ username = json.loads(request.body)['username'] backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client( request.user.username, backend) self.ensure_user_exists(username, backend) auth_client.add_application_collaborator(app_id, username) return self.respond()
def get(self, request): """Get the list of public keys for this user. Return format (JSON): { 'backend1': [{ "key_name": "my_key_name", "key": "ssh-rsa ..." }, ...], 'backend2': [...], ... } :param django.http.HttpRequest request: the request object :rtype: django.http.HttpResponse """ result = {} for backend in request.user.profile.get_paas_backends(): auth_client = get_backend_authenticated_client( request.user.username, backend) result[backend] = auth_client.get_keys() return self.respond(result)
def post(self, request, app_id): """Add a collaborator to this app. The body of the request must be a JSON with the format { "username": "******", } :param django.http.HttpRequest request: the request object :param str app_id: the ID of the app :rtype: django.http.HttpResponse """ username = json.loads(request.body)['username'] backend = self.get_backend_for_app(app_id) auth_client = get_backend_authenticated_client(request.user.username, backend) self.ensure_user_exists(username, backend) auth_client.add_application_collaborator(app_id, username) return self.respond()
def test_ensure_user_exists_failure_does_not_exist(settings): with pytest.raises(paas_backends.BackendsUserError): paas_backends.get_backend_authenticated_client( 'doesnotexist', settings.DEFAULT_PAAS_BACKEND)
def test_ensure_user_exists_failure_no_backend(user): with pytest.raises(paas_backends.BackendsMissingError): paas_backends.get_backend_authenticated_client(user.username, 'doesnotexist')
def test_ensure_user_exists_failure_no_backend(user): with pytest.raises(paas_backends.BackendsMissingError): paas_backends.get_backend_authenticated_client( user.username, 'doesnotexist')
def test_ensure_user_exists_failure_does_not_exist(settings): with pytest.raises(paas_backends.BackendsUserError): paas_backends.get_backend_authenticated_client( 'doesnotexist', settings.DEFAULT_PAAS_BACKEND)
def test_ensure_user_exists_failure_no_credentials(client, user, mock_backend_client, settings): with mock.patch('api_server.paas_backends.get_backend_client') as mocked: mocked.return_value = mock_backend_client with pytest.raises(paas_backends.BackendsUserError): paas_backends.get_backend_authenticated_client( user.username, 'doesnotexist')