4
votes

I would like to backup my app's datastore programmatically, on a regular basis.

It seems possible to create a cron that backs up the datastore, according to https://developers.google.com/appengine/articles/scheduled_backups

However, I require a more fine-grained solution: Create different backup files for dynamically changing namespaces.

Is it possible to simply call the /_ah/datastore_admin/backup.create url with GET/POST?

3

3 Answers

3
votes

Yes; I'm doing exactly that in order to implement some logic that couldn't be done with cron.

Use the taskqueue API to add the URL request, like this:

from google.appengine.api import taskqueue
taskqueue.add(url='/_ah/datastore_admin/backup.create',
              method='GET',
              target='ah-builtin-python-bundle',
              params={'kind': ('MyKind1', 'MyKind2')})

If you want to use more parameters that would otherwise go into the cron url, like 'filesystem', put those in the params dict alongside 'kind'.

2
votes

Programmatically backup datastore based on environment

This comes in addition to Jamie's answer. I needed to backup the datastore to Cloud Storage, based on the environment (staging/production). Unfortunately, this can no longer be achieved via a cronjob so I needed to do it programmatically and create a cron to my script. I can confirm that what's below is working, as I saw there were some people complaining that they get a 404. However, it's only working on a live environment, not on the local development server.

from datetime import datetime

from flask.views import MethodView

from google.appengine.api import taskqueue
from google.appengine.api.app_identity import app_identity


class BackupDatastoreView(MethodView):

    BUCKETS = {
        'app-id-staging': 'datastore-backup-staging',
        'app-id-production': 'datastore-backup-production'
    }

    def get(self):

        environment = app_identity.get_application_id()

        task = taskqueue.add(
            url='/_ah/datastore_admin/backup.create',
            method='GET',
            target='ah-builtin-python-bundle',
            queue_name='backup',
            params={
                'filesystem': 'gs',
                'gs_bucket_name': self.get_bucket_name(environment),
                'kind': (
                    'Kind1',
                    'Kind2',
                    'Kind3'
                )
            }
        )

        if task:
            return 'Started backing up %s' % environment

    def get_bucket_name(self, environment):

        return "{bucket}/{date}".format(
            bucket=self.BUCKETS.get(environment, 'datastore-backup'),
            date=datetime.now().strftime("%d-%m-%Y %H:%M")
        )
0
votes

You can now use the managed export and import feature, which can be accessed through gcloud or the Datastore Admin API:

Exporting and Importing Entities

Scheduling an Export