Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

StorageHealthCheck - problem with overwriting file_name by some backends #199

Closed
Quadric opened this issue Oct 5, 2018 · 1 comment
Closed

Comments

@Quadric
Copy link
Contributor

Quadric commented Oct 5, 2018

There is an issue when some storage backend overwrites requested file_name to something else (for ex. avoiding duplicates) - and when it happens there is a problem with this backend implementation. Please look at this method on StorageHealthCheck

        storage = self.get_storage()
        # save the file
        file_name = storage.save(
            file_name, ContentFile(content=file_content)
        )
        # read the file and compare
        if not storage.exists(file_name):
            raise ServiceUnavailable('File does not exist')
        with storage.open(file_name) as f:
            if not f.read() == file_content:
                raise ServiceUnavailable('File content does not match')

Look at this line:

file_name = storage.save(
    file_name, ContentFile(content=file_content)
)

storage is allowed to overwrite the requested file_name - which is OK, and later the rest of code for this method is also OK - but since then this "file_name" may change.

Thats why this method:

def check_status(self):
        try:
            # write the file to the storage backend
            file_name = self.get_file_name()
            file_content = self.get_file_content()
            self.check_save(file_name, file_content)
            self.check_delete(file_name)
            return True
        except Exception:
            raise ServiceUnavailable('Unknown exception')

may not work OK because 'check_save' and 'check_delete' uses the "original" requested file_name - but as we've seen this "file_name" could be overwritten by check_save method - making method check_delete looking for invalid file_name.

It could be fixed by adding "return file_name" to "check_save" method, like this:

def check_save(self, file_name, file_content):
        storage = self.get_storage()
        # save the file
        file_name = storage.save(
            file_name, ContentFile(content=file_content)
        )
        # read the file and compare
        if not storage.exists(file_name):
            raise ServiceUnavailable('File does not exist')
        with storage.open(file_name) as f:
            if not f.read() == file_content:
                raise ServiceUnavailable('File content does not match')
        return file_name

And use that file name in check_status method:

def check_status(self):
        try:
            # write the file to the storage backend
            file_name = self.get_file_name()
            file_content = self.get_file_content()
            file_name = self.check_save(file_name, file_content)
            self.check_delete(file_name)
            return True
        except Exception:
            raise ServiceUnavailable('Unknown exception')

What do you think?

@Quadric
Copy link
Contributor Author

Quadric commented Oct 5, 2018

OK i've created a pull request #200

@Quadric Quadric closed this as completed Oct 5, 2018
codingjoe pushed a commit that referenced this issue Oct 5, 2018
Storage backends will call `get_available_name` before saving a file, which can alter the path on some storage backend implementations.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant