Exemple #1
0
    def _list_dir(self, dir_drive: str, dir_tail: str) -> List[str]:
        response: Dict[str, List[Dict[str, str]]]
        try:
            response = self._s3_client.list_objects(
                Bucket=dir_drive,
                Prefix=dir_tail
            )
        except Exception:
            raise FileSystemOperationError(traceback.format_exc())

        items: List[str] = []
        for item in response.get("Contents", []):
            items.append(item["Key"])

        while response.get("IsTruncated", False):
            marker = response.get("NextMarker") or items[-1]
            try:
                response = self._s3_client.list_objects(
                    Bucket=dir_drive,
                    Prefix=dir_tail,
                    Marker=marker
                )
            except Exception:
                raise FileSystemOperationError(traceback.format_exc())

            for item in response.get("Contents", []):
                items.append(item["Key"])

        return items
Exemple #2
0
 def file_read(self, path: Path) -> bytes:
     parent_dir: MemoryDirectory
     try:
         parent_dir = self._get_dir(path.parent)
         return parent_dir.get_file(path.basename).contents
     except (NotADirectoryError, NotAFileError):
         raise FileSystemOperationError(traceback.format_exc())
Exemple #3
0
 def _remove(self, path: Path, is_dir: bool) -> None:
     tail_str: str = self._separator.join(path.tail)
     if is_dir and tail_str:
         tail_str += self._separator
     response: Dict[str, Union[bool, List[Dict[str, str]]]] = {
         "IsTruncated": True
     }
     while response.get("IsTruncated", False):
         contents = cast(List[Dict[str, str]], response.get("Contents", []))
         marker = cast(str, response.get("NextMarker"))
         if not marker and contents:
             marker = contents[-1]["Key"]
         if not marker:
             marker = ""
         try:
             response = self._s3_client.list_objects(
                 Bucket=path.drive,
                 Prefix=tail_str,
                 Marker=marker,
             )
             contents = cast(List[Dict[str, str]],
                             response.get('Contents', []))
             if contents:
                 self._s3_client.delete_objects(
                     Bucket=path.drive,
                     Delete={
                         'Objects': [{
                             'Key': f['Key']
                         } for f in contents
                                     if is_dir or f['Key'] == tail_str]
                     })
         except Exception:
             raise FileSystemOperationError(traceback.format_exc())
Exemple #4
0
 def file_write(self, path: Path, content: bytes) -> None:
     try:
         parent_path: str = self.path_to_string(path.parent)
         if not os.path.exists(parent_path):
             os.makedirs(parent_path)
         with open(self.path_to_string(path), "wb") as f:
             f.write(content)
     except Exception:
         raise FileSystemOperationError(traceback.format_exc())
Exemple #5
0
 def file_read(self, path: Path) -> bytes:
     prefix: str = self._separator.join(path.tail)
     try:
         data = BytesIO()
         self._s3_client.download_fileobj(path.drive, prefix, data)
         data.seek(0)
         return data.read()
     except Exception:
         raise FileSystemOperationError(traceback.format_exc())
Exemple #6
0
    def dir_list(self, path: Path) -> Iterable[FSObjectPath]:
        tail_str: str = self._separator.join(path.tail)
        if tail_str:
            tail_str += self._separator

        response: Dict[str, Union[bool, List[Dict[str, str]], str]] = {
            "IsTruncated": True
        }
        marker = ""
        while response.get("IsTruncated", False):
            try:
                response = self._s3_client.list_objects(
                    Bucket=path.drive,
                    Prefix=tail_str,
                    Delimiter=self._separator,
                    Marker=marker)
            except Exception:
                raise FileSystemOperationError(traceback.format_exc())

            contents = cast(List[Dict[str, str]], response.get("Contents", []))
            for item in contents:
                file_name: str = item["Key"]
                if file_name != tail_str:
                    if file_name.endswith(self._separator):
                        yield FSObjectPath(
                            FSObjectType.DIR,
                            Path(path.drive,
                                 *(file_name.split(self._separator)[:-1])))
                    else:
                        yield FSObjectPath(
                            FSObjectType.FILE,
                            Path(path.drive,
                                 *file_name.split(self._separator)))

            for item in cast(List[Dict[str, str]],
                             response.get("CommonPrefixes", [])):
                dir_name: str = item["Prefix"]
                yield FSObjectPath(
                    FSObjectType.DIR,
                    Path(path.drive, *(dir_name.split(self._separator)[:-1])))

                marker = cast(str, response.get("NextMarker"))
                if not marker and contents:
                    marker = contents[-1]["Key"]
                if not marker:
                    marker = ""
