async def create_container(self, data): status, contr, err = Container.parse(data) if status != 200: return status, None, err status, _, _ = await self.__contr_db.get_container( contr.appliance, contr.id) if status == 200: return 409, None, "Container '%s' already exists" % contr.id await self.save_container(contr, True) return 201, contr, None
async def get_containers(self, **filters): return [ Container.parse(c, False)[1] async for c in self.__contr_col.find(filters) ]
async def _get_container(self, **filters): contr = await self.__contr_col.find_one(filters) if not contr: return 404, None, "Container matching '%s' is not found" % filters return Container.parse(contr, False)
def parse(cls, data, from_user=True): def validate_dependencies(contrs): contrs = {c.id: c for c in contrs} parents = {} for c in contrs.values(): nonexist = list(filter(lambda c: c not in contrs, c.dependencies)) if nonexist: return 422, None, "Dependencies '%s' do not exist in this appliance" % nonexist parents.setdefault(c.id, set()).update(c.dependencies) for c, p in parents.items(): cycles = ['%s<->%s' % (c, pp) for pp in filter(lambda x: c in parents.get(x, set()), p)] if cycles: return 422, None, "Cycle(s) found: %s" % cycles return 200, 'Dependencies are valid', None if not isinstance(data, dict): return 422, None, "Failed to parse appliance request format: %s"%type(data) missing = Appliance.REQUIRED - data.keys() if missing: return 400, None, "Missing required field(s) of appliance: %s"%missing fields = {} # instantiate container objects containers, contr_ids = [], set() for c in data.pop('containers', []): if c['id'] in contr_ids: return 400, None, "Duplicate container id: %s"%c['id'] if from_user: for unwanted_f in ('appliance', ): c.pop(unwanted_f, None) status, contr, err = Container.parse(dict(**c, appliance=data['id']), from_user) if status != 200: return status, None, err containers.append(contr) contr_ids.add(contr.id) addresses = set() for c in containers: if c.cmd: addresses.update(get_short_ids(c.cmd)) for arg in c.args: addresses.update(get_short_ids(arg)) for v in c.env.values(): addresses.update(get_short_ids(v)) undefined = list(addresses - contr_ids) if undefined: return 400, None, "Undefined container(s): %s"%undefined status, msg, err = validate_dependencies(containers) if status != 200: return status, None, err fields.update(containers=containers) # instantiate data persistence object if 'data_persistence' in data: status, dp, err = DataPersistence.parse(dict(**data.pop('data_persistence', {}), appliance=data['id']), from_user) if status != 200: return status, None, err fields.update(data_persistence=dp) # instantiate scheduler object if 'scheduler' in data: status, scheduler, err = Scheduler.parse(data.pop('scheduler', {}), from_user) if status != 200: return status, None, err fields.update(scheduler=scheduler) return 200, Appliance(**fields, **data), None