Forbidden Error
actually its more simpler, I have a solution that should work in any environment.
either it be on a:
- Local Development Environment
- Heroku
- AWS
- Azure
- Docker
and or whatever cloud environment you fancy.
Define a function to get the NDB Client with credentials as follows
def get_client() -> ndb.Client:
if is_heroku():
# NOTE: hosted in Heroku service key should be saved as environment variable in heroku or in any platform other than GCP
app_credentials = json.loads(os.environ.get('GOOGLE_APPLICATION_CREDENTIALS'))
credentials = service_account.Credentials.from_service_account_info(info=app_credentials)
ndb_client: ndb.Client = ndb.Client(namespace="main", project=config_instance.PROJECT, credentials=credentials)
else:
# NOTE: could be GCP or another cloud environment
ndb_client: ndb.Client = ndb.Client(namespace="main", project=config_instance.PROJECT)
return ndb_client
then create a python wrapper like this
def use_context(func: Callable) -> Callable:
"""
**use_context**
will insert ndb context for working with ndb. Cloud Databases
**NOTE**
functions/ methods needs to be wrapped by this wrapper when they interact with the database somehow
:param func: function to wrap
:return: function wrapped with ndb.context
"""
@functools.wraps(func)
def wrapper(*args, **kwargs) -> Callable:
ndb_client = get_client()
print(f' ndb_client : {str(ndb_client)}')
with ndb_client.context():
return func(*args, **kwargs)
return wrapper
whenever you need to use GCP NDB Context just call the wrapper function as follows
@use_context
def save_model(model: Optional[ndb.Model]) -> Optional[ndb.Key]:
"""save ndb model to store and return ndb.Key"""
return model.put() if isinstance(model, ndb.Model) else None
NOTE: the contents of GOOGLE_APPLICATION_CREDENTIALS
environment variable needs to be obtained from the JSON file and
the contents of this file needs to be set as an environment variable
if you are on Heroku or any other cloud Offering other than GCP
On Local Development you can save the file on your local drive,
On Docker you can set the environment variable or use the file
control which is which by this logic
if is_heroku():
in my case its just a function that tries to read an environment variable to see if the app is running on Heroku or not
in your case it could be anything as long as it tells you which
environment you are running at so you could choose to load
your key file from local or environment .
Loading JSON Files from Environment Variables
this is just so you can load the contents of a json file from environment variables
app_credentials = json.loads(os.environ.get('GOOGLE_APPLICATION_CREDENTIALS'))
the above allows you to save the actual contents of a JSON File to an
environment variable and then load it back as JSON again,
To avoid having to save the file in the src folder or any other folder.