3

I'm working on a API Rest app that has to work on GCP. The app runs great locally but when I deploy it to GPC it's not working.

I wrote the webservice in Python 3.7, using Flask, SQLAlchemy, Flask-SQLAlchemy, Flask-Restplus (in order to have Swagger).

I don't have any error while deploying, but when I want to access the documentation (swagger) I have "No Api definition provided" message, and when I try to run a GET method I've got a (CRITICAL) Worker timeout error.

I'll appreciate any help you can give me.

Have a great day!!

Here is some of the code:

project structure:

app.yaml
config.py
main.py
requirements.txt
apis/
     __init__.py
     log_resource.py
     trm_resource.py
     ...
marshal_models/
     __init__.py
     log_marshal.py
     trm_marshal.py
     ...
models/
     __init__.py
     log_model.py
     trm_model.py
     ...
res/
     __init__.py
     text_messages.py
     spa_exceptions.py

main.py

from flask import Flask, send_from_directory
from config import config_by_name

from flask_sqlalchemy import SQLAlchemy

from models import db
from apis import api

app = Flask(__name__)
app.config.from_object(config_by_name['prod'])

api.init_app(app)

db.init_app(app)

if __name__ == '__main__':
    app.run(debug=True)

requirements.txt

-i https://pypi.org/simple
aniso8601==8.0.0
attrs==19.3.0
click==7.0
flask-restplus==0.13.0
flask-sqlalchemy==2.4.1
flask-swagger-ui==3.20.9
flask==1.1.1
importlib-metadata==0.23 ; python_version < '3.8'
itsdangerous==1.1.0
jinja2==2.10.3
jsonschema==3.2.0
markupsafe==1.1.1
more-itertools==7.2.0
mysql-connector-python==8.0.18
mysqlclient==1.4.4
protobuf==3.10.0
pyrsistent==0.15.5
pytz==2019.3
simplejson==3.17.0
six==1.13.0
sqlalchemy==1.3.11
werkzeug==0.16.0
zipp==0.6.0
gunicorn==19.9.0

app.yaml

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

runtime_config:
  python_version: 3

config.py

class Config(object):
    DEBUG = False
    TESTING = False

    connection_type = 'gcp'  #tcp/ip
    DB_SERVER = 'XXX.XXX.XXX.XXX' 
    DB_USERNAME = 'XXXX' 
    DB_PASSWORD = 'XXXX' 
    DB_NAME = 'XXXXX'
    SQLALCHEMY_DATABASE_URI = f"mysql+mysqlconnector://{DB_USERNAME}:{DB_PASSWORD}@{DB_SERVER}/{DB_NAME}"
    SQLALCHEMY_TRACK_MODIFICATIONS = False

class ProductionConfig(Config):
    pass

config_by_name = dict(
    dev = DevelopmentConfig,
    test = TestingConfig,
    prod = ProductionConfig
)

apis\__init__.py

from flask_restplus import Api
from .spa_system_resource import api as spa_name_space
from .stage_resource import api as stage_name_space
from .consolidated_resource import api as consolidated_name_space
from .cost_cat_resource import api as cost_cat_name_space
from .cost_resource import api as cost_name_space
from .log_resource import api as log_name_space
from .trm_resource import api as trm_name_space
from .energy_resource import api as energy_price_name_space

api = Api (
    title='API - Spa System',
    version='1.0',
    description='XXXXXX',
    contact='XXXXX',
    contact_email='XXXXXXXXXXX',
    contact_url='XXXXXXXX',
    default_mediatype='application/json',
)

api.add_namespace(spa_name_space)
api.add_namespace(stage_name_space)
api.add_namespace(consolidated_name_space)
api.add_namespace(cost_name_space)
api.add_namespace(cost_cat_name_space)
api.add_namespace(log_name_space)
api.add_namespace(trm_name_space)
api.add_namespace(energy_price_name_space)

extract of one resource file: apis\log_resource.py

