def check_queue(): """ Checks the pending task queue and, given there's not an in-progress task for the given APP + ENV, marks the latest as in progress and fires the execute_task job. """ pending_queues = list(db.session.query( Task.app_id, Task.environment ).filter( Task.status == TaskStatus.pending ).group_by( Task.app_id, Task.environment )) logging.info('Found pending tasks for %d queues', len(pending_queues)) for app_id, environment in pending_queues: app = App.query.get(app_id) with lock(redis, 'taskcheck:{}-{}'.format(app.id, environment), timeout=5): if has_active_task(app.id, environment): logging.info('Task already in progress for %s/%s', app.name, environment) continue task_id = get_pending_task_id(app.id, environment) if not task_id: logging.info('Unable to find a pending task for %s/%s', app.name, environment) continue Task.query.filter( Task.id == task_id ).update({ 'status': TaskStatus.in_progress, }, synchronize_session=False) celery.send_task("freight.execute_task", [task_id])
def check_queue(): """ Checks the pending task queue and, given there's not an in-progress task for the given APP + ENV, marks the latest as in progress and fires the execute_task job. """ pending_queues = list( db.session.query(Task.app_id, Task.environment).filter( Task.status == TaskStatus.pending).group_by( Task.app_id, Task.environment)) logging.info('Found pending tasks for %d queues', len(pending_queues)) for app_id, environment in pending_queues: app = App.query.get(app_id) with lock(redis, 'taskcheck:{}-{}'.format(app.id, environment), timeout=5): if has_active_task(app.id, environment): logging.info('Task already in progress for %s/%s', app.name, environment) continue task_id = get_pending_task_id(app.id, environment) if not task_id: logging.info('Unable to find a pending task for %s/%s', app.name, environment) continue Task.query.filter(Task.id == task_id).update( { 'status': TaskStatus.in_progress, }, synchronize_session=False) celery.send_task("freight.execute_task", [task_id])
def delete(self, app_id): """ Delete an app. """ app = App.query.get(app_id) if app is None: return self.error('Invalid app', name='invalid_resource', status_code=404) celery.send_task("freight.delete_object", kwargs={'model': 'App', 'app_id': app.id}) return self.respond({"id": str(app.id)})
def delete(self, app): """ Delete an app. """ app = App.query.filter(App.name == app).first() if app is None: return self.error('Invalid app', name='invalid_resource', status_code=404) celery.send_task("freight.delete_object", kwargs={ 'model': 'App', 'app_id': app.id }) return self.respond({"id": str(app.id)})
def post(self): """ Given any constraints for a task are within acceptable bounds, create a new task and enqueue it. """ args = self.post_parser.parse_args() app = App.query.filter(App.name == args.app).first() if not app: return self.error('Invalid app', name='invalid_resource', status_code=404) repo = Repository.query.get(app.repository_id) workspace = Workspace( path=repo.get_path(), ) vcs_backend = vcs.get( repo.vcs, url=repo.url, workspace=workspace, ) with lock(redis, 'repo:update:{}'.format(repo.id)): vcs_backend.clone_or_update() ref = app.get_default_ref(args.env) try: sha = vcs_backend.describe(ref) except vcs.UnknownRevision: return self.error('Invalid ref', name='invalid_ref', status_code=400) if not args.force: for check_config in app.checks: check = checks.get(check_config['type']) try: check.check(app, sha, check_config['config']) except CheckPending: pass except CheckError as e: return self.error( message=unicode(e), name='check_failed', ) with lock(redis, 'task:create:{}'.format(app.id), timeout=5): # TODO(dcramer): this needs to be a get_or_create pattern and # ideally moved outside of the lock user = User.query.filter(User.name == args.user).first() if not user: user = User(name=args.user) db.session.add(user) db.session.flush() if not args.force and self._has_active_task(app, args.env): return self.error( message='Another task is already in progress for this app/environment', name='locked', ) task = Task( app_id=app.id, environment=args.env, number=TaskSequence.get_clause(app.id, args.env), name=TaskName.deploy, # TODO(dcramer): ref should default based on app config ref=ref, sha=sha, status=TaskStatus.pending, user_id=user.id, provider=app.provider, data={ 'force': args.force, 'provider_config': app.provider_config, 'notifiers': app.notifiers, 'checks': app.checks, }, ) db.session.add(task) db.session.commit() celery.send_task("freight.execute_task", [task.id]) return self.respond(serialize(task), status_code=201)
def post(self): """ Given any constraints for a task are within acceptable bounds, create a new task and enqueue it. """ args = self.post_parser.parse_args() app = App.query.filter(App.name == args.app).first() if not app: return self.error('Invalid app', name='invalid_resource', status_code=404) repo = Repository.query.get(app.repository_id) workspace = Workspace(path=repo.get_path(), ) vcs_backend = vcs.get( repo.vcs, url=repo.url, workspace=workspace, ) with lock(redis, 'repo:update:{}'.format(repo.id)): vcs_backend.clone_or_update() ref = app.get_default_ref(args.env) try: sha = vcs_backend.describe(ref) except vcs.UnknownRevision: return self.error('Invalid ref', name='invalid_ref', status_code=400) if not args.force: for check_config in app.checks: check = checks.get(check_config['type']) try: check.check(app, sha, check_config['config']) except CheckPending: pass except CheckError as e: return self.error( message=unicode(e), name='check_failed', ) with lock(redis, 'task:create:{}'.format(app.id), timeout=5): # TODO(dcramer): this needs to be a get_or_create pattern and # ideally moved outside of the lock user = User.query.filter(User.name == args.user).first() if not user: user = User(name=args.user) db.session.add(user) db.session.flush() if not args.force and self._has_active_task(app, args.env): return self.error( message= 'Another task is already in progress for this app/environment', name='locked', ) task = Task( app_id=app.id, environment=args.env, number=TaskSequence.get_clause(app.id, args.env), name=TaskName.deploy, # TODO(dcramer): ref should default based on app config ref=ref, sha=sha, status=TaskStatus.pending, user_id=user.id, provider=app.provider, data={ 'force': args.force, 'provider_config': app.provider_config, 'notifiers': app.notifiers, 'checks': app.checks, }, ) db.session.add(task) db.session.commit() celery.send_task("freight.execute_task", [task.id]) return self.respond(serialize(task), status_code=201)