def publish_proto_metadata_update(self): """ Publish protobuf model in ipfs and update existing metadata file """ metadata = load_mpe_service_metadata(self.args.metadata_file) ipfs_hash_base58 = ipfs_utils.publish_proto_in_ipfs( self._get_ipfs_client(), self.args.protodir) metadata.set_simple_field("model_ipfs_hash", ipfs_hash_base58) metadata.save_pretty(self.args.metadata_file)
def metadata_set_method_price(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.set_method_price_in_cogs(self.args.group_name, self.args.package_name, self.args.service_name, self.args.method, self.args.price) metadata.save_pretty(self.args.metadata_file)
def metadata_add_daemon_addresses(self): """ Metadata: add daemon addresses to the group """ metadata = load_mpe_service_metadata(self.args.metadata_file) group_name = metadata.get_group_name_nonetrick(self.args.group_name) for daemon_address in self.args.daemon_addresses: metadata.add_daemon_address_to_group(group_name, daemon_address) metadata.save_pretty(self.args.metadata_file)
def metadata_add_endpoints(self): """ Metadata: add endpoint to the group """ metadata = load_mpe_service_metadata(self.args.metadata_file) group_name = metadata.get_group_name_nonetrick(self.args.group_name) for endpoint in self.args.endpoints: metadata.add_endpoint_to_group(group_name, endpoint) metadata.save_pretty(self.args.metadata_file)
def metadata_add_description(self): """ Metadata: add description """ service_description = {} if (self.args.json): service_description = json.loads(self.args.json) if (self.args.url): if "url" in service_description: raise Exception( "json service description already contains url field") service_description["url"] = self.args.url if (self.args.description): if "description" in service_description: raise Exception( "json service description already contains description field") service_description["description"] = self.args.description if self.args.short_description: if "short_description" in service_description: raise Exception( "json service description already contains short description field") if len(self.args.short_description) > 180: raise Exception( "size of short description must be less than 181 characters" ) service_description["short_description"] = self.args.short_description metadata = load_mpe_service_metadata(self.args.metadata_file) # merge with old service_description if necessary if ("service_description" in metadata): service_description = { **metadata["service_description"], **service_description} metadata.set_simple_field("service_description", service_description) metadata.save_pretty(self.args.metadata_file)
def metadata_add_asset_to_ipfs(self): metadata = load_mpe_service_metadata(self.args.metadata_file) asset_file_ipfs_hash_base58 = ipfs_utils.publish_file_in_ipfs(self._get_ipfs_client(), self.args.asset_file_path) metadata.add_asset(asset_file_ipfs_hash_base58, self.args.asset_type) metadata.save_pretty(self.args.metadata_file)
def metadata_update_endpoints(self): """ Metadata: Remove all endpoints from the group and add new ones """ metadata = load_mpe_service_metadata(self.args.metadata_file) group_name = metadata.get_group_name_nonetrick(self.args.group_name) metadata.remove_all_endpoints_for_group(group_name) for endpoint in self.args.endpoints: metadata.add_endpoint_to_group(group_name, endpoint) metadata.save_pretty(self.args.metadata_file)
def metadata_update_daemon_addresses(self): """ Metadata: Remove all daemon addresses from the group and add new ones """ metadata = load_mpe_service_metadata(self.args.metadata_file) group_name = metadata.get_group_name_nonetrick(self.args.group_name) metadata.remove_all_daemon_addresses_for_group(group_name) for daemon_address in self.args.daemon_addresses: metadata.add_daemon_address_to_group(group_name, daemon_address) metadata.save_pretty(self.args.metadata_file)
def _validate_service_group_with_org_group_and_update_group_id(self, org_id, metadata_file): org_metadata = self._get_organization_metadata_from_registry(org_id) new_service_metadata = load_mpe_service_metadata(metadata_file) org_groups = {} for group in org_metadata.groups: org_groups[group.group_name] = group for group in new_service_metadata.m["groups"]: if group["group_name"] in org_groups: group["group_id"] = org_groups[group["group_name"]].group_id new_service_metadata.save_pretty(metadata_file) else: raise Exception( "Group name %s does not exist in organization" % group["group_name"])
def metadata_validate(self): """Validates the service metadata file for structure and input consistency. Validates whether service metadata (`service_metadata.json` if not provided as argument) is consistent with the schema provided in `service_schema` present in `snet_cli/snet/snet_cli/resources.` Args: metadata_file: Option provided through the command line. (default: service_metadata.json) service_schema: Schema of a consistent service metadata file. Raises: ValidationError: Inconsistent service metadata structure or missing values. docs -> Handling ValidationErrors (https://python-jsonschema.readthedocs.io/en/stable/errors/) """ # Set path to `service_schema` stored in the `resources` directory from cwd of `mpe_service.py` current_path = Path(__file__).parent relative_path = '../../snet/snet_cli/resources/service_schema' path_to_schema = (current_path / relative_path).resolve() with open(path_to_schema, 'r') as f: schema = json.load(f) metadata = load_mpe_service_metadata(self.args.metadata_file) try: validate(instance=metadata.m, schema=schema) except Exception as e: docs = "http://snet-cli-docs.singularitynet.io/service.html" error_message = f"\nVisit {docs} for more information." if e.validator == 'required': raise ValidationError(e.message + error_message) elif e.validator == 'minLength': raise ValidationError(f"`{e.path[-1]}` -> cannot be empty." + error_message) elif e.validator == 'minItems': raise ValidationError( f"`{e.path[-1]}` -> minimum 1 item required." + error_message) elif e.validator == 'type': raise ValidationError(f"`{e.path[-1]}` -> {e.message}" + error_message) elif e.validator == 'enum': raise ValidationError(f"`{e.path[-1]}` -> {e.message}" + error_message) elif e.validator == 'additionalProperties': if len(e.path) != 0: raise ValidationError(f"{e.message} in `{e.path[-2]}`." + error_message) else: raise ValidationError(f"{e.message} in main object." + error_message) else: exit("OK. Ready to publish.")
def _publish_metadata_in_ipfs(self, metadata_file): metadata = load_mpe_service_metadata(metadata_file) mpe_address = self.get_mpe_address() if (self.args.update_mpe_address): metadata.set_simple_field("mpe_address", mpe_address) metadata.save_pretty(self.args.metadata_file) if (mpe_address.lower() != metadata["mpe_address"].lower()): raise Exception( "\n\nmpe_address in metadata does not correspond to the current MultiPartyEscrow contract address\n" + "You have two possibilities:\n" + "1. You can use --multipartyescrow-at to set current mpe address\n" + "2. You can use --update-mpe-address parameter to update mpe_address in metadata before publishing it\n") return self._get_ipfs_client().add_bytes(metadata.get_json().encode("utf-8"))
def metadata_add_media(self): """Metadata: Add new individual media Detects media type for files to be added on IPFS, explict declaration for external resources. """ metadata = load_mpe_service_metadata(self.args.metadata_file) # Support endpoints only with SSL Certificate url_validator = r'https?:\/\/(www\.)?([-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b[-a-zA-Z0-9()@:%_\+.~#?&//=]*)' # Automatic media type identification if search(r'^.+\.(jpg|jpeg|png|gif)$', self.args.media_url): media_type = 'image' elif search(r'^.+\.(mp4)$', self.args.media_url): media_type = 'video' elif search(url_validator, self.args.media_url): while True: try: media_type = input( f"Enter the media type (image, video) present at {self.args.media_url}: " ) except ValueError: print("Choose only between (image, video).") else: if media_type not in ('image', 'video'): print("Choose only between (image, video).") else: break else: if search( r'(https:\/\/)?(www\.)+([-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b[-a-zA-Z0-9()@:%_\+.~#?&//=]*)', self.args.media_url): raise ValueError( "Media endpoint supported only for secure sites.") else: raise ValueError( f"Entered url '{self.args.media_url}' is invalid.") file_extension_validator = r'^.+\.(jpg|jpeg|JPG|png|gif|GIF|mp4)$' # Detect whether to add asset on IPFS or if external resource if search(file_extension_validator, self.args.media_url): asset_file_ipfs_hash_base58 = ipfs_utils.publish_file_in_ipfs( self._get_ipfs_client(), self.args.media_url) metadata.add_media(asset_file_ipfs_hash_base58, media_type, self.args.hero_image) else: metadata.add_media(self.args.media_url, media_type, self.args.hero_image) metadata.save_pretty(self.args.metadata_file)
def metadata_add_group(self): metadata = load_mpe_service_metadata(self.args.metadata_file) self._metadata_add_group(metadata) metadata.save_pretty(self.args.metadata_file)
def metadata_remove_all_daemon_addresses(self): """ Metadata: remove all daemon addresses from all groups """ metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_all_daemon_addresses_for_group(self.args.group_name) metadata.save_pretty(self.args.metadata_file)
def metadata_remove_contributor(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_contributor_by_email(self.args.email_id) metadata.save_pretty(self.args.metadata_file)
def metadata_add_contributor(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.add_contributor(self.args.name, self.args.email_id) metadata.save_pretty(self.args.metadata_file)
def metadata_change_media_order(self): """Metadata: REPL to change order of all individual media.""" metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.change_media_order() metadata.save_pretty(self.args.metadata_file)
def metadata_remove_all_endpoints(self): """ Metadata: remove all endpoints from all groups """ metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_all_endpoints_for_group(self.args.group_name) metadata.save_pretty(self.args.metadata_file)
def metadata_remove_tags(self): metadata = load_mpe_service_metadata(self.args.metadata_file) [metadata.remove_tag(tag) for tag in self.args.tags] metadata.save_pretty(self.args.metadata_file)
def extract_service_api_from_metadata(self): metadata = load_mpe_service_metadata(self.args.metadata_file) safe_extract_proto_from_ipfs(self._get_ipfs_client( ), metadata["model_ipfs_hash"], self.args.protodir)
def metadata_remove_all_assets(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_all_assets() metadata.save_pretty(self.args.metadata_file)
def metadata_remove_assets_of_a_given_type(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_assets(self.args.asset_type) metadata.save_pretty(self.args.metadata_file)
def metadata_set_free_calls(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.set_free_calls_for_group(self.args.group_name, int(self.args.free_calls)) metadata.save_pretty(self.args.metadata_file)
def metadata_remove_group(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_group(self.args.group_name) metadata.save_pretty(self.args.metadata_file)
def metadata_remove_media(self): """Metadata: Remove individual media using unique order key.""" metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_media(self.args.order) metadata.save_pretty(self.args.metadata_file)
def metadata_set_freecall_signer_address(self): metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.set_freecall_signer_address(self.args.group_name, self.args.signer_address) metadata.save_pretty(self.args.metadata_file)
def metadata_remove_all_media(self): """Metadata: Remove all individual media.""" metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.remove_all_media() metadata.save_pretty(self.args.metadata_file)
def _get_service_metadata(self): service_dir = self.get_service_spec_dir(self.args.org_id, self.args.service_id) service_metadata = load_mpe_service_metadata( os.path.join(service_dir, "service_metadata.json")) return service_metadata
def metadata_swap_media_order(self): """Metadata: Swap order of two individual media given 'from' and 'to'.""" metadata = load_mpe_service_metadata(self.args.metadata_file) metadata.swap_media_order(self.args.move_from, self.args.move_to) metadata.save_pretty(self.args.metadata_file)