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

Feature: Backup api #7231

Merged
merged 8 commits into from
Jan 26, 2024
Merged

Conversation

archinksagar
Copy link
Contributor

Please provide feedback on this initial draft of Backup API.
I have added the following API endpoints.

  1. create_backup_plan
  2. create_backup_vault
  3. get_backup_plan - in progress
  4. describe_backup_vault - in progress
  5. delete_backup_plan
  6. list_backup_plans
  7. list_backup_vaults - in progress
  8. list_tags
  9. tag_resource
  10. untag_resource

Things yet to be implemented

  1. describe_backup_vault
  2. Deletion_date and LastExecutionDate in get_backup_plan, list_backup_plans
  3. NumberOfRecoveryPoints, MinRetentionDays, MaxRetentionDays, LockDate in list_backup_vaults
  4. Pagination
  5. Exceptions

Copy link
Collaborator

@bblommers bblommers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @archinksagar, thanks for the PR! This looks good overall, I just have a few nitpicks.

Note that the linter is currently failing as well: https://github.com/getmoto/moto/actions/runs/7586740652/job/20665598379?pr=7231

@@ -0,0 +1,13 @@
"""Test different server responses."""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file doesn't seem to add anything, so let's just delete it

moto/__init__.py Outdated
mock_backup = lazy_load(".backup", "mock_backup", boto3_name="backup")
mock_backup = lazy_load(".backup", "mock_backup", boto3_name="backup")
mock_backup = lazy_load(".backup", "mock_backup", boto3_name="backup")
mock_backup = lazy_load(".backup", "mock_backup", boto3_name="backup")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This needs to only be added once (I know it's a bug in the scaffold-script, it adds this line without checking)

def random_str_utf8(self) -> str:
ran_str = mock_random.get_random_string(length=48)
utf8_bytes = ran_str.encode('utf-8')
return utf8_bytes.decode('utf-8')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reasoning behind the decode/encode operation? It looks like we can just return mock_random.get_random_string(length=48) to get the same outcome. (Or even get rid of the function altogether..)

@bblommers
Copy link
Collaborator

Things yet to be implemented

Out of interest - do you want to add them to this PR as well? Part of a later PR? Or is it just a general note that they are for someone else to implement?

All options are fine by me - I'm just trying to get a feel for how 'ready' this PR is 🙂

@archinksagar
Copy link
Contributor Author

archinksagar commented Jan 19, 2024

@bblommers Thanks for your feedback. Except for pagination and describe_backup_vault , I will implement Exceptions and others I listed. Apart from that, I realized i have to modify "resourcegroupstaggingapi" to use vault tags. I am having trouble figuring out the values for these fields, I don't know when and how they get populated- "Deletion_date" and "LastExecutionDate", "NumberOfRecoveryPoints". Is there any documentation I can refer?

@bblommers
Copy link
Collaborator

If I read the docs here correctly:

  • DeletionDate would only be set after delete_backup_plan is called
  • LastExecutionDate can be empty (None), and maybe should be - as there is no option yet to start_restore_job

The term RecoveryPoints is the same as Backup - so NumberOfRecoveryPoints is just the number of backups that single vault contains. I guess that would be always 0 for now, until we implement start_backup_job

@archinksagar
Copy link
Contributor Author

archinksagar commented Jan 25, 2024

hi @bblommers I have added code to resourcegrouptaggingapi and made few other modifications. I did run make lint, and fixed linting errors. Not sure why the linting is failing.

@bblommers
Copy link
Collaborator

Hey @archinksagar, which version of black you do have installed? Different versions will produce different results. Moto uses black==22.3.0

Running black moto tests should fix that (step of the) build.

https://github.com/getmoto/moto/actions/runs/7659295607/job/20874125053?pr=7231

self.deletion_date: Optional[float] = None
# Deletion Date is updated when the backup_plan is deleted
self.last_execution_date = None # start_restore_job not yet supported
rules = backup_plan.get("Rules")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
rules = backup_plan.get("Rules")
rules = backup_plan["Rules"]

The Rules argument is mandatory anyway. This should fix the mypy error (moto/backup/models.py:34:21: error: Item "None" of "Any | None" has no attribute "__iter__" (not iterable) [union-attr])

@archinksagar
Copy link
Contributor Author

@bblommers Its failing at test/test with "def delete_backup_plan(self, backup_plan_id: str) -> tuple[str, str, float, str]:
E TypeError: 'type' object is not subscriptable" error.
How do i test it in my local, is it 'make test-only'? That would take a long time. Is there a command to test only backup?

@bblommers
Copy link
Collaborator

bblommers commented Jan 25, 2024

@bblommers Its failing at test/test with "def delete_backup_plan(self, backup_plan_id: str) -> tuple[str, str, float, str]: E TypeError: 'type' object is not subscriptable" error. How do i test it in my local, is it 'make test-only'? That would take a long time. Is there a command to test only backup?

@archinksagar You could just run pytest -sv tests/test_backup to only get the tests in that directory.
I think the problem is that tuple is only available as of Python 3.9, that's why 3.7 and 3.8 fail to compile but everything else does run. So if you only test it in a recent Python version, the problem would not show up.

You can use from typing import Tuple instead (note the upper-case T) - that will work in every Python version.

@bblommers
Copy link
Collaborator

@archinksagar Hope you don't mind - I just pushed a fix that should get the ServerMode tests to pass.

The initial version intercepted all URL's (/.+), which is fine for our own request matcher. But when running the tests in ServerMode, the request matching is done by the werkzeug-module, and they require the URL's to be spelled out.

Copy link

codecov bot commented Jan 25, 2024

Codecov Report

Attention: 2 lines in your changes are missing coverage. Please review.

Comparison is base (99e01b5) 95.90% compared to head (5d57a58) 95.91%.
Report is 24 commits behind head on master.

Files Patch % Lines
moto/backup/models.py 98.37% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##           master    #7231    +/-   ##
========================================
  Coverage   95.90%   95.91%            
========================================
  Files         840      845     +5     
  Lines       82608    82958   +350     
========================================
+ Hits        79226    79569   +343     
- Misses       3382     3389     +7     
Flag Coverage Δ
servertests 35.44% <23.44%> (-0.06%) ⬇️
unittests 95.85% <99.04%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@archinksagar
Copy link
Contributor Author

@archinksagar Hope you don't mind - I just pushed a fix that should get the ServerMode tests to pass.

The initial version intercepted all URL's (/.+), which is fine for our own request matcher. But when running the tests in ServerMode, the request matching is done by the werkzeug-module, and they require the URL's to be spelled out.

@bblommers Thanks for fixing it.

Copy link
Collaborator

@bblommers bblommers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM - thank you so much for adding this feature to Moto @archinksagar!

@bblommers bblommers changed the title New feature Backup api Feature: Backup api Jan 26, 2024
@bblommers bblommers added this to the 4.2.14 milestone Jan 26, 2024
@bblommers bblommers linked an issue Jan 26, 2024 that may be closed by this pull request
@bblommers bblommers merged commit 6c7dff6 into getmoto:master Jan 26, 2024
35 checks passed
@moto-payments-app
Copy link

Hi @archinksagar,

Thank you again for contributing to Moto, because PR's like this are the big reason that Moto is as successful as it is.

To show our thanks, we'd like to share some of the donations that we've received with you - it's only fair that you, as a contributor, get to share the spoils.

We've created a companion website with more information:
https://payments.getmoto.org/

Feel free to open a bug or discussion if you run into any problems:
https://github.com/getmoto/payments

Copy link
Contributor

This is now part of moto >= 4.2.14.dev30

@archinksagar archinksagar deleted the feature/backupapi branch November 23, 2024 21:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Question about plans on implementing AWS Backups
2 participants