Detecting environment in GCloud Functions (Live/Emulator) - node.js

GCloud Functions are great and the emulator is a cool tool, but I'm having problems figuring out a way to detect wether I am running in a live mode or in the emulator.
Environment variables would come to mind, but I can't find a way to pass them along to the function when calling.
Runtime config might also be a solution but the emulator does not support this.
Easy fix would be using a param in the payload e.g. isDev: true and then check in the function:
if (data.isDev === true)
{ //use dev config }
else
{ // use live config }
but I'd keep that as a last resort solution.
Any other ideas on what could be a better solution?

Related

How to disable function logs on Gatsby?

So, I am new to gatsby and I am trying to build gatsby functions the way it is written in this documentation: https://www.gatsbyjs.com/docs/reference/functions/getting-started/
However, whenever I execute the function, it logs something like "Executed function "/api/test" in 27ms".
Now, since this will be a frequently called function in the future, I wish to disable the logs preferably just for this function OR for all the functions under /api folder.
Can anyone help please me out?
Try using gatsby-plugin-remove-console plugin:
module.exports = {
plugins: [
'gatsby-plugin-remove-console'
],
};
There isn't any built-in method of disabling logs as far as I know so try using the plugin. However, I'm not sure about its use in Gatsby functions...

How can I access runtime environment variables from a webpack-compiled script that runs in node?

We package and ship a web server that runs in node, using webpack (an admittedly unusual scenario).
In this web server, I would like to access runtime environment variables, not the environment variables from the compile-time run of webpack. However, process.env just contains { NODE_ENV: 'development' }.
Is there some way of accessing the actual runtime process's environment?
The replacement of process.env is actually done by changing code that accesses that variable. If you access it programmatically in a way that avoids this, you will be able to use the underlying variable which is still present:
// avoid cunning webpack replacement of process.env code
let process_env = {}
for (var a of ['env']) {
process_env = process[a]
}
console.log(process.env.HOME) // this gives undefined
console.log(process_env.HOME) // this works

How to get Heroku to ignore a failed import?

I've got a project deployed on heroku using React and node, for which I'm importing a json file which contains various API keys (for firebase, AWS, etc.). In development, I simply do import keys from './keys.json'. However I was aware that wouldn't work in Heroku, so I set up the appropriate environment vars and used process.env to get them. Now though... the whole compilation/build of my project fails because Heroku can't find keys.json (since I don't deploy it, for apparent reasons). Is there any way to get it to ignore this one particular failure during build so it can go ahead and use the env vars?
Wrap the import in a conditional:
var keys = {}
if (!process.env['AWS_KEY']) {
keys = require('./keys.json')['keys'];
}
This has the side effect of giving precedence to environment variables over a local file. If you want the file to have precedence instead, look at fs.existsSync as your conditional (fs.exists could be used with some work).

Changing Express constant based on URL (ie localhost vs production)

I'm fairly new to node and express...
I have a constant I set in my Node/Express application for "Domain". I'm constantly switching between localhost and the actual url when I switch between development and production.
I'm trying to figure out how I can automatically test the URL so that when the code is read on the server (ie actual domain url vs localhost) that it sets the proper domain url.
Here is my code:
function define(name, value) {
Object.defineProperty(exports, name, {
value: value,
enumerable: true
});
}
define("DOMAIN", "http://www.actual_domain.com");
// define("DOMAIN", "http://localhost:3000");
Anyone have a simple solution for this?
Thanks!!
there is many solutions for this, but usually this is done by environment variables, depends on your platform, but, in Linux systems, you do the following in your shell
export ENV_URL="http://www.example.com"
and to make sure its exported successfully
echo $ENV_URL
and in your code you do
const base_url = process.env.ENV_URL || "http://www.default.com";
in your local machine you set the ENV_URL to localhost or whatever you prefer, and in your server you set it to your actual URL.
or you could simply have many configuration files and you can determine the appropriate one by the environemnt variable like
export ENV=PROD
and in your code you can load the prod configuration file that contains your environment configurations.
The de facto way to do this sort of thing is through environment variables. Have a look at 12factor.net for a load of best practices, but in general you want to put differences in the environment into environment variables, then read those variables at runtime.

Is there any better way to pass sensitive data to the program, alternative to env variables?

I want to use npm twitter package, and it recommends to use env variables, but setting it up on windows machines is horror, so I want to avoid env variables. Next try is keep variables in external json file (like here in my repo), which is never be committed, but it’s playing not good with CI, because if it’s not in the repo, how can I use it and test, right?
Let me show.
env variables (windows users’ nightmare):
var Twitter = require('twitter');
var client = new Twitter({
consumer_key: process.env.TWITTER_CONSUMER_KEY,
consumer_secret: process.env.TWITTER_CONSUMER_SECRET,
access_token_key: process.env.TWITTER_ACCESS_TOKEN_KEY,
access_token_secret: process.env.TWITTER_ACCESS_TOKEN_SECRET,
});
untestable crap
var Twitter = require('twitter');
var keys = require('./keys.json');
var client = new Twitter(keys);
with this line in .gitignore:
keys.json
no winners situation; is there any better way?
There are no winners in this situation and it makes me sad. I want to achieve two simple goals: easy consumption and testability. Can you help me? How do you deal with this?
Update: I’m talking in terms of developing opensource lib based on twitter API, not about end user product, that’s I feel unsecure about keeping tokens in repo.
Update 2: Windows users’ have set and setx commands. Hurray! thx to Martin Konecny for noting this.
Solution: while there is no crap in setting up env variables in windows, it’s better to let code consumer to choose how to pass data to his end-product (which is using my lib). So we end up with situation, which has no "data-passing" problem. And because of it it’s testable, because I can use env variables in my tests to test it in Travis CI.
just let your user choose what's best for him. implement (or use library as there are such libraries for most languages) something that will let you pass and shadow properties in many different formats: api, file, envs, command line.
then:
in your local test you can simply use api as part of test configuration
in your integration tests you can put json file (ignored by git)
on travis you can use command line parameters or environment properties
on production you will use environment properties or remote server with configuration
Seeing as this is an open-source project, you will most likely not be able to include your Twitter API keys inside the project itself. I see two potential solutions:
Require the users to register for their own Twitter API
credentials, and add these to your project's config file before
running the project and its tests.
If you are trying to use
something like Travis CI to auto-test any new commits, you may need to mock your requests instead.
Option #2 may not be ideal since it doesn't take into account any future API changes from Twitter, however it allows you to test breakage of any commits assuming the API does remain stable.

Resources