Google App Engine and backends: how to configure it on development server? - google-app-engine

My configuration of backends.yaml
backends:
- name: mybackend
class: B1
instances: 1
options: dynamic
and app.yaml
handlers:
- url: http://mybackend.myapp.appspot.com
script: mybackend.py
login: admin
Running it localy on development server I get this error:
Unable to assign value 'http://mybackend.myapp.appspot.com' to attribute 'url':
Value 'http://mybackend.myapp.appspot.com' for url does not match expression '^(?!\^)/|.|((.).*(?!\$).$'
How can I test backend on development server?

I believe the url should be the relative url from your site. The script should be the python function that's run, not the filename. So your app.yaml should be.
handlers:
- url: /backend
script: mybackend.myfunction
login: admin
Your backend and frontend instances share the same handlers, there's no way to distinguish between them.

Related

Deploying FrontEnd and BackEnd as two separate applications with Google Cloud App Engine

I have two application that I want to deploy with Google Cloud App Engine.
One of them is react front end, and I want to serve this through www.videoo.io
Second one is back-end, which will be served via api.videoo.io
Frontend yaml file react.yaml :
runtime: nodejs16
env: standard
handlers:
- url: /static
static_dir: static
secure: always
- url: www.videoo.io/*
service: frontend
script: auto
secure: always%
API yaml file, api.yaml :
runtime: python37
entrypoint: gunicorn -b :$PORT videoo.wsgi
service: "videoo-api"
env: standard
handlers:
- url: api.videoo.io/*
service: backend
script: auto
secure: always%
Is this the correct way to achieve this ?
What is the best strategy to serve these two separate applications that will interactively communicate (Frontend will make calls to API to get object information that is stored Django app) ?
Here is also my domain name information in Google App Engine settings :
You are on the right path. You are using the microservices architecture which is basically deploying individual apps as parts (services) under a single project.
Your frontend service seems to be your default so you don't need a service name for it. Every GAE App needs a default service.
Rename react.yaml to app.yaml (since it will be your default service) and update the contents to
runtime: nodejs16
env: standard
handlers:
- url: /static
static_dir: static
secure: always
- url: /.*
script: auto
secure: always
Also rename your api.yaml to backend.yaml since that is what you called your service (not sure if this is required but I do that to easily track of what is controlling my service). Update the contents of the file to
service: backend
runtime: python37
entrypoint: gunicorn -b :$PORT videoo.wsgi
env: standard
handlers:
- url: /.*
script: auto
secure: always
You'll need a dispatch.yaml file to route traffic to the different services. Something like
dispatch:
# Send all api traffic to the backend service.
- url: "api.videoo.io/*"
service: backend
# Send all other traffic to the default (frontend).
- url: "*/*"
service: default
Final step is that during your deploy, you will deploy the 2 services in addition to your dispatch.yaml file. The dispatch.yaml file has to be in your project root folder
gcloud app deploy app.yaml dispatch.yaml <path_to_backend.yaml>

Using both OAuth and GAE's Users API within a GAE application

I would like to host my Flask-based web application on GAE.
Regular users are authenticated against Google using flask-oauthlib.
However, I would like to authenticate admin users using GAE's Users API, since it provides, among others, the users.is_current_user_admin().
However, it seems that I cannot protect the admin region from app.yaml, because the following configuration is not valid:
# app.yaml
[...]
handlers:
# For admin users
# THIS IS INVALID!
- url: /admin
login: admin
# For regular users
- url: /.*
script: main.app
Option 1: Create a separate flask app object in the same GAE application:
# app.yaml
[...]
# For admin users
- url: /admin
script: admin.app
login: admin
Is that a good practice? If not, why?
Option 2: Simply implement a function such as:
def is_admin():
return current_user.email in ["admin1#...", "admin2#...", "admin3#..."]
That is, do not rely on GAE's Users API.
Notes:
there are only a few admin users
I do not need fine-grained roles at the moment
Any thoughts (other solutions)?
I have such mixed logins in my non-Flask app, and my handlers look like this:
handlers:
- url: /admin
script: main.app
login: admin
- url: /.*
script: main.app
No need to have a separate app for admin. I don't know how Flask works, but I would expect this to work for you as well.