Exemple #7
0
    def file_write(self, path: Path, content: bytes) -> None:
        try:
            dirs: Tuple[str, ...] = path.parent.tail
            acc_prefix: str = ""
            for dir_ in dirs:
                if acc_prefix:
                    acc_prefix = self._separator.join((acc_prefix, dir_))
                else:
                    acc_prefix = dir_
                self._s3_client.upload_fileobj(BytesIO(b""), path.drive,
                                               acc_prefix + self._separator)

            path_str: str = self.path_to_string(path)
            tail: str = path_str[path_str.find("/") + 1:]
            self._s3_client.upload_fileobj(BytesIO(content), path.drive, tail)
        except Exception:
            raise FileSystemOperationError(traceback.format_exc())
Exemple #8
0
    def file_set_perms(self, path: Path, policies: List[Policy]) -> None:
        """ Set ACL policies for the object.

        Check `norfs.fs.s3.s3_scopes` and `norfs.fs.s3.s3_perms` to understand how :class:`norfs.permissions.Scope` and
        :class:`norfs.permissions.Perm` map to S3 Grantees and Permissions.
        """
        try:
            key = self._separator.join(path.tail)
            acl = self._s3_client.get_object_acl(Bucket=path.drive, Key=key)

            grants = []
            for policy in policies:
                if policy.scope == Scope.OWNER:
                    grantee = acl['Owner'].copy()
                    grantee['Type'] = 'CanonicalUser'
                else:
                    grantee = s3_scopes.get(policy.scope)

                if all((p in policy.perms for p in _ALL_PERMS)):
                    grants.append({
                        'Grantee': grantee,
                        'Permission': 'FULL_CONTROL',
                    })
                else:
                    for perm in policy.perms:
                        permission = s3_perms.get(perm)
                        if permission:
                            grants.append({
                                'Grantee': grantee,
                                'Permission': permission,
                            })

            self._s3_client.put_object_acl(
                AccessControlPolicy={
                    'Grants': grants,
                    'Owner': acl['Owner'],
                },
                Bucket=path.drive,
                Key=key,
            )
        except Exception:
            raise FileSystemOperationError(traceback.format_exc())
Exemple #9
0
    def file_set_properties(self,
                            path: Path,
                            content_type: Optional[str] = None,
                            tags: Optional[Dict[str, str]] = None,
                            metadata: Optional[Dict[str, str]] = None) -> None:
        """ Set properties for the object.
        """
        kwargs: Dict[str, Any] = {}

        if content_type:
            kwargs['ContentType'] = content_type
            kwargs['MetadataDirective'] = 'REPLACE'

        if tags:
            kwargs['Tagging'] = urlencode(tags)
            kwargs['TaggingDirective'] = 'REPLACE'

        if metadata:
            kwargs['Metadata'] = metadata
            kwargs['MetadataDirective'] = 'REPLACE'

        key: str = self._separator.join(path.tail)
        try:
            acl = self._s3_client.get_object_acl(Bucket=path.drive, Key=key)
            self._s3_client.copy_object(Key=key,
                                        Bucket=path.drive,
                                        CopySource={
                                            "Bucket": path.drive,
                                            "Key": key
                                        },
                                        **kwargs)
            self._s3_client.put_object_acl(
                AccessControlPolicy={
                    'Grants': acl['Grants'],
                    'Owner': acl['Owner'],
                },
                Bucket=path.drive,
                Key=key,
            )
        except Exception:
            raise FileSystemOperationError(traceback.format_exc())
Exemple #10
0
 def remove(self) -> None:
     """ Tries to remove self from the file system.
     On failure it raises a :class:`norfs.fs.base.FileSystemOperationError`
     """
     raise FileSystemOperationError(f"Cannot remove {str(self)}")
Exemple #11
0
 def file_remove(self, path: Path) -> None:
     try:
         os.remove(self.path_to_string(path))
     except Exception:
         raise FileSystemOperationError(traceback.format_exc())
Exemple #12
0
 def file_read(self, path: Path) -> bytes:
     try:
         with open(self.path_to_string(path), "rb") as f:
             return f.read()
     except Exception:
         raise FileSystemOperationError(traceback.format_exc())
Exemple #13
0
 def dir_remove(self, path: Path) -> None:
     try:
         shutil.rmtree(self.path_to_string(path))
     except Exception:
         raise FileSystemOperationError(traceback.format_exc())
Exemple #14
0
 def dir_remove(self, path: Path) -> None:
     try:
         current_dir: MemoryDirectory = self._get_dir(path.parent)
         current_dir.remove_dir(path.basename)
     except NotADirectoryError:
         raise FileSystemOperationError(traceback.format_exc())
Exemple #15
0
 def file_remove(self, path: Path) -> None:
     try:
         parent_dir: MemoryDirectory = self._get_dir(path.parent)
         parent_dir.remove_file(path.basename)
     except (NotADirectoryError, NotAFileError):
         raise FileSystemOperationError(traceback.format_exc())