How to patch env_variable using REST API in App Engine Standard? - google-app-engine

Lately I've been deploying apps on App Engine Standard and sometimes I accidentally deploy a version with a typo in my env_variables specified on app.yaml. Let's say that I don't want to deploy a new version because it takes time and this typo should be easily fixed with a "quick patch".
I followed the GAE Admin REST API doc and played around with the API Explorer. It turns out that the request body accepts envVariables so I was thinking that this API can solve my problem but for some reason it fails.
Error:
{
"error": {
"code": 400,
"message": "This operation is only supported on the following field(s): [automatic_scaling.cool_down_period_sec, automatic_scaling.cpu_utilization.target_utilization, automatic_scaling.max_idle_instances, automatic_scaling.max_total_instances, automatic_scaling.min_idle_instances, automatic_scaling.min_total_instances, automatic_scaling.standard_scheduler_settings.max_instances, automatic_scaling.standard_scheduler_settings.min_instances, automatic_scaling.standard_scheduler_settings.target_cpu_utilization, automatic_scaling.standard_scheduler_settings.target_throughput_utilization, instance_class, manual_scaling.instances, serving_status]",
"status": "INVALID_ARGUMENT"
}
}
Request Parameters:
appsId: PROJECT_ID
servicesId: SERVICE_NAME
versionsId: 2021xxxxx
updateMask: envVariables
Request Body:
{
"envVariables": {
"my_key":"my_value"
}
}
Overall question: Is it not possible to patch env_variables on App Engine Standard using REST API or I'm just missing something? Are there any alternatives to avoid redeployment?

Nope, there is no other alternative for this particular use case.
The reason you cannot modify the envVariables using GAE Rest API is that those variables are used when your app is being built in App Engine, so modifying them will imply re-build all the app which implies at the same time you need to redeploy the app.
You can modify the scaling settings since those not depend on the application or how it is built.
Now, that you're able to see envVariables as an option in the API explorer does not mean it is intended to be used with apps.services.versions.patch, in fact that option is shown as well with others just like a generic menu with all the possible options in the API but in the documentation you share it is not mentioned you can use it for the particular method you mention.

Related

AppEnginePlatformWarning: urllib3 is using URLFetch on Google App Engine sandbox instead of sockets