App Engine Python Modules and inbound mail service

I am using App Engine Modules in my python project. (https://developers.google.com/appengine/docs/python/modules/#Python_Background_threads)
I am also receiving email in m project:
https://developers.google.com/appengine/docs/python/mail/receivingmail
I want to direct the emails to my worker module and not the default module. To that end my worker.yaml has the following settings
worker.yaml
api_version: 1
application: integrate
module: worker
version: 1-0-0
runtime: python27
threadsafe: true
inbound_services:
- mail
builtins:
- deferred: on
handlers:
- url: /admin/.+
script: src.worker.main.app
login: admin
- url: /_ah/mail/.+
script: src.worker.main.app
login: admin
- url: /.*
script: src.worker.main.app
app.yaml
api_version: 1
application: integrate
version: 1-0-0
runtime: python27
threadsafe: true
builtins:
- deferred: on
handlers:
- url: /admin/.+
script: src.default.main.app
login: admin
- url: /.*
script: src.default.main.app
I even tried adding a dispatch.yaml
application: integrate
dispatch:
- url: "*/_ah/mail/.+"
module: worker
But no matter what I do the emails which reach my app are handled by the default module. Any idea what I am missing here? I see the emails coming in but no matter what I do they only go to the default module.
Inbound services could be used only within default module and that is expected behavior. The fact that it works for you locally in devserver is a bug, actually.
Just some additional info for the answer which may help folks in a similar situation.
I noticed in the DevServer log:
"Skipping dispatch.yaml rules because /_ah/mail/[EMAIL_ADDRESS_FOR_APP] is not a dispatchable path."
This is no doubt due to local config, however.
Regardless, the workaround I have now using Tasks is:
Dispatch or directly handle Inbound Mail in the default module
Provide a script handler that creates a Task, taking the relevant MailMessage data as the payload
Set the TaskQueue in queue.yaml to target the module you wish to process the payload data, e.g. a 'worker' module

Production server url not there but development server is?

I am running my app on the production server for first time. I have a url with admin logon enabled in the app.yml. The script runs when I browse to its URL when running on the development server. However, after uploading to the production server when I go to the same URL I get the following error:
The requested URL /tasks/ was not found on this server.
Why would this occur? I tried updating again.
The URL and script is the third one in the my app.yml file:
##app.yml file
application: generic_app_name
version: 1
runtime: python
api_version: 1
handlers:
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
- url: /stats.*
script: $PYTHON_LIB/google/appengine/ext/appstats/ui.py
- url: /tasks/SR2pop
script: PopulateSR2.py
login: admin
- url: /
script: dbsample.py
Is the capitalization of your script exactly as specified in app.yaml? The production servers are case-sensitive, but if you're developing on Windows, the development server isn't. Check the capitalization of PopulateSR2.py matches the one in app.yaml.
Also, your file is called app.yaml, not app.yml, right?
Your 3rd handler is going to match only the exact string /tasks/SR2pop. None of your handlers will match /tasks/.

Cron file - disable access (Google App Engine)

I'm running a cron file in Google App Engine. It seems to be working fine, except I don't want anyone to be able to access the URL.
Here is my .cron file:
cron:
- description: testing cron
url: /tester
schedule: every 1 minutes
I tried adding: "login: admin" underneath "schedule", but I get:
enter code here
Error parsing yaml file:
Unexpected attribute 'login' for object of type <class 'google.appengine.api.croninfo.CronEntry'>.
So how do I prevent someone from calling the url and running a script that should be automated?
Thanks
You restrict access to URLs in app.yaml. Add a correspondent entry for your cron tester:
application: hello-cron
version: 1
runtime: python
api_version: 1
handlers:
- url: /tester
script: tester.py
login: admin

Resources