Redeploying OpenAPI spec into App Engine standard environment - google-app-engine

When I do some changes in OpenAPI spec, which don't involve any changes in the code, do I need to redeploy the code along with the new specification?
When I deploy OpenAPI spec with gcloud service-management deploy command I get back in it's output new service configuration version, which I should set to the ENDPOINTS_SERVICE_VERSION parameter in the app.yaml file.
I'm not sure but it looks like I have to redeploy the app every time I deploy a new version of my OpenAPI spec, even when the application code doesn't change I still need to point it to the right service configuration version with the new ENDPOINTS_SERVICE_VERSION value, is that right?
If so, then it's different from what is described in the How API Deployment Works document for AE flex environment under the "Redeployment" section, where it says the following:
You can use the gcloud service-management deploy command to update
just the API specification without redeploying your backend API server
code or the Extensible Service Proxy. This is useful if you are
changing a configuration-only detail.
When you change the API specification, the Service Control API backing
your running service instances will pick up the change because as it
depends on the same service configuration.
Maybe someone could help to clarify how exactly it works in case of AE standard environment?

Are you using the Endpoints Frameworks? If so, then you will have to deploy the app when you make a new service config version, because, as you mentioned, the app.yaml specifies which service config to use.

Related

How to mix Cloud Run and App Engine deployments in one project?

