def get_caps(self): # name -> id map caps = dict( (self.CAPS_MAP[d["name"]], d["_id"]) for d in Capability._get_collection().find({ "name": { "$in": list(self.CAPS_MAP) } }, { "_id": 1, "name": 1 }) ) # object -> caps add_expr = dict( (c, {"$in": [caps[c], "$caps.capability"]}) for c in caps ) project_expr = dict((c, 1) for c in caps) project_expr["_id"] = 1 return dict( (d["_id"], dict((x, d[x]) for x in d if x != "_id")) for d in ObjectCapabilities._get_collection().aggregate([ {"$addFields": add_expr}, {"$project": project_expr} ]) )
def get_caps(self): # name -> id map caps = { self.CAPS_MAP[d["name"]]: d["_id"] for d in Capability._get_collection().find( {"name": { "$in": list(self.CAPS_MAP) }}, { "_id": 1, "name": 1 }) } # object -> caps add_expr = {c: {"$in": [caps[c], "$caps.capability"]} for c in caps} project_expr = {c: 1 for c in caps} project_expr["_id"] = 1 return { d["_id"]: {x: d[x] for x in d if x != "_id"} for d in ObjectCapabilities._get_collection().aggregate( [{ "$addFields": add_expr }, { "$project": project_expr }]) }
def get_capabilities(cls, object): """ Resolve object capabilities :param object: ManagedObject instance or id :return: dict of capability name -> current value """ if hasattr(object, "id"): object = object.id caps = {} oc = ObjectCapabilities._get_collection().find_one({"_id": object}) if oc: for c in oc["caps"]: cc = Capability.get_by_id(c["capability"]) if cc: caps[cc.name] = c.get("value") return caps
def update_capabilities(cls, object, caps, source): """ Update stored capabilities :param object: :param caps: :param source: :return: """ o_label = object if hasattr(object, "id"): o_label = object.name object = object.id o_label += "|%s" % source oc = ObjectCapabilities._get_collection().find_one({"_id": object}) or {} # Update existing capabilities new_caps = [] seen = set() changed = False for ci in oc.get("caps", []): c = Capability.get_by_id(ci["capability"]) cs = ci.get("source") cv = ci.get("value") if not c: logger.info("[%s] Removing unknown capability id %s", o_label, ci["capability"]) continue cn = c.name seen.add(cn) if cs == source: if cn in caps: if caps[cn] != cv: logger.info( "[%s] Changing capability %s: %s -> %s", o_label, cn, cv, caps[cn] ) ci["value"] = caps[cn] changed = True else: logger.info("[%s] Removing capability %s", o_label, cn) changed = True continue elif cn in caps: logger.info( "[%s] Not changing capability %s: " "Already set with source '%s'", o_label, cn, cs, ) new_caps += [ci] # Add new capabilities for cn in set(caps) - seen: c = Capability.get_by_name(cn) if not c: logger.info("[%s] Unknown capability %s, ignoring", o_label, cn) continue logger.info("[%s] Adding capability %s = %s", o_label, cn, caps[cn]) new_caps += [{"capability": c.id, "value": caps[cn], "source": source}] changed = True if changed: logger.info("[%s] Saving changes", o_label) ObjectCapabilities._get_collection().update( {"_id": object}, {"$set": {"caps": new_caps}}, upsert=True ) cache.delete("cred-%s" % object, version=CREDENTIAL_CACHE_VERSION) caps = {} for ci in new_caps: cn = Capability.get_by_id(ci["capability"]) if cn: caps[cn.name] = ci.get("value") return caps