import datetime
from flask import current_app as app
from flask import Flask, request, jsonify, make_response
from flask_sqlalchemy import sqlalchemy

from flask_restplus import Namespace, Resource, reqparse, abort, fields
from werkzeug.exceptions import HTTPException

from res import DatabaseIntegrityError, DatabaseError, EngMsg as msg

from sqlalchemy.exc import SQLAlchemyError, IntegrityError
from models import Log, ModelList
from marshal_models import log_model_dict 

api = Namespace('logs', description=msg.API_NAMESPACE_LOG_DESCRIPTION)

log_model = api.model('log', log_model_dict)

@api.route('/<log_id>')
@api.doc(responses={ 200: msg.API_DOC_RESPONSES_200, 
                         400: msg.API_DOC_RESPONSES_400,
                         409: msg.API_DOC_RESPONSES_409, 
                         500: msg.API_DOC_RESPONSES_500 })
class LogRes(Resource):

    @api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
    @api.marshal_with(log_model, skip_none=True)
    def get(self, log_id):
        try:
            if log_id.isdigit():  
                return Log.query.get(log_id)
            else:
                app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
                return msg.API_DOC_RESPONSES_400, 400     
        except DatabaseIntegrityError as err:
            app.logger.error(err)
            return msg.API_DOC_RESPONSES_409, 409
        except HTTPException as err:
            app.logger.error(f'HTTException: {err}')
            return msg.API_DOC_RESPONSES_400, 400
        except (Exception, DatabaseError) as err:
            app.logger.error(err)
            return msg.API_DOC_RESPONSES_500, 500


    @api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
    @api.expect(log_model, validate=True)
    @api.marshal_with(log_model, skip_none=True)
    def put(self, log_id):
        try:
            if log_id.isdigit():  
                log = Log.query.get(log_id)
                if log:
                    log.update(api.payload)
                return log 
            else:
                app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
                return msg.API_DOC_RESPONSES_400, 400        
        except DatabaseIntegrityError as err:
            app.logger.error(err)
            return msg.API_DOC_RESPONSES_409, 409
        except HTTPException as err:
            app.logger.error(f'HTTException: {err}')
            return msg.API_DOC_RESPONSES_400, 400
        except (Exception, DatabaseError) as err:
            app.logger.error(err)
            return msg.API_DOC_RESPONSES_500, 500

    @api.doc(params={"log_id": msg.API_DOC_PARAMS_LOG_ID})
    @api.response(204, msg.API_DOC_RESPONSES_204)
    def delete(self, log_id):
        try:
            if log_id.isdigit():
                log = Log.query.get(log_id)
                if log:
                    log.delete()
                return msg.API_DOC_RESPONSES_204, 204
            else:
                app.logger.error(TypeError(msg.ERROR_TYPE_ERROR))
                return msg.API_DOC_RESPONSES_400, 400      
        except DatabaseIntegrityError as err:
            app.logger.error(err)
            return msg.API_DOC_RESPONSES_409, 409
        except HTTPException as err:
            app.logger.error(f'HTTException: {err}')
            return msg.API_DOC_RESPONSES_400, 400
        except (Exception, DatabaseError) as err:
            app.logger.error(err)
            return msg.API_DOC_RESPONSES_500, 500

error message in browser trying to call a GET method (updated nov 27 2019):

Error message when trying to call a GET method

error log in gcp (updated nov 27 2019)

