Laravel: Making storage work on App Engine - google-app-engine

I followed the Getting started with Laravel on PHP for App Engine and I'm getting an error when I change the path of the Storage to Google Cloud Storage in local development.
ex.
const BUCKET_NAME = "bucket-name";
$storage_path = "gs://" . BUCKET_NAME . "/storage";
Here is the ErrorException:
file_put_contents(/meta/services.json): failed to open stream: No such file or directory

App Engine doesn't allow you to write to the local filesystem for security and scalability reasons. Fortunately though you can read and write to Google Cloud Storage easily using commands like file_put_contents(). This facility is also emulated in the local dev_appserver.
Take a look at https://github.com/ajessup/laravel for a version of Laravel that's been tweaked to run well on Google App Engine, including writing /meta/services.json to GCS.

This might help.
http://forumsarchive.laravel.io/viewtopic.php?id=9341
"By defining the manifest path in app/config/app.php to point to a Cloud Storage path instead, like this: 'manifest' => 'gs://yourbucketname' .'/meta',"
Looks like storage_path() issue when 'manifest' => storage_path().'/meta',

Related

Google Cloud App Engine PHP 7.2 implement Storge

I am starting using GCloud and have a simple question related to work with App Engine and Cloud Storage.
My PHP application runs over a framework that need a tmp directory, and I try to implement that deploying with tmp folder, in composer.json -> scripts -> try to create a new one and setup permissions, but it shows a read-only file system errors. Also tried to create a symbolic link to /tmp, nothing works.
Understood that I missed some concept, maybe there is a way to map a file system folder to a storage instance (bucket)?
Can anyone explain this?
You are telling us that you tried to implement something but you are not showing us what did you actually tried.
Did you try to write files into a /tmp directory (no need to deploy a /tmp folder with your code, App Engine have one with read/write policy by default) as stated in the public documentation?
Also, Google Cloud Storage is not based on an instance (VM) architecture so asking about "storage instance" is inaccurate.
If writing to a /tmp directory doesn't work for you, sharing with us the code that you tried to implement would be useful.
You can always write your files to a Cloud Storage Bucket by using the sample code provided in the public documentation:
function upload_object($bucketName, $objectName, $source)
{
$storage = new StorageClient();
$file = fopen($source, 'r');
$bucket = $storage->bucket($bucketName);
$object = $bucket->upload($file, [
'name' => $objectName
]);
printf('Uploaded %s to gs://%s/%s' . PHP_EOL, basename($source), $bucketName, $objectName);
}

Determine a running instance's VM class in app engine flexible

I've got auto scaling on in my app engine flexible (PHP) app.yaml file. Is there a gcloud or console way to figure out the machine class of the instances that have been assigned to my service?
I know that I can set the resources I need in terms of disk and RAM in my yaml file, but this is a minimum; actual allocated machines may be different. I'm looking to determine what was allocated after the machine is running.
There's a public feature request already opened for this feature, however it isn't yet available.
As a workaround, you can use the Google API Explorer and use the Stackdriver Logging API v2 > logging.entries.list endpoint. You should get relevant information by entering the following details:
fields: entries/protoPayload
Request body: filter: resource.type="gce_instance_template" AND protoPayload.methodName="v1.compute.instanceTemplates.insert" AND protoPayload.resourceName:"/global/instanceTemplates/aef-"
projectIds: <YOUR_PROJECT_IDS>
You'll see the required information under "machineType".

How to access Google Datastore API with credentials without using environment variables?

Currently I'm getting access to the API though the GOOGLE_APPLICATION_CREDENTIALS environment variable. I created and downloaded a service account key as a .json file and set the environment variable to that file. Due to the requirements of the project I'm working on, I won't be able to do this. I tried using the credentials variable in the constructor for the datastore client object, but I wasn't able to get that to work. How should I be going about this?
I'm running Windows 10, but any solution should be (relatively) OS agnostic. I'm writing in python 3.6.
You can use from_service_account_json():
from google.cloud import datastore
client = datastore.Client.from_service_account_json('/path/to/credentials.json')
var = client.get(client.key('MyKind', '<key value>'))
print(var)
see: https://cloud.google.com/docs/authentication/production#obtaining_and_providing_service_account_credentials_manually

