def _create_object(self, spec, parent, share_with, metakeys): try: blobs = [] config = dict(spec["cfg"]) for first, second in config.items(): if isinstance(second, dict) and list(second.keys()) == ["in-blob"]: if not g.auth_user.has_rights(Capabilities.adding_blobs): raise Forbidden("You are not permitted to add blob objects") blob_obj = self._get_embedded_blob(second["in-blob"], share_with, metakeys) config[first]["in-blob"] = blob_obj.dhash blobs.append(blob_obj) elif isinstance(second, dict) and ("in-blob" in list(second.keys())): raise BadRequest("'in-blob' should be the only key") obj, is_new = Config.get_or_create( config, spec["family"], spec["config_type"], parent=parent, share_with=share_with, metakeys=metakeys ) for blob in blobs: blob.add_parent(obj, commit=False) return obj, is_new except ObjectTypeConflictError: raise Conflict("Object already exists and is not a config")
def send_config_to_karton(cfg: Config) -> str: producer = Producer(identity="karton.mwdb", config=KartonConfig(config.karton.config_path)) task = Task(headers={ "type": "config", "kind": cfg.config_type, "family": cfg.family }, payload={ "config": cfg.cfg, "dhash": cfg.dhash, "attributes": cfg.get_metakeys(as_dict=True, check_permissions=False) }) producer.send_task(task) cfg.add_metakey("karton", task.root_uid, check_permissions=False) logger.info("Configuration sent to karton with %s", task.root_uid) return task.root_uid
def post(self, remote_name, identifier): """ --- summary: Push config from local to remote instance description: | Push config from the local instance to the remote instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Object identifier (SHA256/SHA512/SHA1/MD5) schema: type: string requestBody: required: false description: Additional options for object push content: application/json: schema: RemoteOptionsRequestSchema responses: 200: description: Information about pushed config 404: description: | When the name of the remote instance is not figured in the application config or object doesn't exist """ db_object = Config.access(identifier) if db_object is None: raise NotFound("Object not found") config = db_object.cfg # Extract in-blob references into embedded content for first, second in config.items(): if isinstance(second, dict) and list(second.keys()) == ["in-blob"]: in_blob = second["in-blob"] if not isinstance(in_blob, str): raise BadRequest( "'in-blob' key doesn't contain a correct blob reference" ) embedded_blob = TextBlob.access(in_blob) if not embedded_blob: raise NotFound( f"Referenced blob '{in_blob}' doesn't exist") second["in-blob"] = { "content": embedded_blob.content, "blob_name": embedded_blob.blob_name, "blob_type": embedded_blob.blob_type, } remote = RemoteAPI(remote_name) options = loads_schema(request.get_data(as_text=True), RemoteOptionsRequestSchema()) params = { "family": db_object.family, "cfg": config, "config_type": db_object.config_type, "upload_as": options["upload_as"], } response = remote.request("POST", "config", json=params).json() logger.info( f"{db_object.type} pushed remote", extra={ "dhash": db_object.dhash, "remote_name": remote_name }, ) return response
def post(self, remote_name, identifier): """ --- summary: Pulls config from remote to local instance description: | Pulls config from the remote instance to the local instance security: - bearerAuth: [] tags: - remotes parameters: - in: path name: remote_name description: Name of remote instance schema: type: string - in: path name: identifier description: Config identifier schema: type: string requestBody: required: false description: Additional options for object pull content: application/json: schema: RemoteOptionsRequestSchema responses: 200: description: Information about pulled config content: application/json: schema: ConfigItemResponseSchema 403: description: | No permissions to perform additional operations (e.g. adding parent, metakeys) 404: description: | When the name of the remote instance is not figured in the application config 409: description: Object exists yet but has different type """ remote = RemoteAPI(remote_name) config_spec = remote.request("GET", f"config/{identifier}").json() options = loads_schema(request.get_data(as_text=True), RemoteOptionsRequestSchema()) share_with = get_shares_for_upload(options["upload_as"]) try: config = dict(config_spec["cfg"]) blobs = [] for first, second in config.items(): if isinstance(second, dict) and list( second.keys()) == ["in-blob"]: if not g.auth_user.has_rights(Capabilities.adding_blobs): raise Forbidden( "You are not permitted to add blob objects") in_blob = second["in-blob"] if not isinstance(in_blob, str): raise BadRequest( "'in-blob' is not a correct blob reference") blob_obj = TextBlob.access(in_blob) if not blob_obj: # If blob object doesn't exist locally: pull it as well blob_spec = remote.request("GET", f"blob/{in_blob}").json() blob_obj, _ = TextBlob.get_or_create( content=blob_spec["content"], blob_name=blob_spec["blob_name"], blob_type=blob_spec["blob_type"], share_with=share_with, ) blobs.append(blob_obj) config[first]["in-blob"] = blob_obj.dhash elif isinstance(second, dict) and ("in-blob" in list( second.keys())): raise BadRequest("'in-blob' should be the only key") item, is_new = Config.get_or_create( cfg=config_spec["cfg"], family=config_spec["family"], config_type=config_spec["config_type"], share_with=share_with, ) for blob in blobs: blob.add_parent(item, commit=False) except ObjectTypeConflictError: raise Conflict("Object already exists and is not a config") return self.create_pulled_object(item, is_new)
def on_created_config(self, cfg: Config) -> None: metakeys = cfg.get_metakeys(as_dict=True, check_permissions=False) if "karton" in metakeys: logger.info("Analyzed artifact - not sending to karton") return send_config_to_karton(cfg)