I'm a fan of the cfenv package for Node.js written by Patrick Mueller. It parses environment info in a Bluemix (or Cloud Foundry) application, and provides functions to make it easy to retrieve all of the service attributes you need from VCAP_SERVICES. It also gives access to other important attributes for port, host name/ip address, URL of the application, etc. On top of that, it detects whether your app is running locally or in the cloud. And, when running locally, it provides handy defaults.
I've written a simple wrapper (a local module called cfenv-wrapper) to make local development of Bluemix/Cloud Foundry apps a little easier. My code parses a local copy of your app's environment data, and extracts the data for VCAP_SERVICES and VCAP_APPLICATION. Then, it passes that information to cfenv's initialization function, getAppEnv. After this initialization, you can use the same cfenv interface just as if you were running in the cloud.
The local environment data can be in JSON or properties files meeting the following requirements:
env.json-- JSON file withVCAP_SERVICESinfo as retrieved bycf env. Ifenv.jsonis present, the code will also loadenv_custom.json, which should hold JSON representing your app's user-defined environment variables.env.logfile (deprecated) -- If there's noenv.jsonfile, the wrapper will load a local copy of your app'senv.logfile. This is provided for backwards compatibility with earlier versions ofcfenv-wrapper. After CF 182, CF stopped providing anenv.logfile for security reasons.
NOTE: Many cloud services can be accessed with no changes when running locally. In Bluemix, a partial list of these includes Cloudant, Pitney Bowes, and Twilio. In those cases, you can use env.json and env.log with the exact data provided by CF. However, there are services that don't yet allow connections from outside of Bluemix. For those services, you would need to modify your local file so that it uses info specific to installations of those services in your local environment.
My wrapper also adds two new functions, not in the original cfenv interface:
getEnvVars-- returns JSON data structure containing all environment variables. When running locally, it returns the data from theenv_custom.jsonorenv.logfiles. When running in the cloud, it will return the standardprocess.envruntime variable.getEnvVar(name)-- returns value of the environment variable with the given name. When running locally, it will try to pull the value from theenv_custom.jsonorenv.logfiles. If it can't find it, it falls back to the standardprocess.envruntime variable.
These serve to give you a consistent interface for environment variable resolution in both environments.
You can run a a working deployment of the code on Bluemix by using the link below:
You need to get the code onto your machine in order to run your own copy on Bluemix, another Cloud Foundry-based environment, or locally. You have two main options:
- Use the zip archive for this repository:
- Download master.zip
- Extract to the directory of your choice which should create a directory called
node-cfenv-wrapper-master - Run
cd node-cfenv-wrapper-master
OR
- Use
git clonefrom the command line:cdto the parent directory you want to install the project in- Run
git clone https://github.com/aerwin/node-cfenv-wrapper.git - Run
cd node-cfenv-wrapper/
Before installing the code to Bluemix you will need to:
- Register for an account at www.bluemix.net. If you don't already have an account you can register for a free trial without a credit card.
- Install the
cfcommand line tool: https://github.com/cloudfoundry/cli/releases
If you are not logged into Bluemix, then you should do the following from the command line:
- Set the
cftarget:cf api https://api.ng.bluemix.net - Log into Bluemix:
cf login
Now that you are logged in, you should be able to push your code to Bluemix by simply running:
cf push
You should then see a bunch of console output that eventually ends with something like the what is shown below. NOTE: the string ${random-word} was included as a placeholder in the manifest.yml file so that a unique route (or URL) would be created for your app. So, where you see ${random-word} in the output, you will actually see a randomly chosen word.
Showing health and status for app cfenv-wrapper in org aerwin@us.ibm.com / space test as aerwin@us.ibm.com...
OK
requested state: started
instances: 1/1
usage: 128M x 1 instances
urls: cfenv-wrapper-${random-word}.mybluemix.net
state since cpu memory disk
#0 running 2014-10-04 03:19:59 PM 0.0% 15.7M of 128M 25.1M of 1G
After the successful push, you should be able to run your app by pointing your browser at:
http://cfenv-wrapper-${random-word}.mybluemix.net/
If everything works, the page in the browser should show something like the following (notice Is Local is false):
BASE_INFO
---------
Is Local: false
App Name: cfenv-wrapper
Port: 61400
Bind: 0.0.0.0
URL: https://cfenv-wrapper.mybluemix.net
SERVICES
--------
No services are bound to this app.
ENVIRONMENT VARIABLES
----------------------------
TMPDIR:/home/vcap/tmp
VCAP_APP_PORT:61321
USER:vcap
PATH:/home/vcap/app/vendor/node/bin:/home/vcap/app/bin:/home/vcap/app/node_modules/.bin:/bin:/usr/bin
PWD:/home/vcap/app
SHLVL:1
HOME:/home/vcap/app
PORT:61321
VCAP_APP_HOST:0.0.0.0
MEMORY_LIMIT:128m
_:/home/vcap/app/vendor/node/bin/node
OLDPWD:/home/vcap
If you start binding services or adding environment variables to your app, then you'll see additional data in the SERVICES and ENVIRONMENT VARIABLES sections when you refresh the page.
Information retrieved using cfenv:
BASE_INFO
---------
Is Local: false
App Name: cfenv-wrapper
Port: 61400
Bind: 0.0.0.0
URL: https://cfenv-wrapper.mybluemix.net
SERVICES
--------
CloudantNoSQLDB
CUSTOM ENVIRONMENT VARIABLES
----------------------------
MY_ENVIRONMENT_VARIABLE: Bluemix rules
...
To see a JSON representation of your app's environment data, you can run the following cf command:
cf env APP_NAME
Then, copy the JSON (which starts right after the System-Provided header and ends just before the User-Provided header) into a file named env.json. This file should be in the same place on your local file system that you put the code. That is, as a peer to the server.js file.
If you have user-defined environment variables, put them into a file name env_custom.json. For example, if cf env shows the following user-provided environment variables:
User-Provided:
CUSTOM_ENV_VAR1: Value 1
CUSTOM_ENV_VAR2: Value 2
CUSTOM_ENV_VAR3: Value 3
Then, you would want your env_custom.json file to look like this:
{
"CUSTOM_ENV_VAR1": "Value 1",
"CUSTOM_ENV_VAR2": "Value 2",
"CUSTOM_ENV_VAR3": "Value 3"
}
NOTE: This section is only applicable if running a version of CF earlier than 182.
To see the contents of env.log, you can run the following cf command:
cf files APP_NAME logs/env.log
Then, copy the output into a file named env.log to the same place on your local file system that you put the code. That is, as a peer to the server.js file.
Assuming you have already downloaded and installed Node.js (which also includes npm), then you can run the following command from the code directory (the one containing server.js) to retrieve dependencies:
npm install
Once dependencies are installed, you can run the following command from the code directory:
node server.js
Then, point your browser at the URL that is shown in the console output (e.g., something like http://localhost:6001). You should see similar kinds of information that you saw when running in the cloud. However, the top part will be different (e.g., Is Local will be true and port/url will be changed). But, the SERVICES and ENVIRONMENT VARIABLES sections should reflect whatever was in your env.json \ env_custom.json or env.log files:
Information retrieved using cfenv:
BASE_INFO
---------
Is Local: true
App Name: cfenv-wrapper
Port: 6001
Bind: 0.0.0.0
URL: http://localhost:6001
...
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.