[

 {
   "protoPayload": {
     "@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
     "appId": "p~maximal-beach-255318",
     "versionId": "20191126t083944",
     "requestId": "5dde722800ff01c4db2055869d0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "ip": "217.182.175.162",
     "startTime": "2019-11-27T12:55:04.115931Z",
     "endTime": "2019-11-27T12:55:35.620208Z",
     "latency": "31.504277s",
     "megaCycles": "672",
     "method": "HEAD",
     "resource": "/stages/",
     "httpVersion": "HTTP/1.1",
     "status": 502,
     "responseSize": "122",
     "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
     "urlMapEntry": "auto",
     "host": "maximal-beach-255318.appspot.com",
     "cost": 1.3634e-8,
     "instanceIndex": -1,
     "finished": true,
     "instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
     "appEngineRelease": "1.9.71",
     "traceId": "66545566d74d32b65a44ef6b5e8eb3e1",
     "first": true,
     "traceSampled": true
   },
   "insertId": "5dde72470009773abcebccc9",
   "httpRequest": {
     "status": 502
   },
   "resource": {
     "type": "gae_app",
     "labels": {
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944"
     }
   },
   "timestamp": "2019-11-27T12:55:04.115931Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
   "operation": {
     "id": "5dde722800ff01c4db2055869d0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "producer": "appengine.googleapis.com/request_id",
     "first": true,
     "last": true
   },
   "trace": "projects/maximal-beach-255318/traces/66545566d74d32b65a44ef6b5e8eb3e1",
   "receiveTimestamp": "2019-11-27T12:55:35.626061163Z",
   "traceSampled": true
 },
 {
   "textPayload": "[2019-11-27 12:45:27 +0000] [20] [INFO] Booting worker with pid: 20",
   "insertId": "5dde6fe70007e247c06a652a",
   "resource": {
     "type": "gae_app",
     "labels": {
       "version_id": "20191126t083944",
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318"
     }
   },
   "timestamp": "2019-11-27T12:45:27.516679Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T12:45:27.671289763Z"
 },
 {
   "textPayload": "[2019-11-27 12:45:26 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:19)",
   "insertId": "5dde6fe6000528928a3fd08e",
   "resource": {
     "type": "gae_app",
     "labels": {
       "version_id": "20191126t083944",
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318"
     }
   },
   "timestamp": "2019-11-27T12:45:26.338066Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T12:45:26.344938571Z"
 },
 {
   "protoPayload": {
     "@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
     "appId": "p~maximal-beach-255318",
     "versionId": "20191126t083944",
     "requestId": "5dde6fc700ff0b4dadaec6e11e0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "ip": "190.217.67.6",
     "startTime": "2019-11-27T12:44:55.740781Z",
     "endTime": "2019-11-27T12:45:27.355877Z",
     "latency": "31.615096s",
     "megaCycles": "662",
     "method": "GET",
     "resource": "/logs/",
     "httpVersion": "HTTP/1.1",
     "status": 502,
     "responseSize": "690",
     "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
     "urlMapEntry": "auto",
     "host": "maximal-beach-255318.appspot.com",
     "cost": 7.7113e-8,
     "instanceIndex": -1,
     "finished": true,
     "instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
     "appEngineRelease": "1.9.71",
     "traceId": "17ca3e3af386e29af2197260dd20ca5b",
     "first": true,
     "traceSampled": true
   },
   "insertId": "5dde6fe700056f2d0a6185c7",
   "httpRequest": {
     "status": 502
   },
   "resource": {
     "type": "gae_app",
     "labels": {
       "version_id": "20191126t083944",
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318"
     }
   },
   "timestamp": "2019-11-27T12:44:55.740781Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
   "operation": {
     "id": "5dde6fc700ff0b4dadaec6e11e0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "producer": "appengine.googleapis.com/request_id",
     "first": true,
     "last": true
   },
   "trace": "projects/maximal-beach-255318/traces/17ca3e3af386e29af2197260dd20ca5b",
   "receiveTimestamp": "2019-11-27T12:45:27.357040172Z",
   "traceSampled": true
 },
 {
   "textPayload": "[2019-11-27 12:44:50 +0000] [19] [INFO] Booting worker with pid: 19",
   "insertId": "5dde6fc200029a6115a11cd3",
   "resource": {
     "type": "gae_app",
     "labels": {
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default",
       "zone": "us-east1-3"
     }
   },
   "timestamp": "2019-11-27T12:44:50.170593Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T12:44:50.177293952Z"
 },
 {
   "textPayload": "[2019-11-27 12:44:48 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:18)",
   "insertId": "5dde6fc0000ccba4ab7daec2",
   "resource": {
     "type": "gae_app",
     "labels": {
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default"
     }
   },
   "timestamp": "2019-11-27T12:44:48.838564Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T12:44:48.846320557Z"
 },
 {
   "protoPayload": {
     "@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
     "appId": "p~maximal-beach-255318",
     "versionId": "20191126t083944",
     "requestId": "5dde6fa200ff00ffb6f6484c386b0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "ip": "190.217.67.6",
     "startTime": "2019-11-27T12:44:18.046838Z",
     "endTime": "2019-11-27T12:44:49.927998Z",
     "latency": "31.881160s",
     "megaCycles": "638",
     "method": "GET",
     "resource": "/stages/",
     "httpVersion": "HTTP/1.1",
     "status": 502,
     "responseSize": "690",
     "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
     "urlMapEntry": "auto",
     "host": "maximal-beach-255318.appspot.com",
     "cost": 7.7113e-8,
     "instanceIndex": -1,
     "finished": true,
     "instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
     "appEngineRelease": "1.9.71",
     "traceId": "f9abbbb57697d19e094bc6a7afe46fc4",
     "first": true,
     "traceSampled": true
   },
   "insertId": "5dde6fc1000e377f4c815764",
   "httpRequest": {
     "status": 502
   },
   "resource": {
     "type": "gae_app",
     "labels": {
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944"
     }
   },
   "timestamp": "2019-11-27T12:44:18.046838Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
   "operation": {
     "id": "5dde6fa200ff00ffb6f6484c386b0001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "producer": "appengine.googleapis.com/request_id",
     "first": true,
     "last": true
   },
   "trace": "projects/maximal-beach-255318/traces/f9abbbb57697d19e094bc6a7afe46fc4",
   "receiveTimestamp": "2019-11-27T12:44:49.941671848Z",
   "traceSampled": true
 },
 {
   "protoPayload": {
     "@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
     "appId": "p~maximal-beach-255318",
     "versionId": "20191126t083944",
     "requestId": "5dde6f9000ff09e526316e53900001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "ip": "190.217.67.6",
     "startTime": "2019-11-27T12:44:00.648486Z",
     "endTime": "2019-11-27T12:44:05.324856Z",
     "latency": "4.676370s",
     "megaCycles": "2744",
     "method": "GET",
     "resource": "/favicon.ico",
     "httpVersion": "HTTP/1.1",
     "status": 404,
     "responseSize": "385",
     "referrer": "http://maximal-beach-255318.appspot.com/stages/",
     "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
     "urlMapEntry": "auto",
     "host": "maximal-beach-255318.appspot.com",
     "cost": 4.3027e-8,
     "instanceIndex": -1,
     "finished": true,
     "instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
     "appEngineRelease": "1.9.71",
     "traceId": "18628020e642702bce4c2e0b3187e2ce",
     "first": true,
     "traceSampled": true
   },
   "insertId": "5dde6f9500069b4e77b19ab5",
   "httpRequest": {
     "status": 404
   },
   "resource": {
     "type": "gae_app",
     "labels": {
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default"
     }
   },
   "timestamp": "2019-11-27T12:44:00.648486Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
   "operation": {
     "id": "5dde6f9000ff09e526316e53900001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "producer": "appengine.googleapis.com/request_id",
     "first": true,
     "last": true
   },
   "trace": "projects/maximal-beach-255318/traces/18628020e642702bce4c2e0b3187e2ce",
   "receiveTimestamp": "2019-11-27T12:44:05.434941402Z",
   "traceSampled": true
 },
 {
   "textPayload": "[2019-11-27 12:44:00 +0000] [18] [INFO] Booting worker with pid: 18",
   "insertId": "5dde6f900009af56ce378348",
   "resource": {
     "type": "gae_app",
     "labels": {
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default",
       "zone": "us-east1-3"
     }
   },
   "timestamp": "2019-11-27T12:44:00.634710Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T12:44:00.697087376Z"
 },
 {
   "textPayload": "[2019-11-27 12:43:59 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:15)",
   "insertId": "5dde6f8f00057bd7123ebed3",
   "resource": {
     "type": "gae_app",
     "labels": {
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default"
     }
   },
   "timestamp": "2019-11-27T12:43:59.359383Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T12:43:59.367903796Z"
 },
 {
   "protoPayload": {
     "@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
     "appId": "p~maximal-beach-255318",
     "versionId": "20191126t083944",
     "requestId": "5dde6f7100ff03b1470e1729150001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "ip": "190.217.67.6",
     "startTime": "2019-11-27T12:43:29.241991Z",
     "endTime": "2019-11-27T12:44:00.433791Z",
     "latency": "31.191800s",
     "megaCycles": "670",
     "method": "GET",
     "resource": "/stages/",
     "httpVersion": "HTTP/1.1",
     "status": 502,
     "responseSize": "690",
     "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
     "urlMapEntry": "auto",
     "host": "maximal-beach-255318.appspot.com",
     "cost": 7.7113e-8,
     "instanceIndex": -1,
     "finished": true,
     "instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
     "appEngineRelease": "1.9.71",
     "traceId": "2eb1e05b6e3607b82bc6eb1581f7030b",
     "first": true,
     "traceSampled": true
   },
   "insertId": "5dde6f900006aa2783948800",
   "httpRequest": {
     "status": 502
   },
   "resource": {
     "type": "gae_app",
     "labels": {
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default"
     }
   },
   "timestamp": "2019-11-27T12:43:29.241991Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
   "operation": {
     "id": "5dde6f7100ff03b1470e1729150001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "producer": "appengine.googleapis.com/request_id",
     "first": true,
     "last": true
   },
   "trace": "projects/maximal-beach-255318/traces/2eb1e05b6e3607b82bc6eb1581f7030b",
   "receiveTimestamp": "2019-11-27T12:44:00.443084831Z",
   "traceSampled": true
 },
 {
   "textPayload": "[2019-11-27 07:52:18 +0000] [7] [INFO] Shutting down: Master",
   "insertId": "5dde2b32000662725bdd088d",
   "resource": {
     "type": "gae_app",
     "labels": {
       "version_id": "20191126t083531",
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318"
     }
   },
   "timestamp": "2019-11-27T07:52:18.418418Z",
   "labels": {
     "clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T07:52:18.465138763Z"
 },
 {
   "textPayload": "[2019-11-27 07:52:17 +0000] [20] [INFO] Worker exiting (pid: 20)",
   "insertId": "5dde2b31000cbb519c6bb001",
   "resource": {
     "type": "gae_app",
     "labels": {
       "version_id": "20191126t083531",
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318"
     }
   },
   "timestamp": "2019-11-27T07:52:17.834385Z",
   "labels": {
     "clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T07:52:18.129370130Z"
 },
 {
   "textPayload": "[2019-11-27 07:52:17 +0000] [7] [INFO] Handling signal: term",
   "insertId": "5dde2b310009e8722b2030e5",
   "resource": {
     "type": "gae_app",
     "labels": {
       "version_id": "20191126t083531",
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318"
     }
   },
   "timestamp": "2019-11-27T07:52:17.649330Z",
   "labels": {
     "clone_id": "00c61b117c8a2ff2cf91e014f80fd771ceb13ae6f293bfa1dfe53396a1fe807c93d66bb6"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T07:52:17.795680101Z"
 },
 {
   "textPayload": "[2019-11-27 02:15:44 +0000] [15] [INFO] Booting worker with pid: 15",
   "insertId": "5ddddc5000013018cd840898",
   "resource": {
     "type": "gae_app",
     "labels": {
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default",
       "zone": "us-east1-3"
     }
   },
   "timestamp": "2019-11-27T02:15:44.077848Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
 },
 {
   "textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Using worker: sync",
   "insertId": "5ddddc4f000e3a8221b4647f",
   "resource": {
     "type": "gae_app",
     "labels": {
       "version_id": "20191126t083944",
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318"
     }
   },
   "timestamp": "2019-11-27T02:15:43.932482Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
 },
 {
   "textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Listening at: http://0.0.0.0:8081 (7)",
   "insertId": "5ddddc4f000e3a5ed3d9fe86",
   "resource": {
     "type": "gae_app",
     "labels": {
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944",
       "module_id": "default"
     }
   },
   "timestamp": "2019-11-27T02:15:43.932446Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T02:15:44.269814707Z"
 },
 {
   "textPayload": "[2019-11-27 02:15:43 +0000] [7] [INFO] Starting gunicorn 19.9.0",
   "insertId": "5ddddc4f000e32a95dc08c06",
   "resource": {
     "type": "gae_app",
     "labels": {
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944"
     }
   },
   "timestamp": "2019-11-27T02:15:43.930473Z",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/stderr",
   "receiveTimestamp": "2019-11-27T02:15:43.935820537Z"
 },
 {
   "protoPayload": {
     "@type": "type.googleapis.com/google.appengine.logging.v1.RequestLog",
     "appId": "p~maximal-beach-255318",
     "versionId": "20191126t083944",
     "requestId": "5ddddc4e00ff05cca307340a140001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "ip": "186.84.21.80",
     "startTime": "2019-11-27T02:15:42.380067Z",
     "endTime": "2019-11-27T02:15:45.795201Z",
     "latency": "3.415134s",
     "megaCycles": "4969",
     "method": "GET",
     "resource": "/favicon.ico",
     "httpVersion": "HTTP/1.1",
     "status": 404,
     "responseSize": "380",
     "referrer": "http://maximal-beach-255318.appspot.com/stages/",
     "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.108 Safari/537.36",
     "urlMapEntry": "auto",
     "host": "maximal-beach-255318.appspot.com",
     "cost": 4.2468e-8,
     "wasLoadingRequest": true,
     "instanceIndex": -1,
     "finished": true,
     "instanceId": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49",
     "line": [
       {
         "time": "2019-11-27T02:15:45.794925Z",
         "severity": "INFO",
         "logMessage": "This request caused a new process to be started for your application, and thus caused your application code to be loaded for the first time. This request may thus take longer and use more CPU than a typical request for your application."
       }
     ],
     "appEngineRelease": "1.9.71",
     "traceId": "55744f06ecd2c9f36584f78dd72858dd",
     "first": true,
     "traceSampled": true
   },
   "insertId": "5ddddc51000c22e862aa1128",
   "httpRequest": {
     "status": 404
   },
   "resource": {
     "type": "gae_app",
     "labels": {
       "module_id": "default",
       "zone": "us-east1-3",
       "project_id": "maximal-beach-255318",
       "version_id": "20191126t083944"
     }
   },
   "timestamp": "2019-11-27T02:15:42.380067Z",
   "severity": "INFO",
   "labels": {
     "clone_id": "00c61b117cdf0dc021505dc1db4b8707a84de0d2f54c6da3e7f40f65466f31153b28ae49"
   },
   "logName": "projects/maximal-beach-255318/logs/appengine.googleapis.com%2Frequest_log",
   "operation": {
     "id": "5ddddc4e00ff05cca307340a140001707e6d6178696d616c2d62656163682d3235353331380001323031393131323674303833393434000100",
     "producer": "appengine.googleapis.com/request_id",
     "first": true,
     "last": true
   },
   "trace": "projects/maximal-beach-255318/traces/55744f06ecd2c9f36584f78dd72858dd",
   "receiveTimestamp": "2019-11-27T02:15:45.804618825Z",
   "traceSampled": true
 },

fegloff
  • 51
  • 7
  • Hello @fegloff, can you confirm that you were able to deploy the appilcation without any error? also, I want you to inspect your application with chrome inspector and provide me with errors related to this issue if they exist. can you provide me also with your swagger structure file? – Methkal Khalawi Nov 25 '19 at 15:55
  • thanks @MethkalKhalawi for your help. I checked deploy logs and everything looks fine. When I inspected the app using chrome inspector the following happens: - accesing swagger at "/" url `index.js:1 Mixed Content: The page at '*****' was loaded over HTTPS, but requested an insecure resource 'http://****/swagger.json'. This content should also be served over HTTPS.` also when I enable unsecured content: `(index):1 Access to fetch at 'http://*****' from origin 'https://*****' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.` – fegloff Nov 25 '19 at 16:09
  • @MethkalKhalawi when I try a GET Method (PROJECT_NAME..appspot.com/logs), I have a 502 Bad Gateway followed by nginx at the bottom – fegloff Nov 25 '19 at 17:25

1 Answers1

3

Thanks to the error message that you have provide, things now are more clear. So this message

Mixed Content: The page at '*****' was loaded over HTTPS, but requested an insecure resource 'http://****/swagger.json'. This content should also be served over HTTPS.

Means that your App Engine is trying to serve content over HTTPS. However, your Flask Restplus is sending HTTP requests. Here it’s trying to get “http://****/swagger.json”

with a HTTP request. Due to this mismatch the call was blocked and you received “No API definition provided”.

To solve this issue, I noticed you are using “werkzeug” middleware.

Add this code to your Flask initialization:

from werkzeug.middleware.proxy_fix import ProxyFix

app = Flask(__name__)
app.wsgi_app = ProxyFix(app.wsgi_app)

You can read about the original issue here.

I hope this helps.

Jason R Stevens CFA
  • 2,232
  • 1
  • 22
  • 28
Methkal Khalawi
  • 2,368
  • 1
  • 8
  • 13
  • Thanks for your help @MethkalKhalawi. Your suggestion solves the swagger issue. But i still got 502 Bad Gateway (nginx at the bottom) when I tried to access a service. The App Engine logs shows the following: `[2019-11-26 13:39:03 +0000] [7] [CRITICAL] WORKER TIMEOUT (pid:19)` – fegloff Nov 26 '19 at 13:45
  • hey @fegloff, I'm glad that my solution solved your swagger issue. For you second error "WORKER TIMEOUT", I checked your posted logs but I don't see this error. can you please edit your post and add this error log in addition to 3 logs before this one and 3 after this one from your Logging console? – Methkal Khalawi Nov 27 '19 at 08:39
  • Hey @fegloff, I investigated more on your issue and it seem gunicorn related, check this [issue on Github](https://github.com/benoitc/gunicorn/issues/1801). A workaround offered is to increase timeout value `gunicorn hello:app --timeout ` – Methkal Khalawi Nov 27 '19 at 15:17
  • Hi @MethkalKhalawi you were right, the issue was gunicorn related. I was able to temporary solve the issue by removing gunicorn in requirements.txt and leaving app.yaml with one line: `runtime: python37` in order to let GCP to run the standard gunircon configuration. I think the issue is related to port redirection (the worker doesn't know where to go). Do I have to code something regarding PORT number environment variable? Do I have to set a internal port for my app and code the redirection between APP Engine entry port and my app entry point? Thanks again for all your help! – fegloff Nov 28 '19 at 12:52
  • Can you try to increase the timeout value`gunicorn main:app --timeout ` in your application. You can create [gunicorn.config.py](https://cloud.google.com/appengine/docs/flexible/python/runtime#recommended_gunicorn_configuration) file and use it in app.yaml. this link here may help you. – Methkal Khalawi Nov 28 '19 at 16:01
  • it worked with five min timeout (3000)!!! (also thanks to Luis Calderon from GCP Support) `App.yaml runtime: python37 entrypoint: gunicorn -b :$PORT -t 3000 main:app requirements.txt: Flask==1.1.1 gunicorn==20.0.3 ....` – fegloff Dec 05 '19 at 03:22
  • 1
    @fegloff, if the offered solution worked for you please accept the answer for a better visibility within the community. – Deniss T. Dec 06 '19 at 16:47