5

I have taken the basic python 3 tutorial website on flask from this google cloud tutorial and I am able to set this up and the website works just fine.

In addition , I also wanted to run a python script which runs everyday to collect some data, but the cron job just doesn't work. I also added login: admin to restrict anyone to directly use that url

cron.yaml

cron:
- description: test dispatch vs target
  url: /cronapp
  schedule: every 5 hours

app.yaml

runtime: python
env: flex
entrypoint: gunicorn -b :$PORT main:app

runtime_config:
  python_version: 3

handlers:
- url: /cronapp
  script: cronapp.py
  login: admin

I am calling this as http://myproject.appspot.com/cronapp also doesn't work and returns a 404. what am I doing wrong ? any help is appreciated

user1251323
  • 97
  • 1
  • 6

1 Answers1

4

Your app.yaml file is mixing up the standard environment Handlers element into a flexible environment configuration, so it is probably ignored. You can probably see the cron requests in the app's logs in the developer console (likely with errors, though).

You need to add a handler for /cronapp inside your app code, not in app.yaml. Not entirely sure how you do that (I'm still using only standard environment), it depends on your app and/or its framework. Take a look at the Hello World code review for a flask example.

Update:

I may not be entirely correct, I based my answer on documentation but I just noticed some inconsistencies (I sent some documentation feedback to Google for it).

The flexible environment Securing URLs for cron (which appears mostly copied from the standard environment equivalent) mentions a couple of solutions:

  • one indeed based on the login: admin option to handler:

You can restrict a URL by adding login: admin to the handler configuration section in app.yaml. For more information see Securing URLs

But handler is not mentioned in the Configuring your App with app.yaml and the Securing URLs is pointing to an inexistent tag. So I'm not sure if this is indeed working or not.

  • the second one is based on the X-Appengine-Cron header (same as in the standard environment):

Requests from the Cron Service will also contain a HTTP header:

X-Appengine-Cron: true

The X-Appengine-Cron header is set internally by Google App Engine. If your request handler finds this header it can trust that the request is a cron request. If the header is present in an external user request to your app, it is stripped, except for requests from logged in administrators of the application, who are allowed to set the header for testing purposes.

But in Removed headers it is mentioned that:

In addition, some selected headers that match the following pattern are removed from the request:

  • X-Appengine-*

It's unclear if this extends to X-Appengine-Cron or not. It's worth a try. This is my check in the (standard env, webapp2-based) cron handler code:

    if self.request.headers.get('X-AppEngine-Cron') is None:
        self.abort(403)  # HTTPForbidden
Dan Cornilescu
  • 37,297
  • 11
  • 54
  • 89
  • Thanks Dan. Cron works fine if I put the handler directly in the app. But I don't want the outside world to call this URL. This should only be accessible via cron. Any ideas on how to restrict that ? – user1251323 Jul 28 '17 at 13:23
  • 1
    Thanks Dan for the detailed response. I tested with X-app engine-cron in the headers as you said but looks like it isn't sent with the header in the flexible environment. I will open up a ticket with google. – user1251323 Jul 29 '17 at 13:52
  • I am not sure what has happened now . but a fresh deployment on a fresh new project seems to have worked with X-AppEngine-Cron solution . Thanks again for your help. – user1251323 Jul 29 '17 at 15:40