16

I work on multiple appengine projects in any given week. i.e. assume multiple clients. Earlier I could set application in app.yaml. So whenever I did appcfg.py update.... it would ensure deployment to the right project.

When deploying, the application variable throws an error with gcloud deploy. I had to use gcloud app deploy --project [YOUR_PROJECT_ID]. So what used to be a directory level setting for a project, is now going into our build tooling. And missing out that simple detail can push a project code to the wrong customer. i.e. if I did gcloud config set project proj1 and then somehow did a gcloud app deploy in proj2, it would deploy to proj1. Production deployments are done after detailed verification on the build tools and hence it is less of an issue there because we still use the --project flag.

But its hard to do similar stuff on the development environment. dev_appserver.py doesn't have a --project flag. When starting dev_appserver.py I've to do gcloud config set project <project-id> before I start the server. This is important when I using stuff like PubSub or GCS (in dev topics or dev buckets).

Unfortunately, missing out a simple configuration like setting a project ID in a dev environment can result into uploading blobs/messages/etc into the wrong dev gcs bucket or wrong dev pubsub topic (not using emulators). And this has happened quite a few times especially when starting new projects.

I find the above solutions as hackish-workarounds. Is there a good way to ensure that we do not deploy or develop in a wrong project when working from a certain directory?

anups
  • 583
  • 1
  • 7
  • 18

4 Answers4

7

TL;DR - Not supported based on the current working directory, but there are workarounds.

Available workarounds

gcloud does not directly let you set up a configuration per working directory. Instead, you could use one of these 3 options to achieve something similar:

  1. Specify --project, --region, --zone or the config of interest per command. This is painful but gets the job done.

  2. Specify a different gcloud configuration directory per command (gcloud uses ~/.config/gcloud on *nix by default):

    CLOUDSDK_CONFIG=/path/to/config/dir1 gcloud COMMAND
    CLOUDSDK_CONFIG=/path/to/config/dir2 gcloud COMMAND
    
  3. Create multiple configurations and switch between them as needed.

    gcloud config configurations activate config-1 && gcloud COMMAND
    

Shell helpers

As all of the above options are ways to customize on the command line, aliases and/or functions in your favorite shell will also help make things easier.

For example in bash, option 2 can be implemented as follows:

function gcloud_proj1() {
  CLOUDSDK_CONFIG=CLOUDSDK_CONFIG=/path/to/config/dir1 $@
}

function gcloud_proj2() {
  CLOUDSDK_CONFIG=CLOUDSDK_CONFIG=/path/to/config/dir2 $@
}

gcloud_proj1 COMMAND
gcloud_proj2 COMMAND
Tuxdude
  • 47,485
  • 15
  • 109
  • 110
  • 1
    Even with the ENV `CLOUDSDK_CONFIG`, gcloud is still trying to fetch config from `~/.config/gcloud`. Can you please help me out – Waqar Ahmed Mar 17 '20 at 17:16
3

There's a very nice way I've been using with PyCharm, I suspect you can do so with other IDEs.

You can declare the default env variables for the IDE Terminal, so when you open a new terminal gcloud recognises these env variables and sets the project and account.

pycharm preferences config terminal env variables

No need to switch configurations between projects manually (gcloud config configurations activate ). Terminals open in other projects will inherit it's own GCP project and config from the ENV variables.

dinigo
  • 6,872
  • 4
  • 37
  • 48
2

I've had this problem for years and I believe I found a decent compromise.

  1. Create a simple script called contextual-gcloud. Note the \gcloud, fundamental for future aliasing.
$ cat > contextual-gcloud 
#!/bin/bash

if [ -d .gcloudconfig/ ]; then
    echo "[$0] .gcloudconfig/ directory detected: using that dir for configs instead of default."
    CLOUDSDK_CONFIG=./.gcloudconfig/ \gcloud "$@"
else
    \gcloud "$@"
fi
  1. Add to your .bashrc and reload / start new bash. This will fix autocompletion.

    alias gcloud=contextual-gcloud

  2. That's it! If you have a directory called that way the system will use that instead, which means you can load your configuration into source control etc.. only remember to git ignore stuff like logs, and private stuff (keys, certificates, ..).

Note: auto-completion is fixed by the alias ;)

Code: https://github.com/palladius/sakura/blob/master/bin/contextual-gcloud

Riccardo
  • 1,104
  • 13
  • 22
  • Sir, this is exquisite. And just enough to stop messing up, inadvertently deploying to the wrong project. But do you think it can be extended to take the roots closest `gcloudconfig` file? Just like git will do, so we can invoke those commands from a sub-directory and still have this config set? I'm thinking on having several cloud functions on different folders for the same project. And still being able to deploy them from each of there sub-folders – dinigo Jan 31 '21 at 13:44
0

These are exactly the reasons for which I highly dislike gcloud. Making command line argument mandatory and dropping configuration files support, much too error prone for my taste.

So far I'm still able to use the GAE SDK instead of Google Cloud SDK (see What is the relationship between Google's App Engine SDK and Cloud SDK?), which could be one option - basically keep doing stuff "the old way". Please note that it's no longer the recommended method.

You can find the still compatible GAE SDKs here.

For whenever the above will no longer be an option and I'll be forced to switch to the Cloud SDK my plan is to have version-controlled cheat-sheet text files in each app directory containing the exact cmds to use for running the devserver, deploy, etc for that particular project which I can just copy-paste into the terminal without fear of making mistakes. You carefully set these up once and then you just copy-paste them. As a bonus you can have different branch versions for different environments (staging/production, for example).

Actually I'm using this approach even for the GAE SDK - to prevent accidental deployment of the app-level config files to the wrong GAE app (such deployments must use cmdline arguments to specify the app in multi-service apps).

Or do the same but with environment config files and wrapper scripts instead of cheat-sheet files, if that's your preference.

Dan Cornilescu
  • 39,470
  • 12
  • 57
  • 97