I have a Quarkus application already deployed on Google Cloud Run.
It depends on MySQL, hence there is an instance started on Cloud SQL.
Next step in my deployment process is to add keycloak. From what I've read the best option seems to be Google App Engine.
The approved answer in this question gave me some good insight of what needs to be done ... mostly.
What I did was:
Locally I made a sub-directory in the main project.
In that directory I added the app.yaml and the Dockerfile (as described here for instance).
There I executed the said two commands: gcloud init and gcloud app deploy.
I had my doubts about this set up and they were backed up by the error I got eventually:
ERROR: (gcloud.app.deploy) INVALID_ARGUMENT: The first service (module) you upload to a new application must be the 'default' service (module). Please upload a version of the 'default' service (module) before uploading a version for the 'morph-keycloak-service' service (module).
I understand my set up breaks the overall structure of the project but I'm not sure how to mix those two application with the right services.
I understand keycloak is a stateful application, hence cannot live on Cloud Run (by the way the intention is for keycloak to use the same database instance shared with the application).
So does any one know a more sensible set up, or what can I move in mine in order to fix it?
In short:
The answer really is in reading the error message (thanks #gaefan) - about the error itself it explains enough. So I just commented out the service: my-keycloak-service line in the app.yaml (thus leaving gcloud to implicitly mark it as the default one) and the deployment continued.
Eventually keycloak didn't connect to the database but if I don't manage to adjust the configurations that would probably be a subject to a different question.
On the point of project structure and functionality:
First off, thanks #NoCommandLine and #guillaume-blaquiere for your input!
#NoCommandLine the application on Cloud Run is sort of a headless REST API enabled backend. Most of the API calls are secured by keycloack. A next step in the deployment process would be to port an existing UI (React) client on the Firebase hosting (or on another suitable service - I'm still not completely sure which approach is best) and in order for the users to work with this client properly they must make an SSO through keycloak first.
I'm quite new to GCP and the number and variants of the available options are still overwhelming to me - one must get familiar with the nuances but I guess it takes time. So I'm still taking suggestions on how to adjust my project structure to fit better the services stack. Thanks!

Injecting secrets from CI with GCP AppEngine's app.yml

Thanks for your help in advance!
I'm trying to create a simple but secure way to inject secrets from a commandline call to gcloud app deploy app.yml.
I'm relying on secret information stored in environment variables in my app's runtime, which I can set using the following app.yml:
runtime: nodejs
env: flex
env_variables:
SECRET_KEY: "passed-in-value"
For example, I'd like to be able to do something like
SECRETKEY=${LOCAL_SECRET_VALUE} gcloud app deploy app.yml
or use a cli argument if there is one, but I don't see any here.
At the end of the day, I just need a simple way to inject secrets so I can deploy to my testing environment from my local machine, or to production from a github action. I could just write the app.yml dynamically from my ci script and inject local environment variables, but it seems like there must be a more canonical way.
I can set environment variables with app.yml using the following syntax.
I would like a solution which works with both standard and flex app engine if possible.
Google Cloud has silently released in Beta Secret Manager. The APIs are available but the client libraries aren't yet. The service will be announced soon and will help you to manage your secrets.
The principle is simple: In your yaml files and in your GIT, you simply save a reference to the secret, for example mySecret#2 where 2 is the version number, and mySecret the name of your secret.
Then, perform a simple call to the API to get access to the secret
https://secretmanager.googleapis.com/v1beta1/projects/<myProject>/secrets/<MySecret>/versions/<Version>:access
The call must be secured with a Bearer access token in the header. Be sure that the App Engine service account has the required roles (default service account: YOUR_PROJECT_ID#appspot.gserviceaccount.com), at least roles/
secretmanager.secretAccessor
Note: I don't know how the library will be implemented if you request the secret without giving an explicit version. Is the 1st version which will be taken? the lastest?
For now, there is a lot of manual overhead (get the token, build the URL, manage errors,...). If you can wait a couple of weeks, the life will be easier with client libraries!

In a Java servlet running in GAE Flex, how do I get the containing GCP project ID programatically?

I am writing a web service (java servlet) in the flexible environment of Google App Engine and I would like to be able to retrieve the GCP project ID that I am running in at runtime programatically. How?
There is a SystemProperty which contains such thins as project id, app version, etc:
SystemProperty.applicationId.get()
Javadoc is here: https://cloud.google.com/appengine/docs/java/javadoc/com/google/appengine/api/utils/SystemProperty
SystemProperty is a part of com.google.appengine.api which is not available on App Engine Flex environment.
On Flex your project name is available as environment variable.
So you simply can use just this:
System.getenv("GCLOUD_PROJECT");
Please see Migrating Services from the Standard Environment to the Flexible Environment for more details.
Also please note that on local development server running Jetty this environment variable might not be set. If so the above code will return null on your development machine.
You might want to set it explicitly though for your local development server needs. For example if you use Bash you can do:
export GCLOUD_PROJECT=myproject
Also you can add it to your development server startup script or to your ~/.bashrc script, whatever works better for your needs.

Why is Google App Engine Making --set-default a default parameter?

So, in the past, when I've used Google App Engine, I've utilized their wonderful version system to create an integration, staging, and production environment. When we're ready to go live, we set the production environment to be the default, and it starts receiving traffic at the standard AppSpot URL (myapp.appspot.com), if it's not the default you have to manually go to the version itself (dev.myapp.appspot.com) for your testing. This is an awesome system for a pre-prod deployment with a full test.
However, I just went to do an App Engine deployment today and got this warning:
WARNING: Soon, deployments will set the deployed version to receive all traffic by
default.
To keep the current behavior (where new deployments do not receive any traffic),
use the `--no-promote` flag or run the following command:
$ gcloud config set app/promote_by_default false
To adopt the new behavior early, use the `--promote` flag or run the following
command:
$ gcloud config set app/promote_by_default true
Either passing one of the new flags or setting one of these properties will
silence this message.
So, apparently, very soon Google will make it so that for every deploy of any version, they will just automatically promote that to be the default and be accessible at the standard AppSpot URL.
My question is, what's the benefit in this? I can't use this for A/B testing (since there's no B in the equation here). I can't use this as a pre-prod test, because it takes over my environment right away. Why would I want any version I push up to be the default? Am I missing something? Was I using versions wrong?
I'm just genuinely curious.

google app engine: how to run different version

Suppose I uploaded another version (say, "version: 2" in file app.yaml ) of my Google App Engine application. Version 1 is still the default and version 2 is for testing. How do I run it then?
Once you upload a version on Appengine, you can switch between them easily.
Say that your app name is myapp, currently running version 1. You also have uploaded a version called 2-testing. Your default app (with version 1) can be reached by accessing myapp.appspot.com
If you wanted to access your versions explicitly, you joust need to access <version_name>-dot-myapp.appspot.com. Following the example it would be:
1-dot-myapp.appspot.com or 2-testing-dot-myapp.appspot.com
The -dot- is equivalent to <version>.<appname> but allows you to correctly serve a secure application with SSL
You can mark any version you want as default (serving myapp.appspot.com) using the admin console
edit: this is the official documentation page talking about domains and subdomains in Appengine
Under versions in your admin console you can find the live uri of a version, if you select the version.
And you can use traffic splitting, where you can use your own client ip or a cookie to test a version.
Docs: https://developers.google.com/appengine/docs/adminconsole/trafficsplitting

Resources