I'm getting this error on app engine using flask to make a Slack bot. It happens whenever I send a POST request from Slackbot.
Unfortunately, the url provided in the error is a dead link. How do I go about using sockets instead of URLFetch?
/base/data/home/apps/[REDACTED]/lib/requests/packages/urllib3/contrib/appengine.py:115:
AppEnginePlatformWarning: urllib3 is using URLFetch on Google App
Engine sandbox instead of sockets. To use sockets directly instead of
URLFetch see https://urllib3.readthedocs.io/en/latest/contrib.html.
As detailed on Google's Sockets documentation, sockets can be used by setting the GAE_USE_SOCKETS_HTTPLIB environment variable. This feature seems to be available only on paid apps, and impacts billing.
Though the error you posted gets logged as an Error in App Engine, this thread suggests (see reply #8) that the error is actually meant as a warning, which the text "AppEnginePlatformWarning" seems to suggest anyway.
The comment block on the source page for appengine.py is also instructive.
You didn't post any information about your implementation, but on Google App Engine Standard edition, using URLFetch via the AppEngineManager should be just fine, though you will get the error.
You can use the following to silence this:
import warnings
import urllib3.contrib.appengine
warnings.filterwarnings('ignore', r'urllib3 is using URLFetch', urllib3.contrib.appengine.AppEnginePlatformWarning)
For me, turns out the presence of requests_toolbelt dependency in my project was the problem: it somehow forced the requests library to use urllib3, which requires URLFetch to be present, otherwise it raises an AppEnginePlatformError. As suggested in the app engine docs, monkey-patching Requests with requests_toolbelt forces the former to use URLFetch, which is no longer supported by GAE in a Python 3 runtime.
The solution was to remove requests_toolbelt from my requirements.txt file

GAE Cloud Endpoints custom API public api key issues

I've exposed a few APIs using go-endpoints. The APIs work fine, but what I'd like to do is restrict usage of the APIs to only a few referers. Since I'm not passing any authentication information, I do not need OAuth (actually, I really do not want to use OAuth as I expect anonymous users to utilize a front-end that uses this API... I just want that front-end and perhaps another one to use my API).
Apparently the way to do this is to make a Public API Key using the Google Developers Console (Project --> APIs and auth --> Credentials --> Create new Key).
I've changed my JavaScript to use this key, by passing it as a param: https://my-app-id.appspot.com/_ah/api/myService/v1/doSomething?key=key_from_developer_console
However, when I make the call, I get a 403 back with this error:
"Access Not Configured. The API () is not enabled for your project. Please use the Google Developers Console to update your configuration."
Well, initially I set the referer to my-app-id.appspot.com/*, which is only place I want my API to be used from. So I figured I'd remove it just to see, but I get the same issue.
There are some old posts here about having to enable Contacts API and Google + API. I tried that, and it didn't work either.
So what gives? There is virtually no documentation from Google on this Public API Key feature. This is really driving me up a wall...
I had this exact same problem yesterday. I decided to generate my own key and added in my own logic to check for the 'key' param from the request. I just added the self-generated key to my env_variables and it works. However, if you try to redeploy after taking this approach, you may still see the access configuration issues..at least I have still.

Invalid and/or missing SSL certificate when using Google App Engine

UPDATE: Please, if anyone can help: Google is waiting for inputs and examples of this problem on their bug tracking tool. If you have reproducible steps for this issue, please share them on: https://code.google.com/p/googleappengine/issues/detail?id=10937
I'm trying to fetch data from the StackExchange API using a Google App Engine backend. As you may know, some of StackExchange's APIs are site-specific, requiring developers to run queries against every site the user is registered in.
So, here's my backend code for fetching timeline data from these sites. The feed_info_site variable holds the StackExchange site name (such as 'security', 'serverfault', etc.).
data = json.loads(urllib.urlopen("%sme/timeline?%s" %
(self.API_BASE_URL, urllib.urlencode({"pagesize": 100,
"fromdate": se_since_timestamp, "filter": "!9WWBR
(nmw", "site": feed_info_site, "access_token":
decrypt(self.API_ACCESS_TOKEN_SECRET, self.access_token), "key":
self.API_APP_KEY}))).read())
for item in data['items']:
... # code for parsing timeline items
When running this query on all sites except Stack Overflow, everything works OK. What's weird is, when the feed_info_site variable is set to 'stackoverflow', I get the following error from Google App Engine:
HTTPException: Invalid and/or missing SSL certificate for URL:
https://api.stackexchange.com/2.2/me/timeline?
filter=%219WWBR%28nmw&access_token=
<ACCESS_TOKEN_REMOVED>&fromdate=1&pagesize=100&key=
<API_KEY_REMOVED>&site=stackoverflow
Of course, if I run the same query in Safari, I get the JSON results I'm expecting from the API. So the problem really lies in Google's URLfetch service. I found several topics here on Stack Overflow related to similar HTTPS/SSL exceptions, but no accepted answer solved my problems. I tried removing cacerts.txt files. I also tried making the call with validate_certificate=False, with no success.
I think the problem is not strictly related to HTTPS/SSL. If so, how would you explain that changing a single API parameter would make the request to fail?
Wait for the next update to the app engine (scheduled one soon) then update.
Replace browserid.org/verify with another service (verifier.loogin.persona.org/verify is a good service hosted by Mozilla what could be used)
Make sure cacerts.txt doesnt exist (looks like you have sorted but just in-case :-) )
Attempt again
Good luck!
-Brendan
I was facing the same error, google has updated the app engine now, error resolved, please check the updated docs.

detect AppEngine vs basic server

I am developing a web app to run on either Google's AppEngine or a basic server with file storage (it may not stay that way but that's the current status).
How do I detect whether the AppEngine services (most importantly blobstore) are available at runtime?
I have tried using code like the following:
try{
Class.forName( "com.google.appengine.api.blobstore.BlobstoreServiceFactory" );
logger.info( "Using GAE blobstore backend" );
return new GAEBlobService();
}catch( ClassNotFoundException e ){
logger.info( "Using filesystem-based backend" );
return new FileBlobService();
}
but it doesn't work because BlobstoreServiceFactory is available at compile time. What fails if trying to use GAE's blobstore without a GAE server is the following:
com.google.apphosting.api.ApiProxy$CallNotFoundException: The API package 'blobstore' or call 'CreateUploadURL()' was not found.
There's a few things you can use.
You can check the runtime environment to check the running version of App Engine. Check the section about "The Environment" in the runtime docs: https://developers.google.com/appengine/docs/java/runtime
You could also do what you were doing, and attempt to make an call that uses the SDK API functions (instead of just checking for the existence of a class) and catch the exception. This may negatively impact performance since you're making an extra RPC.
You could check request headers for GAE specific request headers too.

http request from Google App Engine

I'm trying to make http requests from my Google App Engine webapp, and discovered I have to use URLConnection since it's the only whitelisted class. The corresponding Clojure library is clojure.contrib.http.agent, and my code is as follows:
(defroutes example
(GET "/" [] (http/string (http/http-agent "http://www.example.com")))
(route/not-found "Page not found"))
This works fine in my development environment- the browser displays the text for example.com. But when I test it out with Google's development app server:
phrygian:example wei$ dev_appserver.sh war
2010-09-28 14:53:36.120 java[43845:903] [Java CocoaComponent compatibility mode]: Enabled
...
INFO: The server is running at http://localhost:8080/
It just hangs when I load the page. No error, or anything. Any idea what might be going on?
http-agent creates threads so that might be why it does not work.
From the API documentation:
Creates (and immediately returns) an Agent representing an HTTP
request running in a new thread.
You could try http-connection, which is a wrapper around HttpURLConnection, so this should work.
Another alternative is to try clj-http. The API seems to be a bit more high-level, but it uses Apache HttpComponents which might be blacklisted.
I am guessing http.async.client is a definite no-go due to its strong asynchronous approach.
You might want to try appengine.urlfetch/fetch from appengine-clj (http://github.com/r0man/appengine-clj, also in clojars)

Resources