Play 2.0 Scala Heroku instance isn't seeing ev

2019-09-08 05:42发布

问题:

I'm using Play! 2.0 Scala edition on Heroku. Heroku does not seem to see/use all my configuration variables in the Procfile.

For instance, in my application.conf I have the following variables (amongst others):

mongodb.default.db = "nyancat"
mongodb.default.host = "localhost"
mongodb.default.port = 27017

These should be the defaults for local development. However, I want my Heroku instance to use a MongoLabs instance. (Unfortunately, Salat doesn't configure with a URI, so I had to break it down into host, port, yada yada, i.e. MONGOLAB_URI isn't used)

My Procfile now looks like this:

☆  cat Procfile                                             
web: target/start -Dsecurehostname="https://example.org" \
-Dhostname="http://example.org" -Dhttp.port=$PORT \
-DapplyEvolutions.default=true -Ddb.default.driver=org.postgresql.Driver \
-Ddb.default.url=$DATABASE_URL -Dredis=$REDISTOGO_URL \
-Dmailgun.apikey=$MAILGUN_API_KEY -Dmongodb.default.db="heroku_appXXXXXXX" \
-Dmongodb.default.host="dsXXXXXX.mongolab.com" -Dmongodb.default.port=XXXXX \
-Dmongodb.default.user="heroku_appXXXXXXX" \
-Dmongodb.default.password="foobared_not"

I push and restart, but the remote MongoDB connection still says it connects on localhost:27017

Redis and everything else works fine and dandy.

The remote log shows this when starting up, and it clearly doesn't contain all the parameters in my Procfile:

2012-05-20T19:35:18+00:00 heroku[web.1]: Starting process with command \
`target/start -Dhostname="https://example.org" -Dhttp.port=XXXXX \
-DapplyEvolutions.default=true -Ddb.default.driver=org.postgresql.Driver \
-Ddb.default.url=<HIDDEN> -Dredis=<HIDDEN> -Dmailgun.apikey=<HIDDEN>`

I.e. no mongo.* parameters anywhere in the logs.

Please let me know if I'm missing anything, thanks fellas.


UPDATE

I tried to emulate Heroku locally, using sbt stage and running the app with foreman start. I set the environment variables which would be set by Heroku, and run it like this:

app git:(master) ☆  DATABASE_URL="jdbc:h2:mem:mydatabase;MODE=PostgreSQL" \
  REDISTOGO_URL="redis://ignored:foobared@localhost:6379/" \
  foreman start
20:20:27 web.1     | started with pid 43382
20:20:27 web.1     | Play server process ID is 43382
20:20:29 web.1     | [info] play - database [default] connected at jdbc:h2:mem:mydatabase
20:20:29 web.1     | [info] play - mongodb [default] connected at "heroku_appXXXXXXX"@"dsXXXXXX.mongolab.com":XXXXX/"heroku_appXXXXXXX"
20:20:30 web.1     | [info] play - Application started (Prod)
20:20:30 web.1     | [info] play - Listening for HTTP on port 5000...

foreman picks up my PRODUCTION MongoDB values as it is in the Procfile, which validates my argument that Heroku is perhaps using an older version of my Procfile for some unknown reason.

On my Heroku instance, the Procfile is definitely does not have the immutable flag set either:

~ $ lsattr Procfile
------------------- Procfile

UPDATE 2

I'm using MongoDB Salat plugin for Play Framework 2 (Scala only).

Here's a pattern I picked up:

Every push succeeded before I started implementing MongoDB support.

Then I integrated the Salat plugin, signed up for a MongoLabs account, and the fun started. The plugin above doesn't support com.mongodb.MongoURI and due to the way it parses configuration, it will blow up if you give it -Dmongodb.uri. It expects a keyspace, like "default".

Which brings us back to the mongodb.default.* switches I've been using above.

Now my development cycle looks like this:

push, fail
push (without changes), success, but seemingly with old Procfile
<make change>
push, fail
push (without changes), success, but seemingly with old Procfile
<make change>
push, fail
push (without changes), success, but seemingly with old Procfile
...

And most annoyingly, the failing push just logs this:

Heroku push rejected due to an unrecognized error.

...and the heroku logs -t output only show this:

2012-05-22T07:23:59+00:00 heroku[slugc]: Slug compilation failed: unrecognized error

It works locally, BTW.

I've brought all this so Heroku support's attention since it could be that they swallow errors thrown by Typesafe's Config when it could just make things clearer from the start.

I've also asked them not to allow those second pushes to succeed, but then use an old Procfile. Very misleading.

Needless to say, I'm now also implementing MongoURI support for the Salat plugin.


UPDATE 3

I've implemented support for mongodb.default.uri in the Play! Salat plugin (and deployed it using lib/), but Heroku still throws an error whenever I push anything mongo-related in my Procfile.

I've asked Heroku support the same question, and perhaps someone here can answer: does Heroku limit the variables you can use in Procfile?

回答1:

Note that the Procfile's start command can be a maximum of 255 characters long. I expect all your mongodb configurations are way beyond that.

I suggest you refer to an alternative configuration file. for your non environment variable dependant configurations E.g.:

web: target/start -Dhttp.port=$PORT -Ddb.default.url=$DATABASE_URL \
-Dredis=$REDISTOGO_URL -Dmailgun.apikey=$MAILGUN_API_KEY \
-Dconfig.resource=heroku-prod.conf

And in conf/heroku-prod.conf:

include "application.conf"                                        

securehostname="https://example.org" 
hostname="http://example.org" 
applyEvolutions.default=true
db.default.driver=org.postgresql.Driver 
mongodb.default.db="heroku_appXXXXXXX"
mongodb.default.host="dsXXXXXX.mongolab.com"
mongodb.default.port=XXXXX \
mongodb.default.user="heroku_appXXXXXXX"
mongodb.default.password="foobared_not"


回答2:

Maybe that some variables are enabled by plugins? I didn't checked the heroku api, but it could be a clue.

The second point is how you accessed those variables, my guess is that the typesafe configuration system doesn't fallback to command line options.

The last point is according to https://github.com/playframework/Play20/blob/master/framework/src/play/src/main/scala/play/api/Configuration.scala you can add an application.conf in the root of the classpath , it will be used in production mode instead of explicitly retrieving it from conf/.

My 2c



回答3:

You can also try doing your configuration like this in application.conf ....

I'm not sure if this heroku, production mode, or something else but I have noticed something strange about environment variables set with 'heroku config' also.

In application.conf, if one uses the notation

google.client=$(GOOGCLIENTID)

everything seems ok running on the local workstation. I can verify with 'heroku config' that the variable is set, but it clearly is not propagated to the configuration when running on heroku.

However, this notation works ok:

google.client=$(?GOOGCLIENTID)

Hope it helps.



回答4:

Are there any funny characters in $MAILGUN_API_KEY? Try moving -Dmailgun.apikey=$MAILGUN_API_KEY to the end...