google apps from app engine

I want to produce a Google Apps document based on a (Google doc) template stored on the users Google Drive and some XML data held by a servlet running on Google App Engine.
Preferably I want to run as much as possible on the GAE. Is it possible to run Apps Service APIs on GAE or download/manipulate Google doc on GAE? I have not been able to find anything suitable
One alternative is obviously to implement the merge functionality using an Apps Script transferring the XML as parameters and initiate the script through http from GAE, but it just seem somewhat awkward in comparison.
EDIT:
Specifically I am looking for the replaceText script functionality, as shown in the Apps script snippet below, to be implemented in GAE. Remaining code is supported through Drive/Mail API, I guess..
// Get document template, copy it as a new temp doc, and save the Doc’s id
var copyId = DocsList.getFileById(providedTemplateId)
.makeCopy('My-title')
.getId();
var copyDoc = DocumentApp.openById(copyId);
var copyBody = copyDoc.getActiveSection();
// Replace place holder keys,
copyBody.replaceText("CustomerAddressee", fullName);
var todaysDate = Utilities.formatDate(new Date(), "GMT+2", "dd/MM-yyyy");
copyBody.replaceText("DateToday", todaysDate);
// Save and close the temporary document
copyDoc.saveAndClose();
// Convert temporary document to PDF by using the getAs blob conversion
var pdf = DocsList.getFileById(copyId).getAs("application/pdf");
// Attach PDF and send the email
MailApp.sendEmail({
to: email_address,
subject: "Proposal",
htmlBody: "Hi,<br><br>Here is my file :)<br>Enjoy!<br><br>Regards Tony",
attachments: pdf});
As you already found out, apps script is currently the only one that can access an api to modify google docs. All other ways cannot do it unless you export to another format (like pdf or .doc) then use libraries that can modify those, then reupload the new file asking to convert to a google doc native format, which in some cases would loose some format/comments/named ranges and other google doc features. So like you said, if you must use the google docs api you must call apps script (as a content service). Also note that the sample apps script code you show is old and uses the deptecated docsList so you need to port it to the Drive api.
Apps script pretty much piggy backs on top of the standard published Google APIs. Increasingly the behaviours are becoming more familiar.
Obviously apps script is js based and gae not. All the APIs apart from those related to script running are available in the standard gae client runtimes.
No code to check here so I'm afraid generic answer is all I have.
I see now it can be solved by using the Google Drive API to export (download) the Google Apps Doc file as PDF (or other formats) to GAE, and do simple replace-text editing using e.g. the iText library

devappserver2, remote_api, and --default_partition

To access a remote datastore locally using the original dev_appserver I would set --default_partition=s as mentioned here
In March 2013 Google made devappserver2 the default development server, and it does not support --default_partition resulting in the original, dreaded:
BadRequestError: app s~appname cannot access app dev~appname's data
It appears like the first few requests are served correctly with
os.environ["APPLICATION_ID"] == 's~appname'
Then a subsequent request results in a call to /_ah/warmup and then
os.environ["APPLICATION_ID"] == 'dev~appname'
The docs specifically mention related topics but appear geared to dev_appserver here
Warning! Do not get the App ID from the environment variable. The development server simulates the production App Engine service. One way in which it does this is to prepend a string (dev~) to the APPLICATION_ID environment variable, which is similar to the string prepended in production for applications using the High Replication Datastore. You can modify this behavior with the --default_partition flag, choosing a value of "" to match the master-slave option in production. Google recommends always getting the application ID using the get_application_id() method, and never using the APPLICATION_ID environment variable.
You can do the following dirty little trick:
from google.appengine.datastore.entity_pb import Reference
DEV = os.environ['SERVER_SOFTWARE'].startswith('Development')
def myApp(*args):
return os.environ['APPLICATION_ID'].replace("dev~", "s~")
if DEV:
Reference.app = myApp

Resources